Skip to content

Commit 23d390b

Browse files
authored
core(legacy-javascript): update to target Baseline (#16366)
1 parent 7f59676 commit 23d390b

File tree

23 files changed

+3230
-939
lines changed

23 files changed

+3230
-939
lines changed

cli/test/smokehouse/test-definitions/legacy-javascript.js

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,41 +31,66 @@ const expectations = {
3131
items: [
3232
{
3333
url: 'http://localhost:10200/legacy-javascript.js',
34-
wastedBytes: '73000 +/- 2000',
34+
wastedBytes: '127000 +/- 2000',
3535
subItems: {
3636
items: [
37+
{signal: 'Object.getOwnPropertyDescriptor'},
38+
{signal: 'Array.prototype.concat'},
39+
{signal: 'Array.prototype.copyWithin'},
40+
{signal: 'Array.prototype.every'},
3741
{signal: 'Array.prototype.fill'},
3842
{signal: 'Array.prototype.filter'},
3943
{signal: 'Array.prototype.findIndex'},
4044
{signal: 'Array.prototype.find'},
45+
{signal: 'Array.prototype.flatMap'},
46+
{signal: 'Array.prototype.flat'},
4147
{signal: 'Array.prototype.forEach'},
4248
{signal: 'Array.from'},
49+
{signal: 'Array.prototype.includes'},
50+
{signal: 'Array.prototype.indexOf'},
4351
{signal: 'Array.isArray'},
52+
{signal: 'Array.prototype.join'},
4453
{signal: 'Array.prototype.map'},
4554
{signal: 'Array.of'},
55+
{signal: 'Array.prototype.slice'},
4656
{signal: 'Array.prototype.some'},
47-
{signal: 'Date.now'},
48-
{signal: 'Date.prototype.toISOString'},
49-
{signal: 'Date.prototype.toJSON'},
50-
{signal: 'Number.isInteger'},
51-
{signal: 'Number.isSafeInteger'},
52-
{signal: 'Object.defineProperties'},
53-
{signal: 'Object.defineProperty'},
57+
{signal: 'Array.prototype.sort'},
58+
{signal: 'Math.acosh'},
59+
{signal: 'Math.asinh'},
60+
{signal: 'Math.atanh'},
61+
{signal: 'Math.cbrt'},
62+
{signal: 'Math.clz32'},
63+
{signal: 'Math.cosh'},
64+
{signal: 'Math.expm1'},
65+
{signal: 'Math.fround'},
66+
{signal: 'Math.hypot'},
67+
{signal: 'Math.imul'},
68+
{signal: 'Math.log10'},
69+
{signal: 'Math.log1p'},
70+
{signal: 'Math.log2'},
71+
{signal: 'Math.sign'},
72+
{signal: 'Math.sinh'},
73+
{signal: 'Math.tanh'},
74+
{signal: 'Math.trunc'},
75+
{signal: 'Object.assign'},
76+
{signal: 'Object.create'},
5477
{signal: 'Object.entries'},
5578
{signal: 'Object.freeze'},
79+
{signal: 'Object.fromEntries'},
5680
{signal: 'Object.getOwnPropertyDescriptors'},
5781
{signal: 'Object.getPrototypeOf'},
5882
{signal: 'Object.isExtensible'},
5983
{signal: 'Object.isFrozen'},
6084
{signal: 'Object.isSealed'},
85+
{signal: 'Object.is'},
6186
{signal: 'Object.keys'},
6287
{signal: 'Object.preventExtensions'},
6388
{signal: 'Object.seal'},
6489
{signal: 'Object.setPrototypeOf'},
6590
{signal: 'Object.values'},
91+
{signal: 'Promise.allSettled'},
6692
{signal: 'Reflect.apply'},
6793
{signal: 'Reflect.construct'},
68-
{signal: 'Reflect.defineProperty'},
6994
{signal: 'Reflect.deleteProperty'},
7095
{signal: 'Reflect.getOwnPropertyDescriptor'},
7196
{signal: 'Reflect.getPrototypeOf'},
@@ -75,9 +100,23 @@ const expectations = {
75100
{signal: 'Reflect.ownKeys'},
76101
{signal: 'Reflect.preventExtensions'},
77102
{signal: 'Reflect.setPrototypeOf'},
103+
{signal: 'Reflect.set'},
78104
{signal: 'String.prototype.codePointAt'},
105+
{signal: 'String.prototype.endsWith'},
106+
{signal: 'String.fromCodePoint'},
107+
{signal: 'String.prototype.includes'},
108+
{signal: 'String.prototype.link'},
109+
{signal: 'String.prototype.matchAll'},
110+
{signal: 'String.prototype.padEnd'},
111+
{signal: 'String.prototype.padStart'},
79112
{signal: 'String.raw'},
80113
{signal: 'String.prototype.repeat'},
114+
{signal: 'String.prototype.startsWith'},
115+
{signal: 'String.prototype.trimEnd'},
116+
{signal: 'String.prototype.trimStart'},
117+
{signal: 'String.prototype.trim'},
118+
{signal: 'Promise.any'},
119+
{signal: 'String.prototype.replaceAll'},
81120
{signal: '@babel/plugin-transform-classes'},
82121
{signal: '@babel/plugin-transform-regenerator'},
83122
{signal: '@babel/plugin-transform-spread'},

core/audits/byte-efficiency/legacy-javascript.js

Lines changed: 20 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
*/
66

77
/**
8-
* @fileoverview Identifies polyfills and transforms that should not be present if using module/nomodule pattern.
9-
* @see https://docs.google.com/document/d/1ItjJwAd6e0Ts6yMbvh8TN3BBh_sAd58rYE1whnpuxaA/edit Design document
8+
* @fileoverview Identifies polyfills and transforms that should not be present if needing to support only Baseline browsers.
9+
* @see https://docs.google.com/document/d/1ItjJwAd6e0Ts6yMbvh8TN3BBh_sAd58rYE1whnpuxaA/edit Design document (old, based on module/nomodule pattern)
1010
* @see https://docs.google.com/spreadsheets/d/1z28Au8wo8-c2UsM2lDVEOJcI3jOkb2c951xEBqzBKCc/edit?usp=sharing Legacy babel transforms / polyfills
1111
* ./core/scripts/legacy-javascript - verification tool.
1212
*/
@@ -27,6 +27,12 @@ import * as i18n from '../../lib/i18n/i18n.js';
2727
import {estimateCompressionRatioForContent} from '../../lib/script-helpers.js';
2828
import {LH_ROOT} from '../../../shared/root.js';
2929

30+
const polyfillModuleDataJson = fs.readFileSync(
31+
`${LH_ROOT}/core/audits/byte-efficiency/polyfill-module-data.json`, 'utf-8');
32+
33+
/** @type {import('../../scripts/legacy-javascript/create-polyfill-module-data.js').PolyfillModuleData} */
34+
const polyfillModuleData = JSON.parse(polyfillModuleDataJson);
35+
3036
const graphJson = fs.readFileSync(
3137
`${LH_ROOT}/core/audits/byte-efficiency/polyfill-graph-data.json`, 'utf-8');
3238

@@ -39,7 +45,7 @@ const UIStrings = {
3945
// eslint-disable-next-line max-len
4046
// TODO: developer.chrome.com article. this codelab is good starting place: https://web.dev/articles/codelab-serve-modern-code
4147
/** Description of a Lighthouse audit that tells the user about old JavaScript that is no longer needed. This is displayed after a user expands the section to see more. No character length limits. The last sentence starting with 'Learn' becomes link text to additional documentation. */
42-
description: 'Polyfills and transforms enable legacy browsers to use new JavaScript features. However, many aren\'t necessary for modern browsers. For your bundled JavaScript, adopt a modern script deployment strategy using [module/nomodule feature detection](https://philipwalton.com/articles/deploying-es2015-code-in-production-today/) to reduce the amount of code shipped to modern browsers, while retaining support for legacy browsers. [Learn how to serve modern JavaScript](https://web.dev/articles/codelab-serve-modern-code)',
48+
description: 'Polyfills and transforms enable legacy browsers to use new JavaScript features. However, many aren\'t necessary for modern browsers. Consider modifying your JavaScript build process to not transpile [Baseline](https://web.dev/baseline) features, unless you know you must support legacy browsers. [Learn why most sites can deploy ES6+ code without transpiling](https://philipwalton.com/articles/the-state-of-es5-on-the-web/)',
4349
/** Warning text that an outdated version of the library "core-js" was found, and the developer should upgrade. */
4450
// eslint-disable-next-line max-len
4551
detectedCoreJs2Warning: 'Version 2 of core-js was detected on the page. You should upgrade to version 3 for many performance improvements.',
@@ -170,105 +176,31 @@ class LegacyJavascript extends ByteEfficiencyAudit {
170176
// TODO: perhaps this is the wrong place to check for a CDN polyfill. Remove?
171177
// expression += `|;e\\([^,]+,${qt(objectWithoutPrototype)},{${property}:`;
172178

173-
// core-js@2 minified pattern.
174-
// $export($export.S,"Date",{now:function
175-
expression += `|\\$export\\([^,]+,${qt(objectWithoutPrototype)},{${property}:`;
176-
177179
// core-js@3 minified pattern.
178180
// {target:"Array",proto:true},{fill:fill
179181
// {target:"Array",proto:true,forced:!HAS_SPECIES_SUPPORT||!USES_TO_LENGTH},{filter:
180182
expression += `|{target:${qt(objectWithoutPrototype)}\\S*},{${property}:`;
181183
} else {
182-
// WeakSet, etc.
183-
expression += `|function ${property}\\(`;
184+
// Detect polyfills for new classes: Map, Set, WeakSet, etc.
185+
// TODO: so far, no class polyfills are enabled for detection.
186+
// See `modulesToSkip` in create-polyfill-module-data.js
187+
188+
// collection("Map",
189+
// expression += `|collection\\(${qt(property)},`;
184190
}
185191

186192
return expression;
187193
}
188194

189-
static getPolyfillData() {
190-
/** @type {Array<{name: string, modules: string[], corejs?: boolean}>} */
191-
const data = [
192-
{name: 'focus-visible', modules: ['focus-visible']},
193-
];
194-
195-
const coreJsPolyfills = [
196-
['Array.prototype.fill', 'es6.array.fill'],
197-
['Array.prototype.filter', 'es6.array.filter'],
198-
['Array.prototype.find', 'es6.array.find'],
199-
['Array.prototype.findIndex', 'es6.array.find-index'],
200-
['Array.prototype.forEach', 'es6.array.for-each'],
201-
['Array.from', 'es6.array.from'],
202-
['Array.isArray', 'es6.array.is-array'],
203-
['Array.prototype.map', 'es6.array.map'],
204-
['Array.of', 'es6.array.of'],
205-
['Array.prototype.some', 'es6.array.some'],
206-
['Date.now', 'es6.date.now'],
207-
['Date.prototype.toISOString', 'es6.date.to-iso-string'],
208-
['Date.prototype.toJSON', 'es6.date.to-json'],
209-
['Date.prototype.toString', 'es6.date.to-string'],
210-
['Function.prototype.name', 'es6.function.name'],
211-
['Number.isInteger', 'es6.number.is-integer'],
212-
['Number.isSafeInteger', 'es6.number.is-safe-integer'],
213-
['Object.defineProperties', 'es6.object.define-properties'],
214-
['Object.defineProperty', 'es6.object.define-property'],
215-
['Object.freeze', 'es6.object.freeze'],
216-
['Object.getPrototypeOf', 'es6.object.get-prototype-of'],
217-
['Object.isExtensible', 'es6.object.is-extensible'],
218-
['Object.isFrozen', 'es6.object.is-frozen'],
219-
['Object.isSealed', 'es6.object.is-sealed'],
220-
['Object.keys', 'es6.object.keys'],
221-
['Object.preventExtensions', 'es6.object.prevent-extensions'],
222-
['Object.seal', 'es6.object.seal'],
223-
['Object.setPrototypeOf', 'es6.object.set-prototype-of'],
224-
['Reflect.apply', 'es6.reflect.apply'],
225-
['Reflect.construct', 'es6.reflect.construct'],
226-
['Reflect.defineProperty', 'es6.reflect.define-property'],
227-
['Reflect.deleteProperty', 'es6.reflect.delete-property'],
228-
['Reflect.get', 'es6.reflect.get'],
229-
['Reflect.getOwnPropertyDescriptor', 'es6.reflect.get-own-property-descriptor'],
230-
['Reflect.getPrototypeOf', 'es6.reflect.get-prototype-of'],
231-
['Reflect.has', 'es6.reflect.has'],
232-
['Reflect.isExtensible', 'es6.reflect.is-extensible'],
233-
['Reflect.ownKeys', 'es6.reflect.own-keys'],
234-
['Reflect.preventExtensions', 'es6.reflect.prevent-extensions'],
235-
['Reflect.setPrototypeOf', 'es6.reflect.set-prototype-of'],
236-
['String.prototype.codePointAt', 'es6.string.code-point-at'],
237-
['String.raw', 'es6.string.raw'],
238-
['String.prototype.repeat', 'es6.string.repeat'],
239-
['Object.entries', 'es7.object.entries'],
240-
['Object.getOwnPropertyDescriptors', 'es7.object.get-own-property-descriptors'],
241-
['Object.values', 'es7.object.values'],
242-
];
243-
244-
for (const [name, coreJs2Module] of coreJsPolyfills) {
245-
// es-shims follows a pattern for its packages.
246-
// Tack it onto the corejs size estimation, as it is likely close in size.
247-
const esShimModule = name.toLowerCase();
248-
data.push({
249-
name,
250-
modules: [
251-
coreJs2Module,
252-
// corejs 3 module name
253-
coreJs2Module
254-
.replace('es6.', 'es.')
255-
.replace('es7.', 'es.')
256-
.replace('typed.', 'typed-array.'),
257-
esShimModule,
258-
],
259-
corejs: true,
260-
});
261-
}
262-
263-
return data;
195+
static getPolyfillModuleData() {
196+
return polyfillModuleData;
264197
}
265198

266199
static getCoreJsPolyfillData() {
267-
return this.getPolyfillData().filter(d => d.corejs).map(d => {
200+
return this.getPolyfillModuleData().filter(d => d.corejs).map(d => {
268201
return {
269202
name: d.name,
270-
coreJs2Module: d.modules[0],
271-
coreJs3Module: d.modules[1],
203+
coreJs3Module: d.modules[0],
272204
};
273205
});
274206
}
@@ -329,7 +261,7 @@ class LegacyJavascript extends ByteEfficiencyAudit {
329261
static detectAcrossScripts(matcher, scripts, bundles) {
330262
/** @type {Map<LH.Artifacts.Script, PatternMatchResult[]>} */
331263
const scriptToMatchResults = new Map();
332-
const polyfillData = this.getPolyfillData();
264+
const polyfillData = this.getPolyfillModuleData();
333265

334266
for (const script of Object.values(scripts)) {
335267
if (!script.content) continue;

0 commit comments

Comments
 (0)