From 1bb8659d11d2adb281587979339c46956e45ad57 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Tue, 9 Jul 2019 10:38:42 -0700 Subject: [PATCH] Only consider a class "registered" when it is the top-most prototype Fixes #5567 --- lib/legacy/class.js | 18 ++++++++++----- test/unit/behaviors.html | 40 ++++++++++++++++++++++++++++++++++ test/unit/mixin-behaviors.html | 18 +++++++++++++-- 3 files changed, 68 insertions(+), 8 deletions(-) diff --git a/lib/legacy/class.js b/lib/legacy/class.js index f28f15d93f..b7bf2592e7 100644 --- a/lib/legacy/class.js +++ b/lib/legacy/class.js @@ -302,17 +302,23 @@ function GenerateClassFromInfo(info, Base, behaviors) { // only proceed if the generated class' prototype has not been registered. const generatedProto = PolymerGenerated.prototype; if (!generatedProto.hasOwnProperty('__hasRegisterFinished')) { - generatedProto.__hasRegisterFinished = true; + // make sure legacy lifecycle is called on the *element*'s prototype + // and not the generated class prototype; if the element has been + // extended, these are *not* the same. + const proto = Object.getPrototypeOf(this); + // Only set flag when generated prototype itself is registered, + // as this element may be extended from, and needs to run `registered` + // on all behaviors on the subclass as well. + if (proto === generatedProto) { + generatedProto.__hasRegisterFinished = true; + } // ensure superclass is registered first. super._registered(); // copy properties onto the generated class lazily if we're optimizing, - if (legacyOptimizations) { + if (legacyOptimizations && !Object.hasOwnProperty(generatedProto, '__hasCopiedProperties')) { + generatedProto.__hasCopiedProperties = true; copyPropertiesToProto(generatedProto); } - // make sure legacy lifecycle is called on the *element*'s prototype - // and not the generated class prototype; if the element has been - // extended, these are *not* the same. - const proto = Object.getPrototypeOf(this); let list = lifecycle.beforeRegister; if (list) { for (let i=0; i < list.length; i++) { diff --git a/test/unit/behaviors.html b/test/unit/behaviors.html index 6af4b6512b..0b1cd3bd3b 100644 --- a/test/unit/behaviors.html +++ b/test/unit/behaviors.html @@ -439,6 +439,23 @@ } }); + const inheritedBehavior = { + registered() { + this.foo = {}; + } + }; + + Polymer({ + is: 'x-base-behavior', + behaviors: [inheritedBehavior], + hasFoo() { + return Boolean(this.foo); + } + }); + + class XInherit extends customElements.get('x-base-behavior') {} + customElements.define('x-inherit-behavior', XInherit); + @@ -525,6 +542,18 @@ + + + + + + + + diff --git a/test/unit/mixin-behaviors.html b/test/unit/mixin-behaviors.html index 6f1eb74774..481fb0caf6 100644 --- a/test/unit/mixin-behaviors.html +++ b/test/unit/mixin-behaviors.html @@ -395,14 +395,17 @@ const Base = mixinBehaviors([{ registered() { - this.usedExtendedProto = this.canUseExtendedProto; + this.usedExtendedProto = Boolean(this.canUseExtendedProto); } }], PolymerElement); + customElements.define('registered-super', Base); + customElements.define('registered-proto', mixinBehaviors([ {canUseExtendedProto: true} ], Base)); +