What is the problem with array.push implementation in chrome based browsers?

239 views Asked by At

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:

corejs-array.push

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"]
2

There are 2 answers

2
Bergi On BEST ANSWER

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:

  • if you take an array and make its .length non-writable
  • then proceed to call .push(), which would attempt to write the .length and fail
  • but actually do not pass any arguments, so the .length doesn't actually change
  • and if you still expect this to throw an exception

…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).

5
Chukwujiobi Canon On

So what is the problem?

When browsers allowed making array lengths non-writable as seen here, it affected the Array.push() method since Array.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:

properErrorOnNonWritableLength().