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:
See also
Polyfill of Array.prototype.push in core-js with fixes of this method
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
...
2
Answers
When browsers allowed making array lengths non-writable as seen here, it affected the
Array.push()
method sinceArray.push()
adds the specified elements to the end of an array and returns the new length of the array. If the array length is made non-writable, the array will not be able to update it. This causes an error. Unfortunately, with this addition, a bug was discovered. Core-js has added a polyfill which is what you just came across: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 expectedTypeError
but anInternalError
.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 anarray-set-length.js
method to do that, which has to do the writability check explicitly in some engines).