Stage 2 Draft / August 1, 2023

Change Array by copy

1 Indexed Collections

1.1 Array Objects

1.1.1 Properties of the Array Prototype Object

1.1.1.1 Array.prototype.sort ( comparefn )

When the sort method is called, the following steps are taken:

  1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception.
  2. Let obj be ? ToObject(this value).
  3. Let len be ? LengthOfArrayLike(obj).
  4. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparefn and performs the following steps when called:
    1. If x and y are both undefined, return +0𝔽.
    2. If x is undefined, return 1𝔽.
    3. If y is undefined, return -1𝔽.
    4. If comparefn is not undefined, then
      1. Let v be ? ToNumber(? Call(comparefn, undefined, « x, y »)).
      2. If v is NaN, return +0𝔽.
      3. Return v.
    5. [id="step-sortcompare-tostring-x"] Let xString be ? ToString(x).
    6. [id="step-sortcompare-tostring-y"] Let yString be ? ToString(y).
    7. Let xSmaller be ! IsLessThan(xString, yString, true).
    8. If xSmaller is true, return -1𝔽.
    9. Let ySmaller be ! IsLessThan(yString, xString, true).
    10. If ySmaller is true, return 1𝔽.
    11. Return +0𝔽.
    12. Return ? CompareArrayElements(x, y, comparefn).
  5. Return ? SortIndexedProperties(obj, len, SortCompare).
  6. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, true).
  7. Let itemCount be the number of elements in sortedList.
  8. Let j be 0.
  9. Repeat, while j < itemCount,
    1. Perform ? Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. NOTE: The call to SortIndexedProperties in step 6 has the skipHoles parameter set to true. The remaining indexes are deleted to preserve the number of holes that were detected and excluded from the sort.
  11. Repeat, while j < len,
    1. Perform ? DeletePropertyOrThrow(obj, ! ToString(𝔽(j))).
    2. Set j to j + 1.
  12. Return obj.

1.1.1.2 CompareArrayElements ( x, y, comparefn )

The abstract operation CompareArrayElements takes arguments x, y, and comparefn (a function object or undefined) and returns either a normal completion containing a Number or an abrupt completion. It performs the following steps when called:

  1. If x and y are both undefined, return +0𝔽.
  2. If x is undefined, return 1𝔽.
  3. If y is undefined, return -1𝔽.
  4. If comparefn is not undefined, then
    1. Let v be ? ToNumber(? Call(comparefn, undefined, « x, y »)).
    2. If v is NaN, return +0𝔽.
    3. Return v.
  5. Let xString be ? ToString(x).
  6. Let yString be ? ToString(y).
  7. Let xSmaller be ! IsLessThan(xString, yString, true).
  8. If xSmaller is true, return -1𝔽.
  9. Let ySmaller be ! IsLessThan(yString, xString, true).
  10. If ySmaller is true, return 1𝔽.
  11. Return +0𝔽.

1.1.1.3 SortIndexedProperties ( obj, len, SortCompare, skipHoles )

The abstract operation SortIndexedProperties takes arguments obj (an Object), len (a non-negative integer), SortCompare (an Abstract Closure with two parameters), and skipHoles (a Boolean) and returns either a normal completion containing an Objecta List or an abrupt completion. It performs the following steps when called:

  1. Let items be a new empty List.
  2. Let k be 0.
  3. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kPresent be ? HasProperty(obj, Pk).
    3. If skipHoles is true, then
      1. Let kRead be ? HasProperty(obj, Pk).
    4. Else,
      1. Let kRead be true.
    5. If kPresentkRead is true, then
      1. Let kValue be ? Get(obj, Pk).
      2. Append kValue to items.
    6. Set k to k + 1.
  4. Let itemCount be the number of elements in items.
  5. Sort items using an implementation-defined sequence of calls to SortCompare. If any such call returns an abrupt completion, stop before performing any further calls to SortCompare or steps in this algorithm and return that Completion Record.
  6. Let j be 0.
  7. Repeat, while j < itemCount,
    1. Perform ? Set(obj, ! ToString(𝔽(j)), items[j], true).
    2. Set j to j + 1.
  8. Repeat, while j < len,
    1. Perform ? DeletePropertyOrThrow(obj, ! ToString(𝔽(j))).
    2. Set j to j + 1.
  9. Return obj.
  10. Return items.

1.1.1.4 Array.prototype.toReversed ( )

When the toReversed method is called, the following steps are taken:

  1. Let O be ? ToObject(this value).
  2. Let len be ? LengthOfArrayLike(O).
  3. Let A be ? ArrayCreate(𝔽(len)).
  4. Let k be 0.
  5. Repeat, while k < len,
    1. Let from be ! ToString(𝔽(len - k - 1)).
    2. Let Pk be ! ToString(𝔽(k)).
    3. Let fromValue be ? Get(O, from).
    4. Perform ! CreateDataPropertyOrThrow(A, Pk, fromValue).
    5. Set k to k + 1.
  6. Return A.

1.1.1.5 Array.prototype.toSorted ( comparefn )

When the toSorted method is called, the following steps are taken:

  1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception.
  2. Let O be ? ToObject(this value).
  3. Let len be ? LengthOfArrayLike(O).
  4. Let A be ? ArrayCreate(𝔽(len)).
  5. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparefn and performs the following steps when called:
    1. Return ? CompareArrayElements(x, y, comparefn).
  6. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, false).
  7. Let j be 0.
  8. Repeat, while j < len,
    1. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(j)), sortedList[j]).
    2. Set j to j + 1.
  9. Return A.

1.1.1.6 Array.prototype.toSpliced ( start, deleteCount, ...items )

When the toSpliced method is called, the following steps are taken:

  1. Let O be ? ToObject(this value).
  2. Let len be ? LengthOfArrayLike(O).
  3. Let relativeStart be ? ToIntegerOrInfinity(start).
  4. If relativeStart is -∞, let actualStart be 0.
  5. Else if relativeStart < 0, let actualStart be max(len + relativeStart, 0).
  6. Else, let actualStart be min(relativeStart, len).
  7. Let insertCount be the number of elements in items.
  8. If start is not present, then
    1. Let actualDeleteCount be 0.
  9. Else if deleteCount is not present, then
    1. Let actualDeleteCount be len - actualStart.
  10. Else,
    1. Let dc be ? ToIntegerOrInfinity(deleteCount).
    2. Let actualDeleteCount be the result of clamping dc between 0 and len - actualStart.
  11. Let newLen be len + insertCount - actualDeleteCount.
  12. If newLen > 253 - 1, throw a TypeError exception.
  13. Let A be ? ArrayCreate(𝔽(newLen)).
  14. Let i be 0.
  15. Let r be actualStart + actualDeleteCount.
  16. Repeat, while i < actualStart,
    1. Let Pi be ! ToString(𝔽(i)).
    2. Let iValue be ? Get(O, Pi).
    3. Perform ! CreateDataPropertyOrThrow(A, Pi, iValue).
    4. Set i to i + 1.
  17. For each element E of items, do
    1. Let Pi be ! ToString(𝔽(i)).
    2. Perform ! CreateDataPropertyOrThrow(A, Pi, E).
    3. Set i to i + 1.
  18. Repeat, while i < newLen,
    1. Let Pi be ! ToString(𝔽(i)).
    2. Let from be ! ToString(𝔽(r)).
    3. Let fromValue be ? Get(O, from).
    4. Perform ! CreateDataPropertyOrThrow(A, Pi, fromValue).
    5. Set i to i + 1.
    6. Set r to r + 1.
  19. Return A.

1.1.1.7 Array.prototype.with ( index, value )

When the with method is called, the following steps are taken:

  1. Let O be ? ToObject(this value).
  2. Let len be ? LengthOfArrayLike(O).
  3. Let relativeIndex be ? ToIntegerOrInfinity(index).
  4. If relativeIndex ≥ 0, let actualIndex be relativeIndex.
  5. Else, let actualIndex be len + relativeIndex.
  6. If actualIndexlen or actualIndex < 0, throw a RangeError exception.
  7. Let A be ? ArrayCreate(𝔽(len)).
  8. Let k be 0.
  9. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. If k is actualIndex, let fromValue be value.
    3. Else, let fromValue be ? Get(O, Pk).
    4. Perform ! CreateDataPropertyOrThrow(A, Pk, fromValue).
    5. Set k to k + 1.
  10. Return A.

1.1.1.8 Array.prototype [ @@unscopables ]

The initial value of the @@unscopables data property is an object created by the following steps:

  1. Let unscopableList be ! OrdinaryObjectCreate(null).
  2. Perform ! CreateDataPropertyOrThrow(unscopableList, "at", true).
  3. Perform ! CreateDataPropertyOrThrow(unscopableList, "copyWithin", true).
  4. Perform ! CreateDataPropertyOrThrow(unscopableList, "entries", true).
  5. Perform ! CreateDataPropertyOrThrow(unscopableList, "fill", true).
  6. Perform ! CreateDataPropertyOrThrow(unscopableList, "find", true).
  7. Perform ! CreateDataPropertyOrThrow(unscopableList, "findIndex", true).
  8. Perform ! CreateDataPropertyOrThrow(unscopableList, "flat", true).
  9. Perform ! CreateDataPropertyOrThrow(unscopableList, "flatMap", true).
  10. Perform ! CreateDataPropertyOrThrow(unscopableList, "includes", true).
  11. Perform ! CreateDataPropertyOrThrow(unscopableList, "keys", true).
  12. Perform ! CreateDataPropertyOrThrow(unscopableList, "toReversed", true).
  13. Perform ! CreateDataPropertyOrThrow(unscopableList, "toSorted", true).
  14. Perform ! CreateDataPropertyOrThrow(unscopableList, "toSpliced", true).
  15. Perform ! CreateDataPropertyOrThrow(unscopableList, "values", true).
  16. Return unscopableList.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

Note

The reason that "with" is not included in the unscopableList is because it is already a reserved word.

1.2 TypedArray Objects

1.2.1 Abstract Operations for TypedArray Objects

1.2.1.1 TypedArrayCreateSameType ( exemplar, argumentList )

The abstract operation TypedArrayCreateSameType takes arguments exemplar (a TypedArray) and argumentList. It is used to specify the creation of a new TypedArray using a constructor function that is derived from exemplar. Unlike TypedArraySpeciesCreate, which can construct custom TypedArray subclasses through the use of @@species, this operation always uses one of the built-in TypedArray constructors. It performs the following steps when called:

  1. Assert: exemplar is an Object that has [[TypedArrayName]] and [[ContentType]] internal slots.
  2. Let constructor be the intrinsic object listed in column one of Table 63 for exemplar.[[TypedArrayName]].
  3. Let result be ? TypedArrayCreate(constructor, argumentList).
  4. Assert: result has [[TypedArrayName]] and [[ContentType]] internal slots.
  5. Assert: result.[[ContentType]] is exemplar.[[ContentType]].
  6. Return result.

1.2.2 The %TypedArray% Intrinsic Object

1.2.2.1 Properties of the %TypedArray% Prototype Object

1.2.2.1.1 %TypedArray%.prototype.sort ( comparefn )

The following steps are performed:

  1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Perform ? ValidateTypedArray(obj).
  4. Let len be obj.[[ArrayLength]].
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 1.1.1.1.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparefn and performs the following steps when called:
    1. Assert: x is a Number and y is a Number, or x is a BigInt and y is a BigInt.
    2. If comparefn is not undefined, then
      1. Let v be ? ToNumber(? Call(comparefn, undefined, « x, y »)).
      2. If v is NaN, return +0𝔽.
      3. Return v.
    3. If x and y are both NaN, return +0𝔽.
    4. If x is NaN, return 1𝔽.
    5. If y is NaN, return -1𝔽.
    6. If x < y, return -1𝔽.
    7. If x > y, return 1𝔽.
    8. If x is -0𝔽 and y is +0𝔽, return -1𝔽.
    9. If x is +0𝔽 and y is -0𝔽, return 1𝔽.
    10. Return +0𝔽.
    11. Return ? CompareTypedArrayElements(x, y, comparefn).
  7. Return ? SortIndexedProperties(obj, len, SortCompare).
  8. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, false).
  9. Let j be 0.
  10. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  11. Return obj.

1.2.2.1.2 CompareTypedArrayElements ( x, y, comparefn )

The abstract operation CompareTypedArrayElements takes arguments x, y, and comparefn (a function object or undefined) and returns either a normal completion containing a Number or an abrupt completion. It performs the following steps when called:

  1. Assert: x is a Number and y is a Number, or x is a BigInt and y is a BigInt.
  2. If comparefn is not undefined, then
    1. Let v be ? ToNumber(? Call(comparefn, undefined, « x, y »)).
    2. If v is NaN, return +0𝔽.
    3. Return v.
  3. If x and y are both NaN, return +0𝔽.
  4. If x is NaN, return 1𝔽.
  5. If y is NaN, return -1𝔽.
  6. If x < y, return -1𝔽.
  7. If x > y, return 1𝔽.
  8. If x is -0𝔽 and y is +0𝔽, return -1𝔽.
  9. If x is +0𝔽 and y is -0𝔽, return 1𝔽.
  10. Return +0𝔽.
Note
This performs a numeric comparison rather than the string comparison used in 1.1.1.2.

1.2.2.1.3 %TypedArray%.prototype.toReversed ( )

When the toReversed method is called, the following steps are taken:

  1. Let O be the this value.
  2. Perform ? ValidateTypedArray(O).
  3. Let length be O.[[ArrayLength]].
  4. Let A be ? TypedArrayCreateSameType(O, « 𝔽(length) »).
  5. Let k be 0.
  6. Repeat, while k < length,
    1. Let from be ! ToString(𝔽(length - k - 1)).
    2. Let Pk be ! ToString(𝔽(k)).
    3. Let fromValue be ! Get(O, from).
    4. Perform ! Set(A, Pk, fromValue, true).
    5. Set k to k + 1.
  7. Return A.

1.2.2.1.4 %TypedArray%.prototype.toSorted ( comparefn )

When the toSorted method is called, the following steps are taken:

  1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception.
  2. Let O be the this value.
  3. Perform ? ValidateTypedArray(O).
  4. Let len be O.[[ArrayLength]].
  5. Let A be ? TypedArrayCreateSameType(O, « 𝔽(len) »).
  6. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 1.1.1.5.
  7. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparefn and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparefn).
  8. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, false).
  9. Let j be 0.
  10. Repeat, while j < len,
    1. Perform ! Set(A, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  11. Return A.

1.2.2.1.5 %TypedArray%.prototype.with ( index, value )

When the with method is called, the following steps are taken:

  1. Let O be the this value.
  2. Perform ? ValidateTypedArray(O).
  3. Let len be O.[[ArrayLength]].
  4. Let relativeIndex be ? ToIntegerOrInfinity(index).
  5. If relativeIndex ≥ 0, let actualIndex be relativeIndex.
  6. Else, let actualIndex be len + relativeIndex.
  7. If O.[[ContentType]] is BigInt, set value to ? ToBigInt(value).
  8. Else, set value to ? ToNumber(value).
  9. If ! IsValidIntegerIndex(O, 𝔽(actualIndex)) is false, throw a RangeError exception.
  10. Let A be ? TypedArrayCreateSameType(O, « 𝔽(len) »).
  11. Let k be 0.
  12. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. If k is actualIndex, let fromValue be value.
    3. Else, let fromValue be ! Get(O, Pk).
    4. Perform ! Set(A, Pk, fromValue, true).
    5. Set k to k + 1.
  13. Return A.

A Copyright & Software License

Copyright Notice

© 2023 Robin Ricard, Ashley Claymore

Software License

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.