From 16db93501b8836e4246f68d4f43075f919c201d4 Mon Sep 17 00:00:00 2001 From: Steven Lambert <2433219+straker@users.noreply.github.com> Date: Thu, 14 Dec 2023 11:45:19 -0700 Subject: [PATCH 1/3] fix: add Object.values polyfill for node <=6 --- lib/core/imports/index.js | 35 +--- lib/core/imports/polyfills.js | 325 ++++++++++++++++++++++++++++++++++ lib/core/utils/pollyfills.js | 289 ------------------------------ 3 files changed, 328 insertions(+), 321 deletions(-) create mode 100644 lib/core/imports/polyfills.js diff --git a/lib/core/imports/index.js b/lib/core/imports/index.js index 63622d7636..80aa717d57 100644 --- a/lib/core/imports/index.js +++ b/lib/core/imports/index.js @@ -1,45 +1,16 @@ +import './polyfills'; + +// some of these imports require polyfills to be loaded first import { CssSelectorParser } from 'css-selector-parser'; import doT from '@deque/dot'; import emojiRegexText from 'emoji-regex'; import memoize from 'memoizee'; import Color from 'colorjs.io'; -import es6promise from 'es6-promise'; -import { Uint32Array } from 'typedarray'; -import 'weakmap-polyfill'; -import hasOwn from 'core-js-pure/actual/object/has-own'; - -if (!('hasOwn' in Object)) { - Object.hasOwn = hasOwn; -} - // prevent striping newline characters from strings (e.g. failure // summaries). value must be synced with build/configure.js doT.templateSettings.strip = false; -if (!('Promise' in window)) { - es6promise.polyfill(); -} - -if (!('Uint32Array' in window)) { - window.Uint32Array = Uint32Array; -} -if (window.Uint32Array) { - // @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/some - if (!('some' in window.Uint32Array.prototype)) { - Object.defineProperty(window.Uint32Array.prototype, 'some', { - value: Array.prototype.some - }); - } - - if (!('reduce' in window.Uint32Array.prototype)) { - // @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/reduce - Object.defineProperty(window.Uint32Array.prototype, 'reduce', { - value: Array.prototype.reduce - }); - } -} - /** * Namespace `axe.imports` which holds required external dependencies * diff --git a/lib/core/imports/polyfills.js b/lib/core/imports/polyfills.js new file mode 100644 index 0000000000..5725632e43 --- /dev/null +++ b/lib/core/imports/polyfills.js @@ -0,0 +1,325 @@ +import es6promise from 'es6-promise'; +import { Uint32Array } from 'typedarray'; +import 'weakmap-polyfill'; +import hasOwn from 'core-js-pure/actual/object/has-own'; +import values from 'core-js-pure/actual/object/values'; + +if (!('hasOwn' in Object)) { + Object.hasOwn = hasOwn; +} + +if (!('values' in Object)) { + Object.values = values; +} + +if (!('Promise' in window)) { + es6promise.polyfill(); +} + +if (!('Uint32Array' in window)) { + window.Uint32Array = Uint32Array; +} +if (window.Uint32Array) { + // @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/some + if (!('some' in window.Uint32Array.prototype)) { + Object.defineProperty(window.Uint32Array.prototype, 'some', { + value: Array.prototype.some + }); + } + + if (!('reduce' in window.Uint32Array.prototype)) { + // @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/reduce + Object.defineProperty(window.Uint32Array.prototype, 'reduce', { + value: Array.prototype.reduce + }); + } +} + +/* + These polyfills came directly from the ES Specification itself + Contained within: + - Object.assign + - Array.prototype.find +*/ +if (typeof Object.assign !== 'function') { + (function () { + Object.assign = function (target) { + if (target === undefined || target === null) { + throw new TypeError('Cannot convert undefined or null to object'); + } + + var output = Object(target); + for (var index = 1; index < arguments.length; index++) { + var source = arguments[index]; + if (source !== undefined && source !== null) { + for (var nextKey in source) { + if (source.hasOwnProperty(nextKey)) { + output[nextKey] = source[nextKey]; + } + } + } + } + return output; + }; + })(); +} + +if (!Array.prototype.find) { + Object.defineProperty(Array.prototype, 'find', { + value: function (predicate) { + if (this === null) { + throw new TypeError('Array.prototype.find called on null or undefined'); + } + if (typeof predicate !== 'function') { + throw new TypeError('predicate must be a function'); + } + var list = Object(this); + var length = list.length >>> 0; + var thisArg = arguments[1]; + var value; + + for (var i = 0; i < length; i++) { + value = list[i]; + if (predicate.call(thisArg, value, i, list)) { + return value; + } + } + return undefined; + } + }); +} + +if (!Array.prototype.findIndex) { + Object.defineProperty(Array.prototype, 'findIndex', { + value: function (predicate, thisArg) { + if (this === null) { + throw new TypeError('Array.prototype.find called on null or undefined'); + } + if (typeof predicate !== 'function') { + throw new TypeError('predicate must be a function'); + } + var list = Object(this); + var length = list.length >>> 0; + var value; + + for (var i = 0; i < length; i++) { + value = list[i]; + if (predicate.call(thisArg, value, i, list)) { + return i; + } + } + return -1; + } + }); +} + +if (!Array.prototype.includes) { + Object.defineProperty(Array.prototype, 'includes', { + value: function (searchElement) { + var O = Object(this); + var len = parseInt(O.length, 10) || 0; + if (len === 0) { + return false; + } + var n = parseInt(arguments[1], 10) || 0; + var k; + if (n >= 0) { + k = n; + } else { + k = len + n; + if (k < 0) { + k = 0; + } + } + var currentElement; + while (k < len) { + currentElement = O[k]; + if ( + searchElement === currentElement || + (searchElement !== searchElement && currentElement !== currentElement) + ) { + // NaN !== NaN + return true; + } + k++; + } + return false; + } + }); +} + +// Production steps of ECMA-262, Edition 5, 15.4.4.17 +// Reference: http://es5.github.io/#x15.4.4.17 +if (!Array.prototype.some) { + Object.defineProperty(Array.prototype, 'some', { + value: function (fun) { + if (this == null) { + throw new TypeError('Array.prototype.some called on null or undefined'); + } + + if (typeof fun !== 'function') { + throw new TypeError(); + } + + var t = Object(this); + var len = t.length >>> 0; + + var thisArg = arguments.length >= 2 ? arguments[1] : void 0; + for (var i = 0; i < len; i++) { + if (i in t && fun.call(thisArg, t[i], i, t)) { + return true; + } + } + + return false; + } + }); +} + +if (!Array.from) { + Object.defineProperty(Array, 'from', { + value: (function () { + var toStr = Object.prototype.toString; + var isCallable = function (fn) { + return ( + typeof fn === 'function' || toStr.call(fn) === '[object Function]' + ); + }; + var toInteger = function (value) { + var number = Number(value); + if (isNaN(number)) { + return 0; + } + if (number === 0 || !isFinite(number)) { + return number; + } + return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); + }; + var maxSafeInteger = Math.pow(2, 53) - 1; + var toLength = function (value) { + var len = toInteger(value); + return Math.min(Math.max(len, 0), maxSafeInteger); + }; + + // The length property of the from method is 1. + return function from(arrayLike /*, mapFn, thisArg */) { + // 1. Let C be the this value. + var C = this; + + // 2. Let items be ToObject(arrayLike). + var items = Object(arrayLike); + + // 3. ReturnIfAbrupt(items). + if (arrayLike == null) { + throw new TypeError( + 'Array.from requires an array-like object - not null or undefined' + ); + } + + // 4. If mapfn is undefined, then let mapping be false. + var mapFn = arguments.length > 1 ? arguments[1] : void undefined; + var T; + if (typeof mapFn !== 'undefined') { + // 5. else + // 5. a If IsCallable(mapfn) is false, throw a TypeError exception. + if (!isCallable(mapFn)) { + throw new TypeError( + 'Array.from: when provided, the second argument must be a function' + ); + } + + // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. + if (arguments.length > 2) { + T = arguments[2]; + } + } + + // 10. Let lenValue be Get(items, "length"). + // 11. Let len be ToLength(lenValue). + var len = toLength(items.length); + + // 13. If IsConstructor(C) is true, then + // 13. a. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len. + // 14. a. Else, Let A be ArrayCreate(len). + var A = isCallable(C) ? Object(new C(len)) : new Array(len); + + // 16. Let k be 0. + var k = 0; + // 17. Repeat, while k < len… (also steps a - h) + var kValue; + while (k < len) { + kValue = items[k]; + if (mapFn) { + A[k] = + typeof T === 'undefined' + ? mapFn(kValue, k) + : mapFn.call(T, kValue, k); + } else { + A[k] = kValue; + } + k += 1; + } + // 18. Let putStatus be Put(A, "length", len, true). + A.length = len; + // 20. Return A. + return A; + }; + })() + }); +} + +if (!String.prototype.includes) { + String.prototype.includes = function (search, start) { + if (typeof start !== 'number') { + start = 0; + } + if (start + search.length > this.length) { + return false; + } else { + return this.indexOf(search, start) !== -1; + } + }; +} + +// @see https://github.com/jonathantneal/array-flat-polyfill/blob/master/src/polyfill-flat.js +if (!Array.prototype.flat) { + Object.defineProperty(Array.prototype, 'flat', { + configurable: true, + value: function flat() { + var depth = isNaN(arguments[0]) ? 1 : Number(arguments[0]); + + return depth + ? Array.prototype.reduce.call( + this, + function (acc, cur) { + if (Array.isArray(cur)) { + acc.push.apply(acc, flat.call(cur, depth - 1)); + } else { + acc.push(cur); + } + + return acc; + }, + [] + ) + : Array.prototype.slice.call(this); + }, + writable: true + }); +} + +// linked from MDN docs on isConnected +// @see https://gist.github.com/eligrey/f109a6d0bf4efe3461201c3d7b745e8f +if (window.Node && !('isConnected' in window.Node.prototype)) { + Object.defineProperty(window.Node.prototype, 'isConnected', { + get() { + return ( + !this.ownerDocument || + !( + this.ownerDocument.compareDocumentPosition(this) & + this.DOCUMENT_POSITION_DISCONNECTED + ) + ); + } + }); +} diff --git a/lib/core/utils/pollyfills.js b/lib/core/utils/pollyfills.js index 6829b80dc8..1783f12946 100644 --- a/lib/core/utils/pollyfills.js +++ b/lib/core/utils/pollyfills.js @@ -1,81 +1,3 @@ -/* - These polyfills came directly from the ES Specification itself - Contained within: - - Object.assign - - Array.prototype.find -*/ -if (typeof Object.assign !== 'function') { - (function () { - Object.assign = function (target) { - if (target === undefined || target === null) { - throw new TypeError('Cannot convert undefined or null to object'); - } - - var output = Object(target); - for (var index = 1; index < arguments.length; index++) { - var source = arguments[index]; - if (source !== undefined && source !== null) { - for (var nextKey in source) { - if (source.hasOwnProperty(nextKey)) { - output[nextKey] = source[nextKey]; - } - } - } - } - return output; - }; - })(); -} - -if (!Array.prototype.find) { - Object.defineProperty(Array.prototype, 'find', { - value: function (predicate) { - if (this === null) { - throw new TypeError('Array.prototype.find called on null or undefined'); - } - if (typeof predicate !== 'function') { - throw new TypeError('predicate must be a function'); - } - var list = Object(this); - var length = list.length >>> 0; - var thisArg = arguments[1]; - var value; - - for (var i = 0; i < length; i++) { - value = list[i]; - if (predicate.call(thisArg, value, i, list)) { - return value; - } - } - return undefined; - } - }); -} - -if (!Array.prototype.findIndex) { - Object.defineProperty(Array.prototype, 'findIndex', { - value: function (predicate, thisArg) { - if (this === null) { - throw new TypeError('Array.prototype.find called on null or undefined'); - } - if (typeof predicate !== 'function') { - throw new TypeError('predicate must be a function'); - } - var list = Object(this); - var length = list.length >>> 0; - var value; - - for (var i = 0; i < length; i++) { - value = list[i]; - if (predicate.call(thisArg, value, i, list)) { - return i; - } - } - return -1; - } - }); -} - // Spelled incorrectly intentionally (backwards compatibility). export function pollyfillElementsFromPoint() { if (document.elementsFromPoint) return document.elementsFromPoint; @@ -149,214 +71,3 @@ export function pollyfillElementsFromPoint() { if (typeof window.addEventListener === 'function') { document.elementsFromPoint = pollyfillElementsFromPoint(); } - -if (!Array.prototype.includes) { - Object.defineProperty(Array.prototype, 'includes', { - value: function (searchElement) { - var O = Object(this); - var len = parseInt(O.length, 10) || 0; - if (len === 0) { - return false; - } - var n = parseInt(arguments[1], 10) || 0; - var k; - if (n >= 0) { - k = n; - } else { - k = len + n; - if (k < 0) { - k = 0; - } - } - var currentElement; - while (k < len) { - currentElement = O[k]; - if ( - searchElement === currentElement || - (searchElement !== searchElement && currentElement !== currentElement) - ) { - // NaN !== NaN - return true; - } - k++; - } - return false; - } - }); -} - -// Production steps of ECMA-262, Edition 5, 15.4.4.17 -// Reference: http://es5.github.io/#x15.4.4.17 -if (!Array.prototype.some) { - Object.defineProperty(Array.prototype, 'some', { - value: function (fun) { - if (this == null) { - throw new TypeError('Array.prototype.some called on null or undefined'); - } - - if (typeof fun !== 'function') { - throw new TypeError(); - } - - var t = Object(this); - var len = t.length >>> 0; - - var thisArg = arguments.length >= 2 ? arguments[1] : void 0; - for (var i = 0; i < len; i++) { - if (i in t && fun.call(thisArg, t[i], i, t)) { - return true; - } - } - - return false; - } - }); -} - -if (!Array.from) { - Object.defineProperty(Array, 'from', { - value: (function () { - var toStr = Object.prototype.toString; - var isCallable = function (fn) { - return ( - typeof fn === 'function' || toStr.call(fn) === '[object Function]' - ); - }; - var toInteger = function (value) { - var number = Number(value); - if (isNaN(number)) { - return 0; - } - if (number === 0 || !isFinite(number)) { - return number; - } - return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); - }; - var maxSafeInteger = Math.pow(2, 53) - 1; - var toLength = function (value) { - var len = toInteger(value); - return Math.min(Math.max(len, 0), maxSafeInteger); - }; - - // The length property of the from method is 1. - return function from(arrayLike /*, mapFn, thisArg */) { - // 1. Let C be the this value. - var C = this; - - // 2. Let items be ToObject(arrayLike). - var items = Object(arrayLike); - - // 3. ReturnIfAbrupt(items). - if (arrayLike == null) { - throw new TypeError( - 'Array.from requires an array-like object - not null or undefined' - ); - } - - // 4. If mapfn is undefined, then let mapping be false. - var mapFn = arguments.length > 1 ? arguments[1] : void undefined; - var T; - if (typeof mapFn !== 'undefined') { - // 5. else - // 5. a If IsCallable(mapfn) is false, throw a TypeError exception. - if (!isCallable(mapFn)) { - throw new TypeError( - 'Array.from: when provided, the second argument must be a function' - ); - } - - // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. - if (arguments.length > 2) { - T = arguments[2]; - } - } - - // 10. Let lenValue be Get(items, "length"). - // 11. Let len be ToLength(lenValue). - var len = toLength(items.length); - - // 13. If IsConstructor(C) is true, then - // 13. a. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len. - // 14. a. Else, Let A be ArrayCreate(len). - var A = isCallable(C) ? Object(new C(len)) : new Array(len); - - // 16. Let k be 0. - var k = 0; - // 17. Repeat, while k < len… (also steps a - h) - var kValue; - while (k < len) { - kValue = items[k]; - if (mapFn) { - A[k] = - typeof T === 'undefined' - ? mapFn(kValue, k) - : mapFn.call(T, kValue, k); - } else { - A[k] = kValue; - } - k += 1; - } - // 18. Let putStatus be Put(A, "length", len, true). - A.length = len; - // 20. Return A. - return A; - }; - })() - }); -} - -if (!String.prototype.includes) { - String.prototype.includes = function (search, start) { - if (typeof start !== 'number') { - start = 0; - } - if (start + search.length > this.length) { - return false; - } else { - return this.indexOf(search, start) !== -1; - } - }; -} - -// @see https://github.com/jonathantneal/array-flat-polyfill/blob/master/src/polyfill-flat.js -if (!Array.prototype.flat) { - Object.defineProperty(Array.prototype, 'flat', { - configurable: true, - value: function flat() { - var depth = isNaN(arguments[0]) ? 1 : Number(arguments[0]); - - return depth - ? Array.prototype.reduce.call( - this, - function (acc, cur) { - if (Array.isArray(cur)) { - acc.push.apply(acc, flat.call(cur, depth - 1)); - } else { - acc.push(cur); - } - - return acc; - }, - [] - ) - : Array.prototype.slice.call(this); - }, - writable: true - }); -} - -// linked from MDN docs on isConnected -// @see https://gist.github.com/eligrey/f109a6d0bf4efe3461201c3d7b745e8f -if (window.Node && !('isConnected' in window.Node.prototype)) { - Object.defineProperty(window.Node.prototype, 'isConnected', { - get() { - return ( - !this.ownerDocument || - !( - this.ownerDocument.compareDocumentPosition(this) & - this.DOCUMENT_POSITION_DISCONNECTED - ) - ); - } - }); -} From a69d494b48751ceb6650cfbfc867cedde3281e13 Mon Sep 17 00:00:00 2001 From: Steven Lambert <2433219+straker@users.noreply.github.com> Date: Thu, 14 Dec 2023 11:51:15 -0700 Subject: [PATCH 2/3] rename file --- lib/core/utils/index.js | 2 +- .../utils/{pollyfills.js => pollyfill-elements-from-point.js} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename lib/core/utils/{pollyfills.js => pollyfill-elements-from-point.js} (100%) diff --git a/lib/core/utils/index.js b/lib/core/utils/index.js index 6e18e7f99c..360c1d7283 100644 --- a/lib/core/utils/index.js +++ b/lib/core/utils/index.js @@ -63,7 +63,7 @@ export { default as parseCrossOriginStylesheet } from './parse-crossorigin-style export { default as parseSameOriginStylesheet } from './parse-sameorigin-stylesheet'; export { default as parseStylesheet } from './parse-stylesheet'; export { default as performanceTimer } from './performance-timer'; -export { pollyfillElementsFromPoint } from './pollyfills'; +export { pollyfillElementsFromPoint } from './pollyfill-elements-from-point'; export { default as preloadCssom } from './preload-cssom'; export { default as preloadMedia } from './preload-media'; export { default as preload, shouldPreload, getPreloadConfig } from './preload'; diff --git a/lib/core/utils/pollyfills.js b/lib/core/utils/pollyfill-elements-from-point.js similarity index 100% rename from lib/core/utils/pollyfills.js rename to lib/core/utils/pollyfill-elements-from-point.js From e16d0b30ddd032a60f0a3942fd77de701901d8d9 Mon Sep 17 00:00:00 2001 From: Steven Lambert <2433219+straker@users.noreply.github.com> Date: Thu, 14 Dec 2023 11:54:55 -0700 Subject: [PATCH 3/3] forgot to commit eslint --- .eslintrc.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index 0dd3a87d43..d5dd272f22 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -109,7 +109,10 @@ module.exports = { }, { // polyfills are mostly copy-pasted from sources so we don't control their styling - files: ['lib/core/utils/pollyfills.js'], + files: [ + 'lib/core/imports/polyfills.js', + 'lib/core/utils/pollyfill-elements-from-point.js' + ], env: { browser: false },