diff --git a/lib/mixins/element-mixin.html b/lib/mixins/element-mixin.html index 41d7551767..9f2733d234 100644 --- a/lib/mixins/element-mixin.html +++ b/lib/mixins/element-mixin.html @@ -576,7 +576,6 @@ */ _initializeProperties() { Polymer.telemetry.instanceCount++; - hostStack.registerHost(this); this.constructor.finalize(); const importPath = this.constructor.importPath; // note: finalize template when we have access to `localName` to @@ -649,9 +648,7 @@ */ ready() { if (this._template) { - hostStack.beginHosting(this); this.root = this._stampTemplate(this._template); - hostStack.endHosting(this); this.$ = this.root.$; } super.ready(); @@ -785,53 +782,6 @@ return PolymerElement; }); - /** - * Helper api for enqueing client dom created by a host element. - * - * By default elements are flushed via `_flushProperties` when - * `connectedCallback` is called. Elements attach their client dom to - * themselves at `ready` time which results from this first flush. - * This provides an ordering guarantee that the client dom an element - * creates is flushed before the element itself (i.e. client `ready` - * fires before host `ready`). - * - * However, if `_flushProperties` is called *before* an element is connected, - * as for example `Templatize` does, this ordering guarantee cannot be - * satisfied because no elements are connected. (Note: Bound elements that - * receive data do become enqueued clients and are properly ordered but - * unbound elements are not.) - * - * To maintain the desired "client before host" ordering guarantee for this - * case we rely on the "host stack. Client nodes registers themselves with - * the creating host element when created. This ensures that all client dom - * is readied in the proper order, maintaining the desired guarantee. - * - * @private - */ - let hostStack = { - - stack: [], - - registerHost(inst) { - if (this.stack.length) { - let host = this.stack[this.stack.length-1]; - host._enqueueClient(inst); - } - }, - - beginHosting(inst) { - this.stack.push(inst); - }, - - endHosting(inst) { - let stackLen = this.stack.length; - if (stackLen && this.stack[stackLen-1] == inst) { - this.stack.pop(); - } - } - - } - /** * Provides basic tracking of element definitions (registrations) and * instance counts. diff --git a/lib/mixins/property-effects.html b/lib/mixins/property-effects.html index adfe6e26fc..917f29fa03 100644 --- a/lib/mixins/property-effects.html +++ b/lib/mixins/property-effects.html @@ -1086,6 +1086,7 @@ */ _initializeProperties() { super._initializeProperties(); + hostStack.registerHost(this); this.__dataClientsInitialized = false; this.__dataPendingClients = null; this.__dataToNotify = null; @@ -1431,22 +1432,40 @@ if (!this.__dataClientsInitialized) { this.__dataClientsInitialized = true; this._readyClients(); + this.__dataInitialized = true; + } else { + // Flush all clients + let clients = this.__dataPendingClients; + if (clients) { + this.__dataPendingClients = null; + for (let i=0; i < clients.length; i++) { + let client = clients[i]; + if (client.__dataPending) { + client._flushProperties(); + } + } + } } - // Flush all clients + } + + /** + * Perform any initial setup on client dom. Called before the first + * `_flushProperties` call on client dom and before any element + * observers are called. + * + * @protected + */ + _readyClients() { let clients = this.__dataPendingClients; if (clients) { this.__dataPendingClients = null; for (let i=0; i < clients.length; i++) { let client = clients[i]; - // boot up client if necessary, otherwise flush properties if (!client.__dataPropertiesEnabled) { client._enableProperties(); - } else if (client.__dataPending) { - client._flushProperties(); } } } - this.__dataInitialized = true; } /** @@ -1494,15 +1513,6 @@ } } - /** - * Perform any initial setup on client dom. Called before the first - * `_flushProperties` call on client dom and before any element - * observers are called. - * - * @protected - */ - _readyClients() {} - /** * Implements `PropertyAccessors`'s properties changed callback. * @@ -2205,7 +2215,9 @@ * @protected */ _stampTemplate(template) { + hostStack.beginHosting(this); let dom = super._stampTemplate(template); + hostStack.endHosting(this); let templateInfo = this._bindTemplate(template, true); // Add template-instance-specific data to instanced templateInfo templateInfo.nodeList = dom.nodeList; @@ -2505,5 +2517,52 @@ return PropertyEffects; }); + /** + * Helper api for enqueing client dom created by a host element. + * + * By default elements are flushed via `_flushProperties` when + * `connectedCallback` is called. Elements attach their client dom to + * themselves at `ready` time which results from this first flush. + * This provides an ordering guarantee that the client dom an element + * creates is flushed before the element itself (i.e. client `ready` + * fires before host `ready`). + * + * However, if `_flushProperties` is called *before* an element is connected, + * as for example `Templatize` does, this ordering guarantee cannot be + * satisfied because no elements are connected. (Note: Bound elements that + * receive data do become enqueued clients and are properly ordered but + * unbound elements are not.) + * + * To maintain the desired "client before host" ordering guarantee for this + * case we rely on the "host stack. Client nodes registers themselves with + * the creating host element when created. This ensures that all client dom + * is readied in the proper order, maintaining the desired guarantee. + * + * @private + */ + let hostStack = { + + stack: [], + + registerHost(inst) { + if (this.stack.length) { + let host = this.stack[this.stack.length-1]; + host._enqueueClient(inst); + } + }, + + beginHosting(inst) { + this.stack.push(inst); + }, + + endHosting(inst) { + let stackLen = this.stack.length; + if (stackLen && this.stack[stackLen-1] == inst) { + this.stack.pop(); + } + } + + } + })();