diff --git a/lib/mixins/disable-upgrade-mixin.js b/lib/mixins/disable-upgrade-mixin.js index 8b2022a6eb..d77d10507b 100644 --- a/lib/mixins/disable-upgrade-mixin.js +++ b/lib/mixins/disable-upgrade-mixin.js @@ -15,6 +15,8 @@ import { dedupingMixin } from '../utils/mixin.js'; const DISABLED_ATTR = 'disable-upgrade'; +let observedAttributesGetter; + /** * Element class mixin that allows the element to boot up in a non-enabled * state when the `disable-upgrade` attribute is present. This mixin is @@ -51,6 +53,22 @@ export const DisableUpgradeMixin = dedupingMixin((base) => { */ const superClass = ElementMixin(base); + // Work around for closure bug #126934458. Using `super` in a property + // getter does not work so instead we search the Base prototype for an + // implementation of observedAttributes so that we can override and call + // the `super` getter. Note, this is done one time ever because we assume + // that `Base` is always comes from `Polymer.LegacyElementMixn`. + if (!observedAttributesGetter) { + let ctor = superClass; + while (ctor && !observedAttributesGetter) { + const desc = Object.getOwnPropertyDescriptor(ctor, 'observedAttributes'); + if (desc) { + observedAttributesGetter = desc.get; + } + ctor = Object.getPrototypeOf(ctor.prototype).constructor; + } + } + /** * @polymer * @mixinClass @@ -58,11 +76,26 @@ export const DisableUpgradeMixin = dedupingMixin((base) => { */ class DisableUpgradeClass extends superClass { - /** - * @suppress {missingProperties} go/missingfnprops - */ static get observedAttributes() { - return super.observedAttributes.concat(DISABLED_ATTR); + return observedAttributesGetter.call(this).concat(DISABLED_ATTR); + } + + // Prevent element from initializing properties when it's upgrade disabled. + /** @override */ + _initializeProperties() { + if (!this.hasAttribute(DISABLED_ATTR)) { + super._initializeProperties(); + } else { + this.__isUpgradeDisabled = true; + } + } + + // Prevent element from enabling properties when it's upgrade disabled. + /** @override */ + _enableProperties() { + if (!this.__isUpgradeDisabled) { + super._enableProperties(); + } } /** @@ -75,8 +108,14 @@ export const DisableUpgradeMixin = dedupingMixin((base) => { */ attributeChangedCallback(name, old, value, namespace) { if (name == DISABLED_ATTR) { - if (!this.__dataEnabled && value == null && this.isConnected) { - super.connectedCallback(); + // When disable-upgrade is removed, intialize properties and + // provoke connectedCallback if the element is already connected. + if (!this.__dataEnabled && value == null) { + super._initializeProperties(); + this.__isUpgradeDisabled = false; + if (this.isConnected) { + super.connectedCallback(); + } } } else { super.attributeChangedCallback( @@ -84,37 +123,18 @@ export const DisableUpgradeMixin = dedupingMixin((base) => { } } - /* - NOTE: cannot gate on attribute because this is called before - attributes are delivered. Therefore, we stub this out and - call `super._initializeProperties()` manually. - */ - /** @override */ - _initializeProperties() {} - - // prevent user code in connected from running + // Prevent element from connecting when it's upgrade disabled. /** @override */ connectedCallback() { - if (this.__dataEnabled || !this.hasAttribute(DISABLED_ATTR)) { + if (!this.__isUpgradeDisabled) { super.connectedCallback(); } } - // prevent element from turning on properties - /** @override */ - _enableProperties() { - if (!this.hasAttribute(DISABLED_ATTR)) { - if (!this.__dataEnabled) { - super._initializeProperties(); - } - super._enableProperties(); - } - } - - // only go if "enabled" + // Prevent element from disconnecting when it's upgrade disabled. /** @override */ disconnectedCallback() { - if (this.__dataEnabled) { + if (!this.__isUpgradeDisabled) { super.disconnectedCallback(); } }