diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ecad99a4446..a60498d79b1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ - `%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 +- 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/README.md b/README.md index 498d1f1dcf15..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.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; @@ -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 @@ -667,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 }; @@ -706,6 +708,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 @@ -713,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 @@ -735,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 @@ -742,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): diff --git a/packages/core-js-compat/src/data.mjs b/packages/core-js-compat/src/data.mjs index e2e149e11d8e..f92dd73c826d 100644 --- a/packages/core-js-compat/src/data.mjs +++ b/packages/core-js-compat/src/data.mjs @@ -274,6 +274,14 @@ export const data = { safari: '9.0', rhino: '1.7.13', }, + 'es.array.push': { + // bug with setting length + // chrome: '103', + // edge: '15', + firefox: '55', + // 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 firefox: '4', @@ -339,6 +347,13 @@ export const data = { firefox: '67', safari: '13', }, + 'es.array.unshift': { + chrome: '71', + firefox: '23', + 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 67a6d43c9444..e7ca94d4ae60 100644 --- a/packages/core-js-compat/src/modules-by-versions.mjs +++ b/packages/core-js-compat/src/modules-by-versions.mjs @@ -142,6 +142,8 @@ export default { 3.23: [ '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/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/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/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/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/index.js b/packages/core-js/es/array/index.js index 668f4da0f367..a7289e10f1a9 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'); @@ -30,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/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/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/index.js b/packages/core-js/es/array/virtual/index.js index 1ed5fd3a4685..6aa118e5c98d 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'); @@ -27,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/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/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/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/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/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/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/modules/es.array.push.js b/packages/core-js/modules/es.array.push.js new file mode 100644 index 000000000000..7ebabe3c25ea --- /dev/null +++ b/packages/core-js/modules/es.array.push.js @@ -0,0 +1,39 @@ +'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'); + +var INCORRECT_TO_LENGTH = fails(function () { + return [].push.call({ length: 0x100000000 }, 1) !== 4294967297; +}); + +// 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 = !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 +$({ 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; + doesNotExceedSafeInteger(len + argCount); + for (var i = 0; i < argCount; i++) { + O[len] = arguments[i]; + len++; + } + O.length = len; + return len; + } +}); 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..1823bffa462b --- /dev/null +++ b/packages/core-js/modules/es.array.unshift.js @@ -0,0 +1,42 @@ +'use strict'; +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'); + +// IE8- +var INCORRECT_RESULT = [].unshift(0) !== 1; + +// 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 +$({ 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 deletePropertyOrThrow(O, to); + } + for (var j = 0; j < argCount; j++) { + O[j] = arguments[j]; + } + } return O.length = len + argCount; + } +}); 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/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/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/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 3709e87cad39..649b96dcb863 100644 --- a/tests/commonjs.mjs +++ b/tests/commonjs.mjs @@ -72,11 +72,13 @@ 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'); 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')([])); @@ -101,11 +103,13 @@ 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'); 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([])); @@ -465,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); @@ -551,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); diff --git a/tests/compat/tests.js b/tests/compat/tests.js index ada5e19ae6a5..9487d6962cbe 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(); + } catch (error) { + return error instanceof TypeError; + } + }, 'es.array.reduce': function () { try { Array.prototype.reduce.call(null, function () { /* empty */ }, 1); @@ -512,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(); + } catch (error) { + return error instanceof TypeError; + } + }, 'es.array-buffer.constructor': [ARRAY_BUFFER_SUPPORT, function () { try { return !ArrayBuffer(1); diff --git a/tests/pure/es.array.push.js b/tests/pure/es.array.push.js new file mode 100644 index 000000000000..181ca92787c9 --- /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 (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 new file mode 100644 index 000000000000..bca883a08380 --- /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 (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/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 => { diff --git a/tests/tests/es.array.push.js b/tests/tests/es.array.push.js new file mode 100644 index 000000000000..de0671ada6d6 --- /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 (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 new file mode 100644 index 000000000000..332a69636e0a --- /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 (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); + } +});