core(legacy-javascript): reduce polyfills, fix core-js import in test#10937
Conversation
| {signal: 'String.prototype.codePointAt'}, | ||
| {signal: 'String.fromCodePoint'}, | ||
| {signal: 'String.raw'}, | ||
| {signal: 'String.prototype.repeat'}, |
There was a problem hiding this comment.
This should have been a clue something was wrong. the legacy-javascript.js fixture here is the core-js@3 esmodules: false variant, which should have dozens of variants.
| }, /** @type {string[]} */ ([])).join(', '); | ||
| variants.push({name: dir, signals}); | ||
|
|
||
| const signals = []; |
There was a problem hiding this comment.
#10867 should have failed this test in CI .... fixing here
There was a problem hiding this comment.
oh this is a thorny problem. we don't know when to run these tests because something they depend on changed :/
I don't have any great ideas to fix this though other than catching it the next time. you?
There was a problem hiding this comment.
but test-legacy-javascript.sh checks for any file with legacy-javascript in the path. It should have triggered on a change to the audit.
There was a problem hiding this comment.
well then that's even more alarming :)
my point is still a problem I don't know a good way to deal with, but perhaps less urgent than outright broken testing 😆
There was a problem hiding this comment.
it did fail but didn't exit with code 1
https://travis-ci.org/github/GoogleChrome/lighthouse/builds/696156441#L1224
need to add
main().catch(err => {
console.error(err);
process.exit(1);
})| 1352 true/main.bundle.min.js | ||
| 188400 false/main.bundle.min.js | ||
| 64217 true/main.bundle.min.js | ||
| 63536 true-and-bugfixes/main.bundle.min.js |
There was a problem hiding this comment.
The small difference from bugfixes: true is because it only reduces the number of transforms applied. And the main.js file used is super small.
There was a problem hiding this comment.
oh, and adding bugfixes variant is orthogonal to the rest of this PR, I just wanted to add this.
| 'Object.defineProperty(String.prototype, "repeat", function() {})', | ||
| 'Object.defineProperty(String.prototype, \'repeat\', function() {})', | ||
| 'Object.defineProperty(window, \'WeakMap\', function() {})', | ||
| // Currently are no polyfills that declare a class. May be in the future. |
There was a problem hiding this comment.
I'm hopeful that we can somehow get preset-modules to workaround the bugs that require Promises to be polyfilled. keeping this around + the code in legacy-javascript that detects this.
patrickhulce
left a comment
There was a problem hiding this comment.
I'm struggling to interpret the output in babel/babel#11700 (comment) a bit. Could you help me out?
Does each row of the polyfill say which target requires that the polyfill be used?
For example for the typed arrays it looks like safari 10.1 forces it, even though Uint8Array was in Safari 5. I'm guessing there is some bug that makes it not behave exactly the same way?
I wish we had a better way to track each of these bugs, what they are/why you need them and/or an even more modern delivery discriminant than esmodules. Some of these are really massive polyfills just for what I'm guessing is like one obscure bug fix of a 3 year old versioned browser.
| }, /** @type {string[]} */ ([])).join(', '); | ||
| variants.push({name: dir, signals}); | ||
|
|
||
| const signals = []; |
There was a problem hiding this comment.
oh this is a thorny problem. we don't know when to run these tests because something they depend on changed :/
I don't have any great ideas to fix this though other than catching it the next time. you?
| ['String.prototype.startsWith', 'es6.string.starts-with'], | ||
| ['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'}, |
There was a problem hiding this comment.
aren't these all the biggest ones? and they're really all included in every esmodules: true bundle? :(
| ['Number.isSafeInteger', 'es6.number.is-safe-integer'], | ||
| ['Number.parseFloat', 'es6.number.parse-float'], | ||
| ['Number.parseInt', 'es6.number.parse-int'], | ||
| ['Object.assign', 'es6.object.assign'], |
There was a problem hiding this comment.
I'm still incredulous that modern browsers need Object.assign polyfilled... 😢
| ['Object.preventExtensions', 'es6.object.prevent-extensions'], | ||
| ['Object.seal', 'es6.object.seal'], | ||
| ['Object.setPrototypeOf', 'es6.object.set-prototype-of'], | ||
| ['Promise', 'es6.promise'], |
Yes. and each polyfill or transform that matches one of these targets is printed out.
Honestly, I can't figure this out.
It seems that because safari is not listed, that it would get polyfilled for all versions of safari (ios too). If this is WAI I must assume there is some bug in all versions Safari that makes typed arrays inconsistent with other browsers. typed-array was added in core-js@2, can't find much discussion other than this: zloirock/core-js#90 @developit said that all methods that accept a regex parameter must be polyfilled in older browsers. I don't see a similar reason to polyfill the typed arrays. EDIT: seems it's only b/c of a bug in A really nice thing about the caniuse data is that is gives reasons/comments in the data for such things.
that's the dream ... @paulirish and I want to explore extending
https://github.com/zloirock/core-js/blob/master/packages/core-js-compat/src/data.js#L705
|
|
Also, I have some catching up to do on the babel polyfill space :) babel/babel#11700 (comment) It seems the logic for determining what polyfills are needed is being pulled up to a new plugin @hzoo I understand this stuff is experimental atm, just wondering if the plan is to later modify |
|
The plan is to keep the polyfills and the transforms separated, so eventually everyone will need to use one of the new polyfill providers. On the other hand, we are exploring the idea moving back preset-env into If you are 100% sure that the typed arrays bug doesn't affect your code, you can use the |
Interesting, thanks for the insight.
Thanks @nicolo-ribaudo . The goal of this audit ultimately is to recommend other developers to use We could go further and say "exclude typed polyfills" because the bug is seemingly so negligible yet the polyfill so large. We'd much rather explore the possibility of getting that to be the default behavior of |
|
Also note that currently |
patrickhulce
left a comment
There was a problem hiding this comment.
sad day but important 👍
| ['Array.prototype.forEach', 'es6.array.for-each'], | ||
| ['Array.from', 'es6.array.from'], | ||
| ['Array.isArray', 'es6.array.is-array'], | ||
| ['Array.prototype.lastIndexOf', 'es6.array.last-index-of'], |
There was a problem hiding this comment.
instead of removing these can we flag them with an extra property or move them to another array somewhere? it'd be nice to keep track of what we should detect once we figure out how to solve the bugfixes problem and not lose all this research
There was a problem hiding this comment.
what we should detect is simply any polyfill that will never be in a bundle w/ esmodules: true, bugfixes: true (using either core-js@2 or core-js@3). everything being removed fails that criteria. if we add any back, it'll be because something changed upstream (and we can just add back to this list) or we accompany it with documentation for how and why to exclude (what we may do for typed-array, promise).
so I'm ok w/ just deleting these items. git blame and these PRs are enough history for me if I need to refer back for some reason.
This list is derived from the diff of the debug output when you toggle esmodule: true/false. It may be good to print out that output in legacy-javascript/run.js (doing much more than that would be more work than I'd like)
sidenote on the line you commented on... last-index-of used to be set to an older version of safari but was bumped here: zloirock/core-js@e4cea55
no idea what bug this is preventing lol https://github.com/zloirock/core-js/blob/master/packages/core-js/internals/array-method-uses-to-length.js
There was a problem hiding this comment.
alright wfm
I'd think future me would be annoyed by having to hunt down an ancient PR and copy paste individual lines from a diff that no longer merges for this info but I'll defer to your future self since it's almost definitely going to be you anyway :)
| }, /** @type {string[]} */ ([])).join(', '); | ||
| variants.push({name: dir, signals}); | ||
|
|
||
| const signals = []; |
There was a problem hiding this comment.
it did fail but didn't exit with code 1
https://travis-ci.org/github/GoogleChrome/lighthouse/builds/696156441#L1224
need to add
main().catch(err => {
console.error(err);
process.exit(1);
})| all-legacy-polyfills | ||
| 175764 all-legacy-polyfills-core-js-3/main.bundle.min.js | ||
| 125257 all-legacy-polyfills-core-js-2/main.bundle.min.js | ||
| 85169 all-legacy-polyfills-core-js-3/main.bundle.min.js |
There was a problem hiding this comment.
ouch, takin' a 50% hit to the ceiling of benefit :(
| 'WeakMap = function() {}', | ||
| 'window.WeakMap = function() {}', | ||
| 'function WeakMap() {}', | ||
| // 'WeakMap = function() {}', |
There was a problem hiding this comment.
should we delete these or are these comments important?
There was a problem hiding this comment.
Did you see my comment a few lines up
There was a problem hiding this comment.
I did, I just didn't make the connection :)
maybe just group all 4 of them together with that comment?
| 'WeakMap = function() {}', | ||
| 'window.WeakMap = function() {}', | ||
| 'function WeakMap() {}', | ||
| // 'WeakMap = function() {}', |
There was a problem hiding this comment.
I did, I just didn't make the connection :)
maybe just group all 4 of them together with that comment?
| ['Array.prototype.forEach', 'es6.array.for-each'], | ||
| ['Array.from', 'es6.array.from'], | ||
| ['Array.isArray', 'es6.array.is-array'], | ||
| ['Array.prototype.lastIndexOf', 'es6.array.last-index-of'], |
There was a problem hiding this comment.
alright wfm
I'd think future me would be annoyed by having to hunt down an ancient PR and copy paste individual lines from a diff that no longer merges for this info but I'll defer to your future self since it's almost definitely going to be you anyway :)
I think we would be glad to chat or work with y'all on this! |
|
If next time you will have questions about what and why polyfilled, please, ask me or at least take a look at tests that generate |
The PR addresses two things:
require('core-js')is vital forpreset-envto import any polyfills. The esmodules variants were missing this, so the bundles only differed minimally (transforms). After adding this, I noticed thatObject.createwas included forcore-js@2+esmodule: true, so I removed that polyfill.core-js@3 esmodules: truevariant had many signals–the expectation is that there be none. I realized that many polyfills should not be used as discriminators for identifying an module/nomodule build. See preset-env core-js 3 includes extra polyfills babel/babel#11700 (comment) . This resulted in removing ~25 polyfills (see below).Related: #10852