Skip to content

Commit

Permalink
Ensure registered is always called on element prototype
Browse files Browse the repository at this point in the history
Previously, it could be called on a superclass' prototype and not the element's prototype.
  • Loading branch information
Steven Orvell committed Nov 13, 2018
1 parent d64a9c2 commit 50ad018
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 30 deletions.
49 changes: 29 additions & 20 deletions lib/legacy/class.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,12 +215,12 @@ function mergeElementProperties(a, b) {
behaviors not active on the superclass. In order to call through to the
entire list of lifecycle methods, it's important to call `super`.
The element's `properties`, `observers`, and the `_registered` method
are controlled via the finalization mechanism provided by `PropertiesMixin`.
The element's `properties` and `observers` are controlled via the finalization
mechanism provided by `PropertiesMixin`. `Properties` and `observers` are
collected by manually traversing the prototype chain and merging.
`Properties` and `observers` are collected by manually traversing the prototype
chain and merging. The `_registered` method is called via
`LegacyElementMixin._finalizeClass`.
To limit changes, the `_registered` method is called via `_initializeProperties`
and not `_finalizeClass`.
*/
/**
Expand Down Expand Up @@ -284,7 +284,6 @@ function GenerateClassFromInfo(info, Base, behaviors) {
/**
* @return {void}
*/
// Called on element prototype
_registered() {
/* NOTE: `beforeRegister` is called here for bc, but the behavior
is different than in 1.x. In 1.0, the method was called *after*
Expand All @@ -293,21 +292,31 @@ function GenerateClassFromInfo(info, Base, behaviors) {
in `beforeRegister` or `registered`. It is no longer possible to set
`is` in `beforeRegister` as you could in 1.x.
*/
const proto = this;
// copy properties lazily if we're optimizing
if (legacyOptimizations) {
copyPropertiesToProto(proto);
}
let list = lifecycle.beforeRegister;
if (list) {
for (let i=0; i < list.length; i++) {
list[i].call(proto);
// only proceed if the generated class' prototype has not been registered.
const generatedProto = PolymerGenerated.prototype;
if (!generatedProto.hasOwnProperty('__hasRegisterFinished')) {
generatedProto.__hasRegisterFinished = true;
// ensure superclass is registered first.
super._registered();
// copy properties onto the generated class lazily if we're optimizing,
if (legacyOptimizations) {
copyPropertiesToProto(generatedProto);
}
}
list = lifecycle.registered;
if (list) {
for (let i=0; i < list.length; i++) {
list[i].call(proto);
// make sure legacy lifecycle is called on the *element*'s prototype
// and not the generated class prototype; if the element has been
// extended, these are *not* the same.
const proto = Object.getPrototypeOf(this);
let list = lifecycle.beforeRegister;
if (list) {
for (let i=0; i < list.length; i++) {
list[i].call(proto);
}
}
list = lifecycle.registered;
if (list) {
for (let i=0; i < list.length; i++) {
list[i].call(proto);
}
}
}
}
Expand Down
16 changes: 6 additions & 10 deletions lib/legacy/legacy-element-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,6 @@ export const LegacyElementMixin = dedupingMixin((base) => {
return this.prototype.importMeta;
}

static _finalizeClass() {
// Note, call `_registered` only if this specific prototype has
// an implementation; this ensures `_registered` is not called
// on extenders that do not implement it.
if (this.prototype.hasOwnProperty('_registered')) {
this.prototype._registered();
}
super._finalizeClass();
}

/**
* Legacy callback called during the `constructor`, for overriding
* by the user.
Expand Down Expand Up @@ -183,6 +173,12 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @suppress {invalidCasts}
*/
_initializeProperties() {
let proto = Object.getPrototypeOf(this);
if (!proto.hasOwnProperty('__hasRegisterFinished')) {
this._registered();
// backstop in case the `_registered` implementation does not set this
proto.__hasRegisterFinished = true;
}
super._initializeProperties();
this.root = /** @type {HTMLElement} */(this);
this.created();
Expand Down

0 comments on commit 50ad018

Please sign in to comment.