From 5a304e012cf79fece99830a296ef6bfa9603a802 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Thu, 28 Apr 2022 12:21:06 +0700 Subject: [PATCH 01/11] add `Array.prototype.push` polyfill --- CHANGELOG.md | 1 + README.md | 4 ++- packages/core-js-compat/src/data.mjs | 7 ++++ .../src/modules-by-versions.mjs | 1 + packages/core-js/actual/array/push.js | 3 ++ packages/core-js/actual/array/virtual/push.js | 3 ++ packages/core-js/es/array/index.js | 1 + packages/core-js/es/array/push.js | 4 +++ packages/core-js/es/array/virtual/index.js | 1 + packages/core-js/es/array/virtual/push.js | 4 +++ packages/core-js/full/array/push.js | 3 ++ packages/core-js/full/array/virtual/push.js | 3 ++ packages/core-js/modules/es.array.push.js | 35 +++++++++++++++++++ packages/core-js/stable/array/push.js | 3 ++ packages/core-js/stable/array/virtual/push.js | 3 ++ tests/commonjs.mjs | 2 ++ tests/compat/tests.js | 8 +++++ tests/pure/es.array.push.js | 22 ++++++++++++ tests/tests/es.array.push.js | 26 ++++++++++++++ 19 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 packages/core-js/actual/array/push.js create mode 100644 packages/core-js/actual/array/virtual/push.js create mode 100644 packages/core-js/es/array/push.js create mode 100644 packages/core-js/es/array/virtual/push.js create mode 100644 packages/core-js/full/array/push.js create mode 100644 packages/core-js/full/array/virtual/push.js create mode 100644 packages/core-js/modules/es.array.push.js create mode 100644 packages/core-js/stable/array/push.js create mode 100644 packages/core-js/stable/array/virtual/push.js create mode 100644 tests/pure/es.array.push.js create mode 100644 tests/tests/es.array.push.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ecad99a4446..831549f461ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - `%TypedArray%.prototype.findLastIndex` - Changed the order of operations in `%TypedArray%.prototype.with` following [proposal-change-array-by-copy/86](https://github.com/tc39/proposal-change-array-by-copy/issues/86), per June 2022 TC39 meeting - [Decorator Metadata proposal](https://github.com/tc39/proposal-decorator-metadata) extracted from [Decorators proposal](https://github.com/tc39/proposal-decorators) as a separate stage 2 proposal, `Symbol.metadataKey` replaces `Symbol.metadata` +- Added `Array.prototype.push` polyfill with some fixes for modern engines - Fixed a bug in the order of getting flags in `RegExp.prototype.flags` in the actual version of V8 - Fixed property descriptors of some `Math` and `Number` constants - Added detection of NodeJS [bug](https://github.com/nodejs/node/issues/41038) in `structuredClone` that can not clone `DOMException` (just in case for future versions that will fix other issues) diff --git a/README.md b/README.md index 498d1f1dcf15..63bbcadbd7f3 100644 --- a/README.md +++ b/README.md @@ -637,7 +637,7 @@ Error.prototype.toString.call({ message: 1, name: 2 }) === '2: 1'; // => true ``` #### ECMAScript: Array[⬆](#index) -Modules [`es.array.from`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.from.js), [`es.array.is-array`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.is-array.js), [`es.array.of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.of.js), [`es.array.copy-within`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.copy-within.js), [`es.array.fill`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.fill.js), [`es.array.find`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.find.js), [`es.array.find-index`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.find-index.js), [`es.array.find-last`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.find-last.js), [`es.array.find-last-index`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.find-last-index.js), [`es.array.iterator`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.iterator.js), [`es.array.includes`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.includes.js), [`es.array.slice`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.slice.js), [`es.array.join`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.join.js), [`es.array.index-of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.index-of.js), [`es.array.last-index-of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.last-index-of.js), [`es.array.every`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.every.js), [`es.array.some`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.some.js), [`es.array.for-each`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.for-each.js), [`es.array.map`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.map.js), [`es.array.filter`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.filter.js), [`es.array.reduce`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.reduce.js), [`es.array.reduce-right`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.reduce-right.js), [`es.array.reverse`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.reverse.js), [`es.array.sort`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.sort.js), [`es.array.flat`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.flat.js), [`es.array.flat-map`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.flat-map.js), [`es.array.unscopables.flat`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.unscopables.flat.js), [`es.array.unscopables.flat-map`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.unscopables.flat-map.js), [`es.array.at`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.at.js). +Modules [`es.array.from`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.from.js), [`es.array.is-array`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.is-array.js), [`es.array.of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.of.js), [`es.array.copy-within`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.copy-within.js), [`es.array.fill`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.fill.js), [`es.array.find`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.find.js), [`es.array.find-index`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.find-index.js), [`es.array.find-last`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.find-last.js), [`es.array.find-last-index`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.find-last-index.js), [`es.array.iterator`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.iterator.js), [`es.array.includes`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.includes.js), [`es.array.push`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.push.js), [`es.array.slice`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.slice.js), [`es.array.join`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.join.js), [`es.array.index-of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.index-of.js), [`es.array.last-index-of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.last-index-of.js), [`es.array.every`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.every.js), [`es.array.some`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.some.js), [`es.array.for-each`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.for-each.js), [`es.array.map`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.map.js), [`es.array.filter`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.filter.js), [`es.array.reduce`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.reduce.js), [`es.array.reduce-right`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.reduce-right.js), [`es.array.reverse`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.reverse.js), [`es.array.sort`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.sort.js), [`es.array.flat`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.flat.js), [`es.array.flat-map`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.flat-map.js), [`es.array.unscopables.flat`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.unscopables.flat.js), [`es.array.unscopables.flat-map`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.unscopables.flat-map.js), [`es.array.at`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.at.js). ```js class Array { at(index: int): any; @@ -660,6 +660,7 @@ class Array { keys(): Iterator; lastIndexOf(searchElement: any, from?: number): number; map(mapFn: (value: any, index: number, target: any) => any, thisArg?: any): Array; // with adding support of @@species + push(...args: Array): uint; reduce(callbackfn: (memo: any, value: any, index: number, target: any) => any, initialValue?: any): any; reduceRight(callbackfn: (memo: any, value: any, index: number, target: any) => any, initialValue?: any): any; reverse(): this; // Safari 12.0 bug fix @@ -706,6 +707,7 @@ core-js(-pure)/es|stable|actual|full/array/join core-js(-pure)/es|stable|actual|full/array/keys core-js(-pure)/es|stable|actual|full/array/last-index-of core-js(-pure)/es|stable|actual|full/array/map +core-js(-pure)/es|stable|actual|full/array/push core-js(-pure)/es|stable|actual|full/array/reduce core-js(-pure)/es|stable|actual|full/array/reduce-right core-js(-pure)/es|stable|actual|full/array/reverse diff --git a/packages/core-js-compat/src/data.mjs b/packages/core-js-compat/src/data.mjs index e2e149e11d8e..882008ffe6d8 100644 --- a/packages/core-js-compat/src/data.mjs +++ b/packages/core-js-compat/src/data.mjs @@ -274,6 +274,13 @@ export const data = { safari: '9.0', rhino: '1.7.13', }, + 'es.array.push': { + // bug with setting length + // chrome: '103', + // edge: '15', + firefox: '55', + safari: '15.4', + }, 'es.array.reduce': { chrome: '83', // https://bugs.chromium.org/p/chromium/issues/detail?id=1049982 firefox: '4', diff --git a/packages/core-js-compat/src/modules-by-versions.mjs b/packages/core-js-compat/src/modules-by-versions.mjs index 67a6d43c9444..3ad876057502 100644 --- a/packages/core-js-compat/src/modules-by-versions.mjs +++ b/packages/core-js-compat/src/modules-by-versions.mjs @@ -142,6 +142,7 @@ export default { 3.23: [ 'es.array.find-last', 'es.array.find-last-index', + 'es.array.push', 'es.typed-array.find-last', 'es.typed-array.find-last-index', 'esnext.symbol.metadata-key', diff --git a/packages/core-js/actual/array/push.js b/packages/core-js/actual/array/push.js new file mode 100644 index 000000000000..9dc66e4e6f9e --- /dev/null +++ b/packages/core-js/actual/array/push.js @@ -0,0 +1,3 @@ +var parent = require('../../stable/array/push'); + +module.exports = parent; diff --git a/packages/core-js/actual/array/virtual/push.js b/packages/core-js/actual/array/virtual/push.js new file mode 100644 index 000000000000..647c73738f99 --- /dev/null +++ b/packages/core-js/actual/array/virtual/push.js @@ -0,0 +1,3 @@ +var parent = require('../../../stable/array/virtual/push'); + +module.exports = parent; diff --git a/packages/core-js/es/array/index.js b/packages/core-js/es/array/index.js index 668f4da0f367..6b84a52b97c4 100644 --- a/packages/core-js/es/array/index.js +++ b/packages/core-js/es/array/index.js @@ -20,6 +20,7 @@ require('../../modules/es.array.iterator'); require('../../modules/es.array.join'); require('../../modules/es.array.last-index-of'); require('../../modules/es.array.map'); +require('../../modules/es.array.push'); require('../../modules/es.array.reduce'); require('../../modules/es.array.reduce-right'); require('../../modules/es.array.reverse'); diff --git a/packages/core-js/es/array/push.js b/packages/core-js/es/array/push.js new file mode 100644 index 000000000000..64481638d938 --- /dev/null +++ b/packages/core-js/es/array/push.js @@ -0,0 +1,4 @@ +require('../../modules/es.array.push'); +var entryUnbind = require('../../internals/entry-unbind'); + +module.exports = entryUnbind('Array', 'push'); diff --git a/packages/core-js/es/array/virtual/index.js b/packages/core-js/es/array/virtual/index.js index 1ed5fd3a4685..118f416f6ba4 100644 --- a/packages/core-js/es/array/virtual/index.js +++ b/packages/core-js/es/array/virtual/index.js @@ -17,6 +17,7 @@ require('../../../modules/es.array.iterator'); require('../../../modules/es.array.join'); require('../../../modules/es.array.last-index-of'); require('../../../modules/es.array.map'); +require('../../../modules/es.array.push'); require('../../../modules/es.array.reduce'); require('../../../modules/es.array.reduce-right'); require('../../../modules/es.array.reverse'); diff --git a/packages/core-js/es/array/virtual/push.js b/packages/core-js/es/array/virtual/push.js new file mode 100644 index 000000000000..ea7cfdfc9975 --- /dev/null +++ b/packages/core-js/es/array/virtual/push.js @@ -0,0 +1,4 @@ +require('../../../modules/es.array.push'); +var entryVirtual = require('../../../internals/entry-virtual'); + +module.exports = entryVirtual('Array').push; diff --git a/packages/core-js/full/array/push.js b/packages/core-js/full/array/push.js new file mode 100644 index 000000000000..9c4ff552eb99 --- /dev/null +++ b/packages/core-js/full/array/push.js @@ -0,0 +1,3 @@ +var parent = require('../../actual/array/push'); + +module.exports = parent; diff --git a/packages/core-js/full/array/virtual/push.js b/packages/core-js/full/array/virtual/push.js new file mode 100644 index 000000000000..ff2759f2015e --- /dev/null +++ b/packages/core-js/full/array/virtual/push.js @@ -0,0 +1,3 @@ +var parent = require('../../../actual/array/virtual/push'); + +module.exports = parent; diff --git a/packages/core-js/modules/es.array.push.js b/packages/core-js/modules/es.array.push.js new file mode 100644 index 000000000000..228885db21e8 --- /dev/null +++ b/packages/core-js/modules/es.array.push.js @@ -0,0 +1,35 @@ +'use strict'; +var $ = require('../internals/export'); +var toObject = require('../internals/to-object'); +var lengthOfArrayLike = require('../internals/length-of-array-like'); +var fails = require('../internals/fails'); + +var $TypeError = TypeError; +var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF; + +var INCORRECT_TO_LENGTH = fails(function () { + return [].push.call({ length: 0x100000000 }, 1) !== 4294967297; +}); + +var SILENT_ON_NON_WRITABLE_LENGTH = !fails(function () { + // eslint-disable-next-line es-x/no-object-defineproperty -- safe + Object.defineProperty([], 'length', { writable: false }).push(); +}); + +// `Array.prototype.push` method +// https://tc39.es/ecma262/#sec-array.prototype.push +$({ target: 'Array', proto: true, arity: 1, forced: INCORRECT_TO_LENGTH || SILENT_ON_NON_WRITABLE_LENGTH }, { + // eslint-disable-next-line no-unused-vars -- required for `.length` + push: function push(item) { + var O = toObject(this); + var len = lengthOfArrayLike(O); + var argCount = arguments.length; + if (len + argCount > MAX_SAFE_INTEGER) throw $TypeError('Maximum allowed length exceeded'); + for (var i = 0; i < argCount; i++) { + O[len] = arguments[i]; + len++; + } + O.length = len; + return len; + } +}); diff --git a/packages/core-js/stable/array/push.js b/packages/core-js/stable/array/push.js new file mode 100644 index 000000000000..af5586455b6f --- /dev/null +++ b/packages/core-js/stable/array/push.js @@ -0,0 +1,3 @@ +var parent = require('../../es/array/push'); + +module.exports = parent; diff --git a/packages/core-js/stable/array/virtual/push.js b/packages/core-js/stable/array/virtual/push.js new file mode 100644 index 000000000000..cf4565aa22b0 --- /dev/null +++ b/packages/core-js/stable/array/virtual/push.js @@ -0,0 +1,3 @@ +var parent = require('../../../es/array/virtual/push'); + +module.exports = parent; diff --git a/tests/commonjs.mjs b/tests/commonjs.mjs index 3709e87cad39..82289316559c 100644 --- a/tests/commonjs.mjs +++ b/tests/commonjs.mjs @@ -72,6 +72,7 @@ for (PATH of ['core-js-pure', 'core-js']) { ok(typeof load(NS, 'array/flat-map') == 'function'); ok(typeof load(NS, 'array/some') == 'function'); ok(typeof load(NS, 'array/every') == 'function'); + ok(typeof load(NS, 'array/push') == 'function'); ok(typeof load(NS, 'array/reduce') == 'function'); ok(typeof load(NS, 'array/reduce-right') == 'function'); ok(typeof load(NS, 'array/reverse') == 'function'); @@ -101,6 +102,7 @@ for (PATH of ['core-js-pure', 'core-js']) { ok(typeof load(NS, 'array/virtual/flat-map') == 'function'); ok(typeof load(NS, 'array/virtual/some') == 'function'); ok(typeof load(NS, 'array/virtual/every') == 'function'); + ok(typeof load(NS, 'array/virtual/push') == 'function'); ok(typeof load(NS, 'array/virtual/reduce') == 'function'); ok(typeof load(NS, 'array/virtual/reduce-right') == 'function'); ok(typeof load(NS, 'array/virtual/reverse') == 'function'); diff --git a/tests/compat/tests.js b/tests/compat/tests.js index ada5e19ae6a5..0157a61eb7d4 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -424,6 +424,14 @@ GLOBAL.tests = { function F() { /* empty */ } return Array.of.call(F) instanceof F; }, + 'es.array.push': function () { + if ([].push.call({ length: 0x100000000 }, 1) !== 4294967297) return false; + try { + Object.defineProperty([], 'length', { writable: false }).push(); + return false; + } catch (error) { /* empty */ } + return true; + }, 'es.array.reduce': function () { try { Array.prototype.reduce.call(null, function () { /* empty */ }, 1); diff --git a/tests/pure/es.array.push.js b/tests/pure/es.array.push.js new file mode 100644 index 000000000000..5c37c99c4411 --- /dev/null +++ b/tests/pure/es.array.push.js @@ -0,0 +1,22 @@ +import { DESCRIPTORS, STRICT } from '../helpers/constants'; + +import push from 'core-js-pure/es/array/virtual/push'; +import defineProperty from 'core-js-pure/es/object/define-property'; + +QUnit.test('Array#push', assert => { + assert.isFunction(push); + + const object = { length: 0x100000000 }; + assert.same(push.call(object, 1), 0x100000001, 'proper ToLength #1'); + assert.same(object[0x100000000], 1, 'proper ToLength #2'); + + if (DESCRIPTORS) { + assert.throws(() => push.call(defineProperty([], 'length', { writable: false }), 1), TypeError, 'now-writable length, with arg'); + assert.throws(() => push.call(defineProperty([], 'length', { writable: false })), TypeError, 'now-writable length, without arg'); + } + + if (STRICT) { + assert.throws(() => push.call(null), TypeError); + assert.throws(() => push.call(undefined), TypeError); + } +}); diff --git a/tests/tests/es.array.push.js b/tests/tests/es.array.push.js new file mode 100644 index 000000000000..3dcc97317a1d --- /dev/null +++ b/tests/tests/es.array.push.js @@ -0,0 +1,26 @@ +import { DESCRIPTORS, STRICT } from '../helpers/constants'; + +const { defineProperty } = Object; + +QUnit.test('Array#push', assert => { + const { push } = Array.prototype; + assert.isFunction(push); + assert.arity(push, 1); + assert.name(push, 'push'); + assert.looksNative(push); + assert.nonEnumerable(Array.prototype, 'push'); + + const object = { length: 0x100000000 }; + assert.same(push.call(object, 1), 0x100000001, 'proper ToLength #1'); + assert.same(object[0x100000000], 1, 'proper ToLength #2'); + + if (DESCRIPTORS) { + assert.throws(() => push.call(defineProperty([], 'length', { writable: false }), 1), TypeError, 'now-writable length, with arg'); + assert.throws(() => push.call(defineProperty([], 'length', { writable: false })), TypeError, 'now-writable length, without arg'); + } + + if (STRICT) { + assert.throws(() => push.call(null), TypeError); + assert.throws(() => push.call(undefined), TypeError); + } +}); From c31c3e45577cf529e89b0e56a3654d3ad7860734 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Tue, 3 May 2022 09:21:18 +0700 Subject: [PATCH 02/11] add a link --- packages/core-js/modules/es.array.push.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/core-js/modules/es.array.push.js b/packages/core-js/modules/es.array.push.js index 228885db21e8..7bcc7c327d3d 100644 --- a/packages/core-js/modules/es.array.push.js +++ b/packages/core-js/modules/es.array.push.js @@ -11,6 +11,8 @@ var INCORRECT_TO_LENGTH = fails(function () { return [].push.call({ length: 0x100000000 }, 1) !== 4294967297; }); +// V8 and Safari < 15.4 +// https://bugs.chromium.org/p/v8/issues/detail?id=12681 var SILENT_ON_NON_WRITABLE_LENGTH = !fails(function () { // eslint-disable-next-line es-x/no-object-defineproperty -- safe Object.defineProperty([], 'length', { writable: false }).push(); From 0d7d897c8fffbdaafec70c06fab7a03aa9484ef8 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Wed, 18 May 2022 15:48:48 +0700 Subject: [PATCH 03/11] it's still not fixed in Safari 15.4 - only in TP --- packages/core-js-compat/src/data.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core-js-compat/src/data.mjs b/packages/core-js-compat/src/data.mjs index 882008ffe6d8..68f8970ca00e 100644 --- a/packages/core-js-compat/src/data.mjs +++ b/packages/core-js-compat/src/data.mjs @@ -279,7 +279,8 @@ export const data = { // chrome: '103', // edge: '15', firefox: '55', - safari: '15.4', + // the same to Chrome bug fixed only in Safari TP + // safari: '15.4', }, 'es.array.reduce': { chrome: '83', // https://bugs.chromium.org/p/chromium/issues/detail?id=1049982 From d80a05e020a41546b2d5325b0c47eb68f3c11c40 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Tue, 31 May 2022 23:17:39 +0700 Subject: [PATCH 04/11] use `doesNotExceedSafeInteger` helper --- packages/core-js/modules/es.array.push.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/core-js/modules/es.array.push.js b/packages/core-js/modules/es.array.push.js index 7bcc7c327d3d..e51342f2842c 100644 --- a/packages/core-js/modules/es.array.push.js +++ b/packages/core-js/modules/es.array.push.js @@ -2,16 +2,14 @@ var $ = require('../internals/export'); var toObject = require('../internals/to-object'); var lengthOfArrayLike = require('../internals/length-of-array-like'); +var doesNotExceedSafeInteger = require('../internals/does-not-exceed-safe-integer'); var fails = require('../internals/fails'); -var $TypeError = TypeError; -var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF; - var INCORRECT_TO_LENGTH = fails(function () { return [].push.call({ length: 0x100000000 }, 1) !== 4294967297; }); -// V8 and Safari < 15.4 +// V8 and Safari <= 15.4 // https://bugs.chromium.org/p/v8/issues/detail?id=12681 var SILENT_ON_NON_WRITABLE_LENGTH = !fails(function () { // eslint-disable-next-line es-x/no-object-defineproperty -- safe @@ -26,7 +24,7 @@ $({ target: 'Array', proto: true, arity: 1, forced: INCORRECT_TO_LENGTH || SILEN var O = toObject(this); var len = lengthOfArrayLike(O); var argCount = arguments.length; - if (len + argCount > MAX_SAFE_INTEGER) throw $TypeError('Maximum allowed length exceeded'); + doesNotExceedSafeInteger(len + argCount); for (var i = 0; i < argCount; i++) { O[len] = arguments[i]; len++; From 53fb22259e80417bc6da315ac4c35215526e3db5 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Tue, 31 May 2022 23:23:15 +0700 Subject: [PATCH 05/11] add `Array.prototype.unshift` polyfill --- packages/core-js-compat/src/data.mjs | 7 ++++ .../src/modules-by-versions.mjs | 1 + packages/core-js/es/array/index.js | 1 + packages/core-js/es/array/virtual/index.js | 1 + packages/core-js/modules/es.array.unshift.js | 40 +++++++++++++++++++ tests/compat/tests.js | 8 ++++ 6 files changed, 58 insertions(+) create mode 100644 packages/core-js/modules/es.array.unshift.js diff --git a/packages/core-js-compat/src/data.mjs b/packages/core-js-compat/src/data.mjs index 68f8970ca00e..aac76868740f 100644 --- a/packages/core-js-compat/src/data.mjs +++ b/packages/core-js-compat/src/data.mjs @@ -347,6 +347,13 @@ export const data = { firefox: '67', safari: '13', }, + 'es.array.unshift': { + chrome: '71', + firefox: '4', + ie: '9', + // bug with setting length fixed only in Safari TP + // safari: '15.4', + }, 'es.array-buffer.constructor': { chrome: '26', edge: '14', diff --git a/packages/core-js-compat/src/modules-by-versions.mjs b/packages/core-js-compat/src/modules-by-versions.mjs index 3ad876057502..e7ca94d4ae60 100644 --- a/packages/core-js-compat/src/modules-by-versions.mjs +++ b/packages/core-js-compat/src/modules-by-versions.mjs @@ -143,6 +143,7 @@ export default { 'es.array.find-last', 'es.array.find-last-index', 'es.array.push', + 'es.array.unshift', 'es.typed-array.find-last', 'es.typed-array.find-last-index', 'esnext.symbol.metadata-key', diff --git a/packages/core-js/es/array/index.js b/packages/core-js/es/array/index.js index 6b84a52b97c4..a7289e10f1a9 100644 --- a/packages/core-js/es/array/index.js +++ b/packages/core-js/es/array/index.js @@ -31,6 +31,7 @@ require('../../modules/es.array.species'); require('../../modules/es.array.splice'); require('../../modules/es.array.unscopables.flat'); require('../../modules/es.array.unscopables.flat-map'); +require('../../modules/es.array.unshift'); require('../../modules/es.object.to-string'); require('../../modules/es.string.iterator'); var path = require('../../internals/path'); diff --git a/packages/core-js/es/array/virtual/index.js b/packages/core-js/es/array/virtual/index.js index 118f416f6ba4..6aa118e5c98d 100644 --- a/packages/core-js/es/array/virtual/index.js +++ b/packages/core-js/es/array/virtual/index.js @@ -28,6 +28,7 @@ require('../../../modules/es.array.species'); require('../../../modules/es.array.splice'); require('../../../modules/es.array.unscopables.flat'); require('../../../modules/es.array.unscopables.flat-map'); +require('../../../modules/es.array.unshift'); require('../../../modules/es.object.to-string'); var entryVirtual = require('../../../internals/entry-virtual'); diff --git a/packages/core-js/modules/es.array.unshift.js b/packages/core-js/modules/es.array.unshift.js new file mode 100644 index 000000000000..2eb3f8732ae4 --- /dev/null +++ b/packages/core-js/modules/es.array.unshift.js @@ -0,0 +1,40 @@ +'use strict'; +var $ = require('../internals/export'); +var toObject = require('../internals/to-object'); +var lengthOfArrayLike = require('../internals/length-of-array-like'); +var doesNotExceedSafeInteger = require('../internals/does-not-exceed-safe-integer'); +var fails = require('../internals/fails'); + +// IE8- +var INCORRECT_RESULT = [].unshift(0) !== 1; + +// V8 ~ Chrome < 71 and Safari <= 15.4 +var SILENT_ON_NON_WRITABLE_LENGTH = !fails(function () { + // eslint-disable-next-line es-x/no-object-defineproperty -- safe + Object.defineProperty([], 'length', { writable: false }).unshift(); +}); + +// `Array.prototype.unshift` method +// https://tc39.es/ecma262/#sec-array.prototype.unshift +$({ target: 'Array', proto: true, arity: 1, forced: INCORRECT_RESULT || SILENT_ON_NON_WRITABLE_LENGTH }, { + // eslint-disable-next-line no-unused-vars -- required for `.length` + unshift: function unshift(item) { + var O = toObject(this); + var len = lengthOfArrayLike(O); + var argCount = arguments.length; + if (argCount) { + doesNotExceedSafeInteger(len + argCount); + var k = len; + while (k--) { + var to = k + argCount; + if (k in O) O[to] = O[k]; + else delete O[to]; + } + for (var j = 0; j < argCount; j++) { + O[j] = arguments[j]; + } + } + O.length = len + argCount; + return len; + } +}); diff --git a/tests/compat/tests.js b/tests/compat/tests.js index 0157a61eb7d4..4b60108aebe0 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -520,6 +520,14 @@ GLOBAL.tests = { 'es.array.unscopables.flat-map': function () { return Array.prototype[Symbol.unscopables].flatMap; }, + 'es.array.unshift': function () { + if ([].unshift(0) !== 1) return false; + try { + Object.defineProperty([], 'length', { writable: false }).unshift(); + return false; + } catch (error) { /* empty */ } + return true; + }, 'es.array-buffer.constructor': [ARRAY_BUFFER_SUPPORT, function () { try { return !ArrayBuffer(1); From 56aac5747564000478462cbdf2c3dc5febd506f3 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Wed, 1 Jun 2022 02:04:16 +0700 Subject: [PATCH 06/11] some improvements --- CHANGELOG.md | 1 + packages/core-js/modules/es.array.unshift.js | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 831549f461ed..a60498d79b1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Changed the order of operations in `%TypedArray%.prototype.with` following [proposal-change-array-by-copy/86](https://github.com/tc39/proposal-change-array-by-copy/issues/86), per June 2022 TC39 meeting - [Decorator Metadata proposal](https://github.com/tc39/proposal-decorator-metadata) extracted from [Decorators proposal](https://github.com/tc39/proposal-decorators) as a separate stage 2 proposal, `Symbol.metadataKey` replaces `Symbol.metadata` - Added `Array.prototype.push` polyfill with some fixes for modern engines +- Added `Array.prototype.unshift` polyfill with some fixes for modern engines - Fixed a bug in the order of getting flags in `RegExp.prototype.flags` in the actual version of V8 - Fixed property descriptors of some `Math` and `Number` constants - Added detection of NodeJS [bug](https://github.com/nodejs/node/issues/41038) in `structuredClone` that can not clone `DOMException` (just in case for future versions that will fix other issues) diff --git a/packages/core-js/modules/es.array.unshift.js b/packages/core-js/modules/es.array.unshift.js index 2eb3f8732ae4..f0f19f93aede 100644 --- a/packages/core-js/modules/es.array.unshift.js +++ b/packages/core-js/modules/es.array.unshift.js @@ -2,6 +2,7 @@ var $ = require('../internals/export'); var toObject = require('../internals/to-object'); var lengthOfArrayLike = require('../internals/length-of-array-like'); +var deletePropertyOrThrow = require('../internals/delete-property-or-throw'); var doesNotExceedSafeInteger = require('../internals/does-not-exceed-safe-integer'); var fails = require('../internals/fails'); @@ -28,7 +29,7 @@ $({ target: 'Array', proto: true, arity: 1, forced: INCORRECT_RESULT || SILENT_O while (k--) { var to = k + argCount; if (k in O) O[to] = O[k]; - else delete O[to]; + else deletePropertyOrThrow(O, to); } for (var j = 0; j < argCount; j++) { O[j] = arguments[j]; From f719025cfbe9648502e1ce1b11542ccc8ad24cac Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Thu, 9 Jun 2022 20:08:43 +0700 Subject: [PATCH 07/11] add new entries --- packages/core-js/actual/array/unshift.js | 3 +++ packages/core-js/actual/array/virtual/unshift.js | 3 +++ packages/core-js/actual/instance/push.js | 3 +++ packages/core-js/actual/instance/unshift.js | 3 +++ packages/core-js/es/array/unshift.js | 4 ++++ packages/core-js/es/array/virtual/unshift.js | 4 ++++ packages/core-js/es/instance/push.js | 9 +++++++++ packages/core-js/es/instance/unshift.js | 9 +++++++++ packages/core-js/full/array/unshift.js | 3 +++ packages/core-js/full/array/virtual/unshift.js | 3 +++ packages/core-js/full/instance/push.js | 3 +++ packages/core-js/full/instance/unshift.js | 3 +++ packages/core-js/stable/array/unshift.js | 3 +++ packages/core-js/stable/array/virtual/unshift.js | 3 +++ packages/core-js/stable/instance/push.js | 3 +++ packages/core-js/stable/instance/unshift.js | 3 +++ tests/commonjs.mjs | 14 ++++++++++++++ 17 files changed, 76 insertions(+) create mode 100644 packages/core-js/actual/array/unshift.js create mode 100644 packages/core-js/actual/array/virtual/unshift.js create mode 100644 packages/core-js/actual/instance/push.js create mode 100644 packages/core-js/actual/instance/unshift.js create mode 100644 packages/core-js/es/array/unshift.js create mode 100644 packages/core-js/es/array/virtual/unshift.js create mode 100644 packages/core-js/es/instance/push.js create mode 100644 packages/core-js/es/instance/unshift.js create mode 100644 packages/core-js/full/array/unshift.js create mode 100644 packages/core-js/full/array/virtual/unshift.js create mode 100644 packages/core-js/full/instance/push.js create mode 100644 packages/core-js/full/instance/unshift.js create mode 100644 packages/core-js/stable/array/unshift.js create mode 100644 packages/core-js/stable/array/virtual/unshift.js create mode 100644 packages/core-js/stable/instance/push.js create mode 100644 packages/core-js/stable/instance/unshift.js diff --git a/packages/core-js/actual/array/unshift.js b/packages/core-js/actual/array/unshift.js new file mode 100644 index 000000000000..28f8300120ad --- /dev/null +++ b/packages/core-js/actual/array/unshift.js @@ -0,0 +1,3 @@ +var parent = require('../../stable/array/unshift'); + +module.exports = parent; diff --git a/packages/core-js/actual/array/virtual/unshift.js b/packages/core-js/actual/array/virtual/unshift.js new file mode 100644 index 000000000000..7b0eb15cde3c --- /dev/null +++ b/packages/core-js/actual/array/virtual/unshift.js @@ -0,0 +1,3 @@ +var parent = require('../../../stable/array/virtual/unshift'); + +module.exports = parent; diff --git a/packages/core-js/actual/instance/push.js b/packages/core-js/actual/instance/push.js new file mode 100644 index 000000000000..360f6b658300 --- /dev/null +++ b/packages/core-js/actual/instance/push.js @@ -0,0 +1,3 @@ +var parent = require('../../stable/instance/push'); + +module.exports = parent; diff --git a/packages/core-js/actual/instance/unshift.js b/packages/core-js/actual/instance/unshift.js new file mode 100644 index 000000000000..360f6b658300 --- /dev/null +++ b/packages/core-js/actual/instance/unshift.js @@ -0,0 +1,3 @@ +var parent = require('../../stable/instance/push'); + +module.exports = parent; diff --git a/packages/core-js/es/array/unshift.js b/packages/core-js/es/array/unshift.js new file mode 100644 index 000000000000..53e5341d1d20 --- /dev/null +++ b/packages/core-js/es/array/unshift.js @@ -0,0 +1,4 @@ +require('../../modules/es.array.unshift'); +var entryUnbind = require('../../internals/entry-unbind'); + +module.exports = entryUnbind('Array', 'unshift'); diff --git a/packages/core-js/es/array/virtual/unshift.js b/packages/core-js/es/array/virtual/unshift.js new file mode 100644 index 000000000000..1cd711e5710b --- /dev/null +++ b/packages/core-js/es/array/virtual/unshift.js @@ -0,0 +1,4 @@ +require('../../../modules/es.array.unshift'); +var entryVirtual = require('../../../internals/entry-virtual'); + +module.exports = entryVirtual('Array').unshift; diff --git a/packages/core-js/es/instance/push.js b/packages/core-js/es/instance/push.js new file mode 100644 index 000000000000..a58a52a46548 --- /dev/null +++ b/packages/core-js/es/instance/push.js @@ -0,0 +1,9 @@ +var isPrototypeOf = require('../../internals/object-is-prototype-of'); +var method = require('../array/virtual/push'); + +var ArrayPrototype = Array.prototype; + +module.exports = function (it) { + var own = it.push; + return it === ArrayPrototype || (isPrototypeOf(ArrayPrototype, it) && own === ArrayPrototype.push) ? method : own; +}; diff --git a/packages/core-js/es/instance/unshift.js b/packages/core-js/es/instance/unshift.js new file mode 100644 index 000000000000..94e1864c69ee --- /dev/null +++ b/packages/core-js/es/instance/unshift.js @@ -0,0 +1,9 @@ +var isPrototypeOf = require('../../internals/object-is-prototype-of'); +var method = require('../array/virtual/unshift'); + +var ArrayPrototype = Array.prototype; + +module.exports = function (it) { + var own = it.unshift; + return it === ArrayPrototype || (isPrototypeOf(ArrayPrototype, it) && own === ArrayPrototype.unshift) ? method : own; +}; diff --git a/packages/core-js/full/array/unshift.js b/packages/core-js/full/array/unshift.js new file mode 100644 index 000000000000..8024fe4f5300 --- /dev/null +++ b/packages/core-js/full/array/unshift.js @@ -0,0 +1,3 @@ +var parent = require('../../actual/array/unshift'); + +module.exports = parent; diff --git a/packages/core-js/full/array/virtual/unshift.js b/packages/core-js/full/array/virtual/unshift.js new file mode 100644 index 000000000000..e48022815442 --- /dev/null +++ b/packages/core-js/full/array/virtual/unshift.js @@ -0,0 +1,3 @@ +var parent = require('../../../actual/array/virtual/unshift'); + +module.exports = parent; diff --git a/packages/core-js/full/instance/push.js b/packages/core-js/full/instance/push.js new file mode 100644 index 000000000000..f2b1b1585bc2 --- /dev/null +++ b/packages/core-js/full/instance/push.js @@ -0,0 +1,3 @@ +var parent = require('../../actual/instance/push'); + +module.exports = parent; diff --git a/packages/core-js/full/instance/unshift.js b/packages/core-js/full/instance/unshift.js new file mode 100644 index 000000000000..f2b1b1585bc2 --- /dev/null +++ b/packages/core-js/full/instance/unshift.js @@ -0,0 +1,3 @@ +var parent = require('../../actual/instance/push'); + +module.exports = parent; diff --git a/packages/core-js/stable/array/unshift.js b/packages/core-js/stable/array/unshift.js new file mode 100644 index 000000000000..60669c0a15ac --- /dev/null +++ b/packages/core-js/stable/array/unshift.js @@ -0,0 +1,3 @@ +var parent = require('../../es/array/unshift'); + +module.exports = parent; diff --git a/packages/core-js/stable/array/virtual/unshift.js b/packages/core-js/stable/array/virtual/unshift.js new file mode 100644 index 000000000000..ac076d58ecba --- /dev/null +++ b/packages/core-js/stable/array/virtual/unshift.js @@ -0,0 +1,3 @@ +var parent = require('../../../es/array/virtual/unshift'); + +module.exports = parent; diff --git a/packages/core-js/stable/instance/push.js b/packages/core-js/stable/instance/push.js new file mode 100644 index 000000000000..c1d3a2e5bad9 --- /dev/null +++ b/packages/core-js/stable/instance/push.js @@ -0,0 +1,3 @@ +var parent = require('../../es/instance/push'); + +module.exports = parent; diff --git a/packages/core-js/stable/instance/unshift.js b/packages/core-js/stable/instance/unshift.js new file mode 100644 index 000000000000..c1d3a2e5bad9 --- /dev/null +++ b/packages/core-js/stable/instance/unshift.js @@ -0,0 +1,3 @@ +var parent = require('../../es/instance/push'); + +module.exports = parent; diff --git a/tests/commonjs.mjs b/tests/commonjs.mjs index 82289316559c..649b96dcb863 100644 --- a/tests/commonjs.mjs +++ b/tests/commonjs.mjs @@ -78,6 +78,7 @@ for (PATH of ['core-js-pure', 'core-js']) { ok(typeof load(NS, 'array/reverse') == 'function'); ok(typeof load(NS, 'array/index-of') == 'function'); ok(typeof load(NS, 'array/last-index-of') == 'function'); + ok(typeof load(NS, 'array/unshift') == 'function'); ok(load(NS, 'array/concat')([1, 2, 3], [4, 5, 6]).length === 6); ok(load(NS, 'array/copy-within')([1, 2, 3, 4, 5], 0, 3)[0] === 4); ok('next' in load(NS, 'array/entries')([])); @@ -108,6 +109,7 @@ for (PATH of ['core-js-pure', 'core-js']) { ok(typeof load(NS, 'array/virtual/reverse') == 'function'); ok(typeof load(NS, 'array/virtual/index-of') == 'function'); ok(typeof load(NS, 'array/virtual/last-index-of') == 'function'); + ok(typeof load(NS, 'array/virtual/unshift') == 'function'); ok(load(NS, 'array/virtual/concat').call([1, 2, 3], [4, 5, 6]).length === 6); ok(load(NS, 'array/virtual/copy-within').call([1, 2, 3, 4, 5], 0, 3)[0] === 4); ok('next' in load(NS, 'array/virtual/entries').call([])); @@ -467,6 +469,12 @@ for (PATH of ['core-js-pure', 'core-js']) { ok(typeof instancePadStart('') == 'function'); ok(instancePadStart('').call('a', 3, 'b') === 'bba'); + const instancePush = load(NS, 'instance/push'); + ok(typeof instancePush == 'function'); + ok(instancePush({}) === undefined); + ok(typeof instancePush([]) == 'function'); + ok(instancePush([]).call([1], 8) === 2); + const instanceReduceRight = load(NS, 'instance/reduce-right'); ok(typeof instanceReduceRight == 'function'); ok(instanceReduceRight({}) === undefined); @@ -553,6 +561,12 @@ for (PATH of ['core-js-pure', 'core-js']) { ok(typeof instanceTrim('') == 'function'); ok(instanceTrim('').call(' 1 ') === '1'); + const instanceUnshift = load(NS, 'instance/unshift'); + ok(typeof instanceUnshift == 'function'); + ok(instanceUnshift({}) === undefined); + ok(typeof instanceUnshift([]) == 'function'); + ok(instanceUnshift([]).call([1], 8) === 2); + const instanceValues = load(NS, 'instance/values'); ok(typeof instanceValues == 'function'); ok(instanceValues({}) === undefined); From e3b9d7e95c9b2db3362a32bf193f21dc7ebe336a Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Thu, 9 Jun 2022 21:31:47 +0700 Subject: [PATCH 08/11] update docs --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 63bbcadbd7f3..f5f2dbf8b53d 100644 --- a/README.md +++ b/README.md @@ -637,7 +637,7 @@ Error.prototype.toString.call({ message: 1, name: 2 }) === '2: 1'; // => true ``` #### ECMAScript: Array[⬆](#index) -Modules [`es.array.from`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.from.js), [`es.array.is-array`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.is-array.js), [`es.array.of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.of.js), [`es.array.copy-within`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.copy-within.js), [`es.array.fill`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.fill.js), [`es.array.find`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.find.js), [`es.array.find-index`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.find-index.js), [`es.array.find-last`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.find-last.js), [`es.array.find-last-index`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.find-last-index.js), [`es.array.iterator`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.iterator.js), [`es.array.includes`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.includes.js), [`es.array.push`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.push.js), [`es.array.slice`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.slice.js), [`es.array.join`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.join.js), [`es.array.index-of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.index-of.js), [`es.array.last-index-of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.last-index-of.js), [`es.array.every`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.every.js), [`es.array.some`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.some.js), [`es.array.for-each`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.for-each.js), [`es.array.map`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.map.js), [`es.array.filter`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.filter.js), [`es.array.reduce`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.reduce.js), [`es.array.reduce-right`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.reduce-right.js), [`es.array.reverse`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.reverse.js), [`es.array.sort`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.sort.js), [`es.array.flat`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.flat.js), [`es.array.flat-map`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.flat-map.js), [`es.array.unscopables.flat`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.unscopables.flat.js), [`es.array.unscopables.flat-map`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.unscopables.flat-map.js), [`es.array.at`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.at.js). +Modules [`es.array.from`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.from.js), [`es.array.is-array`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.is-array.js), [`es.array.of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.of.js), [`es.array.copy-within`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.copy-within.js), [`es.array.fill`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.fill.js), [`es.array.find`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.find.js), [`es.array.find-index`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.find-index.js), [`es.array.find-last`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.find-last.js), [`es.array.find-last-index`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.find-last-index.js), [`es.array.iterator`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.iterator.js), [`es.array.includes`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.includes.js), [`es.array.push`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.push.js), [`es.array.slice`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.slice.js), [`es.array.join`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.join.js), [`es.array.unshift`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.unshift.js), [`es.array.index-of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.index-of.js), [`es.array.last-index-of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.last-index-of.js), [`es.array.every`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.every.js), [`es.array.some`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.some.js), [`es.array.for-each`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.for-each.js), [`es.array.map`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.map.js), [`es.array.filter`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.filter.js), [`es.array.reduce`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.reduce.js), [`es.array.reduce-right`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.reduce-right.js), [`es.array.reverse`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.reverse.js), [`es.array.sort`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.sort.js), [`es.array.flat`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.flat.js), [`es.array.flat-map`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.flat-map.js), [`es.array.unscopables.flat`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.unscopables.flat.js), [`es.array.unscopables.flat-map`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.unscopables.flat-map.js), [`es.array.at`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.array.at.js). ```js class Array { at(index: int): any; @@ -668,6 +668,7 @@ class Array { splice(start?: number, deleteCount?: number, ...items: Array): Array; // with adding support of @@species some(callbackfn: (value: any, index: number, target: any) => boolean, thisArg?: any): boolean; sort(comparefn?: (a: any, b: any) => number): this; // with modern behavior like stable sort + unshift(...args: Array): uint; values(): Iterator; @@iterator(): Iterator; @@unscopables: { [newMethodNames: string]: true }; @@ -715,6 +716,7 @@ core-js(-pure)/es|stable|actual|full/array/slice core-js(-pure)/es|stable|actual|full/array/splice core-js(-pure)/es|stable|actual|full/array/some core-js(-pure)/es|stable|actual|full/array/sort +core-js(-pure)/es|stable|actual|full/array/unshift core-js(-pure)/es|stable|actual|full/array/values core-js(-pure)/es|stable|actual|full/array/virtual/at core-js(-pure)/es|stable|actual|full/array/virtual/concat @@ -737,6 +739,7 @@ core-js(-pure)/es|stable|actual|full/array/virtual/join core-js(-pure)/es|stable|actual|full/array/virtual/keys core-js(-pure)/es|stable|actual|full/array/virtual/last-index-of core-js(-pure)/es|stable|actual|full/array/virtual/map +core-js(-pure)/es|stable|actual|full/array/virtual/push core-js(-pure)/es|stable|actual|full/array/virtual/reduce core-js(-pure)/es|stable|actual|full/array/virtual/reduce-right core-js(-pure)/es|stable|actual|full/array/virtual/reverse @@ -744,6 +747,7 @@ core-js(-pure)/es|stable|actual|full/array/virtual/slice core-js(-pure)/es|stable|actual|full/array/virtual/some core-js(-pure)/es|stable|actual|full/array/virtual/sort core-js(-pure)/es|stable|actual|full/array/virtual/splice +core-js(-pure)/es|stable|actual|full/array/virtual/unshift core-js(-pure)/es|stable|actual|full/array/virtual/values ``` [*Examples*](https://tinyurl.com/2br28bgj): From 77dcc86afabfff02823ffa13f694998b6cac2f62 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Thu, 9 Jun 2022 22:34:37 +0700 Subject: [PATCH 09/11] add some tests --- packages/core-js/modules/es.array.unshift.js | 4 +--- tests/pure/es.array.unshift.js | 20 ++++++++++++++++ tests/tests/es.array.unshift.js | 24 ++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 tests/pure/es.array.unshift.js create mode 100644 tests/tests/es.array.unshift.js diff --git a/packages/core-js/modules/es.array.unshift.js b/packages/core-js/modules/es.array.unshift.js index f0f19f93aede..f43cefd444c2 100644 --- a/packages/core-js/modules/es.array.unshift.js +++ b/packages/core-js/modules/es.array.unshift.js @@ -34,8 +34,6 @@ $({ target: 'Array', proto: true, arity: 1, forced: INCORRECT_RESULT || SILENT_O for (var j = 0; j < argCount; j++) { O[j] = arguments[j]; } - } - O.length = len + argCount; - return len; + } return O.length = len + argCount; } }); diff --git a/tests/pure/es.array.unshift.js b/tests/pure/es.array.unshift.js new file mode 100644 index 000000000000..329b03971091 --- /dev/null +++ b/tests/pure/es.array.unshift.js @@ -0,0 +1,20 @@ +import { DESCRIPTORS, STRICT } from '../helpers/constants'; + +import unshift from 'core-js-pure/es/array/virtual/unshift'; +import defineProperty from 'core-js-pure/es/object/define-property'; + +QUnit.test('Array#unshift', assert => { + assert.isFunction(unshift); + + assert.same(unshift.call([1], 0), 2, 'proper result'); + + if (DESCRIPTORS) { + assert.throws(() => unshift.call(defineProperty([], 'length', { writable: false }), 1), TypeError, 'now-writable length, with arg'); + assert.throws(() => unshift.call(defineProperty([], 'length', { writable: false })), TypeError, 'now-writable length, without arg'); + } + + if (STRICT) { + assert.throws(() => unshift.call(null), TypeError); + assert.throws(() => unshift.call(undefined), TypeError); + } +}); diff --git a/tests/tests/es.array.unshift.js b/tests/tests/es.array.unshift.js new file mode 100644 index 000000000000..d2ca83e1a412 --- /dev/null +++ b/tests/tests/es.array.unshift.js @@ -0,0 +1,24 @@ +import { DESCRIPTORS, STRICT } from '../helpers/constants'; + +const { defineProperty } = Object; + +QUnit.test('Array#unshift', assert => { + const { unshift } = Array.prototype; + assert.isFunction(unshift); + assert.arity(unshift, 1); + assert.name(unshift, 'unshift'); + assert.looksNative(unshift); + assert.nonEnumerable(Array.prototype, 'unshift'); + + assert.same(unshift.call([1], 0), 2, 'proper result'); + + if (DESCRIPTORS) { + assert.throws(() => unshift.call(defineProperty([], 'length', { writable: false }), 1), TypeError, 'now-writable length, with arg'); + assert.throws(() => unshift.call(defineProperty([], 'length', { writable: false })), TypeError, 'now-writable length, without arg'); + } + + if (STRICT) { + assert.throws(() => unshift.call(null), TypeError); + assert.throws(() => unshift.call(undefined), TypeError); + } +}); From 408971e1d9fac9dc668586cb4e98e50def41a221 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Fri, 10 Jun 2022 06:19:06 +0700 Subject: [PATCH 10/11] make it properly work in some old engines --- packages/core-js-compat/src/data.mjs | 2 +- packages/core-js/modules/es.array.push.js | 14 +++++++++----- packages/core-js/modules/es.array.unshift.js | 15 +++++++++------ tests/compat/tests.js | 12 ++++++------ tests/pure/es.array.push.js | 10 +++++----- tests/pure/es.array.unshift.js | 10 +++++----- tests/tests/es.array.push.js | 10 +++++----- tests/tests/es.array.unshift.js | 10 +++++----- 8 files changed, 45 insertions(+), 38 deletions(-) diff --git a/packages/core-js-compat/src/data.mjs b/packages/core-js-compat/src/data.mjs index aac76868740f..f92dd73c826d 100644 --- a/packages/core-js-compat/src/data.mjs +++ b/packages/core-js-compat/src/data.mjs @@ -349,7 +349,7 @@ export const data = { }, 'es.array.unshift': { chrome: '71', - firefox: '4', + firefox: '23', ie: '9', // bug with setting length fixed only in Safari TP // safari: '15.4', diff --git a/packages/core-js/modules/es.array.push.js b/packages/core-js/modules/es.array.push.js index e51342f2842c..7ebabe3c25ea 100644 --- a/packages/core-js/modules/es.array.push.js +++ b/packages/core-js/modules/es.array.push.js @@ -9,12 +9,16 @@ var INCORRECT_TO_LENGTH = fails(function () { return [].push.call({ length: 0x100000000 }, 1) !== 4294967297; }); -// V8 and Safari <= 15.4 +// V8 and Safari <= 15.4, FF < 23 throws InternalError // https://bugs.chromium.org/p/v8/issues/detail?id=12681 -var SILENT_ON_NON_WRITABLE_LENGTH = !fails(function () { - // eslint-disable-next-line es-x/no-object-defineproperty -- safe - Object.defineProperty([], 'length', { writable: false }).push(); -}); +var SILENT_ON_NON_WRITABLE_LENGTH = !function () { + try { + // eslint-disable-next-line es-x/no-object-defineproperty -- safe + Object.defineProperty([], 'length', { writable: false }).push(); + } catch (error) { + return error instanceof TypeError; + } +}(); // `Array.prototype.push` method // https://tc39.es/ecma262/#sec-array.prototype.push diff --git a/packages/core-js/modules/es.array.unshift.js b/packages/core-js/modules/es.array.unshift.js index f43cefd444c2..1823bffa462b 100644 --- a/packages/core-js/modules/es.array.unshift.js +++ b/packages/core-js/modules/es.array.unshift.js @@ -4,16 +4,19 @@ var toObject = require('../internals/to-object'); var lengthOfArrayLike = require('../internals/length-of-array-like'); var deletePropertyOrThrow = require('../internals/delete-property-or-throw'); var doesNotExceedSafeInteger = require('../internals/does-not-exceed-safe-integer'); -var fails = require('../internals/fails'); // IE8- var INCORRECT_RESULT = [].unshift(0) !== 1; -// V8 ~ Chrome < 71 and Safari <= 15.4 -var SILENT_ON_NON_WRITABLE_LENGTH = !fails(function () { - // eslint-disable-next-line es-x/no-object-defineproperty -- safe - Object.defineProperty([], 'length', { writable: false }).unshift(); -}); +// V8 ~ Chrome < 71 and Safari <= 15.4, FF < 23 throws InternalError +var SILENT_ON_NON_WRITABLE_LENGTH = !function () { + try { + // eslint-disable-next-line es-x/no-object-defineproperty -- safe + Object.defineProperty([], 'length', { writable: false }).unshift(); + } catch (error) { + return error instanceof TypeError; + } +}(); // `Array.prototype.unshift` method // https://tc39.es/ecma262/#sec-array.prototype.unshift diff --git a/tests/compat/tests.js b/tests/compat/tests.js index 4b60108aebe0..9487d6962cbe 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -428,9 +428,9 @@ GLOBAL.tests = { if ([].push.call({ length: 0x100000000 }, 1) !== 4294967297) return false; try { Object.defineProperty([], 'length', { writable: false }).push(); - return false; - } catch (error) { /* empty */ } - return true; + } catch (error) { + return error instanceof TypeError; + } }, 'es.array.reduce': function () { try { @@ -524,9 +524,9 @@ GLOBAL.tests = { if ([].unshift(0) !== 1) return false; try { Object.defineProperty([], 'length', { writable: false }).unshift(); - return false; - } catch (error) { /* empty */ } - return true; + } catch (error) { + return error instanceof TypeError; + } }, 'es.array-buffer.constructor': [ARRAY_BUFFER_SUPPORT, function () { try { diff --git a/tests/pure/es.array.push.js b/tests/pure/es.array.push.js index 5c37c99c4411..181ca92787c9 100644 --- a/tests/pure/es.array.push.js +++ b/tests/pure/es.array.push.js @@ -10,12 +10,12 @@ QUnit.test('Array#push', assert => { assert.same(push.call(object, 1), 0x100000001, 'proper ToLength #1'); assert.same(object[0x100000000], 1, 'proper ToLength #2'); - if (DESCRIPTORS) { - assert.throws(() => push.call(defineProperty([], 'length', { writable: false }), 1), TypeError, 'now-writable length, with arg'); - assert.throws(() => push.call(defineProperty([], 'length', { writable: false })), TypeError, 'now-writable length, without arg'); - } - if (STRICT) { + if (DESCRIPTORS) { + assert.throws(() => push.call(defineProperty([], 'length', { writable: false }), 1), TypeError, 'now-writable length, with arg'); + assert.throws(() => push.call(defineProperty([], 'length', { writable: false })), TypeError, 'now-writable length, without arg'); + } + assert.throws(() => push.call(null), TypeError); assert.throws(() => push.call(undefined), TypeError); } diff --git a/tests/pure/es.array.unshift.js b/tests/pure/es.array.unshift.js index 329b03971091..bca883a08380 100644 --- a/tests/pure/es.array.unshift.js +++ b/tests/pure/es.array.unshift.js @@ -8,12 +8,12 @@ QUnit.test('Array#unshift', assert => { assert.same(unshift.call([1], 0), 2, 'proper result'); - if (DESCRIPTORS) { - assert.throws(() => unshift.call(defineProperty([], 'length', { writable: false }), 1), TypeError, 'now-writable length, with arg'); - assert.throws(() => unshift.call(defineProperty([], 'length', { writable: false })), TypeError, 'now-writable length, without arg'); - } - if (STRICT) { + if (DESCRIPTORS) { + assert.throws(() => unshift.call(defineProperty([], 'length', { writable: false }), 1), TypeError, 'now-writable length, with arg'); + assert.throws(() => unshift.call(defineProperty([], 'length', { writable: false })), TypeError, 'now-writable length, without arg'); + } + assert.throws(() => unshift.call(null), TypeError); assert.throws(() => unshift.call(undefined), TypeError); } diff --git a/tests/tests/es.array.push.js b/tests/tests/es.array.push.js index 3dcc97317a1d..de0671ada6d6 100644 --- a/tests/tests/es.array.push.js +++ b/tests/tests/es.array.push.js @@ -14,12 +14,12 @@ QUnit.test('Array#push', assert => { assert.same(push.call(object, 1), 0x100000001, 'proper ToLength #1'); assert.same(object[0x100000000], 1, 'proper ToLength #2'); - if (DESCRIPTORS) { - assert.throws(() => push.call(defineProperty([], 'length', { writable: false }), 1), TypeError, 'now-writable length, with arg'); - assert.throws(() => push.call(defineProperty([], 'length', { writable: false })), TypeError, 'now-writable length, without arg'); - } - if (STRICT) { + if (DESCRIPTORS) { + assert.throws(() => push.call(defineProperty([], 'length', { writable: false }), 1), TypeError, 'now-writable length, with arg'); + assert.throws(() => push.call(defineProperty([], 'length', { writable: false })), TypeError, 'now-writable length, without arg'); + } + assert.throws(() => push.call(null), TypeError); assert.throws(() => push.call(undefined), TypeError); } diff --git a/tests/tests/es.array.unshift.js b/tests/tests/es.array.unshift.js index d2ca83e1a412..332a69636e0a 100644 --- a/tests/tests/es.array.unshift.js +++ b/tests/tests/es.array.unshift.js @@ -12,12 +12,12 @@ QUnit.test('Array#unshift', assert => { assert.same(unshift.call([1], 0), 2, 'proper result'); - if (DESCRIPTORS) { - assert.throws(() => unshift.call(defineProperty([], 'length', { writable: false }), 1), TypeError, 'now-writable length, with arg'); - assert.throws(() => unshift.call(defineProperty([], 'length', { writable: false })), TypeError, 'now-writable length, without arg'); - } - if (STRICT) { + if (DESCRIPTORS) { + assert.throws(() => unshift.call(defineProperty([], 'length', { writable: false }), 1), TypeError, 'now-writable length, with arg'); + assert.throws(() => unshift.call(defineProperty([], 'length', { writable: false })), TypeError, 'now-writable length, without arg'); + } + assert.throws(() => unshift.call(null), TypeError); assert.throws(() => unshift.call(undefined), TypeError); } From 19f126a1da30f8164d996c584ccbe6ae332d6c0a Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Fri, 10 Jun 2022 17:11:43 +0700 Subject: [PATCH 11/11] disable some test262 tests --- tests/test262.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/test262.js b/tests/test262.js index f608b0ce48a0..f59a9547cc60 100644 --- a/tests/test262.js +++ b/tests/test262.js @@ -46,12 +46,16 @@ const exclude = [ '/ArrayBuffer/prototype/transfer/', '/Function/prototype/toString/', '/Object/internals/DefineOwnProperty/', - '/Object/prototype/toString/symbol-tag-non-str-builtin', // conflict with iterators helpers proposal + // conflict with iterators helpers proposal + '/Object/prototype/toString/symbol-tag-non-str-builtin', '/RegExp/property-escapes/', 'resizable-buffer', 'resize-arraybuffer', 'detached-buffer', 'detach-typedarray', + // we can't implement this behavior on methods 100% proper and compatible with ES3 + // in case of application some hacks this line will be removed + 'not-a-constructor', ]; module.exports = test => {