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 }, 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/utils/pollyfills.js b/lib/core/imports/polyfills.js similarity index 78% rename from lib/core/utils/pollyfills.js rename to lib/core/imports/polyfills.js index 6829b80dc8..5725632e43 100644 --- a/lib/core/utils/pollyfills.js +++ b/lib/core/imports/polyfills.js @@ -1,8 +1,45 @@ +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 + - Object.assign + - Array.prototype.find */ if (typeof Object.assign !== 'function') { (function () { @@ -76,80 +113,6 @@ if (!Array.prototype.findIndex) { }); } -// Spelled incorrectly intentionally (backwards compatibility). -export function pollyfillElementsFromPoint() { - if (document.elementsFromPoint) return document.elementsFromPoint; - if (document.msElementsFromPoint) return document.msElementsFromPoint; - - var usePointer = (function () { - var element = document.createElement('x'); - element.style.cssText = 'pointer-events:auto'; - return element.style.pointerEvents === 'auto'; - })(); - - var cssProp = usePointer ? 'pointer-events' : 'visibility'; - var cssDisableVal = usePointer ? 'none' : 'hidden'; - - var style = document.createElement('style'); - style.innerHTML = usePointer - ? '* { pointer-events: all }' - : '* { visibility: visible }'; - - return function (x, y) { - var current, i, d; - var elements = []; - var previousPointerEvents = []; - - // startup - document.head.appendChild(style); - - while ( - (current = document.elementFromPoint(x, y)) && - elements.indexOf(current) === -1 - ) { - // push the element and its current style - elements.push(current); - - previousPointerEvents.push({ - value: current.style.getPropertyValue(cssProp), - priority: current.style.getPropertyPriority(cssProp) - }); - - // add "pointer-events: none", to get to the underlying element - current.style.setProperty(cssProp, cssDisableVal, 'important'); - } - - // Due to negative index, documentElement could actually not be the last, - // so we'll simply move it to the end - if (elements.indexOf(document.documentElement) < elements.length - 1) { - elements.splice(elements.indexOf(document.documentElement), 1); - elements.push(document.documentElement); - } - - // restore the previous pointer-events values - for ( - i = previousPointerEvents.length; - !!(d = previousPointerEvents[--i]); - - ) { - elements[i].style.setProperty( - cssProp, - d.value ? d.value : '', - d.priority - ); - } - - // teardown; - document.head.removeChild(style); - - return elements; - }; -} - -if (typeof window.addEventListener === 'function') { - document.elementsFromPoint = pollyfillElementsFromPoint(); -} - if (!Array.prototype.includes) { Object.defineProperty(Array.prototype, 'includes', { value: function (searchElement) { 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/pollyfill-elements-from-point.js b/lib/core/utils/pollyfill-elements-from-point.js new file mode 100644 index 0000000000..1783f12946 --- /dev/null +++ b/lib/core/utils/pollyfill-elements-from-point.js @@ -0,0 +1,73 @@ +// Spelled incorrectly intentionally (backwards compatibility). +export function pollyfillElementsFromPoint() { + if (document.elementsFromPoint) return document.elementsFromPoint; + if (document.msElementsFromPoint) return document.msElementsFromPoint; + + var usePointer = (function () { + var element = document.createElement('x'); + element.style.cssText = 'pointer-events:auto'; + return element.style.pointerEvents === 'auto'; + })(); + + var cssProp = usePointer ? 'pointer-events' : 'visibility'; + var cssDisableVal = usePointer ? 'none' : 'hidden'; + + var style = document.createElement('style'); + style.innerHTML = usePointer + ? '* { pointer-events: all }' + : '* { visibility: visible }'; + + return function (x, y) { + var current, i, d; + var elements = []; + var previousPointerEvents = []; + + // startup + document.head.appendChild(style); + + while ( + (current = document.elementFromPoint(x, y)) && + elements.indexOf(current) === -1 + ) { + // push the element and its current style + elements.push(current); + + previousPointerEvents.push({ + value: current.style.getPropertyValue(cssProp), + priority: current.style.getPropertyPriority(cssProp) + }); + + // add "pointer-events: none", to get to the underlying element + current.style.setProperty(cssProp, cssDisableVal, 'important'); + } + + // Due to negative index, documentElement could actually not be the last, + // so we'll simply move it to the end + if (elements.indexOf(document.documentElement) < elements.length - 1) { + elements.splice(elements.indexOf(document.documentElement), 1); + elements.push(document.documentElement); + } + + // restore the previous pointer-events values + for ( + i = previousPointerEvents.length; + !!(d = previousPointerEvents[--i]); + + ) { + elements[i].style.setProperty( + cssProp, + d.value ? d.value : '', + d.priority + ); + } + + // teardown; + document.head.removeChild(style); + + return elements; + }; +} + +if (typeof window.addEventListener === 'function') { + document.elementsFromPoint = pollyfillElementsFromPoint(); +}