From 33568b6753a0784b1accbd91ce7bde15e79c7e0f Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Sat, 25 Jun 2022 01:07:11 +0700 Subject: [PATCH] change the order of operations in `%TypedArray%.prototype.toSpliced` https://github.com/tc39/proposal-change-array-by-copy/issues/89 --- CHANGELOG.md | 1 + .../core-js/internals/array-to-spliced.js | 36 --------------- .../core-js/internals/is-big-int-array.js | 8 ++++ .../modules/esnext.array.to-spliced.js | 35 ++++++++++++-- .../modules/esnext.typed-array.to-spliced.js | 46 +++++++++++++++++-- .../modules/esnext.typed-array.with.js | 10 ++-- 6 files changed, 84 insertions(+), 52 deletions(-) delete mode 100644 packages/core-js/internals/array-to-spliced.js create mode 100644 packages/core-js/internals/is-big-int-array.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 61685f0ca3f4..d86339dc5355 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## Changelog ##### Unreleased +- Changed the order of operations in `%TypedArray%.prototype.toSpliced` following [proposal-change-array-by-copy/89](https://github.com/tc39/proposal-change-array-by-copy/issues/89) - Fixed regression of some IE8- issues ##### [3.23.2 - 2022.06.21](https://github.com/zloirock/core-js/releases/tag/v3.23.2) diff --git a/packages/core-js/internals/array-to-spliced.js b/packages/core-js/internals/array-to-spliced.js deleted file mode 100644 index 52862d8f9e17..000000000000 --- a/packages/core-js/internals/array-to-spliced.js +++ /dev/null @@ -1,36 +0,0 @@ -var lengthOfArrayLike = require('../internals/length-of-array-like'); -var doesNotExceedSafeInteger = require('../internals/does-not-exceed-safe-integer'); -var toAbsoluteIndex = require('../internals/to-absolute-index'); -var toIntegerOrInfinity = require('../internals/to-integer-or-infinity'); - -var max = Math.max; -var min = Math.min; - -// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.toSpliced -// https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.toSpliced -module.exports = function (O, C, args) { - var start = args[0]; - var deleteCount = args[1]; - var len = lengthOfArrayLike(O); - var actualStart = toAbsoluteIndex(start, len); - var argumentsLength = args.length; - var k = 0; - var insertCount, actualDeleteCount, newLen, A; - if (argumentsLength === 0) { - insertCount = actualDeleteCount = 0; - } else if (argumentsLength === 1) { - insertCount = 0; - actualDeleteCount = len - actualStart; - } else { - insertCount = argumentsLength - 2; - actualDeleteCount = min(max(toIntegerOrInfinity(deleteCount), 0), len - actualStart); - } - newLen = doesNotExceedSafeInteger(len + insertCount - actualDeleteCount); - A = new C(newLen); - - for (; k < actualStart; k++) A[k] = O[k]; - for (; k < actualStart + insertCount; k++) A[k] = args[k - actualStart + 2]; - for (; k < newLen; k++) A[k] = O[k + actualDeleteCount - insertCount]; - - return A; -}; diff --git a/packages/core-js/internals/is-big-int-array.js b/packages/core-js/internals/is-big-int-array.js new file mode 100644 index 000000000000..3d5559e2beed --- /dev/null +++ b/packages/core-js/internals/is-big-int-array.js @@ -0,0 +1,8 @@ +var classof = require('../internals/classof'); +var uncurryThis = require('../internals/function-uncurry-this'); + +var slice = uncurryThis(''.slice); + +module.exports = function (it) { + return slice(classof(it), 0, 3) === 'Big'; +}; diff --git a/packages/core-js/modules/esnext.array.to-spliced.js b/packages/core-js/modules/esnext.array.to-spliced.js index 628d14ec85fa..3315eff70f58 100644 --- a/packages/core-js/modules/esnext.array.to-spliced.js +++ b/packages/core-js/modules/esnext.array.to-spliced.js @@ -1,18 +1,43 @@ 'use strict'; var $ = require('../internals/export'); -var toIndexedObject = require('../internals/to-indexed-object'); -var arraySlice = require('../internals/array-slice'); -var arrayToSpliced = require('../internals/array-to-spliced'); var addToUnscopables = require('../internals/add-to-unscopables'); +var doesNotExceedSafeInteger = require('../internals/does-not-exceed-safe-integer'); +var lengthOfArrayLike = require('../internals/length-of-array-like'); +var toAbsoluteIndex = require('../internals/to-absolute-index'); +var toIndexedObject = require('../internals/to-indexed-object'); +var toIntegerOrInfinity = require('../internals/to-integer-or-infinity'); var $Array = Array; +var max = Math.max; +var min = Math.min; // `Array.prototype.toSpliced` method // https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.toSpliced $({ target: 'Array', proto: true, arity: 2 }, { - // eslint-disable-next-line no-unused-vars -- required for .length toSpliced: function toSpliced(start, deleteCount /* , ...items */) { - return arrayToSpliced(toIndexedObject(this), $Array, arraySlice(arguments)); + var O = toIndexedObject(this); + var len = lengthOfArrayLike(O); + var actualStart = toAbsoluteIndex(start, len); + var argumentsLength = arguments.length; + var k = 0; + var insertCount, actualDeleteCount, newLen, A; + if (argumentsLength === 0) { + insertCount = actualDeleteCount = 0; + } else if (argumentsLength === 1) { + insertCount = 0; + actualDeleteCount = len - actualStart; + } else { + insertCount = argumentsLength - 2; + actualDeleteCount = min(max(toIntegerOrInfinity(deleteCount), 0), len - actualStart); + } + newLen = doesNotExceedSafeInteger(len + insertCount - actualDeleteCount); + A = $Array(newLen); + + for (; k < actualStart; k++) A[k] = O[k]; + for (; k < actualStart + insertCount; k++) A[k] = arguments[k - actualStart + 2]; + for (; k < newLen; k++) A[k] = O[k + actualDeleteCount - insertCount]; + + return A; } }); diff --git a/packages/core-js/modules/esnext.typed-array.to-spliced.js b/packages/core-js/modules/esnext.typed-array.to-spliced.js index cb66dffb6f53..f6779975a0a5 100644 --- a/packages/core-js/modules/esnext.typed-array.to-spliced.js +++ b/packages/core-js/modules/esnext.typed-array.to-spliced.js @@ -1,15 +1,51 @@ 'use strict'; var ArrayBufferViewCore = require('../internals/array-buffer-view-core'); -var arraySlice = require('../internals/array-slice'); -var arrayToSpliced = require('../internals/array-to-spliced'); +var isBigIntArray = require('../internals/is-big-int-array'); +var lengthOfArrayLike = require('../internals/length-of-array-like'); +var toAbsoluteIndex = require('../internals/to-absolute-index'); +var toBigInt = require('../internals/to-big-int'); +var toIntegerOrInfinity = require('../internals/to-integer-or-infinity'); +var uncurryThis = require('../internals/function-uncurry-this'); var aTypedArray = ArrayBufferViewCore.aTypedArray; var getTypedArrayConstructor = ArrayBufferViewCore.getTypedArrayConstructor; var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod; +var push = uncurryThis([].push); +var max = Math.max; +var min = Math.min; // `%TypedArray%.prototype.toSpliced` method // https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.toSpliced -// eslint-disable-next-line no-unused-vars -- required for .length exportTypedArrayMethod('toSpliced', function toSpliced(start, deleteCount /* , ...items */) { - return arrayToSpliced(aTypedArray(this), getTypedArrayConstructor(this), arraySlice(arguments)); -}, { arity: 2 }); + var O = aTypedArray(this); + var C = getTypedArrayConstructor(O); + var len = lengthOfArrayLike(O); + var actualStart = toAbsoluteIndex(start, len); + var argumentsLength = arguments.length; + var convertedItems = []; + var k = 0; + var insertCount, actualDeleteCount, newLen, A; + if (argumentsLength === 0) { + insertCount = actualDeleteCount = 0; + } else if (argumentsLength === 1) { + insertCount = 0; + actualDeleteCount = len - actualStart; + } else { + actualDeleteCount = min(max(toIntegerOrInfinity(deleteCount), 0), len - actualStart); + insertCount = argumentsLength - 2; + if (insertCount) { + var IS_BIG_INT = isBigIntArray(O); + for (var i = 2; i < argumentsLength; i++) { + push(convertedItems, IS_BIG_INT ? toBigInt(arguments[i]) : +arguments[i]); + } + } + } + newLen = len + insertCount - actualDeleteCount; + A = new C(newLen); + + for (; k < actualStart; k++) A[k] = O[k]; + for (; k < actualStart + insertCount; k++) A[k] = convertedItems[k - actualStart]; + for (; k < newLen; k++) A[k] = O[k + actualDeleteCount - insertCount]; + + return A; +}); diff --git a/packages/core-js/modules/esnext.typed-array.with.js b/packages/core-js/modules/esnext.typed-array.with.js index 31768c7de892..e2cab009bde4 100644 --- a/packages/core-js/modules/esnext.typed-array.with.js +++ b/packages/core-js/modules/esnext.typed-array.with.js @@ -1,15 +1,13 @@ 'use strict'; var arrayWith = require('../internals/array-with'); var ArrayBufferViewCore = require('../internals/array-buffer-view-core'); +var isBigIntArray = require('../internals/is-big-int-array'); var toIntegerOrInfinity = require('../internals/to-integer-or-infinity'); var toBigInt = require('../internals/to-big-int'); -var classof = require('../internals/classof'); -var uncurryThis = require('../internals/function-uncurry-this'); var aTypedArray = ArrayBufferViewCore.aTypedArray; var getTypedArrayConstructor = ArrayBufferViewCore.getTypedArrayConstructor; var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod; -var slice = uncurryThis(''.slice); var PROPER_ORDER = !!function () { try { @@ -25,8 +23,8 @@ var PROPER_ORDER = !!function () { // `%TypedArray%.prototype.with` method // https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.with exportTypedArrayMethod('with', { 'with': function (index, value) { - aTypedArray(this); + var O = aTypedArray(this); var relativeIndex = toIntegerOrInfinity(index); - var actualValue = slice(classof(this), 0, 3) === 'Big' ? toBigInt(value) : +value; - return arrayWith(this, getTypedArrayConstructor(this), relativeIndex, actualValue); + var actualValue = isBigIntArray(O) ? toBigInt(value) : +value; + return arrayWith(O, getTypedArrayConstructor(O), relativeIndex, actualValue); } }['with'], !PROPER_ORDER);