This proposal adds arbitrary-precision integers to ECMAScript. For motivation and a high-level introduction, see the explainer document.
I attempted to write this specification draft with an eye towards intelligibility and clarifying issues, rather than looking exactly like the final specification. In particular, the translation of the operations on the Number type into the new form are omitted, as they are identical to the previous definitions and would be expressed only as a lengthy refactoring to skip when reading this text.
If you find any part of this specification unclear or confusing, please file an issue.
1Numeric Types
ECMAScript has two built-in numeric types: Number and BigInt. In this specification, every numeric type T contains a multiplicative identity value denoted T::unit. The specification types also have the following abstract operations, likewise denoted T::op for a given operation with specification name op. Unless noted otherwise, argument and result types are all T.
Table 1: Numeric Type Operations
Invocation Synopsis
Value and Purpose
T::unaryMinus(x)
A specification function invoked when applying the unary minus operator. Called by the semantics of the unary - operator.
T::bitwiseNOT(x)
A specification function invoked when applying the bitwise NOT operator. Called by the semantics of the bitwise NOT operator for ~x.
T::exponentiate(x, y)
A specification function invoked when applying the exponentiation operator. Called by the semantics of the exponentiation operator for x ** y.
T::multiply(x, y)
A specification function invoked when applying the multiplication operator. Called by the semantics of the * operator for x * y.
T::divide(x, y)
A specification function invoked when applying the division operator. Called by the semantics of the / operator for x / y.
T::remainder(x, y)
A specification function invoked when applying the truncating remainder ("mod") operator. Called by the semantics of the % operator for x % y.
Revisit this name, as Number::remainder explicitly doesn't do the IEEE 754 remainder operation. However, modulo also seems problematic. (issue)
T::add(x, y)
A specification function invoked when applying the addition operator. Called by the semantics of the + operator for x + y.
T::subtract(x, y)
A specification function invoked when applying the subtraction operator. Called by the semantics of the - operator for x - y.
T::leftShift(x, y)
A specification function invoked when applying the left shift operator to two operands, both of type T. Called by the semantics of the << operator for x << y.
T::signedRightShift(x, y)
A specification function invoked when applying the right shift operator to two operands, both of type T. Called by the semantics of the >> operator for x >> y.
T::unsignedRightShift(x, y)
A specification function invoked when applying the right shift operator to two operands, both of type T. Called by the semantics of the >>> operator for x >>> y.
T::lessThan(x, y)
A specification function invoked when applying one of the four partial-order relational operators. The return value must be false, true, or undefined (for unordered inputs). Called by the Abstract Relational Comparison algorithm for x < y, x > y, x <= y, and x >= y.
T::equal(x, y)
A specification function invoked when applying equality operators. The return value must be false or true. Called by the Strict Equality Comparison algorithm for x == y, x != y, x === y, and x !== y.
T::sameValue(x, y)
A specification function invoked when applying abstract operation SameValue. The return value must be false or true. Called from Object internal methods to test exact value equality. May not throw an exception.
T::sameValueZero(x, y)
A specification function invoked when applying abstract operation SameValueZero. The return value must be false or true. Called from Array, Map, and Set methods to test value equality ignoring differences among members of the zero cohort (e.g., -0 and +0). May not throw an exception.
The T::unit value and T::op operations are not a part of the ECMAScript language; they are defined here solely to aid the specification of the semantics of the ECMAScript language. Other abstract operations are defined throughout this specification.
Because the numeric types are in general not convertible without loss of precision or truncation, the ECMAScript language provides no implicit conversion among these types. Programmers must explicitly call Number and BigInt functions to convert among types when calling a function which requires another type.
Note
The first and subsequent editions of ECMAScript have provided, for certain operators, implicit numeric conversions that could lose precision or truncate. These legacy implicit conversions are maintained for backward compatibility, but not provided for BigInt in order to minimize opportunity for programmer error, and to leave open the option of generalized value types in a future edition.
1.1The BigInt Type
The BigInt type represents a mathematical integer value. The value may be any size and is not limited to a particular bit-width. Generally, where not otherwise noted, operations are designed to return exact mathematically-based answers. For binary operations, BigInts act as two's complement binary strings, with negative numbers treated as having bits set infinitely to the left.
The BigInt::unit value is 1n.
1.1.1BigInt::unaryMinus (x)
The abstract operation BigInt::unaryMinus with an argument x of BigInt type returns the result of negating x.
Note
There is only one 0n value; -0n is the same as 0n.
1.1.2BigInt::bitwiseNOT (x)
The abstract operation BigInt::bitwiseNOT with an argument x of BigInt type returns the one's complement of x; that is, -x - 1.
1.1.3BigInt::exponentiate (base, exponent)
If exponent < 0, throw a RangeError exception.
If base is 0n and exponent is 0n, return 1n.
Return a BigInt representing the mathematical value of base raised to the power exponent.
1.1.4BigInt::multiply (x, y)
The abstract operation BigInt::multiply with two arguments x and y of BigInt type returns a BigInt representing the result of multiplying x and y.
Note
Even if the result has a much larger bit width than the input, the exact mathematical answer is given.
1.1.5BigInt::divide (x, y)
If y is 0n, throw a RangeError exception.
Let quotient be the mathematical value of x divided by y.
Return a BigInt representing quotient rounded towards 0 to the next integral value.
1.1.6BigInt::remainder (n, d)
If d is 0n, throw a RangeError exception.
If n is 0n, return 0n.
Let r be the BigInt defined by the mathematical relation r = n - (d × q) where q is a BigInt that is negative only if n/d is negative and positive only if n/d is positive, and whose magnitude is as large as possible without exceeding the magnitude of the true mathematical quotient of n and d.
Return r.
Note
The sign of the result equals the sign of the dividend.
1.1.7BigInt::add (x, y)
The abstract operation BigInt::add with two arguments x and y of BigInt type returns a BigInt representing the sum of x and y.
1.1.8BigInt::subtract (x, y)
The abstract operation BigInt::subtract with two arguments x and y of BigInt type returns the BigInt representing the difference x minus y.
1.1.9BigInt::leftShift (x, y)
The abstract operation BigInt::leftShift with two arguments x and y of BigInt:
If y < 0, then
Return a BigInt representing x ÷ 2-y, rounding down to the nearest integer, including for negative numbers.
Return a BigInt representing x × 2y.
Note
Semantics here should be equivalent to a bitwise shift, treating the BigInt as an infinite length string of binary two's complement digits.
1.1.10BigInt::signedRightShift (x, y)
The abstract operation BigInt::signedRightShift with arguments x and y of type BigInt:
Return BigInt::leftShift(x, -y).
1.1.11BigInt::unsignedRightShift (x, y)
The abstract operation BigInt::unsignedRightShift with two arguments x and y of type BigInt:
Throw a TypeError exception.
1.1.12BigInt::lessThan (x, y)
The abstract operation BigInt::lessThan with two arguments x and y of BigInt type returns true if x is less than y and false otherwise.
1.1.13BigInt::equal (x, y)
The abstract operation BigInt::equal with two arguments x and y of BigInt type returns true if x and y have the same mathematical integer value and false otherwise.
1.1.14BigInt::sameValue (x, y)
The abstract operation BigInt::sameValue with two arguments x and y of BigInt type:
Return BigInt::equal(x, y).
1.1.15BigInt::sameValueZero (x, y)
The abstract operation BigInt::sameValueZero with two arguments x and y of BigInt type:
Return BigInt::equal(x, y).
1.1.16BitwiseOp(op, x, y)
Let result be 0.
Let shift be 0.
Repeat, until (x = 0 or x = -1) and (y = 0 or y = -1),
Let result be result - 2shift. NOTE: This extends the sign.
Return result.
1.1.17BigInt::bitwiseAND (x, y)
Return BitwiseOp(&, x, y).
1.1.18BigInt::bitwiseXOR (x, y)
Return BitwiseOp(^, x, y).
1.1.19BigInt::bitwiseOR (x, y)
Return BitwiseOp(|, x, y).
As part of the integration with the main specification, the Number type will have a similar definition of operations, derived from the current operator definitions. Because the semantics are not proposed to change, for ease of review, the refactoring is omitted from this spec draft.
Although it would be possible to define a conversion here, to find the nearest Number for a BigInt, such a conversion may lose precision. ToNumber is called implicitly from so many places, but BigInts would not add any value if they lost precision all the time; you might as well just use Numbers instead in the first place. A key design decision of this specification is to disallow implicit conversions, and force programmers to use explicit conversions themselves instead.
The abstract operation RequireObjectCoercible throws an error if argument is a value that cannot be converted to an Object using ToObject. It is defined by Table 7:
The internal comparison abstract operation SameValue(x, y), where x and y are ECMAScript language values, produces true or false. Such a comparison is performed as follows:
If Type(x) is different from Type(y), return false.
The previous Number-related contents of this algorithm will be moved into Number::sameValue.
3.2.2SameValueZero ( x, y )
The internal comparison abstract operation SameValueZero(x, y), where x and y are ECMAScript language values, produces true or false. Such a comparison is performed as follows:
If Type(x) is different from Type(y), return false.
The previous Number-related contents of this algorithm will be moved into Number::sameValueZero.
3.2.3SameValueNonNumberNumeric ( x, y )
The internal comparison abstract operation SameValueNonNumeric(x, y), where neither x nor y are numeric type values, produces true or false. Such a comparison is performed as follows:
If x and y are exactly the same sequence of code units (same length and same code units at corresponding indices), return true; otherwise, return false.
If x and y are both the same Symbol value, return true; otherwise, return false.
If x and y are the same Object value, return true. Otherwise, return false.
3.2.4Abstract Relational Comparison
The comparison x < y, where x and y are values, produces true, false, or undefined (which indicates that at least one operand is NaN). In addition to x and y the algorithm takes a Boolean flag named LeftFirst as a parameter. The flag is used to control the order in which operations with potentially visible side-effects are performed upon x and y. It is necessary because ECMAScript specifies left to right evaluation of expressions. The default value of LeftFirst is true and indicates that the x parameter corresponds to an expression that occurs to the left of the y parameter's corresponding expression. If LeftFirst is false, the reverse is the case and operations must be performed upon y before x. Such a comparison is performed as follows:
If py is a prefix of px, return false. (A String value p is a prefix of String value q if q can be the result of concatenating p and some other String r. Note that any String is a prefix of itself, because r may be the empty String.)
If px is a prefix of py, return true.
Let k be the smallest nonnegative integer such that the code unit at index k within px is different from the code unit at index k within py. (There must be such a k, for neither String is a prefix of the other.)
Let m be the integer that is the code unit at index k within px.
Let n be the integer that is the code unit at index k within py.
If m < n, return true. Otherwise, return false.
Else,
Let nx be ? ToNumber(px). Because px and py are primitive values evaluation order is not important.
If nx and ny are the same Number value, return false.
If nx is +0 and ny is -0, return false.
If nx is -0 and ny is +0, return false.
If nx is +∞, return false.
If ny is +∞, return true.
If ny is -∞, return false.
If nx is -∞, return true.
If the mathematical value of nx is less than the mathematical value of ny —note that these mathematical values are both finite and not both zero—return true. Otherwise, return false.
If Type(px) is BigInt and Type(py) is String, then
The definition here is unchanged, and still uses ToNumber rather than ToNumeric. This means that + will throw on BigInts. The semantics here are designed to allow expressions of the form +x to always return Numbers, which is necessary to preserve assumptions made by asm.js.
4.2.3Unary - Operator
Note
The unary - operator converts its operand to Number type and then negates it. Negating +0 produces -0, and negating -0 produces +0.
No hint is provided in the calls to ToPrimitive in steps 5 and 6. All standard objects except Date objects handle the absence of a hint as if the hint Number were given; Date objects handle the absence of a hint as if the hint String were given. Exotic objects may handle the absence of a hint in some other manner.
Note 2
Step 7 differs from step 5 of the Abstract Relational Comparison algorithm, by using the logical-or operation instead of the logical-and operation.
Let shiftCount be the result of masking out all but the least significant 5 bits of rnum, that is, compute rnum & 0x1F.
Return the result of performing a sign-extending right shift of lnum by shiftCount bits. The most significant bit is propagated. The result is a signed 32-bit integer.
If Type(lnum) is different from Type(rnum), throw a TypeError exception.
Let shiftCount be the result of masking out all but the least significant 5 bits of rnum, that is, compute rnum & 0x1F.
Return the result of performing a zero-filling right shift of lnum by shiftCount bits. Vacated bits are filled with zero. The result is an unsigned 32-bit integer.
If Type(lnum) is different from Type(rnum), throw a TypeError exception.
Otherwise, @ is ^; return T::bitwiseXOR(lnum, rnum).
5BigInt Objects
5.1The BigInt Constructor
The BigInt constructor is the %BigInt% intrinsic object and the initial value of the BigInt property of the global object. When BigInt is called as a function, it performs a type conversion.
The BigInt constructor is not intended to be used with the new operator or to be subclassed. It may be used as the value of an extends clause of a class definition but a super call to the BigInt constructor will cause an exception.
Let mod be a BigInt representing bigintmodulo 2bits.
If mod ≥ 2bits - 1, return mod - 2bits; otherwise, return mod.
5.2.3BigInt.prototype
The initial value of BigInt.prototype is the intrinsic object %BigIntPrototype%.
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.
5.3Properties of the BigInt Prototype Object
The BigInt prototype object is the intrinsic object %BigIntPrototype%. The BigInt prototype object is an ordinary object. The BigInt prototype is not a BigInt object; it does not have a [[BigIntData]] internal slot.
The value of the [[Prototype]] internal slot of the BigInt prototype object is the intrinsic object %ObjectPrototype%.
The abstract operation thisBigIntValue(value) performs the following steps:
The phrase “this BigInt value” within the specification of a method refers to the result returned by calling the abstract operation thisBigIntValue with the this value of the method invocation passed as the argument.
5.3.1BigInt.prototype.constructor
The initial value of BigInt.prototype.constructor is the intrinsic object %BigInt%.
An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the BigInt.prototype.toLocaleString method as specified in the ECMA-402 specification. If an ECMAScript implementation does not include the ECMA-402 API the following specification of the toLocaleString method is used.
Produces a String value that represents this BigInt value formatted according to the conventions of the host environment's current locale. This function is implementation-dependent, and it is permissible, but not encouraged, for it to return the same thing as toString.
The meanings of the optional parameters to this method are defined in the ECMA-402 specification; implementations that do not include ECMA-402 support must not use those parameter positions for anything else.
5.3.3BigInt.prototype.toString ( [ radix ] )
Note
The optional radix should be an integer value in the inclusive range 2 to 36. If radix not present or is undefined the Number 10 is used as the value of radix.
The following steps are performed:
Let x be ? thisBigIntValue(this value).
If radix is not present, let radixNumber be 10.
Else if radix is undefined, let radixNumber be 10.
Return the String representation of this Number value using the radix specified by radixNumber. Letters a-z are used for digits with values 10 through 35. The precise algorithm is implementation-dependent, however the algorithm should be a generalization of that specified in 3.1.4.1.
The toString function is not generic; it throws a TypeError exception if its this value is not a BigInt or a BigInt object. Therefore, it cannot be transferred to other kinds of objects for use as a method.
5.3.4BigInt.prototype.valueOf ( )
Return ? thisBigIntValue(this value).
5.3.5BigInt.prototype [ @@toStringTag ]
The initial value of the @@toStringTag property is the String value "BigInt".
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
The abstract operation SerializeJSONProperty with arguments key, and holder has access to ReplacerFunction from the invocation of the stringify method. Its algorithm is as follows:
See 6.1.6 in the second-to-last paragraph for the definition of the phrase "The Number value for prim".
That paragraph should possibly be refactored into a separate abstract operation; see this bug for more discussion about the integration of different numeric types and casting operations between them.
BigInt is integrated into TypedArray, DataView, SharedArrayBuffer and Atomics by providing Int64 and Uint64 access as represented by BigInts on the ECMAScript side.
The abstract operation ToBigInt64 converts argument to one of 264 integer values in the range -263 through 263-1, inclusive. This abstract operation functions as follows:
The abstract operation ToBigUint64 converts argument to one of 264 integer values in the range 0 through 264-1, inclusive. This abstract operation functions as follows:
The abstract operation RawBytesToNumberNumeric takes three parameters, a String type, a ListrawBytes, and a Boolean isLittleEndian. This operation performs the following steps:
Let elementSize be the Number value of the Element Size value specified in Table 9 for Element Type type.
If isLittleEndian is false, reverse the order of the elements of rawBytes.
If type is "Float32", then
Let value be the byte elements of rawBytes concatenated and interpreted as a little-endian bit string encoding of an IEEE 754-2008 binary32 value.
If value is an IEEE 754-2008 binary32 NaN value, return the NaN Number value.
Return the Number value that corresponds to value.
If type is "Float64", then
Let value be the byte elements of rawBytes concatenated and interpreted as a little-endian bit string encoding of an IEEE 754-2008 binary64 value.
If value is an IEEE 754-2008 binary64 NaN value, return the NaN Number value.
Return the Number value that corresponds to value.
If the first code unit of type is "U" or type is "BigUint64", then
Let intValue be the byte elements of rawBytes concatenated and interpreted as a bit string encoding of an unsigned little-endian binary number.
Else,
Let intValue be the byte elements of rawBytes concatenated and interpreted as a bit string encoding of a binary little-endian two's complement number of bit length elementSize × 8.
If type is "BigUint64" or "BigInt64", return the BigInt value that corresponds to intValue.
Otherwise, return the Number value that corresponds to intValue.
The abstract operation NumberNumericToRawBytes takes three parameters, a String type, a BigInt or a Number value, and a Boolean isLittleEndian. This operation performs the following steps:
If type is "Float32", then
Set rawBytes to a List containing the 4 bytes that are the result of converting value to IEEE 754-2008 binary32 format using “Round to nearest, ties to even” rounding mode. If isLittleEndian is false, the bytes are arranged in big endian order. Otherwise, the bytes are arranged in little endian order. If value is NaN, rawValue may be set to any implementation chosen IEEE 754-2008 binary32 format Not-a-Number encoding. An implementation must always choose the same encoding for each implementation distinguishable NaN value.
Else if type is "Float64", then
Set rawBytes to a List containing the 8 bytes that are the IEEE 754-2008 binary64 format encoding of value. If isLittleEndian is false, the bytes are arranged in big endian order. Otherwise, the bytes are arranged in little endian order. If value is NaN, rawValue may be set to any implementation chosen IEEE 754-2008 binary64 format Not-a-Number encoding. An implementation must always choose the same encoding for each implementation distinguishable NaN value.
Else,
Let n be the Number value of the Element Size specified in Table 9 for Element Type type.
Let convOp be the abstract operation named in the Conversion Operation column in Table 9 for Element Type type.
Let intValue be convOp(value) treated as a mathematical value, whether the result is a BigInt or Number.
If intValue ≥ 0, then
Let rawBytes be a List containing the n-byte binary encoding of intValue. If isLittleEndian is false, the bytes are ordered in big endian order. Otherwise, the bytes are ordered in little endian order.
Else,
Let rawBytes be a List containing the n-byte binary two's complement encoding of intValue. If isLittleEndian is false, the bytes are ordered in big endian order. Otherwise, the bytes are ordered in little endian order.
Return rawBytes.
7.8IntegerIndexedElementSet ( O, index, value )
The abstract operation IntegerIndexedElementSet with arguments O, index, and value performs the following steps:
The abstract operation SetValueInBuffer takes seven parameters, an ArrayBuffer or SharedArrayBuffer arrayBuffer, an integer byteIndex, a String type, a Number value, a Boolean isTypedArray, a String order, and optionally a Boolean isLittleEndian. This operation performs the following steps:
Let eventList be the [[EventList]] field of the element in execution.[[EventLists]] whose [[AgentSignifier]] is AgentSignifier().
If isTypedArray is true and type is "Int8", "Uint8", "Int16", "Uint16", "Int32", or "Uint32", or if type is "BigInt64" or "BigUint64" and order is not "Init" or "Unordered", let noTear be true; otherwise let noTear be false.
BigInt64 and BigUint64, like Float64, are excluded from the list of types which experience noTear writes. That is, non-atomic writes may be observed in a partially completed state.
The abstract operation GetValueFromBuffer takes six parameters, an ArrayBuffer or SharedArrayBuffer arrayBuffer, an integer byteIndex, a String type, a Boolean isTypedArray, a String order, and optionally a Boolean isLittleEndian. This operation performs the following steps:
Let eventList be the [[EventList]] field of the element in execution.[[EventLists]] whose [[AgentSignifier]] is AgentSignifier().
If isTypedArray is true and type is "Int8", "Uint8", "Int16", "Uint16", "Int32", or "Uint32" or if type is "BigInt64" or "BigUint64" and order is not "Init" or "Unordered", let noTear be true; otherwise let noTear be false.
Let rawValue be a List of length elementSize of nondeterministically chosen byte values.
NOTE: In implementations, rawValue is the result of a non-atomic or atomic read instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
Let readEvent be ReadSharedMemory{ [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize }.
Append readEvent to eventList.
Append Chosen Value Record { [[Event]]: readEvent, [[ChosenValue]]: rawValue } to execution.[[ChosenValues]].
Else, let rawValue be a List of elementSize containing, in order, the elementSize sequence of bytes starting with block[byteIndex].
If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
The abstract operation GetModifySetValueInBuffer takes six parameters, a SharedArrayBuffer arrayBuffer, a nonnegative integer byteIndex, a String type, a Number value, a semantic function op, and optionally a Boolean isLittleEndian. This operation performs the following steps:
Assert: IsSharedArrayBuffer(arrayBuffer) is true.
Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
Assert: byteIndex is an integer value ≥ 0.
Assert: Type(value) is BigInt if type is "BigInt64" or "BigUint64"; otherwise, Type(value) is Number.
Let block be arrayBuffer.[[ArrayBufferData]].
Let elementSize be the Number value of the Element Size value specified in Table 9 for Element Type type.
If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
Let rawBytes be NumberNumericToRawBytes(type, value, isLittleEndian).
Let eventList be the [[EventList]] field of the element in execution.[[EventLists]] whose [[AgentSignifier]] is AgentSignifier().
Let rawBytesRead be a List of length elementSize of nondeterministically chosen byte values.
NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
Let rmwEvent be ReadModifyWriteSharedMemory{ [[Order]]: "SeqCst", [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
Append rmwEvent to eventList.
Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
The abstract operation ValidateSharedIntegerTypedArray takes one argument typedArray and an optional Boolean waitable. It performs the following steps:
If waitable is not present, set waitable to false.
If Type(typedArray) is not Object, throw a TypeError exception.
If typedArray does not have a [[TypedArrayName]] internal slot, throw a TypeError exception.
Let typeName be typedArray.[[TypedArrayName]].
If waitable is true, then
If typeName is not "Int32Array" or "BigInt64Array", throw a TypeError exception.
Else,
If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", "Uint32Array", "BigUint64Array", or "BigInt64Array", throw a TypeError exception.
Assert: typedArray has a [[ViewedArrayBuffer]] internal slot.
Let buffer be typedArray.[[ViewedArrayBuffer]].
If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception.
Return buffer.
7.13AtomicReadModifyWrite( typedArray, index, value, op )
The abstract operation AtomicReadModifyWrite takes four arguments, typedArray, index, value, and a pure combining operation op. The pure combining operation op takes two List of byte values arguments and returns a List of byte values. The operation atomically loads a value, combines it with another value, and stores the result of the combination. It returns the loaded value. It performs the following steps:
Let expectedBytes be NumberNumericToRawBytes(elementType, expected, isLittleEndian).
Let elementSize be the Number value of the Element Size value specified in Table 9 for arrayTypeName.
Let offset be typedArray.[[ByteOffset]].
Let indexedPosition be (i × elementSize) + offset.
Let compareExchange denote a semantic function of two List of byte values arguments that returns the second argument if the first argument is element-wise equal to expectedBytes.
Atomics.isLockFree() is an optimization primitive. The intuition is that if the atomic step of an atomic primitive (compareExchange, load, store, add, sub, and, or, xor, or exchange) on a datum of size n bytes will be performed without the calling agent acquiring a lock outside the n bytes comprising the datum, then Atomics.isLockFree(n) will return true. High-performance algorithms will use Atomics.isLockFree to determine whether to use locks or atomic operations in critical sections. If an atomic primitive is not lock-free then it is often more efficient for an algorithm to provide its own locking.
Atomics.isLockFree(4) always returns true as that can be supported on all known relevant hardware. Being able to assume this will generally simplify programs.
Regardless of the value of Atomics.isLockFree, all atomic operations are guaranteed to be atomic. For example, they will never have a visible operation take place in the middle of the operation (e.g., "tearing").
%TypedArray%.prototype.sort is a distinct function that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 22.1.3.25. The implementation of the %TypedArray%.prototype.sort specification may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer indexed properties are not sparse. The only internal methods of the this object that the algorithm may call are [[Get]] and [[Set]].
This function is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.
Upon entry, the following steps are performed to initialize evaluation of the sort function. These steps are used instead of the entry steps in 22.1.3.25:
If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception.
The implementation-defined sort order condition for exotic objects is not applied by %TypedArray%.prototype.sort.
The following version of SortCompare is used by %TypedArray%.prototype.sort. It performs a numeric comparison rather than the string comparison used in 22.1.3.25. SortCompare has access to the comparefn and buffer values of the current invocation of the sort method.
When the TypedArray SortCompare abstract operation is called with two arguments x and y, the following steps are taken:
Assert: Both Type(x) and Type(y) is Number or both are BigInt.
If comparefn is not undefined, then
Let v be ? ToNumber(? Call(comparefn, undefined, « x, y »)).
If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
If v is NaN, return +0.
Return v.
If x and y are both NaN, return +0.
If x is NaN, return 1.
If y is NaN, return -1.
If x < y, return -1.
If x > y, return 1.
If x is -0 and y is +0, return -1.
If x is +0 and y is -0, return 1.
Return +0.
Note
Because NaN always compares greater than any other value, NaN property values always sort to the end of the result when comparefn is not provided.
The abstract operation TypedArraySpeciesCreate with arguments exemplar and argumentList is used to specify the creation of a new TypedArray object using a constructor function that is derived from exemplar. It performs the following steps:
Assert: exemplar is an Object that has a [[TypedArrayName]] internal slot.
Let defaultConstructor be the intrinsic object listed in column one of Table 9 for exemplar.[[TypedArrayName]].
ReturnLet result be ? TypedArrayCreate(constructor, argumentList).
Assert: result has a [[TypedArrayName]] internal slot.
If result.[[TypedArrayName]] contains the substring "Big" and exemplar.[[TypedArrayName]] does not contain the substring "Big", or vice versa, throw a TypeError exception.
Return result.
7.21%TypedArray%.prototype.fill ( value [ , start [ , end ] ] )
The interpretation and use of the arguments of %TypedArray%.prototype.fill are the same as for Array.prototype.fill as defined in 22.1.3.6.
Sets multiple values in this TypedArray, reading the values from the object array. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.
Assert: array is any ECMAScript language value other than an Object with a [[TypedArrayName]] internal slot. If it is such an Object, the definition in 7.23 applies.
Let target be the this value.
If Type(target) is not Object, throw a TypeError exception.
If target does not have a [[TypedArrayName]] internal slot, throw a TypeError exception.
Assert: target has a [[ViewedArrayBuffer]] internal slot.
Sets multiple values in this TypedArray, reading the values from the typedArray argument object. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.
Assert: typedArray has a [[TypedArrayName]] internal slot. If it does not, the definition in 7.22 applies.
Let target be the this value.
If Type(target) is not Object, throw a TypeError exception.
If target does not have a [[TypedArrayName]] internal slot, throw a TypeError exception.
Assert: target has a [[ViewedArrayBuffer]] internal slot.
Set srcByteIndex to srcByteIndex + srcElementSize.
Set targetByteIndex to targetByteIndex + targetElementSize.
Return undefined.
7.24TypedArray ( typedArray )
This description applies only if the TypedArray function is called with at least one argument and the Type of the first argument is Object and that object has a [[TypedArrayName]] internal slot.
TypedArray called with argument typedArray performs the following steps:
Assert: Type(typedArray) is Object and typedArray has a [[TypedArrayName]] internal slot.
If NewTarget is undefined, throw a TypeError exception.
Let constructorName be the String value of the Constructor Name value specified in Table 9 for this TypedArray constructor.
Let O be ? AllocateTypedArray(constructorName, NewTarget, "%TypedArrayPrototype%").
Let srcArray be typedArray.
Let srcData be srcArray.[[ViewedArrayBuffer]].
If IsDetachedBuffer(srcData) is true, throw a TypeError exception.
Let elementType be the String value of the Element Type value in Table 9 for constructorName.
Let elementLength be srcArray.[[ArrayLength]].
Let srcName be the String value of srcArray.[[TypedArrayName]].
Let srcType be the String value of the Element Type value in Table 9 for srcName.
Let srcElementSize be the Element Size value in Table 9 for srcName.
Let srcByteOffset be srcArray.[[ByteOffset]].
Let elementSize be the Element Size value in Table 9 for constructorName.
Set srcByteIndex to srcByteIndex + srcElementSize.
Set targetByteIndex to targetByteIndex + elementSize.
Decrement count by 1.
Set O.[[ViewedArrayBuffer]] to data.
Set O.[[ByteLength]] to byteLength.
Set O.[[ByteOffset]] to 0.
Set O.[[ArrayLength]] to elementLength.
Return O.
7.25SetViewValue ( view, requestIndex, isLittleEndian, type, value )
The abstract operation SetViewValue with arguments view, requestIndex, isLittleEndian, type, and value is used by functions on DataView instances to store values into the view's buffer. It performs the following steps:
If Type(view) is not Object, throw a TypeError exception.
If view does not have a [[DataView]] internal slot, throw a TypeError exception.
Assert: view has a [[ViewedArrayBuffer]] internal slot.
An agent's executing thread executes the jobs in the agent's job queues on the agent's execution contexts independently of other agents, except that an executing thread may be used as the executing thread by multiple agents, provided none of the agents sharing the thread have an Agent Record whose [[CanBlock]] property is true.
Note 1
Some web browsers share a single executing thread across multiple unrelated tabs of a browser window, for example.
The default value computed for the isLittleEndian parameter when it is needed by the algorithms GetValueFromBuffer and SetValueInBuffer. The choice is implementation-dependent and should be the alternative that is most efficient for the implementation. Once the value has been observed it cannot change.
Once the values of [[Signifier]], [[IsLockFree1]], [[IsLockFree2]], and [[IsLockFree8]] have been observed by any agent in the agent cluster they cannot change.
Note 2
The values of [[IsLockFree1]], [[IsLockFree2]], and [[IsLockFree8]] are not necessarily determined by the hardware, but may also reflect implementation choices that can vary over time and between ECMAScript implementations.
There is no [[IsLockFree4]] property: 4-byte atomic operations are always lock-free.
In practice, if an atomic operation is implemented with any type of lock the operation is not lock-free. Lock-free does not imply wait-free: there is no upper bound on how many machine steps may be required to complete a lock-free atomic operation.
That an atomic access of size n is lock-free does not imply anything about the (perceived) atomicity of non-atomic accesses of size n, specifically, non-atomic accesses may still be performed as a sequence of several separate memory accesses. See ReadSharedMemory and WriteSharedMemory for details.