Skip to content

Commit

Permalink
Merge pull request #5577 from Polymer/ie-placeholder-binding
Browse files Browse the repository at this point in the history
Workaround bindings to textarea.placeholder in IE
  • Loading branch information
dfreedm authored Jul 31, 2019
2 parents 69ee468 + ab49f51 commit 7d6d715
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 3 deletions.
48 changes: 48 additions & 0 deletions lib/mixins/template-stamp.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]) {
Expand Down Expand Up @@ -251,6 +298,7 @@ export const TemplateStamp = dedupingMixin(
// For ShadyDom optimization, indicating there is an insertion point
templateInfo.hasInsertionPoint = true;
}
fixPlaceholder(node);
if (element.firstChild) {
this._parseTemplateChildNodes(element, templateInfo, nodeInfo);
}
Expand Down
40 changes: 37 additions & 3 deletions test/unit/property-effects-template.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
<meta charset="utf-8">
<script src="../../node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
<script src="wct-browser-config.js"></script>
<script src="wct-browser-config.js"></script>
<script src="../../node_modules/wct-browser-legacy/browser.js"></script>
<script type="module" src="../../polymer-element.js"></script>
<script type="module" src="../../lib/mixins/gesture-event-listeners.js"></script>
Expand Down Expand Up @@ -282,9 +281,10 @@
</dom-module>

<script type="module">
import '../../polymer-element.js';
import {PolymerElement, html} from '../../polymer-element.js';
import '../../lib/mixins/gesture-event-listeners.js';
import '../../lib/elements/dom-if.js';
import {setLegacyOptimizations} from '../../lib/utils/settings.js';

suite('runtime template stamping', function() {

Expand Down Expand Up @@ -694,7 +694,6 @@
'x-runtime'
]);
});

});

suite('template parsing hooks', () => {
Expand Down Expand Up @@ -818,6 +817,41 @@
document.body.removeChild(el);
});
});

suite('textarea placeholder bug', function() {
class PlaceholderBase extends PolymerElement {
static get template() {
return html`<textarea id="textarea" placeholder="[[value]]"></textarea>`;
}
static get properties() {
return {value: {type: String}};
}
}
test('placeholder binding does not leak to textContent', function() {
customElements.define('placeholder-duplicate', class extends PlaceholderBase {});
const el = document.createElement('placeholder-duplicate');
document.body.appendChild(el);
const textarea = el.$.textarea;
el.value = 'before';
textarea.value = 'Hello!';
el.value = 'after';
assert.equal(textarea.value, 'Hello!');
});
suite('legacyOptimizations', function() {
suiteSetup(function() {
setLegacyOptimizations(true);
});
suiteTeardown(function() {
setLegacyOptimizations(false);
});
test('textarea placeholder binding works with legacyOptimizations', function() {
customElements.define('placeholder-bug', class extends PlaceholderBase {});
const el = document.createElement('placeholder-bug');
document.body.appendChild(el);
assert.doesNotThrow(() => {el.value = 'bar';});
});
});
});
</script>

</body>
Expand Down

0 comments on commit 7d6d715

Please sign in to comment.