Skip to content

Commit

Permalink
Ensure properties and observers are interleaved per behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
Steven Orvell committed Nov 14, 2018
1 parent 2b35a74 commit ad5cb26
Show file tree
Hide file tree
Showing 3 changed files with 607 additions and 1,084 deletions.
88 changes: 32 additions & 56 deletions lib/legacy/class.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,58 +152,6 @@ function flattenBehaviors(behaviors, list, exclude) {
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.]
Expand Down Expand Up @@ -243,15 +191,43 @@ function GenerateClassFromInfo(info, Base, behaviors) {
/** @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;
}

Expand Down
13 changes: 5 additions & 8 deletions lib/mixins/element-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,7 @@ export const ElementMixin = dedupingMixin(base => {
}
// 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);
Expand Down Expand Up @@ -341,6 +334,10 @@ export const ElementMixin = dedupingMixin(base => {
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) {
Expand Down
Loading

0 comments on commit ad5cb26

Please sign in to comment.