Ensure properties and observers are interleaved per behavior

This commit is contained in:
Steven Orvell
2018-11-13 19:37:04 -08:00
parent 6f3057ec7a
commit bbf1acce3d
2 changed files with 39 additions and 67 deletions
+32 -57
View File
@@ -155,58 +155,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
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 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
/** @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 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
/**
* @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*
+7 -10
View File
@@ -230,14 +230,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}
// 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 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
* @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 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
* @protected
* @override
*/
static createProperties(props) {
static createProperties(props) {
for (let p in props) {
createPropertyFromConfig(this.prototype, p, props[p], props);
}