diff --git a/externs/polymer-externs.js b/externs/polymer-externs.js index a45439ae..da5a2317 100644 --- a/externs/polymer-externs.js +++ b/externs/polymer-externs.js @@ -158,6 +158,29 @@ Polymer.orderedComputed; */ var PolymerElement = function() {}; +/** + * The tag name of the cutom element type. + * @type {string|undefined} + */ +PolymerElement.is; +/** + * The template to stamp when creating this element type. + * @type {!HTMLTemplateElement|undefined} + */ +PolymerElement.template; +/** + * The properties of the cutom element type. + * @type {!PolymerElementProperties|undefined} + */ +PolymerElement.properties; +/** + * The observers of this custom element type. + * @type {!Array|undefined} + */ +PolymerElement.observers; +/** @type {!PolymerInit|undefined} */ +PolymerElement.generatedFrom; + /** * On create callback. * @override diff --git a/lib/mixins/properties-changed.js b/lib/mixins/properties-changed.js index 22766a31..cc2801d4 100644 --- a/lib/mixins/properties-changed.js +++ b/lib/mixins/properties-changed.js @@ -134,6 +134,12 @@ export const PropertiesChanged = dedupingMixin( if (!this.hasOwnProperty('__dataAttributes')) { this.__dataAttributes = Object.assign({}, this.__dataAttributes); } + // This check is technically not correct; it's an optimization that + // assumes that if a _property_ name is already in the map (note this is + // an attr->property map), the property mapped directly to the attribute + // and it has already been mapped. This would fail if + // `attributeNameForProperty` were overridden such that this was not the + // case. let attr = this.__dataAttributes[property]; if (!attr) { attr = this.constructor.attributeNameForProperty(property); diff --git a/lib/mixins/template-stamp.js b/lib/mixins/template-stamp.js index 9dafa54f..ee4bc903 100644 --- a/lib/mixins/template-stamp.js +++ b/lib/mixins/template-stamp.js @@ -22,6 +22,53 @@ const templateExtensions = { 'dom-if': true, 'dom-repeat': true }; + +let placeholderBugDetect = false; +let placeholderBug = false; + +function hasPlaceholderBug() { + if (!placeholderBugDetect) { + placeholderBugDetect = true; + const t = document.createElement('textarea'); + t.placeholder = 'a'; + placeholderBug = t.placeholder === t.textContent; + } + return placeholderBug; +} + +/** + * Some browsers have a bug with textarea, where placeholder text is copied as + * a textnode child of the textarea. + * + * If the placeholder is a binding, this can break template stamping in two + * ways. + * + * One issue is that when the `placeholder` attribute is removed when the + * binding is processed, the textnode child of the textarea is deleted, and the + * template info tries to bind into that node. + * + * With `legacyOptimizations` in use, when the template is stamped and the + * `textarea.textContent` binding is processed, no corresponding node is found + * because it was removed during parsing. An exception is generated when this + * binding is updated. + * + * With `legacyOptimizations` not in use, the template is cloned before + * processing and this changes the above behavior. The cloned template also has + * a value property set to the placeholder and textContent. This prevents the + * removal of the textContent when the placeholder attribute is removed. + * Therefore the exception does not occur. However, there is an extra + * unnecessary binding. + * + * @param {!Node} node Check node for placeholder bug + * @return {void} + */ +function fixPlaceholder(node) { + if (hasPlaceholderBug() && node.localName === 'textarea' && node.placeholder + && node.placeholder === node.textContent) { + node.textContent = null; + } +} + function wrapTemplateExtension(node) { let is = node.getAttribute('is'); if (is && templateExtensions[is]) { @@ -251,6 +298,7 @@ export const TemplateStamp = dedupingMixin( // For ShadyDom optimization, indicating there is an insertion point templateInfo.hasInsertionPoint = true; } + fixPlaceholder(element); if (element.firstChild) { this._parseTemplateChildNodes(element, templateInfo, nodeInfo); } diff --git a/test/unit/property-effects-template.html b/test/unit/property-effects-template.html index 395a5060..b3c7a07c 100644 --- a/test/unit/property-effects-template.html +++ b/test/unit/property-effects-template.html @@ -13,7 +13,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN - @@ -286,9 +285,10 @@ customElements.define(XBinding.is, XBinding);