GoogleChrome / lighthouse

Automated auditing, performance metrics, and best practices for the web.
https://developer.chrome.com/docs/lighthouse/overview/
Apache License 2.0
28.45k stars 9.39k forks source link

Some JS polyfills should be added to the list of legacy JS #13440

Open zloirock opened 2 years ago

zloirock commented 2 years ago

Continuation of #13439.

Let's check what core-js modules are not required in engines with ES modules support:

const compat = require('core-js-compat');
compat({ targets: { esmodules: true }, inverse: true }).list;

=>

[
  "es.symbol",
  "es.symbol.has-instance",
  "es.symbol.is-concat-spreadable",
  "es.symbol.iterator",
  "es.symbol.species",
  "es.symbol.to-primitive",
  "es.symbol.to-string-tag",
  "es.symbol.unscopables",
  "es.error.to-string",
  "es.array.concat",
  "es.array.copy-within",
  "es.array.every",
  "es.array.fill",
  "es.array.filter",
  "es.array.find",
  "es.array.find-index",
  "es.array.for-each",
  "es.array.from",
  "es.array.index-of",
  "es.array.is-array",
  "es.array.join",
  "es.array.last-index-of",
  "es.array.map",
  "es.array.of",
  "es.array.slice",
  "es.array.some",
  "es.array.species",
  "es.array.splice",
  "es.array-buffer.is-view",
  "es.data-view",
  "es.date.get-year",
  "es.date.now",
  "es.date.set-year",
  "es.date.to-gmt-string",
  "es.date.to-iso-string",
  "es.date.to-json",
  "es.date.to-primitive",
  "es.date.to-string",
  "es.escape",
  "es.function.bind",
  "es.function.has-instance",
  "es.function.name",
  "es.json.to-string-tag",
  "es.map",
  "es.math.acosh",
  "es.math.asinh",
  "es.math.atanh",
  "es.math.cbrt",
  "es.math.clz32",
  "es.math.cosh",
  "es.math.expm1",
  "es.math.fround",
  "es.math.imul",
  "es.math.log10",
  "es.math.log1p",
  "es.math.log2",
  "es.math.sign",
  "es.math.sinh",
  "es.math.tanh",
  "es.math.to-string-tag",
  "es.math.trunc",
  "es.number.constructor",
  "es.number.epsilon",
  "es.number.is-finite",
  "es.number.is-integer",
  "es.number.is-nan",
  "es.number.is-safe-integer",
  "es.number.max-safe-integer",
  "es.number.min-safe-integer",
  "es.number.to-precision",
  "es.object.create",
  "es.object.define-properties",
  "es.object.define-property",
  "es.object.entries",
  "es.object.freeze",
  "es.object.get-own-property-descriptor",
  "es.object.get-own-property-descriptors",
  "es.object.get-own-property-names",
  "es.object.get-prototype-of",
  "es.object.is",
  "es.object.is-extensible",
  "es.object.is-frozen",
  "es.object.is-sealed",
  "es.object.keys",
  "es.object.prevent-extensions",
  "es.object.seal",
  "es.object.set-prototype-of",
  "es.object.to-string",
  "es.object.values",
  "es.reflect.apply",
  "es.reflect.construct",
  "es.reflect.define-property",
  "es.reflect.delete-property",
  "es.reflect.get",
  "es.reflect.get-own-property-descriptor",
  "es.reflect.get-prototype-of",
  "es.reflect.has",
  "es.reflect.is-extensible",
  "es.reflect.own-keys",
  "es.reflect.prevent-extensions",
  "es.reflect.set-prototype-of",
  "es.regexp.sticky",
  "es.set",
  "es.string.code-point-at",
  "es.string.from-code-point",
  "es.string.iterator",
  "es.string.raw",
  "es.string.repeat",
  "es.string.substr",
  "es.string.anchor",
  "es.string.big",
  "es.string.blink",
  "es.string.bold",
  "es.string.fixed",
  "es.string.fontcolor",
  "es.string.fontsize",
  "es.string.italics",
  "es.string.link",
  "es.string.small",
  "es.string.strike",
  "es.string.sub",
  "es.string.sup",
  "es.typed-array.copy-within",
  "es.typed-array.every",
  "es.typed-array.filter",
  "es.typed-array.find",
  "es.typed-array.find-index",
  "es.typed-array.for-each",
  "es.typed-array.includes",
  "es.typed-array.index-of",
  "es.typed-array.iterator",
  "es.typed-array.join",
  "es.typed-array.last-index-of",
  "es.typed-array.map",
  "es.typed-array.reduce",
  "es.typed-array.reduce-right",
  "es.typed-array.reverse",
  "es.typed-array.slice",
  "es.typed-array.some",
  "es.typed-array.subarray",
  "es.typed-array.to-string",
  "es.unescape",
  "es.weak-map",
  "es.weak-set",
  "web.dom-collections.for-each",
  "web.timers"
]

In addition to currently detected features, it's:

Array.prototype.concat
Array.prototype.copyWithin
Array.prototype.every
Array.prototype.indexOf
Array.prototype.join
Array.prototype.lastIndexOf
Array.prototype.slice
Array.prototype.splice
ArrayBuffer.isView
Date.prototype.getYear
Date.prototype.setYear
Date.prototype.toGMTString
Date.prototype.toPrimitive
Date.prototype.toString
Function.prototype.bind
Math.acosh
Math.asinh
Math.atanh
Math.cbrt
Math.clz32
Math.cosh
Math.expm1
Math.fround
Math.imul
Math.log10
Math.log1p
Math.log2
Math.sign
Math.sinh
Math.tanh
Math.trunc
Number.EPSILON
Number.isFinite
Number.isNaN
Number.MAX_SAFE_INTEGER
Number.MIN_SAFE_INTEGER
Number.prototype.toPrecision
Object.create
Object.getOwnPropertyDescriptor
Object.is
Object.prototype.toString
String.prototype.substr
String.prototype.anchor
String.prototype.big
String.prototype.blink
String.prototype.bold
String.prototype.fixed
String.prototype.fontcolor
String.prototype.fontsize
String.prototype.italics
String.prototype.link
String.prototype.small
String.prototype.strike
String.prototype.sub
String.prototype.sup

DataView
Map
Number
Set
Symbol
WeakMap
WeakSet
escape
unescape
setTimeout
setInterval

It should be added to this list.

connorjclark commented 2 years ago

Thanks for the close attention in this audit. It took me awhile to recall, but we excluded many of these for a reason: https://github.com/GoogleChrome/lighthouse/pull/10937 . I hadn't heard of core-js-compat until now, I'll have to go through the reasoning for excluding some of these and see if it still holds.

connorjclark commented 2 years ago

BTW, we have a test harness for verifying this stuff: yarn test-legacy-javascript

It creates various bundles using core-js@2 and 3 with different options, and snapshots the signals found. The expectation is that we find no signals when bundling withh latest core-js version + esmodules: true. I see we are a few big updates behind ( https://github.com/GoogleChrome/lighthouse/blob/8100b8034507e679c95b2fab5ab48965875443b6/lighthouse-core/scripts/legacy-javascript/run.js#L242 ) so I'm updating that now.

Seems the only signal we giving a false-positive for at the moment is es6.object.get-own-property-names so I am removing that. It makes me wonder why the Array prototype methods you pointed out in #13439 are not being found in the esmodules: true variant. I'd like to understand that first before removing those signals too.

connorjclark commented 2 years ago

Ah, I updated babel too and I see Array.prototype.reduceRight, Array.prototype.reduce, Number.parseInt in the false positives. OK.

zloirock commented 2 years ago

Seems the only signal we giving a false-positive for at the moment is es6.object.get-own-property-names so I am removing that.

That's strange since in the test from the head of this thread you can find es6.object.get-own-property-names in the output, so it should not be polyfilled with esmodules: true.

I'll take a look at test-legacy-javascript tomorrow.

zloirock commented 2 years ago

I hadn't heard of core-js-compat until now, I'll have to go through the reasoning for excluding some of these and see if it still holds.

core-js-compat is the data source that's used for automatic polyfilling in babel and other tools, other data sets are not oriented to polyfilling ES and miss too many cases, so it's strange to orient to something else.

zloirock commented 2 years ago

es6.object.get-own-property-names

Obsolete preset-env core-js: 2 mode uses compat-table as a data source, however even here Object.getOwnPropertyNames should not be polyfilled with esmodules: true target.

zloirock commented 1 year ago

It does not look fixed, https://github.com/GoogleChrome/lighthouse/blob/97ab394d00ac7a145fa9ed498737e1299f5743c5/core/audits/byte-efficiency/legacy-javascript.js#L180-L229