25.1 ArrayBuffer Objects

25.1.1 Notation

The descriptions below in this section, 25.4, and 29 use the read-modify-write modification function internal data structure.

A read-modify-write modification function is a mathematical function that is notationally represented as an abstract closure that takes two Lists of byte values as arguments and returns a List of byte values. These abstract closures satisfy all of the following properties:

  • They perform all their algorithm steps atomically.
  • Their individual algorithm steps are not observable.
Note

To aid verifying that a read-modify-write modification function's algorithm steps constitute a pure, mathematical function, the following editorial conventions are recommended:

  • They do not access, directly or transitively via invoked abstract operations and abstract closures, any language or specification values except their parameters and captured values.
  • They do not return completion values.

25.1.2 Abstract Operations For ArrayBuffer Objects

25.1.2.1 AllocateArrayBuffer ( constructor, byteLength )

The abstract operation AllocateArrayBuffer takes arguments constructor and byteLength (a non-negative integer). It is used to create an ArrayBuffer. It performs the following steps when called:

  1. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] »).
  2. Let block be ? CreateByteDataBlock(byteLength).
  3. Set obj.[[ArrayBufferData]] to block.
  4. Set obj.[[ArrayBufferByteLength]] to byteLength.
  5. Return obj.

25.1.2.2 IsDetachedBuffer ( arrayBuffer )

The abstract operation IsDetachedBuffer takes argument arrayBuffer (an ArrayBuffer or a SharedArrayBuffer). It performs the following steps when called:

  1. If arrayBuffer.[[ArrayBufferData]] is null, return true.
  2. Return false.

25.1.2.3 DetachArrayBuffer ( arrayBuffer [ , key ] )

The abstract operation DetachArrayBuffer takes argument arrayBuffer (an ArrayBuffer) and optional argument key. It performs the following steps when called:

  1. Assert: IsSharedArrayBuffer(arrayBuffer) is false.
  2. If key is not present, set key to undefined.
  3. If SameValue(arrayBuffer.[[ArrayBufferDetachKey]], key) is false, throw a TypeError exception.
  4. Set arrayBuffer.[[ArrayBufferData]] to null.
  5. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
  6. Return NormalCompletion(null).
Note

Detaching an ArrayBuffer instance disassociates the Data Block used as its backing store from the instance and sets the byte length of the buffer to 0. No operations defined by this specification use the DetachArrayBuffer abstract operation. However, an ECMAScript host or implementation may define such operations.

25.1.2.4 CloneArrayBuffer ( srcBuffer, srcByteOffset, srcLength, cloneConstructor )

The abstract operation CloneArrayBuffer takes arguments srcBuffer (an ArrayBuffer or a SharedArrayBuffer), srcByteOffset (a non-negative integer), srcLength (a non-negative integer), and cloneConstructor (a constructor). It creates a new ArrayBuffer whose data is a copy of srcBuffer's data over the range starting at srcByteOffset and continuing for srcLength bytes. It performs the following steps when called:

  1. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, srcLength).
  2. If IsDetachedBuffer(srcBuffer) is true, throw a TypeError exception.
  3. Let srcBlock be srcBuffer.[[ArrayBufferData]].
  4. Let targetBlock be targetBuffer.[[ArrayBufferData]].
  5. Perform CopyDataBlockBytes(targetBlock, 0, srcBlock, srcByteOffset, srcLength).
  6. Return targetBuffer.

25.1.2.5 IsUnsignedElementType ( type )

The abstract operation IsUnsignedElementType takes argument type. It verifies if the argument type is an unsigned TypedArray element type. It performs the following steps when called:

  1. If type is Uint8, Uint8C, Uint16, Uint32, or BigUint64, return true.
  2. Return false.

25.1.2.6 IsUnclampedIntegerElementType ( type )

The abstract operation IsUnclampedIntegerElementType takes argument type. It verifies if the argument type is an Integer TypedArray element type not including Uint8C. It performs the following steps when called:

  1. If type is Int8, Uint8, Int16, Uint16, Int32, or Uint32, return true.
  2. Return false.

25.1.2.7 IsBigIntElementType ( type )

The abstract operation IsBigIntElementType takes argument type. It verifies if the argument type is a BigInt TypedArray element type. It performs the following steps when called:

  1. If type is BigUint64 or BigInt64, return true.
  2. Return false.

25.1.2.8 IsNoTearConfiguration ( type, order )

The abstract operation IsNoTearConfiguration takes arguments type and order. It performs the following steps when called:

  1. If ! IsUnclampedIntegerElementType(type) is true, return true.
  2. If ! IsBigIntElementType(type) is true and order is not Init or Unordered, return true.
  3. Return false.

25.1.2.9 RawBytesToNumeric ( type, rawBytes, isLittleEndian )

The abstract operation RawBytesToNumeric takes arguments type (a TypedArray element type), rawBytes (a List), and isLittleEndian (a Boolean). It performs the following steps when called:

  1. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  2. If isLittleEndian is false, reverse the order of the elements of rawBytes.
  3. If type is Float32, then
    1. Let value be the byte elements of rawBytes concatenated and interpreted as a little-endian bit string encoding of an IEEE 754-2019 binary32 value.
    2. If value is an IEEE 754-2019 binary32 NaN value, return the NaN Number value.
    3. Return the Number value that corresponds to value.
  4. If type is Float64, then
    1. Let value be the byte elements of rawBytes concatenated and interpreted as a little-endian bit string encoding of an IEEE 754-2019 binary64 value.
    2. If value is an IEEE 754-2019 binary64 NaN value, return the NaN Number value.
    3. Return the Number value that corresponds to value.
  5. If ! IsUnsignedElementType(type) is true, then
    1. Let intValue be the byte elements of rawBytes concatenated and interpreted as a bit string encoding of an unsigned little-endian binary number.
  6. Else,
    1. 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.
  7. If ! IsBigIntElementType(type) is true, return the BigInt value that corresponds to intValue.
  8. Otherwise, return the Number value that corresponds to intValue.

25.1.2.10 GetValueFromBuffer ( arrayBuffer, byteIndex, type, isTypedArray, order [ , isLittleEndian ] )

The abstract operation GetValueFromBuffer takes arguments arrayBuffer (an ArrayBuffer or SharedArrayBuffer), byteIndex (a non-negative integer), type (a TypedArray element type), isTypedArray (a Boolean), and order (SeqCst or Unordered) and optional argument isLittleEndian (a Boolean). It performs the following steps when called:

  1. Assert: IsDetachedBuffer(arrayBuffer) is false.
  2. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  3. Let block be arrayBuffer.[[ArrayBufferData]].
  4. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  5. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventList be the [[EventList]] field of the element in execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Let rawValue be a List of length elementSize whose elements are nondeterministically chosen byte values.
    5. 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.
    6. Let readEvent be ReadSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize }.
    7. Append readEvent to eventList.
    8. Append Chosen Value Record { [[Event]]: readEvent, [[ChosenValue]]: rawValue } to execution.[[ChosenValues]].
  6. Else, let rawValue be a List whose elements are bytes from block at indices byteIndex (inclusive) through byteIndex + elementSize (exclusive).
  7. Assert: The number of elements in rawValue is elementSize.
  8. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  9. Return RawBytesToNumeric(type, rawValue, isLittleEndian).

25.1.2.11 NumericToRawBytes ( type, value, isLittleEndian )

The abstract operation NumericToRawBytes takes arguments type (a TypedArray element type), value (a BigInt or a Number), and isLittleEndian (a Boolean). It performs the following steps when called:

  1. If type is Float32, then
    1. Let rawBytes be a List whose elements are the 4 bytes that are the result of converting value to IEEE 754-2019 binary32 format using roundTiesToEven 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, rawBytes may be set to any implementation chosen IEEE 754-2019 binary32 format Not-a-Number encoding. An implementation must always choose the same encoding for each implementation distinguishable NaN value.
  2. Else if type is Float64, then
    1. Let rawBytes be a List whose elements are the 8 bytes that are the IEEE 754-2019 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, rawBytes may be set to any implementation chosen IEEE 754-2019 binary64 format Not-a-Number encoding. An implementation must always choose the same encoding for each implementation distinguishable NaN value.
  3. Else,
    1. Let n be the Element Size value specified in Table 73 for Element Type type.
    2. Let convOp be the abstract operation named in the Conversion Operation column in Table 73 for Element Type type.
    3. Let intValue be (convOp(value)).
    4. If intValue ≥ 0, then
      1. Let rawBytes be a List whose elements are 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.
    5. Else,
      1. Let rawBytes be a List whose elements are 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.
  4. Return rawBytes.

25.1.2.12 SetValueInBuffer ( arrayBuffer, byteIndex, type, value, isTypedArray, order [ , isLittleEndian ] )

The abstract operation SetValueInBuffer takes arguments arrayBuffer (an ArrayBuffer or SharedArrayBuffer), byteIndex (a non-negative integer), type (a TypedArray element type), value (a Number or a BigInt), isTypedArray (a Boolean), and order (SeqCst, Unordered, or Init) and optional argument isLittleEndian (a Boolean). It performs the following steps when called:

  1. Assert: IsDetachedBuffer(arrayBuffer) is false.
  2. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  3. Assert: Type(value) is BigInt if ! IsBigIntElementType(type) is true; otherwise, Type(value) is Number.
  4. Let block be arrayBuffer.[[ArrayBufferData]].
  5. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  6. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  7. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  8. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventList be the [[EventList]] field of the element in execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventList.
  9. Else, store the individual bytes of rawBytes into block, starting at block[byteIndex].
  10. Return NormalCompletion(undefined).

25.1.2.13 GetModifySetValueInBuffer ( arrayBuffer, byteIndex, type, value, op [ , isLittleEndian ] )

The abstract operation GetModifySetValueInBuffer takes arguments arrayBuffer (an ArrayBuffer or a SharedArrayBuffer), byteIndex (a non-negative integer), type (a TypedArray element type), value (a Number or a BigInt), and op (a read-modify-write modification function) and optional argument isLittleEndian (a Boolean). It performs the following steps when called:

  1. Assert: IsDetachedBuffer(arrayBuffer) is false.
  2. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  3. Assert: Type(value) is BigInt if ! IsBigIntElementType(type) is true; otherwise, Type(value) is Number.
  4. Let block be arrayBuffer.[[ArrayBufferData]].
  5. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  6. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  7. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  8. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventList be the [[EventList]] field of the element in execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. 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.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: SeqCst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventList.
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  9. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  10. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).

25.1.3 The ArrayBuffer Constructor

The ArrayBuffer constructor:

  • is %ArrayBuffer%.
  • is the initial value of the "ArrayBuffer" property of the global object.
  • creates and initializes a new ArrayBuffer when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified ArrayBuffer behaviour must include a super call to the ArrayBuffer constructor to create and initialize subclass instances with the internal state necessary to support the ArrayBuffer.prototype built-in methods.

25.1.3.1 ArrayBuffer ( length )

When the ArrayBuffer function is called with argument length, the following steps are taken:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let byteLength be ? ToIndex(length).
  3. Return ? AllocateArrayBuffer(NewTarget, byteLength).

25.1.4 Properties of the ArrayBuffer Constructor

The ArrayBuffer constructor:

  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • has the following properties:

25.1.4.1 ArrayBuffer.isView ( arg )

The isView function takes one argument arg, and performs the following steps:

  1. If Type(arg) is not Object, return false.
  2. If arg has a [[ViewedArrayBuffer]] internal slot, return true.
  3. Return false.

25.1.4.2 ArrayBuffer.prototype

The initial value of ArrayBuffer.prototype is the ArrayBuffer prototype object.

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

25.1.4.3 get ArrayBuffer [ @@species ]

ArrayBuffer[@@species] is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Return the this value.

The value of the "name" property of this function is "get [Symbol.species]".

Note

ArrayBuffer prototype methods normally use their this value's constructor to create a derived object. However, a subclass constructor may over-ride that default behaviour by redefining its @@species property.

25.1.5 Properties of the ArrayBuffer Prototype Object

The ArrayBuffer prototype object:

  • is %ArrayBuffer.prototype%.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
  • is an ordinary object.
  • does not have an [[ArrayBufferData]] or [[ArrayBufferByteLength]] internal slot.

25.1.5.1 get ArrayBuffer.prototype.byteLength

ArrayBuffer.prototype.byteLength is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, return +0𝔽.
  5. Let length be O.[[ArrayBufferByteLength]].
  6. Return 𝔽(length).

25.1.5.2 ArrayBuffer.prototype.constructor

The initial value of ArrayBuffer.prototype.constructor is %ArrayBuffer%.

25.1.5.3 ArrayBuffer.prototype.slice ( start, end )

The following steps are taken:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart is -∞, let first be 0.
  8. Else if relativeStart < 0, let first be max(len + relativeStart, 0).
  9. Else, let first be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd is -∞, let final be 0.
  12. Else if relativeEnd < 0, let final be max(len + relativeEnd, 0).
  13. Else, let final be min(relativeEnd, len).
  14. Let newLen be max(final - first, 0).
  15. Let ctor be ? SpeciesConstructor(O, %ArrayBuffer%).
  16. Let new be ? Construct(ctor, « 𝔽(newLen) »).
  17. Perform ? RequireInternalSlot(new, [[ArrayBufferData]]).
  18. If IsSharedArrayBuffer(new) is true, throw a TypeError exception.
  19. If IsDetachedBuffer(new) is true, throw a TypeError exception.
  20. If SameValue(new, O) is true, throw a TypeError exception.
  21. If new.[[ArrayBufferByteLength]] < newLen, throw a TypeError exception.
  22. NOTE: Side-effects of the above steps may have detached O.
  23. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  24. Let fromBuf be O.[[ArrayBufferData]].
  25. Let toBuf be new.[[ArrayBufferData]].
  26. Perform CopyDataBlockBytes(toBuf, 0, fromBuf, first, newLen).
  27. Return new.

25.1.5.4 ArrayBuffer.prototype [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "ArrayBuffer".

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

25.1.6 Properties of ArrayBuffer Instances

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot.

ArrayBuffer instances whose [[ArrayBufferData]] is null are considered to be detached and all operators to access or modify data contained in the ArrayBuffer instance will fail.

ArrayBuffer instances whose [[ArrayBufferDetachKey]] is set to a value other than undefined need to have all DetachArrayBuffer calls passing that same "detach key" as an argument, otherwise a TypeError will result. This internal slot is only ever set by certain embedding environments, not by algorithms in this specification.