diff --git a/lib/legacy/class.html b/lib/legacy/class.html index 026fa98eef..0c8acab5b2 100644 --- a/lib/legacy/class.html +++ b/lib/legacy/class.html @@ -152,6 +152,24 @@ return info.observers; } + /** + * @return {HTMLTemplateElement} template for this class + */ + static get template() { + if (!this.hasOwnProperty(JSCompiler_renameProperty('_template', this))) { + this._template = + // Accept template: _null to short-circuit dom-module lookup + info._template !== undefined ? info._template : + // Look in dom-module associated with this element's is + this._getTemplateFromDomModule() || + // Look up in the chain + Base.template || + // Use any template set on the prototype via registered callback + this.prototype._template; + } + return this._template; + } + /** * @return {void} */ diff --git a/lib/mixins/element-mixin.html b/lib/mixins/element-mixin.html index b2082f292a..032ad27708 100644 --- a/lib/mixins/element-mixin.html +++ b/lib/mixins/element-mixin.html @@ -275,27 +275,6 @@ } } - /** - * Look up template from dom-module for element - * - * @param {!string} is Element name to look up - * @return {!HTMLTemplateElement} Template found in dom module, or - * undefined if not found - * @private - */ - function getTemplateFromDomModule(is) { - let template = null; - if (is && Polymer.DomModule) { - template = Polymer.DomModule.import(is, 'template'); - // Under strictTemplatePolicy, require any element with an `is` - // specified to have a dom-module - if (Polymer.strictTemplatePolicy && !template) { - throw new Error(`strictTemplatePolicy: expecting dom-module or null template for ${is}`); - } - } - return template; - } - /** * @polymer * @mixinClass @@ -368,6 +347,30 @@ } } + /** + * Look up template from dom-module for element + * + * @param {!string} is Element name to look up + * @return {!HTMLTemplateElement} Template found in dom module, or + * undefined if not found + * @protected + */ + static _getTemplateFromDomModule() { + let template = null; + const is = /** @type {PolymerElementConstructor}*/ (this).is; + // Under strictTemplatePolicy in 3.x+, dom-module lookup is only allowed + // when opted-in via allowTemplateFromDomModule + if (is && Polymer.DomModule) { + template = Polymer.DomModule.import(is, 'template'); + // Under strictTemplatePolicy, require any element with an `is` + // specified to have a dom-module + if (Polymer.strictTemplatePolicy && !template) { + throw new Error(`strictTemplatePolicy: expecting dom-module or null template for ${is}`); + } + } + return template; + } + /** * Returns the template that will be stamped into this element's shadow root. * @@ -408,11 +411,8 @@ static get template() { if (!this.hasOwnProperty(JSCompiler_renameProperty('_template', this))) { this._template = - // Take any template set on the prototype, including null (for legacy - // support, setting in registered callback, etc.) - this.prototype._template !== undefined ? this.prototype._template : // Look in dom-module associated with this element's is - getTemplateFromDomModule(/** @type {PolymerElementConstructor}*/ (this).is) || + this._getTemplateFromDomModule() || // Next look for superclass template (call the super impl this // way so that `this` points to the superclass) Object.getPrototypeOf(/** @type {PolymerElementConstructor}*/ (this).prototype).constructor.template; diff --git a/test/unit/behaviors.html b/test/unit/behaviors.html index ffa011f562..3a9c915f50 100644 --- a/test/unit/behaviors.html +++ b/test/unit/behaviors.html @@ -22,7 +22,7 @@ - + @@ -298,9 +298,9 @@ _template: Polymer.html`
` }; - window.templateBehaviorFromRegister = { + window.templateBehaviorFromRegistered = { registered: function() { - this._template = Polymer.html`
`; + this._template = Polymer.html`
`; } }; @@ -311,6 +311,13 @@ } }); + Polymer({ + is: 'template-from-base', + behaviors: [ + window.templateBehavior1 + ] + }); + Polymer({ is: 'template-from-behavior', behaviors: [ @@ -329,8 +336,7 @@ Polymer({ is: 'template-from-behavior-registered', behaviors: [ - window.templateBehavior1, - window.templateBehaviorFromRegister + window.templateBehaviorFromRegistered ] }); @@ -367,6 +373,12 @@ + + + + `' + '
'; }, /trusted-element re-registered/); - const el = document.createElement('trusted-element'); - document.getElementById('target').appendChild(el); - assert.notOk(el.shadowRoot); + let el; + assertThrows(function() { + el = document.createElement('trusted-element'); + document.getElementById('target').appendChild(el); + }, /expecting dom-module or null template/); + assert.notOk(el && el.shadowRoot); assert.notOk(document.getElementById('injected')); }); @@ -230,7 +238,7 @@ }, /trusted-element re-registered/); const el = document.createElement('trusted-element'); document.getElementById('target').appendChild(el); - assert.notOk(el.shadowRoot); + assert.notOk(el && el.shadowRoot); assert.notOk(document.getElementById('injected')); }); @@ -261,9 +269,12 @@ ' `' + '
'; }, /trusted-element-legacy re-registered/); - const el = document.createElement('trusted-element-legacy'); - document.getElementById('target').appendChild(el); - assert.notOk(el.shadowRoot); + let el; + assertThrows(function() { + el = document.createElement('trusted-element-legacy'); + document.getElementById('target').appendChild(el); + }, /expecting dom-module or null template/); + assert.notOk(el && el.shadowRoot); assert.notOk(document.getElementById('injected')); }); @@ -276,9 +287,9 @@ ' `' + ''; }, /trusted-element-legacy re-registered/); - const el = document.createElement('trusted-element-legacy'); + const el = document.createElement('trusted-element'); document.getElementById('target').appendChild(el); - assert.notOk(el.shadowRoot); + assert.notOk(el && el.shadowRoot); assert.notOk(document.getElementById('injected')); }); @@ -292,7 +303,7 @@ Polymer({ is: 'has-no-template-legacy', _template: null - }); + }, /expecting dom-module or null template/); let el = document.createElement('has-no-template-legacy'); document.getElementById('target').appendChild(el); assert.notOk(el.shadowRoot);