diff --git a/lib/legacy/class.html b/lib/legacy/class.html index e416c58314..ce3ff47214 100644 --- a/lib/legacy/class.html +++ b/lib/legacy/class.html @@ -155,58 +155,6 @@ return list; } - function mergePropertyInfo(a, b) { - if ('value' in b) { - a.value = b.value; - // ensure property value is always overridden. - } else if ('value' in a) { - delete a.value; - } - if (typeof b === 'function') { - a.type = b; - return; - } - if ('type' in b) { - a.type = b.type; - } - // readOnly: cannot become false and takes on `computed` value - a.readOnly = a.readOnly || Boolean(a.computed) || b.readOnly || Boolean(b.computed); - // computed: first in wins - if ('computed' in b) { - a.computed = a.computed || b.computed; - } - // reflectToAttribute: cannot become false - if ('reflectToAttribute' in b) { - a.reflectToAttribute = a.reflectToAttribute || b.reflectToAttribute; - } - // notify: cannot become false (only install 1x) - if ('notify' in b) { - a.notify = a.notify || b.notify; - } - // make this an array - if ('observer' in b) { - if (!a.observer) { - a.observer = b.observer; - // we have both: make array and push onto - } else { - if (!Array.isArray(a.observer)) { - a.observer = [a.observer]; - } - a.observer.push(b.observer); - } - } - } - - // Note, the properties in `b` are normalized before being merged - // into `a`. This means that given `a == {}` and `b == {foo: String}`, - // the result is `a == {foo: {type: String}}`. - function mergeElementProperties(a, b) { - for (let p in b) { - a[p] = a[p] || {}; - mergePropertyInfo(a[p], b[p]); - } - } - /* Note about construction and extension of legacy classes. [Changed in Q4 2018 to optimize performance.] @@ -245,15 +193,43 @@ /** @private */ class PolymerGenerated extends Base { + // explicitly not calling super._finalizeClass + static _finalizeClass() { + // if calling via a subclass that hasn't been generated, pass through to super + if (!this.hasOwnProperty('generatedFrom')) { + super._finalizeClass(); + } else { + // interleave properties and observers per behavior and `info` + if (behaviorList) { + for (let i=0, b; i < behaviorList.length; i++) { + b = behaviorList[i]; + if (b.properties) { + this.createProperties(b.properties); + } + if (b.observers) { + this.createObservers(b.observers, b.properties); + } + } + } + if (info.properties) { + this.createProperties(info.properties); + } + if (info.observers) { + this.createObservers(info.observers, info.properties); + } + // make sure to prepare the element template + this._prepareTemplate(); + } + } + static get properties() { const properties = {}; if (behaviorList) { - for (let i=0, b; i < behaviorList.length; i++) { - b = behaviorList[i]; - mergeElementProperties(properties, b.properties); + for (let i=0; i < behaviorList.length; i++) { + Object.assign(properties, behaviorList[i].properties); } } - mergeElementProperties(properties, info.properties); + Object.assign(properties, info.properties); return properties; } @@ -289,7 +265,6 @@ /** * @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* diff --git a/lib/mixins/element-mixin.html b/lib/mixins/element-mixin.html index c9b5e189c8..ae7db9423d 100644 --- a/lib/mixins/element-mixin.html +++ b/lib/mixins/element-mixin.html @@ -230,14 +230,7 @@ } // always add observer if (info.observer) { - if (Array.isArray(info.observer)) { - for (let i=0; i < info.observer.length; i++) { - const o = info.observer[i]; - proto._createPropertyObserver(name, o, allProps[o]); - } - } else { - proto._createPropertyObserver(name, info.observer, allProps[info.observer]); - } + proto._createPropertyObserver(name, info.observer, allProps[info.observer]); } // always create the mapping from attribute back to property for deserialization. proto._addPropertyToAttributeMap(name); @@ -324,12 +317,16 @@ * @override * @suppress {missingProperties} Interfaces in closure do not inherit statics, but classes do */ - static _finalizeClass() { + static _finalizeClass() { super._finalizeClass(); const observers = ownObservers(this); if (observers) { this.createObservers(observers, this._properties); } + this._prepareTemplate(); + } + + static _prepareTemplate() { // note: create "working" template that is finalized at instance time let template = /** @type {PolymerElementConstructor} */ (this).template; if (template) { @@ -352,7 +349,7 @@ * @protected * @override */ - static createProperties(props) { + static createProperties(props) { for (let p in props) { createPropertyFromConfig(this.prototype, p, props[p], props); }