fix(compiler): keep DOM.hasProperty
in sync between browser and transformer.
Right now, we always return true until we have property schema support (#2014). Fixes #2984 Closes #2981
This commit is contained in:
parent
7ee6963f5d
commit
b3a763a718
@ -98,17 +98,19 @@ final _keyCodeToKeyMap = const {
|
|||||||
class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
||||||
js.JsFunction _setProperty;
|
js.JsFunction _setProperty;
|
||||||
js.JsFunction _getProperty;
|
js.JsFunction _getProperty;
|
||||||
js.JsFunction _hasProperty;
|
|
||||||
BrowserDomAdapter() {
|
BrowserDomAdapter() {
|
||||||
_setProperty = js.context.callMethod('eval', ['(function(el, prop, value) { el[prop] = value; })']);
|
_setProperty = js.context.callMethod('eval', ['(function(el, prop, value) { if (prop in el) el[prop] = value; })']);
|
||||||
_getProperty = js.context.callMethod('eval', ['(function(el, prop) { return el[prop]; })']);
|
_getProperty = js.context.callMethod('eval', ['(function(el, prop) { return el[prop]; })']);
|
||||||
_hasProperty = js.context.callMethod('eval', ['(function(el, prop) { return prop in el; })']);
|
|
||||||
}
|
}
|
||||||
static void makeCurrent() {
|
static void makeCurrent() {
|
||||||
setRootDomAdapter(new BrowserDomAdapter());
|
setRootDomAdapter(new BrowserDomAdapter());
|
||||||
}
|
}
|
||||||
bool hasProperty(Element element, String name) =>
|
bool hasProperty(Element element, String name) {
|
||||||
_hasProperty.apply([element, name]);
|
// Always return true as the serverside version html_adapter.dart does so.
|
||||||
|
// TODO: change this once we have schema support.
|
||||||
|
// Note: This nees to kept in sync with html_adapter.dart!
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void setProperty(Element element, String name, Object value) =>
|
void setProperty(Element element, String name, Object value) =>
|
||||||
_setProperty.apply([element, name, value]);
|
_setProperty.apply([element, name, value]);
|
||||||
|
@ -11,7 +11,9 @@ class Html5LibDomAdapter implements DomAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hasProperty(element, String name) {
|
hasProperty(element, String name) {
|
||||||
// This is needed for serverside compile to generate the right getters/setters...
|
// This is needed for serverside compile to generate the right getters/setters.
|
||||||
|
// TODO: change this once we have property schema support.
|
||||||
|
// Attention: Keep this in sync with browser_adapter.dart!
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1245,31 +1245,33 @@ export function main() {
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('Missing property bindings', () => {
|
if (!IS_DARTIUM) {
|
||||||
it('should throw on bindings to unknown properties',
|
describe('Missing property bindings', () => {
|
||||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
it('should throw on bindings to unknown properties',
|
||||||
tcb =
|
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||||
tcb.overrideView(MyComp,
|
tcb =
|
||||||
new viewAnn.View({template: '<div unknown="{{ctxProp}}"></div>'}))
|
tcb.overrideView(MyComp,
|
||||||
|
new viewAnn.View({template: '<div unknown="{{ctxProp}}"></div>'}))
|
||||||
|
|
||||||
PromiseWrapper.catchError(tcb.createAsync(MyComp), (e) => {
|
PromiseWrapper.catchError(tcb.createAsync(MyComp), (e) => {
|
||||||
expect(e.message).toEqual(
|
expect(e.message).toEqual(
|
||||||
`Can't bind to 'unknown' since it isn't a know property of the 'div' element and there are no matching directives with a corresponding property`);
|
`Can't bind to 'unknown' since it isn't a know property of the 'div' element and there are no matching directives with a corresponding property`);
|
||||||
async.done();
|
async.done();
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should not throw for property binding to a non-existing property when there is a matching directive property',
|
it('should not throw for property binding to a non-existing property when there is a matching directive property',
|
||||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||||
tcb.overrideView(
|
tcb.overrideView(
|
||||||
MyComp,
|
MyComp,
|
||||||
new viewAnn.View(
|
new viewAnn.View(
|
||||||
{template: '<div my-dir [elprop]="ctxProp"></div>', directives: [MyDir]}))
|
{template: '<div my-dir [elprop]="ctxProp"></div>', directives: [MyDir]}))
|
||||||
.createAsync(MyComp)
|
.createAsync(MyComp)
|
||||||
.then((val) => { async.done(); });
|
.then((val) => { async.done(); });
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Disabled until a solution is found, refs:
|
// Disabled until a solution is found, refs:
|
||||||
// - https://github.com/angular/angular/issues/776
|
// - https://github.com/angular/angular/issues/776
|
||||||
|
@ -22,38 +22,40 @@ export function main() {
|
|||||||
var builder;
|
var builder;
|
||||||
beforeEach(() => { builder = new ProtoViewBuilder(el('<div/>'), ViewType.EMBEDDED); });
|
beforeEach(() => { builder = new ProtoViewBuilder(el('<div/>'), ViewType.EMBEDDED); });
|
||||||
|
|
||||||
describe('verification of properties', () => {
|
if (!IS_DARTIUM) {
|
||||||
|
describe('verification of properties', () => {
|
||||||
|
|
||||||
|
it('should throw for unknown properties', () => {
|
||||||
|
builder.bindElement(el('<div/>')).bindProperty('unknownProperty', emptyExpr());
|
||||||
|
expect(() => builder.build())
|
||||||
|
.toThrowError(
|
||||||
|
`Can't bind to 'unknownProperty' since it isn't a know property of the 'div' element and there are no matching directives with a corresponding property`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow unknown properties if a directive uses it', () => {
|
||||||
|
var binder = builder.bindElement(el('<div/>'));
|
||||||
|
binder.bindDirective(0).bindProperty('someDirProperty', emptyExpr(), 'directiveProperty');
|
||||||
|
binder.bindProperty('directiveProperty', emptyExpr());
|
||||||
|
expect(() => builder.build()).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow unknown properties on custom elements', () => {
|
||||||
|
var binder = builder.bindElement(el('<some-custom/>'));
|
||||||
|
binder.bindProperty('unknownProperty', emptyExpr());
|
||||||
|
expect(() => builder.build()).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw for unknown properties on custom elements if there is an ng component', () => {
|
||||||
|
var binder = builder.bindElement(el('<some-custom/>'));
|
||||||
|
binder.bindProperty('unknownProperty', emptyExpr());
|
||||||
|
binder.setComponentId('someComponent');
|
||||||
|
expect(() => builder.build())
|
||||||
|
.toThrowError(
|
||||||
|
`Can't bind to 'unknownProperty' since it isn't a know property of the 'some-custom' element and there are no matching directives with a corresponding property`);
|
||||||
|
});
|
||||||
|
|
||||||
it('should throw for unknown properties', () => {
|
|
||||||
builder.bindElement(el('<div/>')).bindProperty('unknownProperty', emptyExpr());
|
|
||||||
expect(() => builder.build())
|
|
||||||
.toThrowError(
|
|
||||||
`Can't bind to 'unknownProperty' since it isn't a know property of the 'div' element and there are no matching directives with a corresponding property`);
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
it('should allow unknown properties if a directive uses it', () => {
|
|
||||||
var binder = builder.bindElement(el('<div/>'));
|
|
||||||
binder.bindDirective(0).bindProperty('someDirProperty', emptyExpr(), 'directiveProperty');
|
|
||||||
binder.bindProperty('directiveProperty', emptyExpr());
|
|
||||||
expect(() => builder.build()).not.toThrow();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow unknown properties on custom elements', () => {
|
|
||||||
var binder = builder.bindElement(el('<some-custom/>'));
|
|
||||||
binder.bindProperty('unknownProperty', emptyExpr());
|
|
||||||
expect(() => builder.build()).not.toThrow();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw for unknown properties on custom elements if there is an ng component', () => {
|
|
||||||
var binder = builder.bindElement(el('<some-custom/>'));
|
|
||||||
binder.bindProperty('unknownProperty', emptyExpr());
|
|
||||||
binder.setComponentId('someComponent');
|
|
||||||
expect(() => builder.build())
|
|
||||||
.toThrowError(
|
|
||||||
`Can't bind to 'unknownProperty' since it isn't a know property of the 'some-custom' element and there are no matching directives with a corresponding property`);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('property normalization', () => {
|
describe('property normalization', () => {
|
||||||
it('should normalize "innerHtml" to "innerHTML"', () => {
|
it('should normalize "innerHtml" to "innerHTML"', () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user