I had thought array.push
was a very basic function so I was surprised to see Babel polyfill array.push
for Chromium browsers. I checked the MDN document for array.push and saw that it says:
I checked core-js document and its implementation but it is unclear how it "fixes" the problem in Chromium browsers.
So what is the problem? And how are Firefox/Safari implementations different from Chromium's implementation? Checking the following output for reference.
The corejs3 polyfill added the following polyfills:
es.object.to-string { "ie":"10" }
es.promise { "ie":"10" }
web.dom-collections.for-each { "ie":"10" }
es.array.from { "ie":"10" }
es.string.iterator { "ie":"10" }
es.array.push { "chrome":"115", "edge":"110", "ie":"10" } //Only for Chromium, not for FF & Safari
...
BTW, to let babel not polyfill for array.push
I have to add exclude
to babel setting like this
"useBuiltIns": "usage",
"shippedProposals": true,
"corejs": "3.33"
"exclude": ["es.array.push"]
So what is the problem?
Some engines (in particular V8) are failing the Array/prototype/push /set-length-zero-array-length-is-non-writable test case of the test262 suite. That's a bug, and core-js provides a workaround.
Now what does the test check for? A really obscure edge case:
.length
non-writable.push()
, which would attempt to write the .length
and fail.length
doesn't actually change…then V8 lets you down: it doesn't throw the exception that it should throw but simply returns 0
(the length of the unchanged empty array).
Also there appears to be a second problem, with really old Firefox versions, from before the feature of non-writable .length
properties was introduced (10 years ago!), that it would not throw the expected TypeError
but an InternalError
.
It is unclear how it "fixes" the problem in Chromium browsers.
The polyfill - just like any other polyfill - overwrites Array.prototype.push
with a conforming implementation that simply assigns the respective properties on the receiver. This includes the assignment to .length
, even with an unchanged value, which will throw as expected. (Well actually it calls an array-set-length.js
method to do that, which has to do the writability check explicitly in some engines).