diff --git a/lib/mixins/property-accessors.html b/lib/mixins/property-accessors.html index 7104d229f8..bddf9d4fca 100644 --- a/lib/mixins/property-accessors.html +++ b/lib/mixins/property-accessors.html @@ -137,6 +137,7 @@ _initializeProperties() { this.__serializing = false; this.__dataCounter = 0; + this.__dataEnabled = false; this.__dataInitialized = false; this.__dataInvalid = false; // initialize data with prototype values saved when creating accessors @@ -475,10 +476,16 @@ } } - // TODO(kschaaf): document. + /** + * Call to enable property accessors. This method must be called + * for any side effects of setting properties to occur. For elements, + * generally `connectedCallback` is a normal spot to do so. + * It is safe to call this method multiple times as it only turns + * on property accessors once. + */ _enableProperties() { - if (!this.__dataPropertiesEnabled) { - this.__dataPropertiesEnabled = true; + if (!this.__dataEnabled) { + this.__dataEnabled = true; if (this.__dataInstanceProps) { this._initializeInstanceProperties(this.__dataInstanceProps); this.__dataInstanceProps = null; @@ -490,11 +497,9 @@ /** * Calls the `_propertiesChanged` callback with the current set of * pending changes (and old values recorded when pending changes were - * set), and resets the pending set of changes. + * set), and resets the pending set of changes. Generally, this method + * should not be called in user code. * - * Note that this method must be called once to enable the property - * accessors system. For elements, generally `connectedCallback` - * is a normal spot to do so. * * @protected */ diff --git a/lib/mixins/property-effects.html b/lib/mixins/property-effects.html index 917f29fa03..0591094250 100644 --- a/lib/mixins/property-effects.html +++ b/lib/mixins/property-effects.html @@ -1461,7 +1461,7 @@ this.__dataPendingClients = null; for (let i=0; i < clients.length; i++) { let client = clients[i]; - if (!client.__dataPropertiesEnabled) { + if (!client.__dataEnabled) { client._enableProperties(); } } @@ -1496,13 +1496,21 @@ } /** - * Overrides `PropertyAccessors` to call `_readyClients` callback - * if it was not called as a result of flushing properties. + * Overrides `PropertyAccessors` so that property accessor + * side effects are not enabled until after client dom is fully ready. + * Also calls `_flushClients` callback to ensure client dom is enabled + * that was not enabled as a result of flushing properties. * * @override */ ready() { + // It is important that `super.ready()` is not called here as it + // immediately turns on accessors. Instead, we wait until `readyClients` + // to enable accessors to provide a guarantee that clients are ready + // before processing any accessors side effects. this._flushProperties(); + // If no data was pending, `_flushProperties` will not `flushClients` + // so ensure this is done. if (!this.__dataClientsInitialized) { this._flushClients(); } @@ -2215,6 +2223,8 @@ * @protected */ _stampTemplate(template) { + // Ensures that created dom is `_enqueueClient`'d to this element so + // that it can be flushed on next call to `_flushProperties` hostStack.beginHosting(this); let dom = super._stampTemplate(template); hostStack.endHosting(this);