diff --git a/cjs/interface/element.js b/cjs/interface/element.js index 5d513d6a..4c41ea46 100644 --- a/cjs/interface/element.js +++ b/cjs/interface/element.js @@ -176,6 +176,13 @@ class Element extends ParentNode { return text.join(''); } + set innerText(text) { + text = text === null ? '' : String(text); + this.replaceChildren(); + if (text !== '') + this.appendChild(new Text(this.ownerDocument, text)); + } + /** * @returns {String} */ diff --git a/cjs/mixin/inner-html.js b/cjs/mixin/inner-html.js index ec106d80..9a4857dc 100644 --- a/cjs/mixin/inner-html.js +++ b/cjs/mixin/inner-html.js @@ -2,7 +2,7 @@ const {ELEMENT_NODE, DOCUMENT_FRAGMENT_NODE} = require('../shared/constants.js'); const {CUSTOM_ELEMENTS} = require('../shared/symbols.js'); const {parseFromString} = require('../shared/parse-from-string.js'); -const {ignoreCase} = require('../shared/utils.js'); +const {ignoreCase, String} = require('../shared/utils.js'); /** @@ -21,7 +21,7 @@ const setInnerHtml = (node, html) => { const {constructor} = ownerDocument; const document = new constructor; document[CUSTOM_ELEMENTS] = ownerDocument[CUSTOM_ELEMENTS]; - const {childNodes} = parseFromString(document, ignoreCase(node), html); + const {childNodes} = parseFromString(document, ignoreCase(node), html === null ? '' : String(html)); node.replaceChildren(...childNodes.map(setOwnerDocument, ownerDocument)); }; diff --git a/esm/interface/element.js b/esm/interface/element.js index c98f5f7d..b4d80ef5 100644 --- a/esm/interface/element.js +++ b/esm/interface/element.js @@ -178,6 +178,13 @@ export class Element extends ParentNode { return text.join(''); } + set innerText(text) { + text = text === null ? '' : String(text); + this.replaceChildren(); + if (text !== '') + this.appendChild(new Text(this.ownerDocument, text)); + } + /** * @returns {String} */ diff --git a/esm/mixin/inner-html.js b/esm/mixin/inner-html.js index ac37e8f7..70b24353 100644 --- a/esm/mixin/inner-html.js +++ b/esm/mixin/inner-html.js @@ -1,7 +1,7 @@ import {ELEMENT_NODE, DOCUMENT_FRAGMENT_NODE} from '../shared/constants.js'; import {CUSTOM_ELEMENTS} from '../shared/symbols.js'; import {parseFromString} from '../shared/parse-from-string.js'; -import {ignoreCase} from '../shared/utils.js'; +import {ignoreCase, String} from '../shared/utils.js'; /** @@ -19,7 +19,7 @@ export const setInnerHtml = (node, html) => { const {constructor} = ownerDocument; const document = new constructor; document[CUSTOM_ELEMENTS] = ownerDocument[CUSTOM_ELEMENTS]; - const {childNodes} = parseFromString(document, ignoreCase(node), html); + const {childNodes} = parseFromString(document, ignoreCase(node), html === null ? '' : String(html)); node.replaceChildren(...childNodes.map(setOwnerDocument, ownerDocument)); }; diff --git a/test/html/element.js b/test/html/element.js index 3c3fedd8..30ce789c 100644 --- a/test/html/element.js +++ b/test/html/element.js @@ -159,3 +159,18 @@ assert(node.innerHTML, ''); node.innerHTML = '
The quick brown fox
Jumped over
The lazy\ndog
'; assert(node.innerText, 'The quick brown fox\nJumped over\nThe lazy dog', 'innerText newlines'); assert(node.textContent, 'The quick brown foxJumped overThe lazy\ndog', 'textContent no newlines'); + +// non-string coercion (issue #308) +node.innerHTML = 1; +assert(node.innerHTML, '1', 'innerHTML coerces number'); +node.innerHTML = null; +assert(node.innerHTML, '', 'innerHTML coerces null'); +node.innerHTML = undefined; +assert(node.innerHTML, 'undefined', 'innerHTML coerces undefined'); + +node.innerText = 1; +assert(node.innerText, '1', 'innerText coerces number'); +node.innerText = null; +assert(node.innerText, '', 'innerText coerces null'); +node.innerText = 'sanity'; +assert(node.innerText, 'sanity', 'innerText normal string');