From 99fd03766ae2e30b2e632d2cbc801476097dcfee Mon Sep 17 00:00:00 2001 From: Christian Bewernitz Date: Sun, 30 Oct 2022 00:56:02 +0200 Subject: [PATCH] fix: Provide ponyfill for Array.prototype.find to restore ES5 compatibility --- lib/conventions.js | 26 ++++++++++++++++++++++++++ lib/dom.js | 23 ++++++++--------------- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/lib/conventions.js b/lib/conventions.js index fda7b2fdb..7599e9dc6 100644 --- a/lib/conventions.js +++ b/lib/conventions.js @@ -1,5 +1,30 @@ 'use strict'; +/** + * Ponyfill for `Array.prototype.find` which is only available in ES6 runtimes. + * + * @template {unknown} T + * @param {Array | ({length:number, [number]: T})} list + * @param {function (item: T, index: number, list:Array | ({length:number, [number]: T})):boolean} predicate + * @returns {T | undefined} + * + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find + * @see https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.find + */ +function find(list, predicate) { + if (list && typeof Array.prototype.find === 'function') { + return Array.prototype.find.call(list, predicate); + } + for (var i = 0; i++; i < list.length) { + if (Object.prototype.hasOwnProperty.call(list, i)) { + var item = list[i]; + if (predicate(item, i, list)) { + return item; + } + } + } +} + /** * "Shallow freezes" an object to render it immutable. * Uses `Object.freeze` if available, @@ -330,6 +355,7 @@ var NAMESPACE = freeze({ }); exports.assign = assign; +exports.find = find; exports.freeze = freeze; exports.HTML_BOOLEAN_ATTRIBUTES = HTML_BOOLEAN_ATTRIBUTES; exports.HTML_RAW_TEXT_ELEMENTS = HTML_RAW_TEXT_ELEMENTS; diff --git a/lib/dom.js b/lib/dom.js index 1fe8dcbc1..d2001fdac 100644 --- a/lib/dom.js +++ b/lib/dom.js @@ -1,6 +1,7 @@ 'use strict'; var conventions = require('./conventions'); +var find = conventions.find; var isHTMLRawTextElement = conventions.isHTMLRawTextElement; var isHTMLVoidElement = conventions.isHTMLVoidElement; var MIME_TYPE = conventions.MIME_TYPE; @@ -180,14 +181,6 @@ NodeList.prototype = { } return buf.join(''); }, - /** - * @private - * @param {function (Node):boolean} predicate - * @returns {Node | undefined} - */ - find: function (predicate) { - return Array.prototype.find.call(this, predicate); - }, /** * @private * @param {function (Node):boolean} predicate @@ -832,10 +825,10 @@ function isTextNode(node) { */ function isElementInsertionPossible(doc, child) { var parentChildNodes = doc.childNodes || []; - if (parentChildNodes.find(isElementNode) || isDocTypeNode(child)) { + if (find(parentChildNodes, isElementNode) || isDocTypeNode(child)) { return false; } - var docTypeNode = parentChildNodes.find(isDocTypeNode); + var docTypeNode = find(parentChildNodes, isDocTypeNode); return !(child && docTypeNode && parentChildNodes.indexOf(docTypeNode) > parentChildNodes.indexOf(child)); } /** @@ -870,8 +863,8 @@ function _insertBefore(parent, node, child) { var nodeChildNodes = node.childNodes || []; if (parent.nodeType === Node.DOCUMENT_NODE) { if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { - let nodeChildElements = nodeChildNodes.filter(isElementNode); - if (nodeChildElements.length > 1 || nodeChildNodes.find(isTextNode)) { + var nodeChildElements = nodeChildNodes.filter(isElementNode); + if (nodeChildElements.length > 1 || find(nodeChildNodes, isTextNode)) { throw new DOMException(HIERARCHY_REQUEST_ERR, 'More than one element or text in fragment'); } if (nodeChildElements.length === 1 && !isElementInsertionPossible(parent, child)) { @@ -879,15 +872,15 @@ function _insertBefore(parent, node, child) { } } if (isElementNode(node)) { - if (parentChildNodes.find(isElementNode) || !isElementInsertionPossible(parent, child)) { + if (find(parentChildNodes, isElementNode) || !isElementInsertionPossible(parent, child)) { throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one element can be added and only after doctype'); } } if (isDocTypeNode(node)) { - if (parentChildNodes.find(isDocTypeNode)) { + if (find(parentChildNodes, isDocTypeNode)) { throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one doctype is allowed'); } - let parentElementChild = parentChildNodes.find(isElementNode); + var parentElementChild = find(parentChildNodes, isElementNode); if (child && parentChildNodes.indexOf(parentElementChild) < parentChildNodes.indexOf(child)) { throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can only be inserted before an element'); }