fix(elements): correctly handle getting/setting properties before connecting the element (#36114)

`createCustomElements()` creates some getters/setters for properties
corresponding to component inputs that delegate to the
`NgElementStrategy`. However, it is not guaranteed that the element's
`NgElementStrategy` will have been created when these getters/setters
are called, because some polyfills (e.g. `document-register-element`) do
not call the constructor.

Previously, trying to get/set input properties before connecting the
element to the DOM (via `connectedCallback()`) would fail due to
`NgElementStrategy` not being created.

This commit ensures that the `NgElementStrategy` is always created
before used inside the input property getters/setters (similar to how it
is done for other methods of `NgElement`).

Mentioned in https://github.com/angular/angular/pull/31416/files#r300326698.

PR Close #36114
This commit is contained in:
George Kalpakas
2020-05-20 11:10:20 +03:00
committed by Kara Erickson
parent 4c30aa8343
commit 327980bf49
2 changed files with 22 additions and 0 deletions

View File

@ -94,6 +94,22 @@ if (browserDetection.supportsCustomElements) {
expect(strategy.inputs.get('fooFoo')).toBe('foo-foo-value');
expect(strategy.inputs.get('barBar')).toBe('barBar-value');
});
it('should properly handle getting/setting properties on the element even if the constructor is not called',
() => {
// Create a custom element while ensuring that the `NgElementStrategy` is not created
// inside the constructor. This is done to emulate the behavior of some polyfills that do
// not call the constructor.
strategyFactory.create = () => undefined as unknown as NgElementStrategy;
const element = new NgElementCtor(injector);
strategyFactory.create = TestStrategyFactory.prototype.create;
element.fooFoo = 'foo-foo-value';
element.barBar = 'barBar-value';
expect(strategy.inputs.get('fooFoo')).toBe('foo-foo-value');
expect(strategy.inputs.get('barBar')).toBe('barBar-value');
});
});
}