diff --git a/lib/legacy/class.html b/lib/legacy/class.html
index f99679f3a9..99fa627085 100644
--- a/lib/legacy/class.html
+++ b/lib/legacy/class.html
@@ -24,20 +24,20 @@
attributeChanged: true,
};
- const noBehaviorCopyProps = Object.assign({
+ const noCopyProps = Object.assign({
behaviors: true
}, metaProps);
- const memoizedProps = Object.assign({
+ const filteredProps = Object.assign({
listeners: true,
hostAttributes: true
}, metaProps);
function copyProperties(source, target) {
for (let p in source) {
- // NOTE: cannot copy `noBehaviorCopyProps` methods onto prototype at least because
+ // NOTE: cannot copy `noCopyProps` methods onto prototype at least because
// `super.ready` must be called and is not included in the user fn.
- if (!(p in noBehaviorCopyProps)) {
+ if (!(p in noCopyProps)) {
let pd = Object.getOwnPropertyDescriptor(source, p);
if (pd) {
Object.defineProperty(target, p, pd);
@@ -95,24 +95,19 @@
// If lifecycle is called (super then me), order is
// (1) C.created, (2) A.created, (3) B.created, (4) element.created
// (again same as 1.x)
- function copyBehaviorProperties(behaviors, klass) {
- const meta = {};
- const superMeta = klass.prototype.__behaviorMetaProps;
- if (behaviors) {
- klass.prototype.__behaviorMetaProps = meta;
- for (let i=0; i= 0; i--) {
const hostAttributes = list[i];
@@ -327,6 +344,7 @@
}
}
}
+ super._ensureAttributes();
}
/**
@@ -334,45 +352,38 @@
*/
ready() {
super.ready();
- let list = this.__behaviorMetaProps.ready;
+ let list = lifecycle.ready;
if (list) {
for (let i=0; i < list.length; i++) {
list[i].call(this);
}
}
- if (info.ready) {
- info.ready.call(this);
- }
}
/**
* @return {void}
*/
attached() {
- let list = this.__behaviorMetaProps.attached;
+ super.attached();
+ let list = lifecycle.attached;
if (list) {
for (let i=0; i < list.length; i++) {
list[i].call(this);
}
}
- if (info.attached) {
- info.attached.call(this);
- }
}
/**
* @return {void}
*/
detached() {
- let list = this.__behaviorMetaProps.detached;
+ super.detached();
+ let list = lifecycle.detached;
if (list) {
for (let i=0; i < list.length; i++) {
list[i].call(this);
}
}
- if (info.detached) {
- info.detached.call(this);
- }
}
/**
@@ -385,19 +396,17 @@
* @return {void}
*/
attributeChanged(name, old, value) {
- let list = this.__behaviorMetaProps.attributeChanged;
+ super.attributeChanged();
+ let list = lifecycle.attributeChanged;
if (list) {
for (let i=0; i < list.length; i++) {
list[i].call(this, name, old, value);
}
}
- if (info.attributeChanged) {
- info.attributeChanged.call(this, name, old, value);
- }
}
}
- // apply behaviors
+ // apply behaviors, note actual copying is done lazily at first instance creation
if (behaviors) {
// NOTE: ensure the behavior is extending a class with
// legacy element api. This is necessary since behaviors expect to be able
@@ -405,12 +414,11 @@
if (!Array.isArray(behaviors)) {
behaviors = [behaviors];
}
- let superBehaviors = PolymerGenerated.prototype.behaviors;
+ let superBehaviors = Base.prototype.behaviors;
// get flattened, deduped list of behaviors *not* already on super class
- behaviors = flattenBehaviors(behaviors, null, superBehaviors);
+ activeBehaviors = flattenBehaviors(behaviors, null, superBehaviors);
PolymerGenerated.prototype.behaviors = superBehaviors ?
- superBehaviors.concat(behaviors) : behaviors;
- PolymerGenerated.prototype.__behaviors = behaviors;
+ superBehaviors.concat(behaviors) : activeBehaviors;
}
PolymerGenerated.generatedFrom = info;
diff --git a/test/unit/behaviors.html b/test/unit/behaviors.html
index 98cf74dd7d..d7f23ea09a 100644
--- a/test/unit/behaviors.html
+++ b/test/unit/behaviors.html
@@ -340,6 +340,37 @@
]
});
+ window.ModifyObserversBehavior = {
+
+ __barChangedCalled: 0,
+
+ beforeRegister: function() {
+ const observers = this.constructor.generatedFrom.observers;
+ this.constructor.generatedFrom.observers = observers.concat([
+ '_barChanged(bar)'
+ ]);
+ },
+
+ _barChanged: function() {
+ this.__barChangedCalled++;
+ }
+
+ };
+
+ Polymer({
+ is: 'modify-observers-via-behavior',
+ __zonkChangedCalled: 0,
+ observers: [
+ '_zonkChanged(zonk)'
+ ],
+ behaviors: [
+ window.ModifyObserversBehavior
+ ],
+ _zonkChanged: function() {
+ this.__zonkChangedCalled++;
+ }
+ });
+
});
@@ -396,7 +427,13 @@
-
+
+
+
+
+
+
+
-
-
@@ -273,6 +310,7 @@
HTMLImports.whenReady(function() {
window.registerBehavior1 ={
+ registeredCount: 0,
registered: function() {
this._createPropertyObserver('prop', 'propChanged1');
this._createMethodObserver('propChanged2(prop)');
@@ -320,21 +358,37 @@
}
}
- BehaviorRegistered.prototype.registeredCount = 0;
-
customElements.define(BehaviorRegistered.is, BehaviorRegistered);
class BehaviorRegisteredExt extends BehaviorRegistered {
static get is() { return 'behavior-registered-ext';}
}
- BehaviorRegisteredExt.prototype.registeredCount = 0;
-
customElements.define(BehaviorRegisteredExt.is, BehaviorRegisteredExt);
});
+
+
@@ -359,12 +413,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -409,7 +475,7 @@
});
-suite('behavior.registered', function() {
+suite('behavior.registered/beforeRegister', function() {
test('can install dynamic properties', function() {
var el = fixture('registered');
assert.ok(el.$.content);
@@ -435,6 +501,12 @@
assert.deepEqual(el.registeredProps, [true, true, true]);
});
+ test('add observers via behavior in beforeRegister', function() {
+ var el = fixture('before-register-observers');
+ el.foo = 1;
+ assert.equal(el.__fooChangedCalled, 1);
+ });
+
});
suite('behavior lifecycle', function() {
@@ -446,9 +518,9 @@
});
test('lifecycle', function() {
- assert.equal(el._calledCreated, 2, 'created call count wrong');
- assert.equal(el._calledAttached, 2, 'attached call count wrong');
- assert.equal(el._calledAttributeChanged, 1, 'attributeChanged call count wrong');
+ assert.deepEqual(el.__createdList, ['1', '2'], 'created list wrong');
+ assert.deepEqual(el.__attachedList, ['1', '2'], 'attached list wrong');
+ assert.deepEqual(el.__attributeChangedList, ['1'], 'attributeChanged list wrong');
});
});
@@ -555,9 +627,9 @@
});
test('nested-behavior lifecycle', function() {
- assert.equal(el._calledCreated, 2, 'created call count wrong');
- assert.equal(el._calledAttached, 2, 'attached call count wrong');
- assert.equal(el._calledAttributeChanged, 1, 'attributeChanged call count wrong');
+ assert.deepEqual(el.__createdList, ['2', '1'], 'created list wrong');
+ assert.deepEqual(el.__attachedList, ['2', '1'], 'attached list wrong');
+ assert.deepEqual(el.__attributeChangedList, ['1'], 'attributeChanged list wrong');
});
test('nested-behavior overrides ordering', function() {
@@ -570,6 +642,20 @@
});
+suite('extended-behaviors', function() {
+
+ var el;
+
+ setup(function() {
+ el = fixture('extended-behaviors');
+ });
+
+ test('lifecycle', function() {
+ assert.deepEqual(el.__createdList, ['1', '2', 'sup', '3', '4', 'sub'], 'created list wrong');
+ });
+
+});
+