25 结构化数据(Structured Data)

25.1 ArrayBuffer 对象

25.1.1 记号(Notation)

本小节、25.4 以及 29 中的下述描述使用 “读-改-写 修改函数(read-modify-write modification function)” 内部数据结构。

读-改-写 修改函数 是一种数学函数,以抽象闭包形式表示,接受两个字节值List 作为参数并返回一个字节值List。这些抽象闭包满足以下全部性质:

  • 它们以原子方式执行其全部算法步骤。
  • 其各个算法步骤不可被观察。
Note

为帮助验证读-改-写 修改函数的算法步骤构成一个纯粹的数学函数,建议遵循以下编辑约定:

25.1.2 固定长度与可调整大小(Resizable)的 ArrayBuffer 对象

固定长度 ArrayBuffer(fixed-length ArrayBuffer) 是创建后其字节长度不可改变的 ArrayBuffer。

可调整大小 ArrayBuffer(resizable ArrayBuffer) 是创建后其字节长度可通过调用 ArrayBuffer.prototype.resize ( newLength ) 改变的 ArrayBuffer。

创建何种 ArrayBuffer 对象取决于传递给 ArrayBuffer ( length [ , options ] ) 的参数。

25.1.3 ArrayBuffer 对象的抽象操作

25.1.3.1 AllocateArrayBuffer ( constructor, byteLength [ , maxByteLength ] )

The abstract operation AllocateArrayBuffer takes arguments constructor (a constructor) and byteLength (a non-negative integer) and optional argument maxByteLength (a non-negative integer or empty) and returns 要么是包含一个 ArrayBuffer 的正常完成要么是抛出完成. 用于创建一个 ArrayBuffer。 It performs the following steps when called:

  1. slots 为 « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] »。
  2. 如果存在 maxByteLength 且其不为 empty,令 allocatingResizableBuffertrue;否则令其为 false
  3. allocatingResizableBuffertrue,则
    1. byteLength > maxByteLength,抛出 RangeError 异常。
    2. [[ArrayBufferMaxByteLength]] 追加到 slots
  4. obj 为 ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots)。
  5. block 为 ? CreateByteDataBlock(byteLength)。
  6. obj.[[ArrayBufferData]]block
  7. obj.[[ArrayBufferByteLength]]byteLength
  8. allocatingResizableBuffertrue,则
    1. 若无法创建一个由 maxByteLength 个字节组成的 Data Block block,抛出 RangeError 异常。
    2. 注:可调整大小 ArrayBuffer 设计为可原地增长。实现可在例如无法预先保留虚拟内存时抛出。
    3. obj.[[ArrayBufferMaxByteLength]]maxByteLength
  9. 返回 obj

25.1.3.2 ArrayBufferByteLength ( arrayBuffer, order )

The abstract operation ArrayBufferByteLength takes arguments arrayBuffer (an ArrayBuffer or SharedArrayBuffer) and order (seq-cst or unordered) and returns a non-negative integer. It performs the following steps when called:

  1. IsSharedArrayBuffer(arrayBuffer) 为 truearrayBuffer 具有内部槽 [[ArrayBufferByteLengthData]],则
    1. bufferByteLengthBlockarrayBuffer.[[ArrayBufferByteLengthData]]
    2. rawLengthGetRawBytesFromSharedBlock(bufferByteLengthBlock, 0, biguint64, true, order)。
    3. isLittleEndian 为外层 agent 的 Agent Record[[LittleEndian]] 字段的值。
    4. 返回 (RawBytesToNumeric(biguint64, rawLength, isLittleEndian))。
  2. 断言:IsDetachedBuffer(arrayBuffer) 为 false
  3. 返回 arrayBuffer.[[ArrayBufferByteLength]]

25.1.3.3 ArrayBufferCopyAndDetach ( arrayBuffer, newLength, preserveResizability )

The abstract operation ArrayBufferCopyAndDetach takes arguments arrayBuffer (an ECMAScript language value), newLength (an ECMAScript language value), and preserveResizability (preserve-resizability or fixed-length) and returns 要么是包含一个 ArrayBuffer 的正常完成要么是抛出完成. It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]])。
  2. IsSharedArrayBuffer(arrayBuffer) 为 true,抛出 TypeError 异常。
  3. newLengthundefined,则
    1. newByteLengtharrayBuffer.[[ArrayBufferByteLength]]
  4. 否则,
    1. newByteLength 为 ? ToIndex(newLength)。
  5. IsDetachedBuffer(arrayBuffer) 为 true,抛出 TypeError 异常。
  6. preserveResizabilitypreserve-resizabilityIsFixedLengthArrayBuffer(arrayBuffer) 为 false,则
    1. newMaxByteLengtharrayBuffer.[[ArrayBufferMaxByteLength]]
  7. 否则,
    1. newMaxByteLengthempty
  8. arrayBuffer.[[ArrayBufferDetachKey]] 不为 undefined,抛出 TypeError 异常。
  9. newBuffer 为 ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength)。
  10. copyLengthmin(newByteLength, arrayBuffer.[[ArrayBufferByteLength]])。
  11. fromBlockarrayBuffer.[[ArrayBufferData]]
  12. toBlocknewBuffer.[[ArrayBufferData]]
  13. 执行 CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength)。
  14. 注:新旧 Data Block 的创建与拷贝均不可观察。实现可用零拷贝移动或 realloc
  15. 执行 ! DetachArrayBuffer(arrayBuffer)。
  16. 返回 newBuffer

25.1.3.4 IsDetachedBuffer ( arrayBuffer )

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

  1. arrayBuffer.[[ArrayBufferData]]null,返回 true
  2. 返回 false

25.1.3.5 DetachArrayBuffer ( arrayBuffer [ , key ] )

The abstract operation DetachArrayBuffer takes argument arrayBuffer (an ArrayBuffer) and optional argument key (anything) and returns 要么是包含 unused正常完成要么是抛出完成. It performs the following steps when called:

  1. 断言:IsSharedArrayBuffer(arrayBuffer) 为 false
  2. key 不存在,设 keyundefined
  3. arrayBuffer.[[ArrayBufferDetachKey]] 不为 key,抛出 TypeError 异常。
  4. arrayBuffer.[[ArrayBufferData]]null
  5. arrayBuffer.[[ArrayBufferByteLength]] 为 0。
  6. 返回 unused
Note

分离一个 ArrayBuffer 实例会将其用作后备存储的 Data Block 与该实例解除关联,并将其字节长度设为 0。

25.1.3.6 CloneArrayBuffer ( srcBuffer, srcByteOffset, srcLength )

The abstract operation CloneArrayBuffer takes arguments srcBuffer (an ArrayBuffer or a SharedArrayBuffer), srcByteOffset (a non-negative integer), and srcLength (a non-negative integer) and returns 要么是包含一个 ArrayBuffer 的正常完成要么是抛出完成. 创建一个新的 ArrayBuffer,其数据为 srcBuffersrcByteOffsetsrcLength 字节范围内数据的拷贝。 It performs the following steps when called:

  1. 断言:IsDetachedBuffer(srcBuffer) 为 false
  2. targetBuffer 为 ? AllocateArrayBuffer(%ArrayBuffer%, srcLength)。
  3. srcBlocksrcBuffer.[[ArrayBufferData]]
  4. targetBlocktargetBuffer.[[ArrayBufferData]]
  5. 执行 CopyDataBlockBytes(targetBlock, 0, srcBlock, srcByteOffset, srcLength)。
  6. 返回 targetBuffer

25.1.3.7 GetArrayBufferMaxByteLengthOption ( options )

The abstract operation GetArrayBufferMaxByteLengthOption takes argument options (an ECMAScript language value) and returns 要么是包含非负整数或 empty正常完成要么是抛出完成. It performs the following steps when called:

  1. options 不是 Object,返回 empty
  2. maxByteLength 为 ? Get(options, "maxByteLength")。
  3. maxByteLengthundefined,返回 empty
  4. 返回 ? ToIndex(maxByteLength)。

25.1.3.8 HostResizeArrayBuffer ( buffer, newByteLength )

The host-defined abstract operation HostResizeArrayBuffer takes arguments buffer (an ArrayBuffer) and newByteLength (a non-negative integer) and returns 要么是包含 handledunhandled正常完成要么是抛出完成. 给予宿主机会对 buffer 进行实现自定义的调整大小。若宿主选择不处理,可返回 unhandled 以使用默认行为。

HostResizeArrayBuffer 的实现必须符合以下要求:

  • 抽象操作不会分离 buffer
  • 正常完成并返回 handled,则 buffer.[[ArrayBufferByteLength]]newByteLength

默认实现返回 NormalCompletion(unhandled)。

25.1.3.9 IsFixedLengthArrayBuffer ( arrayBuffer )

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

  1. arrayBuffer 具有内部槽 [[ArrayBufferMaxByteLength]],返回 false
  2. 返回 true

25.1.3.10 IsUnsignedElementType ( type )

The abstract operation IsUnsignedElementType takes argument type (a TypedArray element type) and returns a Boolean. 验证参数 type 是否为无符号的 TypedArray 元素类型。 It performs the following steps when called:

  1. typeuint8, uint8clamped, uint16, uint32, 或 biguint64 之一,返回 true
  2. 返回 false

25.1.3.11 IsUnclampedIntegerElementType ( type )

The abstract operation IsUnclampedIntegerElementType takes argument type (a TypedArray element type) and returns a Boolean. 验证参数 type 是否为不包含 uint8clamped 的整数 TypedArray 元素类型。 It performs the following steps when called:

  1. typeint8, uint8, int16, uint16, int32, 或 uint32 之一,返回 true
  2. 返回 false

25.1.3.12 IsBigIntElementType ( type )

The abstract operation IsBigIntElementType takes argument type (a TypedArray element type) and returns a Boolean. 验证参数 type 是否为 BigInt TypedArray 元素类型。 It performs the following steps when called:

  1. typebiguint64bigint64,返回 true
  2. 返回 false

25.1.3.13 IsNoTearConfiguration ( type, order )

The abstract operation IsNoTearConfiguration takes arguments type (a TypedArray element type) and order (seq-cst, unordered, or init) and returns a Boolean. It performs the following steps when called:

  1. IsUnclampedIntegerElementType(type) 为 true,返回 true
  2. IsBigIntElementType(type) 为 trueorder 既不是 init 也不是 unordered,返回 true
  3. 返回 false

25.1.3.14 RawBytesToNumeric ( type, rawBytes, isLittleEndian )

The abstract operation RawBytesToNumeric takes arguments type (a TypedArray element type), rawBytes (a List of byte values), and isLittleEndian (a Boolean) and returns a Number or a BigInt. It performs the following steps when called:

  1. elementSizeTable 73 中元素类型 type 指定的元素大小值。
  2. isLittleEndianfalse,反转 rawBytes 的元素顺序。
  3. typefloat16,则
    1. value 为将 rawBytes 字节元素拼接并按 IEEE 754-2019 binary16 小端位串编码解释的结果。
    2. value 是 NaN,返回 NaN
    3. 返回与 value 对应的 Number 值。
  4. typefloat32,则
    1. 同上以 binary32 方式处理。
  5. typefloat64,则
    1. 同上以 binary64 方式处理。
  6. IsUnsignedElementType(type) 为 true,则
    1. intValuerawBytes 按小端无符号二进制数的位串编码解释的结果。
  7. 否则,
    1. intValuerawBytes 按小端二补数、位长 elementSize × 8 的位串编码解释的结果。
  8. IsBigIntElementType(type) 为 true,返回与 intValue 对应的 BigInt。
  9. 否则,返回与 intValue 对应的 Number。

25.1.3.15 GetRawBytesFromSharedBlock ( block, byteIndex, type, isTypedArray, order )

The abstract operation GetRawBytesFromSharedBlock takes arguments block (a Shared Data Block), byteIndex (a non-negative integer), type (a TypedArray element type), isTypedArray (a Boolean), and order (seq-cst or unordered) and returns a List of byte values. It performs the following steps when called:

  1. elementSizeTable 73 中元素类型 type 指定的元素大小值。
  2. execution 为外层 agent 的 Agent Record[[CandidateExecution]] 字段。
  3. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
  4. isTypedArraytrueIsNoTearConfiguration(type, order) 为 true,令 noTeartrue;否则为 false
  5. rawValue 为长度 elementSize、元素为非确定性选择字节值List
  6. 注:在实现中,rawValue 是底层硬件非原子或原子读取指令的结果;该非确定性是内存模型对弱一致硬件可观察行为的语义规定。
  7. readEventReadSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize }。
  8. readEvent 追加到 eventsRecord.[[EventList]]
  9. Chosen Value Record { [[Event]]: readEvent, [[ChosenValue]]: rawValue } 追加到 execution.[[ChosenValues]]
  10. 返回 rawValue

25.1.3.16 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 (seq-cst or unordered) and optional argument isLittleEndian (a Boolean) and returns a Number or a BigInt. It performs the following steps when called:

  1. 断言:IsDetachedBuffer(arrayBuffer) 为 false
  2. 断言:arrayBuffer 中自 byteIndex 起有足够字节表示 type 的一个值。
  3. blockarrayBuffer.[[ArrayBufferData]]
  4. elementSizeTable 73 中元素类型 type 的元素大小值。
  5. IsSharedArrayBuffer(arrayBuffer) 为 true,则
    1. 断言:blockShared Data Block
    2. rawValueGetRawBytesFromSharedBlock(block, byteIndex, type, isTypedArray, order)。
  6. 否则,
    1. rawValueblock 中索引区间 [byteIndex, byteIndex + elementSize) 的字节组成的 List
  7. 断言:rawValue 元素个数为 elementSize
  8. isLittleEndian 不存在,设其为外层 agent 的 Agent Record[[LittleEndian]] 字段值。
  9. 返回 RawBytesToNumeric(type, rawValue, isLittleEndian)。

25.1.3.17 NumericToRawBytes ( type, value, isLittleEndian )

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

  1. typefloat16,则
    1. rawBytes 为长度 2 的 List,为将 value 以 roundTiesToEven 模式转换为 IEEE 754-2019 binary16 格式的结果字节(小端序)。若 valueNaNrawBytes 可为实现选择的任一 binary16 NaN 编码;实现对每个可区分 NaN 必须始终选择同一编码。
  2. Else if typefloat32,同理生成 4 字节(binary32)。
  3. Else if typefloat64,同理生成 8 字节(binary64)。
  4. 否则,
    1. nTable 73 中元素类型 type 的元素大小值。
    2. conversionOperation 为同表中该元素类型的 Conversion Operation 列命名的抽象操作
    3. intValue(! conversionOperation(value))。
    4. intValue ≥ 0,则
      1. rawBytes 为按小端序排列的 intValuen 字节二进制编码。
    5. 否则,
      1. rawBytes 为按小端序排列的 intValuen 字节二进制二补数编码。
  5. isLittleEndianfalse,反转 rawBytes 的元素顺序。
  6. 返回 rawBytes

25.1.3.18 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 (seq-cst, unordered, or init) and optional argument isLittleEndian (a Boolean) and returns unused. It performs the following steps when called:

  1. 断言:IsDetachedBuffer(arrayBuffer) 为 false
  2. 断言:arrayBuffer 中自 byteIndex 起有足够字节表示 type 的一个值。
  3. 断言:若 IsBigIntElementType(type) 为 truevalue 为 BigInt;否则为 Number。
  4. blockarrayBuffer.[[ArrayBufferData]]
  5. elementSizeTable 73 中元素类型 type 的元素大小值。
  6. isLittleEndian 不存在,设其为外层 agent 的 Agent Record[[LittleEndian]] 字段值。
  7. rawBytesNumericToRawBytes(type, value, isLittleEndian)。
  8. IsSharedArrayBuffer(arrayBuffer) 为 true,则
    1. execution 为外层 agent 的 Agent Record[[CandidateExecution]] 字段。
    2. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
    3. isTypedArraytrueIsNoTearConfiguration(type, order) 为 true,令 noTeartrue;否则为 false
    4. WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } 追加到 eventsRecord.[[EventList]]
  9. 否则,
    1. rawBytes 的各字节存入 block,起始于 block[byteIndex]。
  10. 返回 unused

25.1.3.19 GetModifySetValueInBuffer ( arrayBuffer, byteIndex, type, value, op )

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 returns a Number or a BigInt. It performs the following steps when called:

  1. 断言:IsDetachedBuffer(arrayBuffer) 为 false
  2. 断言:arrayBuffer 中自 byteIndex 起有足够字节表示 type 的一个值。
  3. 断言:若 IsBigIntElementType(type) 为 truevalue 为 BigInt;否则为 Number。
  4. blockarrayBuffer.[[ArrayBufferData]]
  5. elementSizeTable 73 中元素类型 type 的元素大小值。
  6. isLittleEndian 为外层 agent 的 Agent Record[[LittleEndian]] 字段值。
  7. rawBytesNumericToRawBytes(type, value, isLittleEndian)。
  8. IsSharedArrayBuffer(arrayBuffer) 为 true,则
    1. execution 为外层 agent 的 Agent Record[[CandidateExecution]] 字段。
    2. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
    3. rawBytesRead 为长度 elementSize、元素为非确定性选择字节值List
    4. 注:在实现中,rawBytesRead 来自底层硬件的 load-link、load-exclusive 或读-改-写指令操作数;非确定性用于描述弱一致硬件的可观察行为。
    5. rmwEventReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }。
    6. rmwEvent 追加到 eventsRecord.[[EventList]]
    7. Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } 追加到 execution.[[ChosenValues]]
  9. 否则,
    1. rawBytesRead 为长度 elementSizeList,其元素为自 block[byteIndex] 起的 elementSize 个字节。
    2. rawBytesModifiedop(rawBytesRead, rawBytes)。
    3. rawBytesModified 的字节存入 block,起始于 block[byteIndex]。
  10. 返回 RawBytesToNumeric(type, rawBytesRead, isLittleEndian)。

25.1.4 ArrayBuffer 构造函数

ArrayBuffer 构造函数

  • %ArrayBuffer%
  • 是全局对象 "ArrayBuffer" 属性的初始值。
  • 作为构造函数调用时创建并初始化一个新的 ArrayBuffer。
  • 不应作为函数调用;若如此调用将抛出异常。
  • 可作为类定义 extends 子句的值。继承该指定行为的子类构造函数必须在内部包含对 ArrayBuffer 构造函数super 调用,以创建并初始化具有支持 ArrayBuffer.prototype 内置方法所需内部状态的子类实例。

25.1.4.1 ArrayBuffer ( length [ , options ] )

该函数被调用时执行以下步骤:

  1. 若 NewTarget 为 undefined,抛出 TypeError 异常。
  2. byteLength 为 ? ToIndex(length)。
  3. requestedMaxByteLength 为 ? GetArrayBufferMaxByteLengthOption(options)。
  4. 返回 ? AllocateArrayBuffer(NewTarget, byteLength, requestedMaxByteLength)。

25.1.5 ArrayBuffer 构造函数的属性

ArrayBuffer 构造函数

25.1.5.1 ArrayBuffer.isView ( arg )

该函数被调用时执行以下步骤:

  1. arg 不是 Object,返回 false
  2. arg 具有内部槽 [[ViewedArrayBuffer]],返回 true
  3. 返回 false

25.1.5.2 ArrayBuffer.prototype

ArrayBuffer.prototype 的初始值是 ArrayBuffer 原型对象

该属性的特性为 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

25.1.5.3 get ArrayBuffer [ %Symbol.species% ]

ArrayBuffer[%Symbol.species%] 是一个存取器属性,其 set 访问器为 undefined。其 get 访问器被调用时执行:

  1. 返回 this 值。

该函数 "name" 属性的值为 "get [Symbol.species]"

Note

ArrayBuffer.prototype.slice ( start, end ) 通常使用其 this 值的构造函数创建派生对象。然而,子类构造函数可通过重定义其 %Symbol.species% 属性来覆盖该方法(ArrayBuffer.prototype.slice ( start, end ))的默认行为。

25.1.6 ArrayBuffer 原型对象的属性

ArrayBuffer 原型对象

  • %ArrayBuffer.prototype%
  • [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 普通对象
  • 没有 [[ArrayBufferData]][[ArrayBufferByteLength]] 内部槽。

25.1.6.1 get ArrayBuffer.prototype.byteLength

ArrayBuffer.prototype.byteLength 是一个存取器属性,其 set 访问器为 undefined。其 get 访问器被调用时执行:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. IsSharedArrayBuffer(O) 为 true,抛出 TypeError 异常。
  4. IsDetachedBuffer(O) 为 true,返回 +0𝔽
  5. lengthO.[[ArrayBufferByteLength]]
  6. 返回 𝔽(length)。

25.1.6.2 ArrayBuffer.prototype.constructor

ArrayBuffer.prototype.constructor 的初始值是 %ArrayBuffer%

25.1.6.3 get ArrayBuffer.prototype.detached

ArrayBuffer.prototype.detached 是一个存取器属性,其 set 访问器为 undefined。其 get 访问器被调用时执行:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. IsSharedArrayBuffer(O) 为 true,抛出 TypeError 异常。
  4. 返回 IsDetachedBuffer(O)。

25.1.6.4 get ArrayBuffer.prototype.maxByteLength

ArrayBuffer.prototype.maxByteLength 是一个存取器属性,其 set 访问器为 undefined。其 get 访问器被调用时执行:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. IsSharedArrayBuffer(O) 为 true,抛出 TypeError 异常。
  4. IsDetachedBuffer(O) 为 true,返回 +0𝔽
  5. IsFixedLengthArrayBuffer(O) 为 true,则
    1. lengthO.[[ArrayBufferByteLength]]
  6. 否则,
    1. lengthO.[[ArrayBufferMaxByteLength]]
  7. 返回 𝔽(length)。

25.1.6.5 get ArrayBuffer.prototype.resizable

ArrayBuffer.prototype.resizable 是一个存取器属性,其 set 访问器为 undefined。其 get 访问器被调用时执行:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. IsSharedArrayBuffer(O) 为 true,抛出 TypeError 异常。
  4. IsFixedLengthArrayBuffer(O) 为 false,返回 true;否则返回 false

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]])。
  3. IsSharedArrayBuffer(O) 为 true,抛出 TypeError 异常。
  4. newByteLength 为 ? ToIndex(newLength)。
  5. IsDetachedBuffer(O) 为 true,抛出 TypeError 异常。
  6. newByteLength > O.[[ArrayBufferMaxByteLength]],抛出 RangeError 异常。
  7. hostHandled 为 ? HostResizeArrayBuffer(O, newByteLength)。
  8. hostHandledhandled,返回 undefined
  9. oldBlockO.[[ArrayBufferData]]
  10. newBlock 为 ? CreateByteDataBlock(newByteLength)。
  11. copyLengthmin(newByteLength, O.[[ArrayBufferByteLength]])。
  12. 执行 CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength)。
  13. 注:新 Data Block 的创建与旧 Data Block 的拷贝均不可观察。实现可原地增长或收缩。
  14. O.[[ArrayBufferData]]newBlock
  15. O.[[ArrayBufferByteLength]]newByteLength
  16. 返回 undefined

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. IsSharedArrayBuffer(O) 为 true,抛出 TypeError 异常。
  4. IsDetachedBuffer(O) 为 true,抛出 TypeError 异常。
  5. lenO.[[ArrayBufferByteLength]]
  6. relativeStart 为 ? ToIntegerOrInfinity(start)。
  7. relativeStart = -∞,令 first 为 0。
  8. Else if relativeStart < 0,令 firstmax(len + relativeStart, 0)。
  9. Else,令 firstmin(relativeStart, len)。
  10. endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  11. relativeEnd = -∞,令 final 为 0。
  12. Else if relativeEnd < 0,令 finalmax(len + relativeEnd, 0)。
  13. Else,令 finalmin(relativeEnd, len)。
  14. newLenmax(final - first, 0)。
  15. ctor 为 ? SpeciesConstructor(O, %ArrayBuffer%)。
  16. new 为 ? Construct(ctor, « 𝔽(newLen) »)。
  17. 执行 ? RequireInternalSlot(new, [[ArrayBufferData]])。
  18. IsSharedArrayBuffer(new) 为 true,抛出 TypeError 异常。
  19. IsDetachedBuffer(new) 为 true,抛出 TypeError 异常。
  20. SameValue(new, O) 为 true,抛出 TypeError 异常。
  21. new.[[ArrayBufferByteLength]] < newLen,抛出 TypeError 异常。
  22. 注:以上步骤的副作用可能已分离或调整 O 大小。
  23. IsDetachedBuffer(O) 为 true,抛出 TypeError 异常。
  24. fromBufO.[[ArrayBufferData]]
  25. toBufnew.[[ArrayBufferData]]
  26. currentLenO.[[ArrayBufferByteLength]]
  27. first < currentLen,则
    1. countmin(newLen, currentLen - first)。
    2. 执行 CopyDataBlockBytes(toBuf, 0, fromBuf, first, count)。
  28. 返回 new

25.1.6.8 ArrayBuffer.prototype.transfer ( [ newLength ] )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 返回 ? ArrayBufferCopyAndDetach(O, newLength, preserve-resizability)。

25.1.6.9 ArrayBuffer.prototype.transferToFixedLength ( [ newLength ] )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 返回 ? ArrayBufferCopyAndDetach(O, newLength, fixed-length)。

25.1.6.10 ArrayBuffer.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串 "ArrayBuffer"

该属性特性为 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

25.1.7 ArrayBuffer 实例的属性

ArrayBuffer 实例从 ArrayBuffer 原型对象继承属性。每个实例都有 [[ArrayBufferData]][[ArrayBufferByteLength]][[ArrayBufferDetachKey]] 内部槽。可调整大小的实例还具有 [[ArrayBufferMaxByteLength]] 内部槽。

[[ArrayBufferData]]null 的 ArrayBuffer 实例被视为已分离,对其数据的访问或修改操作均会失败。

[[ArrayBufferDetachKey]] 设为非 undefined 值的 ArrayBuffer 实例,在所有 DetachArrayBuffer 调用中必须传递相同的 “detach key” 作为参数,否则将产生 TypeError。该内部槽仅由某些嵌入环境设置,而非本规范算法。

25.1.8 可调整大小 ArrayBuffer 指南

Note 1

以下是供 ECMAScript 程序员在使用可调整大小 ArrayBuffer 时的指南。

建议在部署环境中(如果可能)对程序进行测试。不同硬件设备的可用物理内存差异很大;虚拟内存子系统也因硬件设备与操作系统不同而差异明显。一个在 64 位桌面浏览器中无内存不足错误的应用,可能在 32 位移动浏览器中耗尽内存。

为可调整大小 ArrayBuffer 选择 "maxByteLength" 选项值时,建议选择应用所需的最小可能值。建议 "maxByteLength" 不超过 1,073,741,824(230 字节或 1GiB)。

请注意:成功构造一个指定最大值的可调整大小 ArrayBuffer 并不保证未来的扩展一定成功。

Note 2

以下是供实现可调整大小 ArrayBuffer 的 ECMAScript 实现者的指南。

Resizable ArrayBuffer 可实现为在调整时复制、通过预留虚拟内存的原地增长、或针对构造函数 "maxByteLength" 选项不同取值的上述方案组合。

宿主是多租户(同时运行许多 ECMAScript 应用),例如 Web 浏览器,并选择通过预留虚拟内存实现原地增长,建议 32 位与 64 位实现对 "maxByteLength" ≥ 1GiB 到 1.5GiB 的值抛出异常。其目的是减少单一应用耗尽虚拟地址空间的可能性并降低互操作风险。

宿主无虚拟内存(例如无 MMU 的嵌入式设备),或宿主仅通过复制实现调整大小,则可接受 "maxByteLength" 选项的任意 Number value for 值。然而,建议当请求的大小永远无法分配时抛出 RangeError。例如请求大小大于设备可用的最大可用内存时。

25.2 SharedArrayBuffer 对象

25.2.1 固定长度与可增长的 SharedArrayBuffer 对象

固定长度 SharedArrayBuffer 是创建后其字节长度不可改变的 SharedArrayBuffer。

可增长 SharedArrayBuffer 是创建后其字节长度可通过调用 SharedArrayBuffer.prototype.grow ( newLength ) 增加的 SharedArrayBuffer。

创建哪种 SharedArrayBuffer 对象取决于传递给 SharedArrayBuffer ( length [ , options ] ) 的参数。

25.2.2 SharedArrayBuffer 对象的抽象操作

25.2.2.1 AllocateSharedArrayBuffer ( constructor, byteLength [ , maxByteLength ] )

The abstract operation AllocateSharedArrayBuffer takes arguments constructor (a constructor) and byteLength (a non-negative integer) and optional argument maxByteLength (a non-negative integer or empty) and returns 要么是包含一个 SharedArrayBuffer 的正常完成要么是抛出完成. 用于创建一个 SharedArrayBuffer。 It performs the following steps when called:

  1. slots 为 « [[ArrayBufferData]] »。
  2. 若存在 maxByteLength 且其不为 empty,令 allocatingGrowableBuffertrue;否则令其为 false
  3. allocatingGrowableBuffertrue,则
    1. byteLength > maxByteLength,抛出 RangeError 异常。
    2. [[ArrayBufferByteLengthData]][[ArrayBufferMaxByteLength]] 追加到 slots
  4. 否则,
    1. [[ArrayBufferByteLength]] 追加到 slots
  5. obj 为 ? OrdinaryCreateFromConstructor(constructor, "%SharedArrayBuffer.prototype%", slots)。
  6. allocatingGrowableBuffertrue,令 allocLengthmaxByteLength;否则令 allocLengthbyteLength
  7. block 为 ? CreateSharedByteDataBlock(allocLength)。
  8. obj.[[ArrayBufferData]]block
  9. allocatingGrowableBuffertrue,则
    1. 断言:byteLengthmaxByteLength
    2. byteLengthBlock 为 ? CreateSharedByteDataBlock(8)。
    3. 执行 SetValueInBuffer(byteLengthBlock, 0, biguint64, (byteLength), true, seq-cst)。
    4. obj.[[ArrayBufferByteLengthData]]byteLengthBlock
    5. obj.[[ArrayBufferMaxByteLength]]maxByteLength
  10. 否则,
    1. obj.[[ArrayBufferByteLength]]byteLength
  11. 返回 obj

25.2.2.2 IsSharedArrayBuffer ( obj )

The abstract operation IsSharedArrayBuffer takes argument obj (an ArrayBuffer or a SharedArrayBuffer) and returns a Boolean. 测试一个对象是否是 ArrayBuffer、SharedArrayBuffer,或它们的子类型。 It performs the following steps when called:

  1. bufferDataobj.[[ArrayBufferData]]
  2. bufferDatanull,返回 false
  3. bufferDataData Block,返回 false
  4. 断言:bufferDataShared Data Block
  5. 返回 true

25.2.2.3 HostGrowSharedArrayBuffer ( buffer, newByteLength )

The host-defined abstract operation HostGrowSharedArrayBuffer takes arguments buffer (a SharedArrayBuffer) and newByteLength (a non-negative integer) and returns 要么是包含 handledunhandled正常完成要么是抛出完成. 给予宿主机会对 buffer 进行实现自定义的增长。若宿主选择不处理增长,可返回 unhandled 以使用默认行为。

HostGrowSharedArrayBuffer 的实现必须符合以下要求:

  • 若该抽象操作未以 unhandled 正常完成,且 newByteLength < 当前 buffer 的字节长度,或 newByteLength > buffer.[[ArrayBufferMaxByteLength]],抛出 RangeError 异常。
  • isLittleEndian 为外层 agent 的 Agent Record[[LittleEndian]] 字段的值。若该抽象操作handled 正常完成,则一个 WriteSharedMemoryReadModifyWriteSharedMemory 事件被加入外层 agent 的候选执行,其 [[Order]]seq-cst[[Payload]]NumericToRawBytes(biguint64, newByteLength, isLittleEndian),[[Block]]buffer.[[ArrayBufferByteLengthData]][[ByteIndex]] 为 0,[[ElementSize]] 为 8,从而并发竞争的 SharedArrayBuffer.prototype.grow 调用不会“丢失”(即静默不做任何事)。
Note

上面第二个要求有意未明确说明如何或何时读取 buffer 的当前字节长度。由于字节长度必须通过底层硬件的原子读-改-写操作更新,使用 load-link/store-conditional 或 load-exclusive/store-exclusive 指令对的体系结构可能希望将该指令对在指令流中保持紧邻。因此,SharedArrayBuffer.prototype.grow 自身不会在调用 HostGrowSharedArrayBuffer 前对 newByteLength 做边界检查,也不要求何时读取当前字节长度。

这与 HostResizeArrayBuffer 形成对比,后者被保证 newByteLength 值 ≥ 0 且 ≤ buffer.[[ArrayBufferMaxByteLength]]

HostGrowSharedArrayBuffer 的默认实现是返回 NormalCompletion(unhandled)。

25.2.3 SharedArrayBuffer 构造函数

SharedArrayBuffer 构造函数

  • %SharedArrayBuffer%
  • 若全局对象存在该属性,则为其 "SharedArrayBuffer" 属性的初始值(见下文)。
  • 作为构造函数调用时创建并初始化一个新的 SharedArrayBuffer。
  • 不应作为函数调用;若如此调用将抛出异常。
  • 可作为类定义 extends 子句的值。欲继承指定 SharedArrayBuffer 行为的子类构造函数必须包含对 SharedArrayBuffer 构造函数super 调用,以创建并初始化具有支持 SharedArrayBuffer.prototype 内置方法所需内部状态的子类实例。

宿主不提供对 SharedArrayBuffers 的并发访问时,可以省略全局对象的 "SharedArrayBuffer" 属性。

Note

不同于 ArrayBufferSharedArrayBuffer 不会被分离,其内部 [[ArrayBufferData]] 槽永不为 null

25.2.3.1 SharedArrayBuffer ( length [ , options ] )

该函数被调用时执行以下步骤:

  1. 若 NewTarget 为 undefined,抛出 TypeError 异常。
  2. byteLength 为 ? ToIndex(length)。
  3. requestedMaxByteLength 为 ? GetArrayBufferMaxByteLengthOption(options)。
  4. 返回 ? AllocateSharedArrayBuffer(NewTarget, byteLength, requestedMaxByteLength)。

25.2.4 SharedArrayBuffer 构造函数的属性

SharedArrayBuffer 构造函数

25.2.4.1 SharedArrayBuffer.prototype

SharedArrayBuffer.prototype 的初始值是 SharedArrayBuffer 原型对象

该属性特性为 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

25.2.4.2 get SharedArrayBuffer [ %Symbol.species% ]

SharedArrayBuffer[%Symbol.species%] 是一个存取器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. 返回 this 值。

该函数 "name" 属性的值为 "get [Symbol.species]"

25.2.5 SharedArrayBuffer 原型对象的属性

SharedArrayBuffer 原型对象

  • %SharedArrayBuffer.prototype%
  • 具有 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个普通对象
  • 没有 [[ArrayBufferData]][[ArrayBufferByteLength]] 内部槽。

25.2.5.1 get SharedArrayBuffer.prototype.byteLength

SharedArrayBuffer.prototype.byteLength 是一个存取器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. IsSharedArrayBuffer(O) 为 false,抛出 TypeError 异常。
  4. lengthArrayBufferByteLength(O, seq-cst)。
  5. 返回 𝔽(length)。

25.2.5.2 SharedArrayBuffer.prototype.constructor

SharedArrayBuffer.prototype.constructor 的初始值是 %SharedArrayBuffer%

25.2.5.3 SharedArrayBuffer.prototype.grow ( newLength )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]])。
  3. IsSharedArrayBuffer(O) 为 false,抛出 TypeError 异常。
  4. newByteLength 为 ? ToIndex(newLength)。
  5. hostHandled 为 ? HostGrowSharedArrayBuffer(O, newByteLength)。
  6. hostHandledhandled,返回 undefined
  7. isLittleEndian 为外层 agent 的 Agent Record[[LittleEndian]] 字段的值。
  8. byteLengthBlockO.[[ArrayBufferByteLengthData]]
  9. currentByteLengthRawBytesGetRawBytesFromSharedBlock(byteLengthBlock, 0, biguint64, true, seq-cst)。
  10. newByteLengthRawBytesNumericToRawBytes(biguint64, (newByteLength), isLittleEndian)。
  11. 重复,
    1. 注:这是一个比较并交换循环,确保对同一缓冲区的并行竞争增长是全序的,不会丢失,也不会静默不执行。循环在能够无竞争地尝试增长时退出。
    2. currentByteLength(RawBytesToNumeric(biguint64, currentByteLengthRawBytes, isLittleEndian))。
    3. newByteLength = currentByteLength,返回 undefined
    4. newByteLength < currentByteLengthnewByteLength > O.[[ArrayBufferMaxByteLength]],抛出 RangeError 异常。
    5. byteLengthDeltanewByteLength - currentByteLength
    6. 若无法创建由 byteLengthDelta 个字节组成的新 Shared Data Block 值,抛出 RangeError 异常。
    7. 注:此处未构造并使用新的 Shared Data Block。对可增长 SharedArrayBuffer 的可观察行为通过在构造时分配最大尺寸 Shared Data Block 指定,此步体现实现若内存不足必须抛出 RangeError 的要求。
    8. readByteLengthRawBytesAtomicCompareExchangeInSharedBlock(byteLengthBlock, 0, 8, currentByteLengthRawBytes, newByteLengthRawBytes)。
    9. ByteListEqual(readByteLengthRawBytes, currentByteLengthRawBytes) 为 true,返回 undefined
    10. currentByteLengthRawBytesreadByteLengthRawBytes
Note

禁止比较交换更新长度的虚假失败。若新长度的边界检查通过且实现未耗尽内存,则总会向候选执行添加一个 ReadModifyWriteSharedMemory 事件(即成功的比较交换)。

对 SharedArrayBuffer.prototype.grow 的并行调用是全序的。例如并发的 sab.grow(10)sab.grow(20),二者之一必定赢得竞争。sab.grow(10) 不会在 sab.grow(20) 先发生时收缩 sab;在那种情况下它将抛出 RangeError。

25.2.5.4 get SharedArrayBuffer.prototype.growable

SharedArrayBuffer.prototype.growable 是一个存取器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. IsSharedArrayBuffer(O) 为 false,抛出 TypeError 异常。
  4. IsFixedLengthArrayBuffer(O) 为 false,返回 true;否则返回 false

25.2.5.5 get SharedArrayBuffer.prototype.maxByteLength

SharedArrayBuffer.prototype.maxByteLength 是一个存取器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. IsSharedArrayBuffer(O) 为 false,抛出 TypeError 异常。
  4. IsFixedLengthArrayBuffer(O) 为 true,则
    1. lengthO.[[ArrayBufferByteLength]]
  5. 否则,
    1. lengthO.[[ArrayBufferMaxByteLength]]
  6. 返回 𝔽(length)。

25.2.5.6 SharedArrayBuffer.prototype.slice ( start, end )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[ArrayBufferData]])。
  3. IsSharedArrayBuffer(O) 为 false,抛出 TypeError 异常。
  4. lenArrayBufferByteLength(O, seq-cst)。
  5. relativeStart 为 ? ToIntegerOrInfinity(start)。
  6. relativeStart = -∞,令 first 为 0。
  7. Else if relativeStart < 0,令 firstmax(len + relativeStart, 0)。
  8. Else,令 firstmin(relativeStart, len)。
  9. endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  10. relativeEnd = -∞,令 final 为 0。
  11. Else if relativeEnd < 0,令 finalmax(len + relativeEnd, 0)。
  12. Else,令 finalmin(relativeEnd, len)。
  13. newLenmax(final - first, 0)。
  14. ctor 为 ? SpeciesConstructor(O, %SharedArrayBuffer%)。
  15. new 为 ? Construct(ctor, « 𝔽(newLen) »)。
  16. 执行 ? RequireInternalSlot(new, [[ArrayBufferData]])。
  17. IsSharedArrayBuffer(new) 为 false,抛出 TypeError 异常。
  18. new.[[ArrayBufferData]]O.[[ArrayBufferData]],抛出 TypeError 异常。
  19. ArrayBufferByteLength(new, seq-cst) < newLen,抛出 TypeError 异常。
  20. fromBufO.[[ArrayBufferData]]
  21. toBufnew.[[ArrayBufferData]]
  22. 执行 CopyDataBlockBytes(toBuf, 0, fromBuf, first, newLen)。
  23. 返回 new

25.2.5.7 SharedArrayBuffer.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串 "SharedArrayBuffer"

该属性特性为 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

25.2.6 SharedArrayBuffer 实例的属性

SharedArrayBuffer 实例从 SharedArrayBuffer 原型对象继承属性。每个 SharedArrayBuffer 实例都有一个 [[ArrayBufferData]] 内部槽。不可增长的 SharedArrayBuffer 实例各自具有一个 [[ArrayBufferByteLength]] 内部槽。可增长的 SharedArrayBuffer 实例各自具有一个 [[ArrayBufferByteLengthData]] 内部槽和一个 [[ArrayBufferMaxByteLength]] 内部槽。

Note

SharedArrayBuffer 实例与 ArrayBuffer 实例不同,永远不会被分离。

25.2.7 可增长 SharedArrayBuffer 指南

Note 1

以下是供使用可增长 SharedArrayBuffer 的 ECMAScript 程序员的指南。

建议在部署环境中(若可行)对程序进行测试。不同硬件设备的可用物理内存差异巨大;虚拟内存子系统同样因硬件与操作系统不同而显著差异。一个在 64 位桌面浏览器中无内存耗尽错误的应用,可能在 32 位移动浏览器中耗尽内存。

可增长 SharedArrayBuffer 选择 "maxByteLength" 选项时,建议选择应用所需的最小可能值。建议 "maxByteLength" 不超过 1073741824(即 1GiB)。

请注意:成功构造一个指定最大值的可增长 SharedArrayBuffer 并不保证后续的增长操作一定成功。

可增长 SharedArrayBuffer 的长度的所有读取并非都是同步的 seq-cst 读取。用于整数索引属性访问(如 u8[idx])的边界检查中的长度读取不是同步的。一般而言,在缺乏显式同步的情况下,一个属性访问在边界内并不意味着同一 agent 中后续的另一个属性访问也在边界内。相比之下,通过 SharedArrayBuffer、%TypedArray%.prototype 和 DataView.prototype 上的 lengthbyteLength getter 对长度的显式读取是同步的。内置方法为检查 TypedArray 是否完全越界而执行的长度读取也是同步的。

Note 2

以下是实现可增长 SharedArrayBuffer 的 ECMAScript 实现者的指南。

建议将可增长 SharedArrayBuffer 实现为通过预留虚拟内存的原地增长。

由于增长操作可与对可增长 SharedArrayBuffer 的内存访问并行发生,内存模型的约束要求即便是无序访问也不得“撕裂”(其值的比特不会混杂)。实际上,这意味着可增长 SharedArrayBuffer 的底层数据块不能在不停顿世界的情况下通过复制来增长。我们不建议以停顿世界作为实现策略,因为它引入串行化点且速度慢。

被增长的内存在创建时必须表现为已归零,包括对任何并行的竞争访问。这可通过按需零填充的虚拟内存页实现,或在手动清零内存时使用谨慎的同步。

针对可增长 SharedArrayBufferTypedArray 视图的整数索引属性访问,旨在可与针对不可增长 SharedArrayBufferTypedArray 视图访问类似地优化,因为整数索引属性读取在底层缓冲区长度上不是同步操作(见上面的程序员指南)。例如,属性访问的边界检查仍可被提升出循环。

在没有虚拟内存的宿主(例如无 MMU 的嵌入式设备)上通过复制实现可增长 SharedArrayBuffer 在实践中很困难。此类宿主可增长 SharedArrayBuffer 的内存使用行为可能与具备虚拟内存的宿主显著不同。这些宿主应清晰地向用户传达内存使用期望。

25.3 DataView 对象

25.3.1 DataView 对象的抽象操作

25.3.1.1 具有缓冲区见证记录的 DataView

具有缓冲区见证记录的 DataView 是一个 Record 值,用于封装一个 DataView 以及已查看缓冲区的缓存字节长度。当被查看缓冲区是可增长 SharedArrayBuffers 时,它用于帮助确保对字节长度数据块只有一次共享内存读取事件。

具有缓冲区见证记录的 DataView 拥有 Table 75 中列出的字段。

Table 75: 具有缓冲区见证记录的 DataView 字段
字段名 含义
[[Object]] a DataView 其缓冲区字节长度被加载的 DataView 对象。
[[CachedBufferByteLength]] a non-negative integer or detached Record 创建时对象的 [[ViewedArrayBuffer]] 的字节长度。

25.3.1.2 MakeDataViewWithBufferWitnessRecord ( obj, order )

The abstract operation MakeDataViewWithBufferWitnessRecord takes arguments obj (a DataView) and order (seq-cst or unordered) and returns a DataView With Buffer Witness Record. It performs the following steps when called:

  1. bufferobj.[[ViewedArrayBuffer]]
  2. IsDetachedBuffer(buffer) 为 true,则
    1. byteLengthdetached
  3. 否则,
    1. byteLengthArrayBufferByteLength(buffer, order)。
  4. 返回 DataView With Buffer Witness Record { [[Object]]: obj, [[CachedBufferByteLength]]: byteLength }。

25.3.1.3 GetViewByteLength ( viewRecord )

The abstract operation GetViewByteLength takes argument viewRecord (a DataView With Buffer Witness Record) and returns a non-negative integer. It performs the following steps when called:

  1. 断言:IsViewOutOfBounds(viewRecord) 为 false
  2. viewviewRecord.[[Object]]
  3. view.[[ByteLength]] 不为 auto,返回 view.[[ByteLength]]
  4. 断言:IsFixedLengthArrayBuffer(view.[[ViewedArrayBuffer]]) 为 false
  5. byteOffsetview.[[ByteOffset]]
  6. byteLengthviewRecord.[[CachedBufferByteLength]]
  7. 断言:byteLength 不为 detached
  8. 返回 byteLength - byteOffset

25.3.1.4 IsViewOutOfBounds ( viewRecord )

The abstract operation IsViewOutOfBounds takes argument viewRecord (a DataView With Buffer Witness Record) and returns a Boolean. It performs the following steps when called:

  1. viewviewRecord.[[Object]]
  2. bufferByteLengthviewRecord.[[CachedBufferByteLength]]
  3. 断言:IsDetachedBuffer(view.[[ViewedArrayBuffer]]) 为 true 当且仅当 bufferByteLengthdetached
  4. bufferByteLengthdetached,返回 true
  5. byteOffsetStartview.[[ByteOffset]]
  6. view.[[ByteLength]]auto,则
    1. byteOffsetEndbufferByteLength
  7. 否则,
    1. byteOffsetEndbyteOffsetStart + view.[[ByteLength]]
  8. byteOffsetStart > bufferByteLengthbyteOffsetEnd > bufferByteLength,返回 true
  9. 注:长度为 0 的 DataView 不被视为越界。
  10. 返回 false

25.3.1.5 GetViewValue ( view, requestIndex, isLittleEndian, type )

The abstract operation GetViewValue takes arguments view (an ECMAScript language value), requestIndex (an ECMAScript language value), isLittleEndian (an ECMAScript language value), and type (a TypedArray element type) and returns 要么是包含 Number 或 BigInt 的正常完成要么是抛出完成. 供 DataView 实例上的函数使用以从其视图缓冲区读取值。 It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(view, [[DataView]])。
  2. 断言:view 具有 [[ViewedArrayBuffer]] 内部槽。
  3. getIndex 为 ? ToIndex(requestIndex)。
  4. isLittleEndianToBoolean(isLittleEndian)。
  5. viewOffsetview.[[ByteOffset]]
  6. viewRecordMakeDataViewWithBufferWitnessRecord(view, unordered)。
  7. 注:当 view 的后备缓冲区是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  8. IsViewOutOfBounds(viewRecord) 为 true,抛出 TypeError 异常。
  9. viewSizeGetViewByteLength(viewRecord)。
  10. elementSizeTable 73 中元素类型 type 指定的元素大小值。
  11. getIndex + elementSize > viewSize,抛出 RangeError 异常。
  12. bufferIndexgetIndex + viewOffset
  13. 返回 GetValueFromBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, false, unordered, isLittleEndian)。

25.3.1.6 SetViewValue ( view, requestIndex, isLittleEndian, type, value )

The abstract operation SetViewValue takes arguments view (an ECMAScript language value), requestIndex (an ECMAScript language value), isLittleEndian (an ECMAScript language value), type (a TypedArray element type), and value (an ECMAScript language value) and returns 要么是包含 undefined正常完成要么是抛出完成. 供 DataView 实例上的函数使用以向其视图缓冲区存储值。 It performs the following steps when called:

  1. 执行 ? RequireInternalSlot(view, [[DataView]])。
  2. 断言:view 具有 [[ViewedArrayBuffer]] 内部槽。
  3. getIndex 为 ? ToIndex(requestIndex)。
  4. IsBigIntElementType(type) 为 true,令 numberValue 为 ? ToBigInt(value)。
  5. 否则,令 numberValue 为 ? ToNumber(value)。
  6. isLittleEndianToBoolean(isLittleEndian)。
  7. viewOffsetview.[[ByteOffset]]
  8. viewRecordMakeDataViewWithBufferWitnessRecord(view, unordered)。
  9. 注:当 view 的后备缓冲区是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  10. IsViewOutOfBounds(viewRecord) 为 true,抛出 TypeError 异常。
  11. viewSizeGetViewByteLength(viewRecord)。
  12. elementSizeTable 73 中元素类型 type 指定的元素大小值。
  13. getIndex + elementSize > viewSize,抛出 RangeError 异常。
  14. bufferIndexgetIndex + viewOffset
  15. 执行 SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian)。
  16. 返回 undefined

25.3.2 DataView 构造函数

DataView 构造函数

  • %DataView%
  • 是全局对象 "DataView" 属性的初始值。
  • 作为构造函数调用时创建并初始化一个新的 DataView。
  • 不应作为函数调用;若如此调用将抛出异常。
  • 可作为类定义 extends 子句的值。欲继承指定 DataView 行为的子类构造函数必须包含对 DataView 构造函数super 调用,以创建并初始化具有支持 DataView.prototype 内置方法所需内部状态的子类实例。

25.3.2.1 DataView ( buffer [ , byteOffset [ , byteLength ] ] )

该函数被调用时执行以下步骤:

  1. 若 NewTarget 为 undefined,抛出 TypeError 异常。
  2. 执行 ? RequireInternalSlot(buffer, [[ArrayBufferData]])。
  3. offset 为 ? ToIndex(byteOffset)。
  4. IsDetachedBuffer(buffer) 为 true,抛出 TypeError 异常。
  5. bufferByteLengthArrayBufferByteLength(buffer, seq-cst)。
  6. offset > bufferByteLength,抛出 RangeError 异常。
  7. bufferIsFixedLengthIsFixedLengthArrayBuffer(buffer)。
  8. byteLengthundefined,则
    1. bufferIsFixedLengthtrue,则
      1. viewByteLengthbufferByteLength - offset
    2. 否则,
      1. viewByteLengthauto
  9. 否则,
    1. viewByteLength 为 ? ToIndex(byteLength)。
    2. offset + viewByteLength > bufferByteLength,抛出 RangeError 异常。
  10. O 为 ? OrdinaryCreateFromConstructor(NewTarget, "%DataView.prototype%", « [[DataView]], [[ViewedArrayBuffer]], [[ByteLength]], [[ByteOffset]] »)。
  11. IsDetachedBuffer(buffer) 为 true,抛出 TypeError 异常。
  12. bufferByteLengthArrayBufferByteLength(buffer, seq-cst)。
  13. offset > bufferByteLength,抛出 RangeError 异常。
  14. byteLength 不为 undefined,则
    1. offset + viewByteLength > bufferByteLength,抛出 RangeError 异常。
  15. O.[[ViewedArrayBuffer]]buffer
  16. O.[[ByteLength]]viewByteLength
  17. O.[[ByteOffset]]offset
  18. 返回 O

25.3.3 DataView 构造函数的属性

DataView 构造函数

25.3.3.1 DataView.prototype

DataView.prototype 的初始值是 DataView 原型对象

该属性特性为 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

25.3.4 DataView 原型对象的属性

DataView 原型对象

  • %DataView.prototype%
  • 具有 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个普通对象
  • 没有 [[DataView]][[ViewedArrayBuffer]][[ByteLength]][[ByteOffset]] 内部槽。

25.3.4.1 get DataView.prototype.buffer

DataView.prototype.buffer 是一个存取器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[DataView]])。
  3. 断言:O 具有 [[ViewedArrayBuffer]] 内部槽。
  4. bufferO.[[ViewedArrayBuffer]]
  5. 返回 buffer

25.3.4.2 get DataView.prototype.byteLength

DataView.prototype.byteLength 是一个存取器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[DataView]])。
  3. 断言:O 具有 [[ViewedArrayBuffer]] 内部槽。
  4. viewRecordMakeDataViewWithBufferWitnessRecord(O, seq-cst)。
  5. IsViewOutOfBounds(viewRecord) 为 true,抛出 TypeError 异常。
  6. sizeGetViewByteLength(viewRecord)。
  7. 返回 𝔽(size)。

25.3.4.3 get DataView.prototype.byteOffset

DataView.prototype.byteOffset 是一个存取器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[DataView]])。
  3. 断言:O 具有 [[ViewedArrayBuffer]] 内部槽。
  4. viewRecordMakeDataViewWithBufferWitnessRecord(O, seq-cst)。
  5. IsViewOutOfBounds(viewRecord) 为 true,抛出 TypeError 异常。
  6. offsetO.[[ByteOffset]]
  7. 返回 𝔽(offset)。

25.3.4.4 DataView.prototype.constructor

DataView.prototype.constructor 的初始值是 %DataView%

25.3.4.5 DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? GetViewValue(view, byteOffset, littleEndian, bigint64)。

25.3.4.6 DataView.prototype.getBigUint64 ( byteOffset [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? GetViewValue(view, byteOffset, littleEndian, biguint64)。

25.3.4.7 DataView.prototype.getFloat16 ( byteOffset [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. littleEndian 不存在,设 littleEndianfalse
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, float16)。

25.3.4.8 DataView.prototype.getFloat32 ( byteOffset [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. littleEndian 不存在,设 littleEndianfalse
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, float32)。

25.3.4.9 DataView.prototype.getFloat64 ( byteOffset [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. littleEndian 不存在,设 littleEndianfalse
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, float64)。

25.3.4.10 DataView.prototype.getInt8 ( byteOffset )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? GetViewValue(view, byteOffset, true, int8)。

25.3.4.11 DataView.prototype.getInt16 ( byteOffset [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. littleEndian 不存在,设 littleEndianfalse
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, int16)。

25.3.4.12 DataView.prototype.getInt32 ( byteOffset [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. littleEndian 不存在,设 littleEndianfalse
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, int32)。

25.3.4.13 DataView.prototype.getUint8 ( byteOffset )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? GetViewValue(view, byteOffset, true, uint8)。

25.3.4.14 DataView.prototype.getUint16 ( byteOffset [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. littleEndian 不存在,设 littleEndianfalse
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, uint16)。

25.3.4.15 DataView.prototype.getUint32 ( byteOffset [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. littleEndian 不存在,设 littleEndianfalse
  3. 返回 ? GetViewValue(view, byteOffset, littleEndian, uint32)。

25.3.4.16 DataView.prototype.setBigInt64 ( byteOffset, value [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? SetViewValue(view, byteOffset, littleEndian, bigint64, value)。

25.3.4.17 DataView.prototype.setBigUint64 ( byteOffset, value [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? SetViewValue(view, byteOffset, littleEndian, biguint64, value)。

25.3.4.18 DataView.prototype.setFloat16 ( byteOffset, value [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. littleEndian 不存在,设 littleEndianfalse
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, float16, value)。

25.3.4.19 DataView.prototype.setFloat32 ( byteOffset, value [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. littleEndian 不存在,设 littleEndianfalse
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, float32, value)。

25.3.4.20 DataView.prototype.setFloat64 ( byteOffset, value [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. littleEndian 不存在,设 littleEndianfalse
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, float64, value)。

25.3.4.21 DataView.prototype.setInt8 ( byteOffset, value )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? SetViewValue(view, byteOffset, true, int8, value)。

25.3.4.22 DataView.prototype.setInt16 ( byteOffset, value [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. littleEndian 不存在,设 littleEndianfalse
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, int16, value)。

25.3.4.23 DataView.prototype.setInt32 ( byteOffset, value [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. littleEndian 不存在,设 littleEndianfalse
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, int32, value)。

25.3.4.24 DataView.prototype.setUint8 ( byteOffset, value )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. 返回 ? SetViewValue(view, byteOffset, true, uint8, value)。

25.3.4.25 DataView.prototype.setUint16 ( byteOffset, value [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. littleEndian 不存在,设 littleEndianfalse
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, uint16, value)。

25.3.4.26 DataView.prototype.setUint32 ( byteOffset, value [ , littleEndian ] )

该方法被调用时执行以下步骤:

  1. viewthis 值。
  2. littleEndian 不存在,设 littleEndianfalse
  3. 返回 ? SetViewValue(view, byteOffset, littleEndian, uint32, value)。

25.3.4.27 DataView.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串 "DataView"

该属性特性为 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

25.3.5 DataView 实例的属性

DataView 实例是从 DataView 原型对象继承属性的普通对象。每个 DataView 实例具有 [[DataView]][[ViewedArrayBuffer]][[ByteLength]][[ByteOffset]] 内部槽。

Note

[[DataView]] 内部槽的值不在本规范中使用。该内部槽的简单存在用于在规范中识别由 DataView 构造函数创建的对象。

25.4 Atomics 对象

Atomics 对象:

  • %Atomics%
  • 是全局对象 "Atomics" 属性的初始值。
  • 是一个普通对象
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 没有 [[Construct]] 内部方法;不能与 new 运算符一起作为构造函数使用。
  • 没有 [[Call]] 内部方法;不能作为函数调用。

Atomics 对象提供在共享内存数组单元上不可分割(原子)操作的函数,以及让 agent 等待和派发原始事件(primitive events)的函数。正确使用 Atomics 函数,可以让通过共享内存通信的多 agent 程序即便在并行 CPU 上也按照可理解的顺序执行。共享内存通信的规则由下文定义的内存模型提供。

Note

关于在 ECMAScript 中编程与实现共享内存的说明性指南,请参见内存模型章节末尾的注释。

25.4.1 Waiter Record

Waiter Record 是一个 Record 值,用于表示一次对 Atomics.waitAtomics.waitAsync 的特定调用。

Waiter Record 拥有 Table 76 中列出的字段。

Table 76: Waiter Record 字段
字段名 取值 含义
[[AgentSignifier]] 一个 agent 标识符 调用 Atomics.waitAtomics.waitAsync 的 agent。
[[PromiseCapability]] 一个 PromiseCapability Recordblocking 若表示一次对 Atomics.waitAsync 的调用,则为生成的 promise,否则为 blocking
[[TimeoutTime]] 一个非负扩展数学值 可能触发超时的最早时间;使用时间值计算。
[[Result]] "ok""timed-out" 调用的返回值。

25.4.2 WaiterList Records

WaiterList Record 用于解释通过 Atomics.waitAtomics.waitAsyncAtomics.notify 进行的等待与通知。

WaiterList Record 拥有 Table 77 中列出的字段。

Table 77: WaiterList Record 字段
字段名 取值 含义
[[Waiters]] 一个 Waiter RecordList 等待与该 WaiterList 关联的位置的 Atomics.waitAtomics.waitAsync 调用。
[[MostRecentLeaveEvent]] 一个 Synchronize 事件empty 最近一次离开其临界区的事件;若从未进入过其临界区则为 empty

在一个 WaiterList 中可以有多个具有相同 agent 标识符的 Waiter Record

agent 集群拥有一个 WaiterList Record 的存储;该存储由 (block, i) 索引,其中 block 是一个 Shared Data Blockiblock 内存中的字节偏移。WaiterList Record 与 agent 无关:在集群中任一 agent 中按 (block, i) 查找都会得到同一 WaiterList Record。

每个 WaiterList Record 有一个 临界区(critical section),控制在求值期间对该 WaiterList Record 的独占访问。一次只能有一个 agent 进入该临界区。进入和离开临界区由抽象操作 EnterCriticalSectionLeaveCriticalSection 控制。对 WaiterList Record 的操作——添加和移除等待的 agent、遍历 agent 列表、挂起与通知列表中的 agent、设置与获取 Synchronize 事件——只能由已进入该临界区的 agent 执行。

25.4.3 Atomics 的抽象操作

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable )

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and returns 要么是包含一个 TypedArray With Buffer Witness Record正常完成,要么是抛出完成. It performs the following steps when called:

  1. taRecord 为 ? ValidateTypedArray(typedArray, unordered)。
  2. 注:当 typedArray 的后备缓冲区是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  3. waitabletrue,则
    1. typedArray.[[TypedArrayName]] 既不是 "Int32Array" 也不是 "BigInt64Array",抛出 TypeError 异常。
  4. 否则,
    1. typeTypedArrayElementType(typedArray)。
    2. IsUnclampedIntegerElementType(type) 为 falseIsBigIntElementType(type) 为 false,抛出 TypeError 异常。
  5. 返回 taRecord

25.4.3.2 ValidateAtomicAccess ( taRecord, requestIndex )

The abstract operation ValidateAtomicAccess takes arguments taRecord (a TypedArray With Buffer Witness Record) and requestIndex (an ECMAScript language value) and returns 要么是包含一个整数的正常完成要么是抛出完成. It performs the following steps when called:

  1. lengthTypedArrayLength(taRecord)。
  2. accessIndex 为 ? ToIndex(requestIndex)。
  3. 断言:accessIndex ≥ 0。
  4. accessIndexlength,抛出 RangeError 异常。
  5. typedArraytaRecord.[[Object]]
  6. elementSizeTypedArrayElementSize(typedArray)。
  7. offsettypedArray.[[ByteOffset]]
  8. 返回 (accessIndex × elementSize) + offset

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex )

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and returns 要么是包含一个整数的正常完成要么是抛出完成. It performs the following steps when called:

  1. taRecord 为 ? ValidateIntegerTypedArray(typedArray, false)。
  2. 返回 ? ValidateAtomicAccess(taRecord, requestIndex)。

25.4.3.4 RevalidateAtomicAccess ( typedArray, byteIndexInBuffer )

The abstract operation RevalidateAtomicAccess takes arguments typedArray (a TypedArray) and byteIndexInBuffer (an integer) and returns 要么是包含 unused正常完成要么是抛出完成. 该操作在 Atomics 方法中所有参数强制类型转换完成后对底层缓冲区中的索引重新验证,因为参数转换可能有任意副作用,会导致缓冲区变为越界。当 typedArray 的后备缓冲区是 SharedArrayBuffer 时该操作不会抛出。 It performs the following steps when called:

  1. taRecordMakeTypedArrayWithBufferWitnessRecord(typedArray, unordered)。
  2. 注:当 typedArray 的后备缓冲区是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  3. IsTypedArrayOutOfBounds(taRecord) 为 true,抛出 TypeError 异常。
  4. 断言:byteIndexInBuffertypedArray.[[ByteOffset]]
  5. byteIndexInBuffertaRecord.[[CachedBufferByteLength]],抛出 RangeError 异常。
  6. 返回 unused

25.4.3.5 GetWaiterList ( block, i )

The abstract operation GetWaiterList takes arguments block (a Shared Data Block) and i (a non-negative integer that is evenly divisible by 4) and returns a WaiterList Record. It performs the following steps when called:

  1. 断言:ii + 3 均是 block 内存中的有效字节偏移。
  2. 返回由 (block, i) 对引用的 WaiterList Record

25.4.3.6 EnterCriticalSection ( WL )

The abstract operation EnterCriticalSection takes argument WL (a WaiterList Record) and returns unused. It performs the following steps when called:

  1. 断言:外层 agent 不在任何 WaiterList Record 的临界区中。
  2. 等待直到没有 agent 在 WL 的临界区中,然后进入 WL 的临界区(期间不允许其他 agent 进入)。
  3. WL.[[MostRecentLeaveEvent]] 不为 empty,则
    1. 注:至少进入过一次临界区的 WL 有由 LeaveCriticalSection 设置的 Synchronize 事件
    2. execution 为外层 agent 的 Agent Record[[CandidateExecution]] 字段。
    3. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
    4. enterEvent 为一个新的 Synchronize 事件
    5. enterEvent 追加到 eventsRecord.[[EventList]]
    6. 将 (WL.[[MostRecentLeaveEvent]], enterEvent) 追加到 eventsRecord.[[AgentSynchronizesWith]]
  4. 返回 unused

当尝试进入临界区的 agent 必须等待另一个 agent 离开时,EnterCriticalSection 存在 争用(contention)。无争用时,EnterCriticalSection 调用的 FIFO 顺序是可观察的;有争用时,实现可选择任意顺序,但不能导致某个 agent 无限期等待。

25.4.3.7 LeaveCriticalSection ( WL )

The abstract operation LeaveCriticalSection takes argument WL (a WaiterList Record) and returns unused. It performs the following steps when called:

  1. 断言:外层 agent 正在 WL 的临界区中。
  2. execution 为外层 agent 的 Agent Record[[CandidateExecution]] 字段。
  3. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
  4. leaveEvent 为一个新的 Synchronize 事件
  5. leaveEvent 追加到 eventsRecord.[[EventList]]
  6. WL.[[MostRecentLeaveEvent]]leaveEvent
  7. 离开 WL 的临界区。
  8. 返回 unused

25.4.3.8 AddWaiter ( WL, waiterRecord )

The abstract operation AddWaiter takes arguments WL (a WaiterList Record) and waiterRecord (a Waiter Record) and returns unused. It performs the following steps when called:

  1. 断言:外层 agent 在 WL 的临界区中。
  2. 断言:WL.[[Waiters]] 中不存在其 [[PromiseCapability]] 字段为 waiterRecord.[[PromiseCapability]][[AgentSignifier]] 字段为 waiterRecord.[[AgentSignifier]]Waiter Record
  3. waiterRecord 追加到 WL.[[Waiters]]
  4. 返回 unused

25.4.3.9 RemoveWaiter ( WL, waiterRecord )

The abstract operation RemoveWaiter takes arguments WL (a WaiterList Record) and waiterRecord (a Waiter Record) and returns unused. It performs the following steps when called:

  1. 断言:外层 agent 在 WL 的临界区中。
  2. 断言:WL.[[Waiters]] 包含 waiterRecord
  3. WL.[[Waiters]] 移除 waiterRecord
  4. 返回 unused

25.4.3.10 RemoveWaiters ( WL, c )

The abstract operation RemoveWaiters takes arguments WL (a WaiterList Record) and c (a non-negative integer or +∞) and returns a List of Waiter Records. It performs the following steps when called:

  1. 断言:外层 agent 在 WL 的临界区中。
  2. lenWL.[[Waiters]] 中元素数量。
  3. nmin(c, len)。
  4. L 为一个 List,其元素为 WL.[[Waiters]] 的前 n 个元素。
  5. 移除 WL.[[Waiters]] 的前 n 个元素。
  6. 返回 L

25.4.3.11 SuspendThisAgent ( WL, waiterRecord )

The abstract operation SuspendThisAgent takes arguments WL (a WaiterList Record) and waiterRecord (a Waiter Record) and returns unused. It performs the following steps when called:

  1. 断言:外层 agent 在 WL 的临界区中。
  2. 断言:WL.[[Waiters]] 包含 waiterRecord
  3. thisAgentAgentSignifier()。
  4. 断言:waiterRecord.[[AgentSignifier]]thisAgent
  5. 断言:waiterRecord.[[PromiseCapability]]blocking
  6. 断言:AgentCanSuspend() 为 true
  7. 执行 LeaveCriticalSection(WL) 并挂起外层 agent 直到时间到达 waiterRecord.[[TimeoutTime]],以一种方式组合操作:使得离开临界区后到挂起生效前到来的通知不会丢失。外层 agent 只能因超时或另一个 agent 使用参数 WLthisAgent 调用 NotifyWaiter(即通过调用 Atomics.notify)而被唤醒。
  8. 执行 EnterCriticalSection(WL)。
  9. 返回 unused

25.4.3.12 NotifyWaiter ( WL, waiterRecord )

The abstract operation NotifyWaiter takes arguments WL (a WaiterList Record) and waiterRecord (a Waiter Record) and returns unused. It performs the following steps when called:

  1. 断言:外层 agent 在 WL 的临界区中。
  2. waiterRecord.[[PromiseCapability]]blocking,则
    1. 唤醒其标识符为 waiterRecord.[[AgentSignifier]] 的 agent。
    2. 注:这会使该 agent 在 SuspendThisAgent 中恢复执行。
  3. 否则若 AgentSignifier() 是 waiterRecord.[[AgentSignifier]],则
    1. promiseCapabilitywaiterRecord.[[PromiseCapability]]
    2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « waiterRecord.[[Result]] »)。
  4. 否则,
    1. 执行 EnqueueResolveInAgentJob(waiterRecord.[[AgentSignifier]], waiterRecord.[[PromiseCapability]], waiterRecord.[[Result]])。
  5. 返回 unused
Note

一个 agent 不得以除传递给宿主之外的任何方式访问另一个 agent 的 promise capability。

25.4.3.13 EnqueueResolveInAgentJob ( agentSignifier, promiseCapability, resolution )

The abstract operation EnqueueResolveInAgentJob takes arguments agentSignifier (an agent signifier), promiseCapability (a PromiseCapability Record), and resolution ("ok" or "timed-out") and returns unused. It performs the following steps when called:

  1. resolveJob 为一个无参数的新 Job 抽象闭包,捕获 agentSignifierpromiseCapabilityresolution,被调用时执行:
    1. 断言:AgentSignifier() 是 agentSignifier
    2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « resolution »)。
    3. 返回 unused
  2. realmInTargetAgent 为 ! GetFunctionRealm(promiseCapability.[[Resolve]])。
  3. 断言:agentSignifierrealmInTargetAgent.[[AgentSignifier]]
  4. 执行 HostEnqueueGenericJob(resolveJob, realmInTargetAgent)。
  5. 返回 unused

25.4.3.14 DoWait ( mode, typedArray, index, value, timeout )

The abstract operation DoWait takes arguments mode (sync or async), typedArray (an ECMAScript language value), index (an ECMAScript language value), value (an ECMAScript language value), and timeout (an ECMAScript language value) and returns 要么是包含一个 Object、"not-equal""timed-out""ok"正常完成,要么是抛出完成. It performs the following steps when called:

  1. taRecord 为 ? ValidateIntegerTypedArray(typedArray, true)。
  2. buffertaRecord.[[Object]].[[ViewedArrayBuffer]]
  3. IsSharedArrayBuffer(buffer) 为 false,抛出 TypeError 异常。
  4. i 为 ? ValidateAtomicAccess(taRecord, index)。
  5. arrayTypeNametypedArray.[[TypedArrayName]]
  6. arrayTypeName"BigInt64Array",令 v 为 ? ToBigInt64(value)。
  7. 否则,令 v 为 ? ToInt32(value)。
  8. q 为 ? ToNumber(timeout)。
  9. qNaN+∞𝔽,令 t 为 +∞;否则若 q-∞𝔽,令 t 为 0;否则令 tmax((q), 0)。
  10. modesyncAgentCanSuspend() 为 false,抛出 TypeError 异常。
  11. blockbuffer.[[ArrayBufferData]]
  12. offsettypedArray.[[ByteOffset]]
  13. byteIndexInBuffer 为 (i × 4) + offset
  14. WLGetWaiterList(block, byteIndexInBuffer)。
  15. modesync,则
    1. promiseCapabilityblocking
    2. resultObjectundefined
  16. 否则,
    1. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
    2. resultObjectOrdinaryObjectCreate(%Object.prototype%)。
  17. 执行 EnterCriticalSection(WL)。
  18. elementTypeTypedArrayElementType(typedArray)。
  19. wGetValueFromBuffer(buffer, byteIndexInBuffer, elementType, true, seq-cst)。
  20. vw,则
    1. 执行 LeaveCriticalSection(WL)。
    2. modesync,返回 "not-equal"
    3. 执行 ! CreateDataPropertyOrThrow(resultObject, "async", false)。
    4. 执行 ! CreateDataPropertyOrThrow(resultObject, "value", "not-equal")。
    5. 返回 resultObject
  21. t = 0 且 modeasync,则
    1. 注:对同步的立即超时没有特殊处理;异步立即超时被特殊处理以快速失败并避免不必要的 Promise 作业。
    2. 执行 LeaveCriticalSection(WL)。
    3. 执行 ! CreateDataPropertyOrThrow(resultObject, "async", false)。
    4. 执行 ! CreateDataPropertyOrThrow(resultObject, "value", "timed-out")。
    5. 返回 resultObject
  22. thisAgentAgentSignifier()。
  23. now 为标识当前时间的时间值 (UTC)。
  24. additionalTimeout 为实现定义的非负数学值
  25. timeoutTime(now) + t + additionalTimeout
  26. 注:当 t 为 +∞ 时,timeoutTime 亦为 +∞。
  27. waiterRecord 为一个新 Waiter Record { [[AgentSignifier]]: thisAgent, [[PromiseCapability]]: promiseCapability, [[TimeoutTime]]: timeoutTime, [[Result]]: "ok" }。
  28. 执行 AddWaiter(WL, waiterRecord)。
  29. modesync,则
    1. 执行 SuspendThisAgent(WL, waiterRecord)。
  30. 否则若 timeoutTime有限的,则
    1. 执行 EnqueueAtomicsWaitAsyncTimeoutJob(WL, waiterRecord)。
  31. 执行 LeaveCriticalSection(WL)。
  32. modesync,返回 waiterRecord.[[Result]]
  33. 执行 ! CreateDataPropertyOrThrow(resultObject, "async", true)。
  34. 执行 ! CreateDataPropertyOrThrow(resultObject, "value", promiseCapability.[[Promise]])。
  35. 返回 resultObject
Note

additionalTimeout 允许实现按需填充超时,例如用于降低能耗或粗化计时器分辨率以缓解计时攻击。该值在不同 DoWait 调用间可能不同。

25.4.3.15 EnqueueAtomicsWaitAsyncTimeoutJob ( WL, waiterRecord )

The abstract operation EnqueueAtomicsWaitAsyncTimeoutJob takes arguments WL (a WaiterList Record) and waiterRecord (a Waiter Record) and returns unused. It performs the following steps when called:

  1. timeoutJob 为一个无参数的新 Job 抽象闭包,捕获 WLwaiterRecord,被调用时执行:
    1. 执行 EnterCriticalSection(WL)。
    2. WL.[[Waiters]] 包含 waiterRecord,则
      1. timeOfJobExecution 为标识当前时间的时间值 (UTC)。
      2. 断言:(timeOfJobExecution) ≥ waiterRecord.[[TimeoutTime]](忽略时间值可能的非单调性)。
      3. waiterRecord.[[Result]]"timed-out"
      4. 执行 RemoveWaiter(WL, waiterRecord)。
      5. 执行 NotifyWaiter(WL, waiterRecord)。
    3. 执行 LeaveCriticalSection(WL)。
    4. 返回 unused
  2. now 为标识当前时间的时间值 (UTC)。
  3. currentRealm当前 Realm Record
  4. 执行 HostEnqueueTimeoutJob(timeoutJob, currentRealm, 𝔽(waiterRecord.[[TimeoutTime]]) - now)。
  5. 返回 unused

25.4.3.16 AtomicCompareExchangeInSharedBlock ( block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes )

The abstract operation AtomicCompareExchangeInSharedBlock takes arguments block (a Shared Data Block), byteIndexInBuffer (an integer), elementSize (a non-negative integer), expectedBytes (a List of byte values), and replacementBytes (a List of byte values) and returns a List of byte values. It performs the following steps when called:

  1. execution 为外层 agent 的 Agent Record[[CandidateExecution]] 字段。
  2. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的 Agent Events Record
  3. rawBytesRead 为长度 elementSizeList,其元素为非确定性选择的字节值
  4. 注:在实现中,rawBytesRead 是底层硬件 load-link、load-exclusive 或读-改-写指令操作数的结果;该非确定性是内存模型对弱一致硬件可观察行为的语义描述。
  5. 注:期望值与读值的比较在读-改-写修改函数之外执行,以避免当期望值不等于读值时产生不必要的强同步。
  6. ByteListEqual(rawBytesRead, expectedBytes) 为 true,则
    1. second 为一个具有参数 (oldBytes, newBytes) 的新读-改-写修改函数,不捕获任何内容,被调用时原子地执行:
      1. 返回 newBytes
    2. eventReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndexInBuffer, [[ElementSize]]: elementSize, [[Payload]]: replacementBytes, [[ModifyOp]]: second }。
  7. 否则,
    1. eventReadSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndexInBuffer, [[ElementSize]]: elementSize }。
  8. event 追加到 eventsRecord.[[EventList]]
  9. Chosen Value Record { [[Event]]: event, [[ChosenValue]]: rawBytesRead } 追加到 execution.[[ChosenValues]]
  10. 返回 rawBytesRead

25.4.3.17 AtomicReadModifyWrite ( typedArray, index, value, op )

The abstract operation AtomicReadModifyWrite takes arguments typedArray (an ECMAScript language value), index (an ECMAScript language value), value (an ECMAScript language value), and op (a read-modify-write modification function) and returns 要么是包含 Number 或 BigInt 的正常完成要么是抛出完成. op 接受两个字节值 List 参数并返回一个字节值 List。该操作原子地加载一个值,将其与另一个值组合并存储组合结果。它返回被加载的值。 It performs the following steps when called:

  1. byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index)。
  2. typedArray.[[ContentType]]bigint,令 v 为 ? ToBigInt(value)。
  3. 否则,令 v𝔽(? ToIntegerOrInfinity(value))。
  4. 执行 ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer)。
  5. buffertypedArray.[[ViewedArrayBuffer]]
  6. elementTypeTypedArrayElementType(typedArray)。
  7. 返回 GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op)。

25.4.3.18 ByteListBitwiseOp ( op, xBytes, yBytes )

The abstract operation ByteListBitwiseOp takes arguments op (&, ^, or |), xBytes (a List of byte values), and yBytes (a List of byte values) and returns a List of byte values. 该操作对参数的所有字节值执行按位运算并返回一个字节值 List。 It performs the following steps when called:

  1. 断言:xBytesyBytes 拥有相同数量的元素。
  2. result 为新空 List
  3. i 为 0。
  4. xBytes 的每个元素 xByte,执行
    1. yByteyBytes[i]。
    2. op&,则
      1. resultByte 为对 xByteyByte 执行按位与的结果。
    3. 否则若 op^,则
      1. resultByte 为按位异或结果。
    4. 否则,
      1. 断言:op|
      2. resultByte 为按位或结果。
    5. ii + 1。
    6. resultByte 追加到 result
  5. 返回 result

25.4.3.19 ByteListEqual ( xBytes, yBytes )

The abstract operation ByteListEqual takes arguments xBytes (a List of byte values) and yBytes (a List of byte values) and returns a Boolean. It performs the following steps when called:

  1. xBytesyBytes 的元素数量不同,返回 false
  2. i 为 0。
  3. xBytes 的每个元素 xByte,执行
    1. yByteyBytes[i]。
    2. xByteyByte,返回 false
    3. ii + 1。
  4. 返回 true

25.4.4 Atomics.add ( typedArray, index, value )

该函数被调用时执行以下步骤:

  1. add 为一个具有参数 (xBytes, yBytes) 的新读-改-写修改函数,捕获 typedArray,被调用时原子地执行:
    1. typeTypedArrayElementType(typedArray)。
    2. isLittleEndian 为外层 agent 的 Agent Record[[LittleEndian]] 字段的值。
    3. xRawBytesToNumeric(type, xBytes, isLittleEndian)。
    4. yRawBytesToNumeric(type, yBytes, isLittleEndian)。
    5. x 是 Number,则
      1. sumNumber::add(x, y)。
    6. 否则,
      1. 断言:x 是 BigInt
      2. sumBigInt::add(x, y)。
    7. sumBytesNumericToRawBytes(type, sum, isLittleEndian)。
    8. 断言:sumBytesxBytesyBytes 拥有相同数量的元素。
    9. 返回 sumBytes
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, add)。

25.4.5 Atomics.and ( typedArray, index, value )

该函数被调用时执行以下步骤:

  1. and 为一个具有参数 (xBytes, yBytes) 的新读-改-写修改函数,不捕获任何内容,被调用时原子地执行:
    1. 返回 ByteListBitwiseOp(&, xBytes, yBytes)。
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, and)。

25.4.6 Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue )

该函数被调用时执行以下步骤:

  1. byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index)。
  2. buffertypedArray.[[ViewedArrayBuffer]]
  3. blockbuffer.[[ArrayBufferData]]
  4. typedArray.[[ContentType]]bigint,则
    1. expected 为 ? ToBigInt(expectedValue)。
    2. replacement 为 ? ToBigInt(replacementValue)。
  5. 否则,
    1. expected𝔽(? ToIntegerOrInfinity(expectedValue))。
    2. replacement𝔽(? ToIntegerOrInfinity(replacementValue))。
  6. 执行 ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer)。
  7. elementTypeTypedArrayElementType(typedArray)。
  8. elementSizeTypedArrayElementSize(typedArray)。
  9. isLittleEndian 为外层 agent 的 Agent Record[[LittleEndian]] 字段的值。
  10. expectedBytesNumericToRawBytes(elementType, expected, isLittleEndian)。
  11. replacementBytesNumericToRawBytes(elementType, replacement, isLittleEndian)。
  12. IsSharedArrayBuffer(buffer) 为 true,则
    1. rawBytesReadAtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes)。
  13. 否则,
    1. rawBytesRead 为长度 elementSizeList,其元素为自 block[byteIndexInBuffer] 起的 elementSize 个字节。
    2. ByteListEqual(rawBytesRead, expectedBytes) 为 true,则
      1. replacementBytes 的各字节写入 block,起始于 block[byteIndexInBuffer]。
  14. 返回 RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian)。

25.4.7 Atomics.exchange ( typedArray, index, value )

该函数被调用时执行以下步骤:

  1. second 为一个具有参数 (oldBytes, newBytes) 的新读-改-写修改函数,不捕获任何内容,被调用时原子地执行:
    1. 返回 newBytes
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, second)。

25.4.8 Atomics.isLockFree ( size )

该函数被调用时执行以下步骤:

  1. n 为 ? ToIntegerOrInfinity(size)。
  2. AR 为外层 agent 的 Agent Record
  3. n = 1,返回 AR.[[IsLockFree1]]
  4. n = 2,返回 AR.[[IsLockFree2]]
  5. n = 4,返回 true
  6. n = 8,返回 AR.[[IsLockFree8]]
  7. 返回 false
Note

此函数是一个优化原语。直觉是:如果大小为 n 字节的数据上的原子原语(compareExchangeloadstoreaddsubandorxorexchange)的原子步骤会在不获取该数据之外的锁的情况下执行,则 Atomics.isLockFree(n) 返回 true。高性能算法将利用该函数决定是否在临界区使用锁或原子操作。若原子原语不是无锁的,算法自行提供锁常常更高效。

Atomics.isLockFree(4) 总是返回 true,因为所有已知相关硬件都能支持。可假定此点通常简化程序。

无论此函数返回何值,所有原子操作都保证原子性。例如,它们不会在操作中间出现可见操作(如“撕裂”)。

25.4.9 Atomics.load ( typedArray, index )

该函数被调用时执行以下步骤:

  1. byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index)。
  2. 执行 ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer)。
  3. buffertypedArray.[[ViewedArrayBuffer]]
  4. elementTypeTypedArrayElementType(typedArray)。
  5. 返回 GetValueFromBuffer(buffer, byteIndexInBuffer, elementType, true, seq-cst)。

25.4.10 Atomics.or ( typedArray, index, value )

该函数被调用时执行以下步骤:

  1. or 为一个具有参数 (xBytes, yBytes) 的新读-改-写修改函数,不捕获任何内容,被调用时原子地执行:
    1. 返回 ByteListBitwiseOp(|, xBytes, yBytes)。
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, or)。

25.4.11 Atomics.store ( typedArray, index, value )

该函数被调用时执行以下步骤:

  1. byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index)。
  2. typedArray.[[ContentType]]bigint,令 v 为 ? ToBigInt(value)。
  3. 否则,令 v𝔽(? ToIntegerOrInfinity(value))。
  4. 执行 ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer)。
  5. buffertypedArray.[[ViewedArrayBuffer]]
  6. elementTypeTypedArrayElementType(typedArray)。
  7. 执行 SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst)。
  8. 返回 v

25.4.12 Atomics.sub ( typedArray, index, value )

该函数被调用时执行以下步骤:

  1. subtract 为一个具有参数 (xBytes, yBytes) 的新读-改-写修改函数,捕获 typedArray,被调用时原子地执行:
    1. typeTypedArrayElementType(typedArray)。
    2. isLittleEndian 为外层 agent 的 Agent Record[[LittleEndian]] 字段的值。
    3. xRawBytesToNumeric(type, xBytes, isLittleEndian)。
    4. yRawBytesToNumeric(type, yBytes, isLittleEndian)。
    5. x 是 Number,则
      1. differenceNumber::subtract(x, y)。
    6. 否则,
      1. 断言:x 是 BigInt
      2. differenceBigInt::subtract(x, y)。
    7. differenceBytesNumericToRawBytes(type, difference, isLittleEndian)。
    8. 断言:differenceBytesxBytesyBytes 拥有相同数量的元素。
    9. 返回 differenceBytes
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, subtract)。

25.4.13 Atomics.wait ( typedArray, index, value, timeout )

该函数将外层 agent 置于等待队列并挂起,直到被通知或等待超时,返回区分这些情形的字符串。

调用时执行以下步骤:

  1. 返回 ? DoWait(sync, typedArray, index, value, timeout)。

25.4.14 Atomics.waitAsync ( typedArray, index, value, timeout )

该函数返回一个 Promise,当调用者 agent 被通知或超时到达时 resolve。

调用时执行以下步骤:

  1. 返回 ? DoWait(async, typedArray, index, value, timeout)。

25.4.15 Atomics.notify ( typedArray, index, count )

该函数通知一些在等待队列中休眠的 agent。

调用时执行以下步骤:

  1. taRecord 为 ? ValidateIntegerTypedArray(typedArray, true)。
  2. byteIndexInBuffer 为 ? ValidateAtomicAccess(taRecord, index)。
  3. countundefined,则
    1. c 为 +∞。
  4. 否则,
    1. intCount 为 ? ToIntegerOrInfinity(count)。
    2. cmax(intCount, 0)。
  5. buffertypedArray.[[ViewedArrayBuffer]]
  6. blockbuffer.[[ArrayBufferData]]
  7. IsSharedArrayBuffer(buffer) 为 false,返回 +0𝔽
  8. WLGetWaiterList(block, byteIndexInBuffer)。
  9. 执行 EnterCriticalSection(WL)。
  10. SRemoveWaiters(WL, c)。
  11. S 的每个元素 W,执行
    1. 执行 NotifyWaiter(WL, W)。
  12. 执行 LeaveCriticalSection(WL)。
  13. nS 中元素数量。
  14. 返回 𝔽(n)。

25.4.16 Atomics.xor ( typedArray, index, value )

该函数被调用时执行以下步骤:

  1. xor 为一个具有参数 (xBytes, yBytes) 的新读-改-写修改函数,不捕获任何内容,被调用时原子地执行:
    1. 返回 ByteListBitwiseOp(^, xBytes, yBytes)。
  2. 返回 ? AtomicReadModifyWrite(typedArray, index, value, xor)。

25.4.17 Atomics [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串 "Atomics"

该属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

25.5 JSON 对象

JSON 对象:

  • %JSON%
  • 是全局对象 "JSON" 属性的初始值。
  • 是一个普通对象
  • 包含两个函数 parsestringify,用于解析与构造 JSON 文本。
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 没有 [[Construct]] 内部方法;不能与 new 运算符一起作为构造函数使用。
  • 没有 [[Call]] 内部方法;不能作为函数调用。

JSON 数据交换格式在 ECMA-404 中定义。本规范使用的 JSON 交换格式完全与 ECMA-404 所描述一致。JSON.parseJSON.stringify 的一致实现必须支持 ECMA-404 规范所描述的精确交换格式,不得删除或扩展该格式。

25.5.1 JSON.parse ( text [ , reviver ] )

该函数解析一个 JSON 文本(JSON 格式的字符串)并生成一个 ECMAScript 语言值。JSON 格式以类似 ECMAScript 字面量、数组初始值与对象初始值的语法表示字面量、数组与对象。解析后,JSON 对象被实现为 ECMAScript 对象;JSON 数组被实现为 ECMAScript Array 实例;JSON 字符串、数字、布尔与 null 分别实现为 ECMAScript 的 String、Number、Boolean 与 null

可选参数 reviver 是一个带两个参数 keyvalue 的函数。它可以过滤并转换结果。解析产生的每个 key/value 对都会调用它,其返回值将替代原始值。若返回收到的值,结构不变;若返回 undefined 则该属性从结果中删除。

  1. jsonString 为 ? ToString(text)。
  2. unfiltered 为 ? ParseJSON(jsonString)。
  3. IsCallable(reviver) 为 true,则
    1. rootOrdinaryObjectCreate(%Object.prototype%)。
    2. rootName 为空字符串。
    3. 执行 ! CreateDataPropertyOrThrow(root, rootName, unfiltered)。
    4. 返回 ? InternalizeJSONProperty(root, rootName, reviver)。
  4. 否则,
    1. 返回 unfiltered

该函数的 "length" 属性为 2𝔽

25.5.1.1 ParseJSON ( text )

The abstract operation ParseJSON takes argument text (a String) and returns 要么是包含一个 ECMAScript 语言值正常完成要么是抛出完成. It performs the following steps when called:

  1. 若 StringToCodePoints(text) 不是 ECMA-404 所规定的有效 JSON 文本,抛出 SyntaxError 异常。
  2. scriptString"("text");" 的字符串连接。
  3. script 为 ParseText(scriptString, Script)。
  4. 注:13.2.5.1 定义的早期错误规则对上述 ParseText 调用有特殊处理。
  5. 断言:script 是一个 Parse Node。
  6. result 为 ! Evaluation of script
  7. 注:13.2.5.5 定义的 PropertyDefinitionEvaluation 语义对上述求值有特殊处理。
  8. 断言:result 不是 String、Number、Boolean、由 ArrayLiteralObjectLiteral 定义的 Object、就是 null
  9. 返回 result

一致实现的 JSON.parse 不允许扩展 JSON 语法。若实现希望支持修改或扩展的 JSON 交换格式,必须定义不同的解析函数。

Note 1

有效 JSON 文本是 ECMAScript PrimaryExpression 语法的子集。步骤 1 验证 jsonString 是否符合该子集,步骤 8 断言求值返回一个适当类型的值。

然而,由于 13.2.5.5 在 ParseJSON 期间行为不同,同一源文本作为 PrimaryExpression 求值与作为 JSON 求值可能产生不同结果。此外,对对象字面量中重复 "__proto__" 属性的 Early Error 在 ParseJSON 中不适用,这意味着尽管语法匹配,并非所有 ParseJSON 接受的文本都可作为 PrimaryExpression 有效。

Note 2

当对象中存在重复名称字符串时,词法上先出现的同键值将被覆盖

25.5.1.2 InternalizeJSONProperty ( holder, name, reviver )

The abstract operation InternalizeJSONProperty takes arguments holder (an Object), name (a String), and reviver (a function object) and returns 要么是包含一个 ECMAScript 语言值正常完成要么是抛出完成.

Note

该算法故意不在 [[Delete]]CreateDataProperty 返回 false 时抛出异常。

调用时执行以下步骤:

  1. val 为 ? Get(holder, name)。
  2. val 是 Object,则
    1. isArray 为 ? IsArray(val)。
    2. isArraytrue,则
      1. len 为 ? LengthOfArrayLike(val)。
      2. I 为 0。
      3. I < len 重复,
        1. prop 为 ! ToString(𝔽(I))。
        2. newElement 为 ? InternalizeJSONProperty(val, prop, reviver)。
        3. newElementundefined,则
          1. 执行 ? val.[[Delete]](prop)。
        4. 否则,
          1. 执行 ? CreateDataProperty(val, prop, newElement)。
        5. II + 1。
    3. 否则,
      1. keys 为 ? EnumerableOwnProperties(val, key)。
      2. keys 的每个 String P,执行
        1. newElement 为 ? InternalizeJSONProperty(val, P, reviver)。
        2. newElementundefined,则
          1. 执行 ? val.[[Delete]](P)。
        3. 否则,
          1. 执行 ? CreateDataProperty(val, P, newElement)。
  3. 返回 ? Call(reviver, holder, « name, val »)。

25.5.2 JSON.stringify ( value [ , replacer [ , space ] ] )

该函数返回一个 UTF-16 编码的 JSON 格式字符串表示一个 ECMAScript 语言值,或 undefined。它可接受三个参数。参数 valueECMAScript 语言值,通常是对象或数组,也可以是 String、Boolean、Number 或 null。可选参数 replacer 要么是函数,改变对象与数组的字符串化方式;要么是由 String 与 Number 组成的数组,充当包含列表,选择会被字符串化的对象属性。可选参数 space 是 String 或 Number,用于在结果中注入空白以提升可读性。

调用时执行以下步骤:

  1. stack 为新空 List
  2. indent 为空字符串。
  3. PropertyListundefined
  4. ReplacerFunctionundefined
  5. replacer 是 Object,则
    1. IsCallable(replacer) 为 true,则
      1. ReplacerFunctionreplacer
    2. 否则,
      1. isArray 为 ? IsArray(replacer)。
      2. isArraytrue,则
        1. PropertyList 为新空 List
        2. len 为 ? LengthOfArrayLike(replacer)。
        3. k 为 0。
        4. k < len 重复,
          1. prop 为 ! ToString(𝔽(k))。
          2. v 为 ? Get(replacer, prop)。
          3. itemundefined
          4. v 是 String,则
            1. itemv
          5. 否则若 v 是 Number,则
            1. item 为 ! ToString(v)。
          6. 否则若 v 是 Object,则
            1. v 具有 [[StringData]][[NumberData]] 内部槽,设 item 为 ? ToString(v)。
          7. item 不为 undefinedPropertyList 不包含 item,则
            1. item 追加到 PropertyList
          8. kk + 1。
  6. space 是 Object,则
    1. space 具有 [[NumberData]] 内部槽,则
      1. space 为 ? ToNumber(space)。
    2. 否则若 space 具有 [[StringData]] 内部槽,则
      1. space 为 ? ToString(space)。
  7. space 是 Number,则
    1. spaceMV 为 ! ToIntegerOrInfinity(space)。
    2. spaceMVmin(10, spaceMV)。
    3. spaceMV < 1,令 gap 为空字符串;否则令 gap 为包含 spaceMV 个代码单元 0x0020 (SPACE) 的字符串。
  8. 否则若 space 是 String,则
    1. space 长度 ≤ 10,令 gapspace;否则令 gapspace 的前 10 个代码单元子串。
  9. 否则,
    1. gap 为空字符串。
  10. wrapperOrdinaryObjectCreate(%Object.prototype%)。
  11. 执行 ! CreateDataPropertyOrThrow(wrapper, 空字符串, value)。
  12. stateJSON Serialization Record { [[ReplacerFunction]]: ReplacerFunction, [[Stack]]: stack, [[Indent]]: indent, [[Gap]]: gap, [[PropertyList]]: PropertyList }。
  13. 返回 ? SerializeJSONProperty(state, 空字符串, wrapper)。

该函数的 "length" 属性为 3𝔽

Note 1

JSON 结构允许任意深度嵌套,但必须非循环。若 value 是或包含循环结构,则该函数必须抛出 TypeError 异常。如下是一个不可字符串化的值示例:

a = [];
a[0] = a;
my_text = JSON.stringify(a); // 必须抛出 TypeError。
Note 2

符号化的原始值呈现如下:

  • null 在 JSON 文本中呈现为字符串值 "null"
  • undefined 不呈现。
  • true 在 JSON 文本中呈现为字符串值 "true"
  • false 在 JSON 文本中呈现为字符串值 "false"
Note 3

字符串值以 QUOTATION MARK (") 代码单元包裹。代码单元 "\\ 前缀转义。控制字符代码单元替换为 \uHHHH 转义序列,或更短形式 \b(BACKSPACE)、\f(FORM FEED)、\n(LINE FEED)、\r(CARRIAGE RETURN)、\t(CHARACTER TABULATION)。

Note 4

有限数字按调用 ToString(number) 的方式字符串化。NaN 与任意符号的 Infinity 表示为字符串值 "null"

Note 5

没有 JSON 表示的值(如 undefined 与函数)不产生字符串,而产生 undefined 值。在数组中这些值表示为字符串值 "null";在对象中不可表示的值会使该属性被排除。

Note 6

对象呈现为 U+007B (LEFT CURLY BRACKET) 后跟零个或多个属性,以 U+002C (COMMA) 分隔,以 U+007D (RIGHT CURLY BRACKET) 结束。属性由表示属性名的带引号字符串、一个 U+003A (COLON) 与字符串化的属性值组成。数组呈现为 U+005B (LEFT SQUARE BRACKET) 开头,零个或多个值以 U+002C (COMMA) 分隔,以 U+005D (RIGHT SQUARE BRACKET) 结束。

25.5.2.1 JSON Serialization Record

JSON Serialization Record 是一个 Record 值,用于实现向 JSON 格式的序列化。

JSON Serialization Record 拥有 Table 78 中列出的字段。

Table 78: JSON Serialization Record 字段
字段名 取值 含义
[[ReplacerFunction]] 一个函数对象undefined 可为对象属性提供替换值的函数(来自 JSON.stringify 的 replacer 参数)。
[[PropertyList]] 一个 String 的 Listundefined 序列化非数组对象时包含的属性名(来自 replacer 参数)。
[[Gap]] 一个 String 缩进单元(来自 space 参数)。
[[Stack]] 一个对象的 List 正在序列化的嵌套对象集合,用于检测循环结构。
[[Indent]] 一个 String 当前缩进。

25.5.2.2 SerializeJSONProperty ( state, key, holder )

The abstract operation SerializeJSONProperty takes arguments state (a JSON Serialization Record), key (a String), and holder (an Object) and returns 要么是包含一个 String 或 undefined正常完成要么是抛出完成. It performs the following steps when called:

  1. value 为 ? Get(holder, key)。
  2. value 是 Objectvalue 是 BigInt,则
    1. toJSON 为 ? GetV(value, "toJSON")。
    2. IsCallable(toJSON) 为 true,则
      1. value 为 ? Call(toJSON, value, « key »)。
  3. state.[[ReplacerFunction]] 不为 undefined,则
    1. value 为 ? Call(state.[[ReplacerFunction]], holder, « key, value »)。
  4. value 是 Object,则
    1. value[[NumberData]] 内部槽,则
      1. value 为 ? ToNumber(value)。
    2. 否则若有 [[StringData]] 内部槽,则
      1. value 为 ? ToString(value)。
    3. 否则若有 [[BooleanData]] 内部槽,则
      1. valuevalue.[[BooleanData]]
    4. 否则若有 [[BigIntData]] 内部槽,则
      1. valuevalue.[[BigIntData]]
  5. valuenull,返回 "null"
  6. valuetrue,返回 "true"
  7. valuefalse,返回 "false"
  8. value 为 String,返回 QuoteJSONString(value)。
  9. value 为 Number,则
    1. value 有限,返回 ! ToString(value)。
    2. 返回 "null"
  10. value 为 BigInt,抛出 TypeError 异常。
  11. value 是 ObjectIsCallable(value) 为 false,则
    1. isArray 为 ? IsArray(value)。
    2. isArraytrue,返回 ? SerializeJSONArray(state, value)。
    3. 返回 ? SerializeJSONObject(state, value)。
  12. 返回 undefined

25.5.2.3 QuoteJSONString ( value )

The abstract operation QuoteJSONString takes argument value (a String) and returns a String. 将 value 用 0x0022 (QUOTATION MARK) 代码单元包裹并对其中某些代码单元转义。该操作将 value 视作 UTF-16 编码的代码点序列,详见 6.1.4。 It performs the following steps when called:

  1. product 为仅由代码单元 0x0022 (QUOTATION MARK) 组成的字符串值。
  2. 对 StringToCodePoints(value) 的每个代码点 C,执行
    1. C 列于 Table 79 “Code Point” 列,则
      1. productproduct 与该行 “Escape Sequence” 列中转义序列的连接。
    2. 否则若 C 数值小于 0x0020 (SPACE) 或与某前导代理后导代理数值相同,则
      1. unit 为数值等于 C 数值的代码单元。
      2. productproductUnicodeEscape(unit) 的连接。
    3. 否则,
      1. productproduct 与 UTF16EncodeCodePoint(C) 的连接。
  3. productproduct 与代码单元 0x0022 (QUOTATION MARK) 的连接。
  4. 返回 product
Table 79: JSON 单字符转义序列
Code Point Unicode 字符名称 转义序列
U+0008 BACKSPACE \b
U+0009 CHARACTER TABULATION \t
U+000A LINE FEED (LF) \n
U+000C FORM FEED (FF) \f
U+000D CARRIAGE RETURN (CR) \r
U+0022 QUOTATION MARK \"
U+005C REVERSE SOLIDUS \\

25.5.2.4 UnicodeEscape ( C )

The abstract operation UnicodeEscape takes argument C (a code unit) and returns a String. 以 Unicode 转义序列表示 C。 It performs the following steps when called:

  1. nC 的数值。
  2. 断言:n ≤ 0xFFFF。
  3. hexn 的字符串表示,按小写十六进制格式。
  4. 返回代码单元 0x005C (REVERSE SOLIDUS)、"u"StringPad(hex, 4, "0", start) 的字符串连接。

25.5.2.5 SerializeJSONObject ( state, value )

The abstract operation SerializeJSONObject takes arguments state (a JSON Serialization Record) and value (an Object) and returns 要么是包含一个 String 的正常完成要么是抛出完成. 序列化一个对象。 It performs the following steps when called:

  1. state.[[Stack]] 包含 value,抛出 TypeError 异常(结构循环)。
  2. value 追加到 state.[[Stack]]
  3. stepBackstate.[[Indent]]
  4. state.[[Indent]]state.[[Indent]]state.[[Gap]] 的连接。
  5. state.[[PropertyList]] 不为 undefined,则
    1. Kstate.[[PropertyList]]
  6. 否则,
    1. K 为 ? EnumerableOwnProperties(value, key)。
  7. partial 为新空 List
  8. K 的每个元素 P,执行
    1. strP 为 ? SerializeJSONProperty(state, P, value)。
    2. strP 不为 undefined,则
      1. memberQuoteJSONString(P)。
      2. membermember":" 的连接。
      3. state.[[Gap]] 非空字符串,则
        1. membermember 与代码单元 0x0020 (SPACE) 的连接。
      4. membermemberstrP 的连接。
      5. member 追加到 partial
  9. partial 为空,则
    1. final"{}"
  10. 否则,
    1. state.[[Gap]] 为空字符串,则
      1. properties 为以代码单元 0x002C (COMMA) 分隔连接 partial 中所有元素字符串的结果(不在首尾插入逗号)。
      2. final"{"properties"}" 的连接。
    2. 否则,
      1. separator 为代码单元 0x002C (COMMA)、代码单元 0x000A (LINE FEED) 与 state.[[Indent]] 的连接。
      2. properties 为以 separator 分隔连接 partial 所有元素字符串的结果(不在首尾插入分隔符)。
      3. final"{"、代码单元 0x000A (LINE FEED)、state.[[Indent]]properties、代码单元 0x000A (LINE FEED)、stepBack"}" 的连接。
  11. 移除 state.[[Stack]] 的最后一个元素。
  12. state.[[Indent]]stepBack
  13. 返回 final

25.5.2.6 SerializeJSONArray ( state, value )

The abstract operation SerializeJSONArray takes arguments state (a JSON Serialization Record) and value (an ECMAScript language value) and returns 要么是包含一个 String 的正常完成要么是抛出完成. 序列化一个数组。 It performs the following steps when called:

  1. state.[[Stack]] 包含 value,抛出 TypeError 异常(结构循环)。
  2. value 追加到 state.[[Stack]]
  3. stepBackstate.[[Indent]]
  4. state.[[Indent]]state.[[Indent]]state.[[Gap]] 的连接。
  5. partial 为新空 List
  6. len 为 ? LengthOfArrayLike(value)。
  7. index 为 0。
  8. index < len 重复,
    1. strP 为 ? SerializeJSONProperty(state, ! ToString(𝔽(index)), value)。
    2. strPundefined,则
      1. "null" 追加到 partial
    3. 否则,
      1. strP 追加到 partial
    4. indexindex + 1。
  9. partial 为空,则
    1. final"[]"
  10. 否则,
    1. state.[[Gap]] 为空字符串,则
      1. properties 为以代码单元 0x002C (COMMA) 分隔连接 partial 所有元素字符串的结果(不在首尾插入逗号)。
      2. final"["properties"]" 的连接。
    2. 否则,
      1. separator 为代码单元 0x002C (COMMA)、代码单元 0x000A (LINE FEED) 与 state.[[Indent]] 的连接。
      2. properties 为以 separator 分隔连接 partial 所有元素字符串的结果(不在首尾插入分隔符)。
      3. final"["、代码单元 0x000A (LINE FEED)、state.[[Indent]]properties、代码单元 0x000A (LINE FEED)、stepBack"]" 的连接。
  11. 移除 state.[[Stack]] 的最后一个元素。
  12. state.[[Indent]]stepBack
  13. 返回 final
Note

数组表示仅包含从 +0𝔽(含)到 array.length(不含)的元素。键不是数组索引的属性被排除。数组字符串化为左方括号、元素(以逗号分隔)与右方括号。

25.5.3 JSON [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串 "JSON"

该属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。