fix(ivy): throw on bindings to unknown properties (#28537)
This commit adds a devMode-only check which will throw if a user attempts to bind a property that does not match a directive input or a known HTML property. Example: ``` <div [unknownProp]="someValue"></div> ``` The above will throw because "unknownProp" is not a known property of HTMLDivElement. This check is similar to the check executed in View Engine during template parsing, but occurs at runtime instead of compile-time. Note: This change uncovered an existing bug with host binding inheritance, so some Material tests had to be turned off. They will be fixed in an upcoming PR. PR Close #28537
This commit is contained in:

committed by
Miško Hevery

parent
7660d0d74a
commit
1950e2d9ba
@ -17,7 +17,7 @@ import {MockBackend, MockConnection} from '@angular/http/testing';
|
||||
import {BrowserModule, DOCUMENT, Title, TransferState, makeStateKey} from '@angular/platform-browser';
|
||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||
import {BEFORE_APP_SERIALIZED, INITIAL_CONFIG, PlatformState, ServerModule, ServerTransferStateModule, platformDynamicServer, renderModule, renderModuleFactory} from '@angular/platform-server';
|
||||
import {fixmeIvy, ivyEnabled} from '@angular/private/testing';
|
||||
import {fixmeIvy, ivyEnabled, modifiedInIvy} from '@angular/private/testing';
|
||||
import {Observable} from 'rxjs';
|
||||
import {first} from 'rxjs/operators';
|
||||
|
||||
@ -99,7 +99,7 @@ class TitleApp {
|
||||
class TitleAppModule {
|
||||
}
|
||||
|
||||
@Component({selector: 'app', template: '{{text}}<h1 [innerText]="h1"></h1>'})
|
||||
@Component({selector: 'app', template: '{{text}}<h1 [textContent]="h1"></h1>'})
|
||||
class MyAsyncServerApp {
|
||||
text = '';
|
||||
h1 = '';
|
||||
@ -276,6 +276,19 @@ class MyHostComponent {
|
||||
class FalseAttributesModule {
|
||||
}
|
||||
|
||||
@Component({selector: 'app', template: '<div [innerText]="foo"></div>'})
|
||||
class InnerTextComponent {
|
||||
foo = 'Some text';
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [InnerTextComponent],
|
||||
bootstrap: [InnerTextComponent],
|
||||
imports: [ServerModule, BrowserModule.withServerTransition({appId: 'inner-text'})]
|
||||
})
|
||||
class InnerTextModule {
|
||||
}
|
||||
|
||||
@Component({selector: 'app', template: '<input [name]="name">'})
|
||||
class MyInputComponent {
|
||||
@Input()
|
||||
@ -528,7 +541,7 @@ class HiddenModule {
|
||||
let doc: string;
|
||||
let called: boolean;
|
||||
let expectedOutput =
|
||||
'<html><head></head><body><app ng-version="0.0.0-PLACEHOLDER">Works!<h1 innertext="fine">fine</h1></app></body></html>';
|
||||
'<html><head></head><body><app ng-version="0.0.0-PLACEHOLDER">Works!<h1 textcontent="fine">fine</h1></app></body></html>';
|
||||
|
||||
beforeEach(() => {
|
||||
// PlatformConfig takes in a parsed document so that it can be cached across requests.
|
||||
@ -567,6 +580,15 @@ class HiddenModule {
|
||||
});
|
||||
}));
|
||||
|
||||
modifiedInIvy('Will not support binding to innerText in Ivy since domino does not')
|
||||
.it('should support binding to innerText', async(() => {
|
||||
renderModule(InnerTextModule, {document: doc}).then(output => {
|
||||
expect(output).toBe(
|
||||
'<html><head></head><body><app ng-version="0.0.0-PLACEHOLDER"><div innertext="Some text">Some text</div></app></body></html>');
|
||||
called = true;
|
||||
});
|
||||
}));
|
||||
|
||||
it('using renderModuleFactory should work',
|
||||
async(inject([PlatformRef], (defaultPlatform: PlatformRef) => {
|
||||
const compilerFactory: CompilerFactory =
|
||||
|
Reference in New Issue
Block a user