-
Notifications
You must be signed in to change notification settings - Fork 9.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core(legacy-javascript): fix core-js 3 detection #10852
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -149,9 +149,14 @@ class LegacyJavascript extends Audit { | |
// TODO: perhaps this is the wrong place to check for a CDN polyfill. Remove? | ||
// expression += `|;e\\([^,]+,${qt(objectWithoutPrototype)},{${property}:`; | ||
|
||
// Minified pattern. | ||
// core-js@2 minified pattern. | ||
// $export($export.S,"Date",{now:function | ||
expression += `|\\$export\\([^,]+,${qt(objectWithoutPrototype)},{${property}:`; | ||
|
||
// core-js@3 minified pattern. | ||
// {target:"Array",proto:true},{fill:fill | ||
// {target:"Array",proto:true,forced:!HAS_SPECIES_SUPPORT||!USES_TO_LENGTH},{filter: | ||
expression += `|{target:${qt(objectWithoutPrototype)}\\S*},{${property}:`; | ||
} else { | ||
// WeakSet, etc. | ||
expression += `|function ${property}\\(`; | ||
|
@@ -161,88 +166,98 @@ class LegacyJavascript extends Audit { | |
} | ||
|
||
static getPolyfillData() { | ||
/** @param {string} coreJs2Module */ | ||
const defineModules = (coreJs2Module) => { | ||
return { | ||
coreJs2Module, | ||
coreJs3Module: coreJs2Module | ||
.replace('es6.', 'es.') | ||
.replace('es7.', 'es.') | ||
.replace('typed.', 'typed-array.'), | ||
}; | ||
}; | ||
return [ | ||
/* eslint-disable max-len */ | ||
{module: 'es6.array.fill', name: 'Array.prototype.fill'}, | ||
{module: 'es6.array.filter', name: 'Array.prototype.filter'}, | ||
{module: 'es6.array.find', name: 'Array.prototype.find'}, | ||
{module: 'es6.array.find-index', name: 'Array.prototype.findIndex'}, | ||
{module: 'es6.array.for-each', name: 'Array.prototype.forEach'}, | ||
{module: 'es6.array.from', name: 'Array.from'}, | ||
{module: 'es6.array.is-array', name: 'Array.isArray'}, | ||
{module: 'es6.array.last-index-of', name: 'Array.prototype.lastIndexOf'}, | ||
{module: 'es6.array.map', name: 'Array.prototype.map'}, | ||
{module: 'es6.array.of', name: 'Array.of'}, | ||
{module: 'es6.array.reduce', name: 'Array.prototype.reduce'}, | ||
{module: 'es6.array.reduce-right', name: 'Array.prototype.reduceRight'}, | ||
{module: 'es6.array.some', name: 'Array.prototype.some'}, | ||
{module: 'es6.date.now', name: 'Date.now'}, | ||
{module: 'es6.date.to-iso-string', name: 'Date.prototype.toISOString'}, | ||
{module: 'es6.date.to-json', name: 'Date.prototype.toJSON'}, | ||
{module: 'es6.date.to-string', name: 'Date.prototype.toString'}, | ||
{module: 'es6.function.name', name: 'Function.prototype.name'}, | ||
{module: 'es6.map', name: 'Map'}, | ||
{module: 'es6.number.is-integer', name: 'Number.isInteger'}, | ||
{module: 'es6.number.is-safe-integer', name: 'Number.isSafeInteger'}, | ||
{module: 'es6.number.parse-float', name: 'Number.parseFloat'}, | ||
{module: 'es6.number.parse-int', name: 'Number.parseInt'}, | ||
{module: 'es6.object.assign', name: 'Object.assign'}, | ||
{module: 'es6.object.create', name: 'Object.create'}, | ||
{module: 'es6.object.define-properties', name: 'Object.defineProperties'}, | ||
{module: 'es6.object.define-property', name: 'Object.defineProperty'}, | ||
{module: 'es6.object.freeze', name: 'Object.freeze'}, | ||
{module: 'es6.object.get-own-property-descriptor', name: 'Object.getOwnPropertyDescriptor'}, | ||
{module: 'es6.object.get-own-property-names', name: 'Object.getOwnPropertyNames'}, | ||
{module: 'es6.object.get-prototype-of', name: 'Object.getPrototypeOf'}, | ||
{module: 'es6.object.is-extensible', name: 'Object.isExtensible'}, | ||
{module: 'es6.object.is-frozen', name: 'Object.isFrozen'}, | ||
{module: 'es6.object.is-sealed', name: 'Object.isSealed'}, | ||
{module: 'es6.object.keys', name: 'Object.keys'}, | ||
{module: 'es6.object.prevent-extensions', name: 'Object.preventExtensions'}, | ||
{module: 'es6.object.seal', name: 'Object.seal'}, | ||
{module: 'es6.object.set-prototype-of', name: 'Object.setPrototypeOf'}, | ||
{module: 'es6.promise', name: 'Promise'}, | ||
{module: 'es6.reflect.apply', name: 'Reflect.apply'}, | ||
{module: 'es6.reflect.construct', name: 'Reflect.construct'}, | ||
{module: 'es6.reflect.define-property', name: 'Reflect.defineProperty'}, | ||
{module: 'es6.reflect.delete-property', name: 'Reflect.deleteProperty'}, | ||
{module: 'es6.reflect.get', name: 'Reflect.get'}, | ||
{module: 'es6.reflect.get-own-property-descriptor', name: 'Reflect.getOwnPropertyDescriptor'}, | ||
{module: 'es6.reflect.get-prototype-of', name: 'Reflect.getPrototypeOf'}, | ||
{module: 'es6.reflect.has', name: 'Reflect.has'}, | ||
{module: 'es6.reflect.is-extensible', name: 'Reflect.isExtensible'}, | ||
{module: 'es6.reflect.own-keys', name: 'Reflect.ownKeys'}, | ||
{module: 'es6.reflect.prevent-extensions', name: 'Reflect.preventExtensions'}, | ||
{module: 'es6.reflect.set', name: 'Reflect.set'}, | ||
{module: 'es6.reflect.set-prototype-of', name: 'Reflect.setPrototypeOf'}, | ||
{module: 'es6.set', name: 'Set'}, | ||
{module: 'es6.string.code-point-at', name: 'String.prototype.codePointAt'}, | ||
{module: 'es6.string.ends-with', name: 'String.prototype.endsWith'}, | ||
{module: 'es6.string.from-code-point', name: 'String.fromCodePoint'}, | ||
{module: 'es6.string.includes', name: 'String.prototype.includes'}, | ||
{module: 'es6.string.raw', name: 'String.raw'}, | ||
{module: 'es6.string.repeat', name: 'String.prototype.repeat'}, | ||
{module: 'es6.string.starts-with', name: 'String.prototype.startsWith'}, | ||
{module: 'es6.string.trim', name: 'String.prototype.trim'}, | ||
{module: 'es6.typed.array-buffer', name: 'ArrayBuffer'}, | ||
{module: 'es6.typed.data-view', name: 'DataView'}, | ||
{module: 'es6.typed.float32-array', name: 'Float32Array'}, | ||
{module: 'es6.typed.float64-array', name: 'Float64Array'}, | ||
{module: 'es6.typed.int16-array', name: 'Int16Array'}, | ||
{module: 'es6.typed.int32-array', name: 'Int32Array'}, | ||
{module: 'es6.typed.int8-array', name: 'Int8Array'}, | ||
{module: 'es6.typed.uint16-array', name: 'Uint16Array'}, | ||
{module: 'es6.typed.uint32-array', name: 'Uint32Array'}, | ||
{module: 'es6.typed.uint8-array', name: 'Uint8Array'}, | ||
{module: 'es6.typed.uint8-clamped-array', name: 'Uint8ClampedArray'}, | ||
{module: 'es6.weak-map', name: 'WeakMap'}, | ||
{module: 'es6.weak-set', name: 'WeakSet'}, | ||
{module: 'es7.array.includes', name: 'Array.prototype.includes'}, | ||
{module: 'es7.object.entries', name: 'Object.entries'}, | ||
{module: 'es7.object.get-own-property-descriptors', name: 'Object.getOwnPropertyDescriptors'}, | ||
{module: 'es7.object.values', name: 'Object.values'}, | ||
{module: 'es7.string.pad-end', name: 'String.prototype.padEnd'}, | ||
{module: 'es7.string.pad-start', name: 'String.prototype.padStart'}, | ||
{...defineModules('es6.array.fill'), name: 'Array.prototype.fill'}, | ||
{...defineModules('es6.array.filter'), name: 'Array.prototype.filter'}, | ||
{...defineModules('es6.array.find'), name: 'Array.prototype.find'}, | ||
{...defineModules('es6.array.find-index'), name: 'Array.prototype.findIndex'}, | ||
{...defineModules('es6.array.for-each'), name: 'Array.prototype.forEach'}, | ||
{...defineModules('es6.array.from'), name: 'Array.from'}, | ||
{...defineModules('es6.array.is-array'), name: 'Array.isArray'}, | ||
{...defineModules('es6.array.last-index-of'), name: 'Array.prototype.lastIndexOf'}, | ||
{...defineModules('es6.array.map'), name: 'Array.prototype.map'}, | ||
{...defineModules('es6.array.of'), name: 'Array.of'}, | ||
{...defineModules('es6.array.reduce'), name: 'Array.prototype.reduce'}, | ||
{...defineModules('es6.array.reduce-right'), name: 'Array.prototype.reduceRight'}, | ||
{...defineModules('es6.array.some'), name: 'Array.prototype.some'}, | ||
{...defineModules('es6.date.now'), name: 'Date.now'}, | ||
{...defineModules('es6.date.to-iso-string'), name: 'Date.prototype.toISOString'}, | ||
{...defineModules('es6.date.to-json'), name: 'Date.prototype.toJSON'}, | ||
{...defineModules('es6.date.to-string'), name: 'Date.prototype.toString'}, | ||
{...defineModules('es6.function.name'), name: 'Function.prototype.name'}, | ||
{...defineModules('es6.map'), name: 'Map'}, | ||
{...defineModules('es6.number.is-integer'), name: 'Number.isInteger'}, | ||
{...defineModules('es6.number.is-safe-integer'), name: 'Number.isSafeInteger'}, | ||
{...defineModules('es6.number.parse-float'), name: 'Number.parseFloat'}, | ||
{...defineModules('es6.number.parse-int'), name: 'Number.parseInt'}, | ||
{...defineModules('es6.object.assign'), name: 'Object.assign'}, | ||
{...defineModules('es6.object.create'), name: 'Object.create'}, | ||
{...defineModules('es6.object.define-properties'), name: 'Object.defineProperties'}, | ||
{...defineModules('es6.object.define-property'), name: 'Object.defineProperty'}, | ||
{...defineModules('es6.object.freeze'), name: 'Object.freeze'}, | ||
{...defineModules('es6.object.get-own-property-descriptor'), name: 'Object.getOwnPropertyDescriptor'}, | ||
{...defineModules('es6.object.get-own-property-names'), name: 'Object.getOwnPropertyNames'}, | ||
{...defineModules('es6.object.get-prototype-of'), name: 'Object.getPrototypeOf'}, | ||
{...defineModules('es6.object.is-extensible'), name: 'Object.isExtensible'}, | ||
{...defineModules('es6.object.is-frozen'), name: 'Object.isFrozen'}, | ||
{...defineModules('es6.object.is-sealed'), name: 'Object.isSealed'}, | ||
{...defineModules('es6.object.keys'), name: 'Object.keys'}, | ||
{...defineModules('es6.object.prevent-extensions'), name: 'Object.preventExtensions'}, | ||
{...defineModules('es6.object.seal'), name: 'Object.seal'}, | ||
{...defineModules('es6.object.set-prototype-of'), name: 'Object.setPrototypeOf'}, | ||
{...defineModules('es6.promise'), name: 'Promise'}, | ||
{...defineModules('es6.reflect.apply'), name: 'Reflect.apply'}, | ||
{...defineModules('es6.reflect.construct'), name: 'Reflect.construct'}, | ||
{...defineModules('es6.reflect.define-property'), name: 'Reflect.defineProperty'}, | ||
{...defineModules('es6.reflect.delete-property'), name: 'Reflect.deleteProperty'}, | ||
{...defineModules('es6.reflect.get'), name: 'Reflect.get'}, | ||
{...defineModules('es6.reflect.get-own-property-descriptor'), name: 'Reflect.getOwnPropertyDescriptor'}, | ||
{...defineModules('es6.reflect.get-prototype-of'), name: 'Reflect.getPrototypeOf'}, | ||
{...defineModules('es6.reflect.has'), name: 'Reflect.has'}, | ||
{...defineModules('es6.reflect.is-extensible'), name: 'Reflect.isExtensible'}, | ||
{...defineModules('es6.reflect.own-keys'), name: 'Reflect.ownKeys'}, | ||
{...defineModules('es6.reflect.prevent-extensions'), name: 'Reflect.preventExtensions'}, | ||
{...defineModules('es6.reflect.set'), name: 'Reflect.set'}, | ||
{...defineModules('es6.reflect.set-prototype-of'), name: 'Reflect.setPrototypeOf'}, | ||
{...defineModules('es6.set'), name: 'Set'}, | ||
{...defineModules('es6.string.code-point-at'), name: 'String.prototype.codePointAt'}, | ||
{...defineModules('es6.string.ends-with'), name: 'String.prototype.endsWith'}, | ||
{...defineModules('es6.string.from-code-point'), name: 'String.fromCodePoint'}, | ||
{...defineModules('es6.string.includes'), name: 'String.prototype.includes'}, | ||
{...defineModules('es6.string.raw'), name: 'String.raw'}, | ||
{...defineModules('es6.string.repeat'), name: 'String.prototype.repeat'}, | ||
{...defineModules('es6.string.starts-with'), name: 'String.prototype.startsWith'}, | ||
{...defineModules('es6.string.trim'), name: 'String.prototype.trim'}, | ||
{coreJs2Module: 'es6.typed.array-buffer', coreJs3Module: 'es.array-buffer.constructor', name: 'ArrayBuffer'}, | ||
{coreJs2Module: 'es6.typed.data-view', coreJs3Module: 'es.data-view', name: 'DataView'}, | ||
{...defineModules('es6.typed.float32-array'), name: 'Float32Array'}, | ||
{...defineModules('es6.typed.float64-array'), name: 'Float64Array'}, | ||
{...defineModules('es6.typed.int16-array'), name: 'Int16Array'}, | ||
{...defineModules('es6.typed.int32-array'), name: 'Int32Array'}, | ||
{...defineModules('es6.typed.int8-array'), name: 'Int8Array'}, | ||
{...defineModules('es6.typed.uint16-array'), name: 'Uint16Array'}, | ||
{...defineModules('es6.typed.uint32-array'), name: 'Uint32Array'}, | ||
{...defineModules('es6.typed.uint8-array'), name: 'Uint8Array'}, | ||
{...defineModules('es6.typed.uint8-clamped-array'), name: 'Uint8ClampedArray'}, | ||
{...defineModules('es6.weak-map'), name: 'WeakMap'}, | ||
{...defineModules('es6.weak-set'), name: 'WeakSet'}, | ||
{...defineModules('es7.array.includes'), name: 'Array.prototype.includes'}, | ||
{...defineModules('es7.object.entries'), name: 'Object.entries'}, | ||
{...defineModules('es7.object.get-own-property-descriptors'), name: 'Object.getOwnPropertyDescriptors'}, | ||
{...defineModules('es7.object.values'), name: 'Object.values'}, | ||
{...defineModules('es7.string.pad-end'), name: 'String.prototype.padEnd'}, | ||
{...defineModules('es7.string.pad-start'), name: 'String.prototype.padStart'}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. drive by: a simpler array and then a Something like static getPolyfillData() {
return [
/* eslint-disable max-len */
['Array.prototype.fill', 'es6.array.fill'],
['Array.prototype.filter', 'es6.array.filter'],
// ...
['String.prototype.trim', 'es6.string.trim'],
// These break the coreJs2/coreJs3 naming pattern so are set explicitly.
{name: 'ArrayBuffer', coreJs2Module: 'es6.typed.array-buffer', coreJs3Module: 'es.array-buffer.constructor'},
{name: 'DataView', coreJs2Module: 'es6.typed.data-view', coreJs3Module: 'es.data-view'},
['Float32Array', 'es6.typed.float32-array'],
// ...
['String.prototype.padStart', 'es7.string.pad-start'],
/* eslint-enable max-len */
].map(info => {
if (!Array.isArray(info)) return info;
const [name, coreJs2Module] = info;
return {
name,
coreJs2Module,
coreJs3Module: coreJs2Module
.replace('es6.', 'es.')
.replace('es7.', 'es.')
.replace('typed.', 'typed-array.'),
};
});
} (could also do an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice :) |
||
/* eslint-enable max-len */ | ||
]; | ||
} | ||
|
@@ -307,11 +322,12 @@ class LegacyJavascript extends Audit { | |
// If it's a bundle with source maps, add in the polyfill modules by name too. | ||
const bundle = bundles.find(b => b.script.src === networkRecord.url); | ||
if (bundle) { | ||
for (const {module, name} of polyfillData) { | ||
for (const {coreJs2Module, coreJs3Module, name} of polyfillData) { | ||
// Skip if the pattern matching found a match for this polyfill. | ||
if (matches.some(m => m.name === name)) continue; | ||
|
||
const source = bundle.rawMap.sources.find(source => source.endsWith(`${module}.js`)); | ||
const source = bundle.rawMap.sources.find(source => | ||
source.endsWith(`${coreJs2Module}.js`) || source.endsWith(`${coreJs3Module}.js`)); | ||
if (!source) continue; | ||
|
||
const mapping = bundle.map.mappings().find(m => m.sourceURL === source); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a somewhat nice transformation from core js 2 -> core js 3 module names. I'm confident that all of these are accurate–otherwise the
all-legacy-polyfills
variants would error during bundling.