mirror of
https://github.com/Polymer/polymer.git
synced 2026-08-19 01:14:44 -05:00
Behaviors
* properly de-dup behaviors from superclasses * apply only "own" behaviors to class
This commit is contained in:
+32
-41
@@ -62,34 +62,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
* @suppress {invalidCasts, checkTypes}
|
||||
*/
|
||||
function mixinBehaviors(behaviors, klass) {
|
||||
if (behaviors) {
|
||||
klass = applyBehaviors(behaviors, klass);
|
||||
}
|
||||
// provides behaviors functionality
|
||||
return GenerateClassFromInfo({}, klass);
|
||||
}
|
||||
|
||||
function applyBehaviors(behaviors, klass) {
|
||||
if (!behaviors) {
|
||||
klass = /** @type {HTMLElement} */(klass); // eslint-disable-line no-self-assign
|
||||
return klass;
|
||||
}
|
||||
// NOTE: ensure the behavior is extending a class with
|
||||
// legacy element api. This is necessary since behaviors expect to be able
|
||||
// to access 1.x legacy api.
|
||||
klass = class extends Polymer.LegacyElementMixin(klass) { };
|
||||
if (!Array.isArray(behaviors)) {
|
||||
behaviors = [behaviors];
|
||||
}
|
||||
let superBehaviors = klass.prototype.behaviors;
|
||||
// get flattened, deduped list of behaviors *not* already on super class
|
||||
behaviors = flattenBehaviors(behaviors, null, superBehaviors);
|
||||
if (superBehaviors) {
|
||||
behaviors = superBehaviors.concat(behaviors);
|
||||
}
|
||||
// Set behaviors on prototype
|
||||
klass.prototype.behaviors = behaviors;
|
||||
return klass;
|
||||
return GenerateClassFromInfo({}, Polymer.LegacyElementMixin(klass), behaviors);
|
||||
}
|
||||
|
||||
// NOTE:
|
||||
@@ -124,20 +97,21 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
// (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<behaviors.length; i++) {
|
||||
copyProperties(behaviors[i], klass.prototype);
|
||||
memoizeBehaviorMetaProps(meta, behaviors[i]);
|
||||
memoizeBehaviorMetaProps(meta, behaviors[i], superMeta);
|
||||
}
|
||||
}
|
||||
klass.prototype.__behaviorMetaProps = meta;
|
||||
}
|
||||
|
||||
function memoizeBehaviorMetaProps(meta, behavior) {
|
||||
function memoizeBehaviorMetaProps(meta, behavior, superMeta) {
|
||||
for (let p in memoizedProps) {
|
||||
if (behavior[p]) {
|
||||
meta[p] = meta[p] || [];
|
||||
meta[p] = meta[p] || (superMeta && superMeta[p] ? superMeta[p].slice() : []);
|
||||
meta[p].push(behavior[p]);
|
||||
}
|
||||
}
|
||||
@@ -222,7 +196,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
* @suppress {checkTypes}
|
||||
* @private
|
||||
*/
|
||||
function GenerateClassFromInfo(info, Base) {
|
||||
function GenerateClassFromInfo(info, Base, behaviors) {
|
||||
|
||||
/** @private */
|
||||
class PolymerGenerated extends Base {
|
||||
@@ -289,6 +263,7 @@ 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*
|
||||
@@ -297,17 +272,20 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
in `beforeRegister` or `registered`. It is no longer possible to set
|
||||
`is` in `beforeRegister` as you could in 1.x.
|
||||
*/
|
||||
const proto = Object.getPrototypeOf(this);
|
||||
copyBehaviorProperties(proto.behaviors, proto.constructor);
|
||||
const proto = this;
|
||||
if (proto.hasOwnProperty('behaviors')) {
|
||||
copyBehaviorProperties(proto.behaviors, proto.constructor);
|
||||
}
|
||||
proto.__behaviorMetaProps = proto.__behaviorMetaProps || {};
|
||||
copyProperties(info, proto);
|
||||
// Note, previously these were interleaved.
|
||||
let list = this.__behaviorMetaProps.beforeRegister;
|
||||
let list = proto.__behaviorMetaProps.beforeRegister;
|
||||
if (list) {
|
||||
for (let i=0; i < list.length; i++) {
|
||||
list[i].call(proto);
|
||||
}
|
||||
}
|
||||
list = this.__behaviorMetaProps.registered;
|
||||
list = proto.__behaviorMetaProps.registered;
|
||||
if (list) {
|
||||
for (let i=0; i < list.length; i++) {
|
||||
list[i].call(proto);
|
||||
@@ -431,7 +409,23 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
if (info.attributeChanged) {
|
||||
info.attributeChanged.call(this, name, old, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// apply behaviors
|
||||
if (behaviors) {
|
||||
// NOTE: ensure the behavior is extending a class with
|
||||
// legacy element api. This is necessary since behaviors expect to be able
|
||||
// to access 1.x legacy api.
|
||||
if (!Array.isArray(behaviors)) {
|
||||
behaviors = [behaviors];
|
||||
}
|
||||
let superBehaviors = PolymerGenerated.prototype.__allBehaviors;
|
||||
// get flattened, deduped list of behaviors *not* already on super class
|
||||
behaviors = flattenBehaviors(behaviors, null, superBehaviors);
|
||||
PolymerGenerated.prototype.__allBehaviors = superBehaviors ?
|
||||
superBehaviors.concat(behaviors) : behaviors;
|
||||
PolymerGenerated.prototype.behaviors = behaviors;
|
||||
}
|
||||
|
||||
PolymerGenerated.generatedFrom = info;
|
||||
@@ -513,10 +507,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
}
|
||||
let klass = mixin ? mixin(Polymer.LegacyElementMixin(HTMLElement)) :
|
||||
Polymer.LegacyElementMixin(HTMLElement);
|
||||
if (info.behaviors) {
|
||||
klass = applyBehaviors(info.behaviors, klass);
|
||||
}
|
||||
klass = GenerateClassFromInfo(info, klass);
|
||||
klass = GenerateClassFromInfo(info, klass, info.behaviors);
|
||||
// decorate klass with registration info
|
||||
klass.is = info.is;
|
||||
return klass;
|
||||
|
||||
@@ -256,11 +256,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
<script>
|
||||
HTMLImports.whenReady(function() {
|
||||
customElements.define('nested-behaviors',
|
||||
class extends Polymer.mixinBehaviors(
|
||||
class extends Polymer.mixinBehaviors([window.BehaviorD, window.LifeCycleBehavior1], Polymer.mixinBehaviors(
|
||||
[
|
||||
[window.BehaviorB, [window.BehaviorC, window.BehaviorB], window.BehaviorA],
|
||||
[window.BehaviorD]
|
||||
], Polymer.Element) {
|
||||
[window.BehaviorB, [window.BehaviorC, window.BehaviorB], window.BehaviorA, window.LifeCycleBehavior2],
|
||||
], Polymer.Element)) {
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -356,7 +355,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
<test-fixture id="nested">
|
||||
<template>
|
||||
<nested-behaviors></nested-behaviors>
|
||||
<nested-behaviors foo="foo"></nested-behaviors>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
@@ -552,7 +551,13 @@ suite('nested-behaviors element', function() {
|
||||
});
|
||||
|
||||
test('nested-behavior dedups', function() {
|
||||
assert.equal(el.behaviors.length, 4);
|
||||
assert.equal(el.behaviors.length, 2);
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
|
||||
test('nested-behavior overrides ordering', function() {
|
||||
|
||||
Reference in New Issue
Block a user