- actually iterate behaviors in reverse order for mixing in

- iterate `behaviors` in natural order for prepping
- aggregate hostAttributes at prep-time for proper override behavior
- fix/add tests
- remove vestigial mixins.html file
This commit is contained in:
Scott J Miles
2015-05-22 12:56:26 -07:00
parent 0ab03bb71e
commit fba14a3317
8 changed files with 91 additions and 82 deletions
+10 -6
View File
@@ -23,6 +23,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
_registerFeatures: function() {
// identity
this._prepIs();
// attributes
this._prepAttributes();
// shared behaviors
this._prepBehaviors();
// inheritance
@@ -31,18 +33,20 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
this._prepConstructor();
},
_prepBehavior: function() {},
_prepBehavior: function(b) {
this._addHostAttributes(b.hostAttributes);
},
_marshalBehavior: function(b) {
},
_initFeatures: function() {
// install host attributes
this._marshalHostAttributes();
// setup debouncers
this._setupDebouncers();
// acquire behaviors
this._marshalBehaviors();
},
_marshalBehavior: function(b) {
// publish attributes to instance
this._installHostAttributes(b.hostAttributes);
}
});
+7 -3
View File
@@ -24,6 +24,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
_registerFeatures: function() {
// identity
this._prepIs();
// attributes
this._prepAttributes();
// shared behaviors
this._prepBehaviors();
// inheritance
@@ -36,7 +38,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
this._prepShady();
},
_prepBehavior: function() {},
_prepBehavior: function(b) {
this._addHostAttributes(b.hostAttributes);
},
_initFeatures: function() {
// manage local dom
@@ -47,6 +51,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
this._stampTemplate();
// host stack
this._popHost();
// install host attributes
this._marshalHostAttributes();
// setup debouncers
this._setupDebouncers();
// instance shared behaviors
@@ -56,8 +62,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
_marshalBehavior: function(b) {
// publish attributes to instance
this._installHostAttributes(b.hostAttributes);
}
});
+6 -3
View File
@@ -28,6 +28,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
_registerFeatures: function() {
// identity
this._prepIs();
// attributes
this._prepAttributes();
// inheritance
this._prepExtends();
// factory
@@ -51,8 +53,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
_prepBehavior: function(b) {
this._addPropertyEffects(b.properties || b.accessors);
this._addPropertyEffects(b.properties);
this._addComplexObserverEffects(b.observers);
this._addHostAttributes(b.hostAttributes);
},
_initFeatures: function() {
@@ -70,6 +73,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
this._popHost();
// concretize template references
this._marshalAnnotationReferences();
// install host attributes
this._marshalHostAttributes();
// setup debouncers
this._setupDebouncers();
// concretize effects on instance
@@ -83,8 +88,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
_marshalBehavior: function(b) {
// publish attributes to instance
this._installHostAttributes(b.hostAttributes);
// establish listeners on instance
this._listenListeners(b.listeners);
}
+11 -6
View File
@@ -60,21 +60,25 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
Polymer.Base._addFeature({
_marshalAttributes: function() {
this._takeAttributes();
_prepAttributes: function() {
this._aggregatedAttributes = {};
},
_installHostAttributes: function(attributes) {
_addHostAttributes: function(attributes) {
if (attributes) {
this._applyAttributes(this, attributes);
this.mixin(this._aggregatedAttributes, attributes);
}
},
_marshalHostAttributes: function() {
this._applyAttributes(this, this._aggregatedAttributes);
},
/* apply attributes to node but avoid overriding existing values */
_applyAttributes: function(node, attr$) {
for (var n in attr$) {
// NOTE: never allow 'class' to be set in hostAttributes
// since shimming classes would make it work
// since shimming classes would make it work
// inconsisently under native SD
if (!this.hasAttribute(n) && (n !== 'class')) {
this.serializeValueToAttribute(attr$[n], n, this);
@@ -82,7 +86,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}
},
_takeAttributes: function() {
_marshalAttributes: function() {
this._takeAttributesToModel(this);
},
@@ -106,6 +110,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
_serializing: false,
reflectPropertyToAttribute: function(name) {
this._serializing = true;
this.serializeValueToAttribute(this[name],
+22 -16
View File
@@ -46,7 +46,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
if (this.behaviors.length) {
this.behaviors = this._flattenBehaviorsList(this.behaviors);
}
this._prepAllBehaviors();
this._prepAllBehaviors(this.behaviors);
},
_flattenBehaviorsList: function(behaviors) {
@@ -54,36 +54,42 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
behaviors.forEach(function(b) {
if (b instanceof Array) {
flat = flat.concat(this._flattenBehaviorsList(b));
} else {
}
// filter out null entries so other iterators don't need to check
else if (b) {
flat.push(b);
} else {
this._warn(this._logf('_flattenBehaviorsList', 'behavior is null, check for missing or 404 import'));
}
}, this);
return flat;
},
_prepAllBehaviors: function() {
// filter so other iterators don't need null check
this.behaviors = this.behaviors.filter(function(b) {
if (b) {
this._mixinBehavior(b);
this._prepBehavior(b);
return true;
}
this._warn(this._logf('_prepAllBehaviors', 'behavior is null, check for missing or 404 import'));
}, this);
_prepAllBehaviors: function(behaviors) {
// traverse the behaviors in _reverse_ order (youngest first) because
// `_mixinBehavior` has _first property wins_ behavior, this is done
// to optimize # of calls to `_copyOwnProperty`
for (var i=behaviors.length-1; i>=0; i--) {
this._mixinBehavior(behaviors[i]);
}
// we iterate a second time so that `_prepBehavior` goes in natural order
// otherwise, it's a tricky detail for implementors of `_prepBehavior`
for (var i=0, l=behaviors.length; i<l; i++) {
this._prepBehavior(behaviors[i]);
}
// prep our prototype-as-behavior
this._prepBehavior(this);
},
_mixinBehavior: function(b) {
var names = Object.getOwnPropertyNames(b);
for (var i=names.length-1, n; i >= 0 && (n=names[i]); i--) {
Object.getOwnPropertyNames(b).forEach(function(n) {
switch (n) {
case 'hostAttributes':
case 'registered':
case 'properties':
case 'observers':
case 'listeners':
case 'keyPresses':
case 'hostAttributes':
case 'created':
case 'attached':
case 'detached':
@@ -97,7 +103,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}
break;
}
}
}, this);
},
_doBehavior: function(name, args) {
-40
View File
@@ -1,40 +0,0 @@
<!--
@license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<script>
/**
* Automatically extend using objects referenced in `mixins` array.
*
* Polymer({
*
* mixins: [
* someMixinObject
* ]
*
* ...
*
* });
*
* @class base feature: mixins
*/
Polymer.Base._addFeature({
_prepMixins: function() {
if (this.mixins) {
this.mixins.forEach(function(m) {
Polymer.Base.extend(this, m);
}, this);
}
}
});
</script>
+21 -3
View File
@@ -35,7 +35,13 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
hasBehaviorA: {
value: true
}
},
_simpleProperty: 'A',
hostAttributes: {
behavior: 'A',
user: 'A'
},
listeners: {
@@ -84,10 +90,17 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
overridablePropertyB: {
value: true
}
},
},
hostAttributes: {
behavior: 'B',
user: 'B'
},
_simpleProperty: 'B',
_disabledChanged: function(disabled) {
this.__disabled = disabled
},
@@ -126,6 +139,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
behaviors: [
Polymer.BehaviorA,
null,
Polymer.BehaviorB
],
@@ -166,7 +180,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
value: true
}
}
},
_simpleProperty: 'C'
};
@@ -178,7 +194,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
value: true
}
}
},
_simpleProperty: 'D'
};
+14 -5
View File
@@ -59,7 +59,9 @@ suite('multi-behaviors element', function() {
var el;
setup(function() {
el = document.createElement('multi-behaviors');
var div = document.createElement('div');
div.innerHTML = '<multi-behaviors user="user"></multi-behaviors>';
el = div.firstElementChild;
document.body.appendChild(el);
});
@@ -103,15 +105,21 @@ suite('multi-behaviors element', function() {
assert.equal(typeof el._setHasOptionsB, 'function');
});
test('behavior overrides are last', function() {
test('multi-behavior overrides ordering', function() {
assert.equal(el._toOverride, Polymer._toOverride, 'Behavior method was not overridden by prototype');
assert(el.overridableProperty, 'Behavior property was not overridden by prototype');
assert(el.overridablePropertyB, 'Behavior property was not overridden by sub-behavior');
assert(el.overridablePropertyB, 'Behavior config-property was not overridden by sub-behavior');
});
test('hostAttributes ordering', function() {
assert.equal(el.attributes.behavior.value, 'B', 'Behavior hostAttribute not overridden by subclass');
assert.equal(el.attributes.user.value, 'user', 'Behavior hostAttribute overrode user attribute');
});
});
suite('nexted-behaviors element', function() {
suite('nested-behaviors element', function() {
var el;
@@ -124,11 +132,12 @@ suite('nexted-behaviors element', function() {
document.body.removeChild(el);
});
test('properties from nested behaviors', function() {
test('nested-behavior overrides ordering', function() {
assert.ok(el.hasBehaviorA, "missing BehaviorA");
assert.ok(el.hasBehaviorB, "missing BehaviorB");
assert.ok(el.hasBehaviorC, "missing BehaviorC");
assert.ok(el.hasBehaviorD, "missing BehaviorD");
assert.equal(el._simpleProperty, 'D', 'Behavior simple property was not overridden by sub-behavior');
});
});