25 구조화된 데이터

25.1 ArrayBuffer 객체

25.1.1 표기법

이 절, 25.4, 그리고 29의 아래 설명들은 read-modify-write 수정 함수 내부 자료 구조를 사용한다.

read-modify-write 수정 함수는 바이트 값의 두 List를 인자로 받아 바이트 값의 List를 반환하는 Abstract Closure로 표현되는 수학적 함수이다. 이러한 Abstract Closure들은 다음 속성을 모두 만족한다:

  • 자신의 모든 알고리즘 단계를 원자적으로 수행한다.
  • 자신의 개별 알고리즘 단계는 관찰 가능하지 않다.
Note

read-modify-write 수정 함수의 알고리즘 단계들이 순수한 수학적 함수를 구성하는지 검증하는 데 도움을 주기 위해, 다음 편집상 규약이 권장된다:

25.1.2 고정 길이 및 크기 조절 가능 ArrayBuffer 객체

고정 길이 ArrayBuffer는 생성 후 바이트 길이가 변경될 수 없는 ArrayBuffer이다.

크기 조절 가능 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 either a normal completion containing an ArrayBuffer or a throw completion. ArrayBuffer를 생성하는 데 사용된다. It performs the following steps when called:

  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty, let allocatingResizableBuffer be true; else let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  5. Let block be ? CreateByteDataBlock(byteLength).
  6. Set obj.[[ArrayBufferData]] to block.
  7. Set obj.[[ArrayBufferByteLength]] to byteLength.
  8. If allocatingResizableBuffer is true, then
    1. If it is not possible to create a Data Block block consisting of maxByteLength bytes, throw a RangeError exception.
    2. NOTE: Resizable ArrayBuffers are designed to be implementable with in-place growth. Implementations may throw if, for example, virtual memory cannot be reserved up front.
    3. Set obj.[[ArrayBufferMaxByteLength]] to maxByteLength.
  9. Return 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. IsGrowableSharedArrayBuffer(arrayBuffer)가 true이면,
    1. bufferByteLengthBlockarrayBuffer.[[ArrayBufferByteLengthData]]라고 하자.
    2. rawLengthGetRawBytesFromSharedBlock(bufferByteLengthBlock, 0, biguint64, true, order)라고 하자.
    3. agentRecord를 주변 agent의 Agent Record라고 하자.
    4. isLittleEndianagentRecord.[[LittleEndian]]이라고 하자.
    5. (RawBytesToNumeric(biguint64, rawLength, isLittleEndian))를 반환한다.
  2. Assert: 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 either a normal completion containing an ArrayBuffer or a throw completion. 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-resizability이고 IsFixedLengthArrayBuffer(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. NOTE: 새 Data Block 생성과 이전 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 either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. Assert: IsSharedArrayBuffer(arrayBuffer)는 false이다.
  2. key가 존재하지 않으면, keyundefined로 설정한다.
  3. arrayBuffer.[[ArrayBufferDetachKey]]key가 아니면, TypeError 예외를 던진다.
  4. arrayBuffer.[[ArrayBufferData]]null로 설정한다.
  5. arrayBuffer.[[ArrayBufferByteLength]]를 0으로 설정한다.
  6. unused를 반환한다.
Note

ArrayBuffer 인스턴스를 detach하면 그 backing store로 사용된 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 either a normal completion containing an ArrayBuffer or a throw completion. srcByteOffset에서 시작해 srcLength 바이트 동안 이어지는 범위에 있는 srcBuffer의 데이터를 복사한 데이터를 가진 새로운 ArrayBuffer를 생성한다. It performs the following steps when called:

  1. Assert: 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 either a normal completion containing either a non-negative integer or empty, or a throw completion. 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 either a normal completion containing either handled or unhandled, or a throw completion. 호스트에게 buffer구현 정의 크기 조절을 수행할 기회를 제공한다. 호스트buffer의 크기 조절을 처리하지 않기로 선택하면, 기본 동작을 위해 unhandled를 반환할 수 있다.

HostResizeArrayBuffer의 구현은 다음 요구사항을 준수해야 한다:

  • 추상 연산buffer를 detach하지 않는다.
  • 추상 연산handled와 함께 정상 완료하면, buffer.[[ArrayBufferByteLength]]newByteLength이다.

HostResizeArrayBuffer의 기본 구현은 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. 인자 typeuint8clamped를 포함하지 않는 Integer 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. typebiguint64 또는 bigint64이면, 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)가 true이고 orderinitunordered도 아니면, 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. elementSize를 요소 타입 type에 대해 Table 70에 지정된 Element Size 값이라고 하자.
  2. isLittleEndianfalse이면, rawBytes 요소들의 순서를 뒤집는다.
  3. typefloat16이면,
    1. valuerawBytes의 바이트 요소들이 연결되어 IEEE 754-2019 binary16 값의 리틀 엔디언 비트 문자열 인코딩으로 해석된 것이라고 하자.
    2. value가 NaN이면, NaN을 반환한다.
    3. value에 대응하는 Number 값을 반환한다.
  4. typefloat32이면,
    1. valuerawBytes의 바이트 요소들이 연결되어 IEEE 754-2019 binary32 값의 리틀 엔디언 비트 문자열 인코딩으로 해석된 것이라고 하자.
    2. value가 NaN이면, NaN을 반환한다.
    3. value에 대응하는 Number 값을 반환한다.
  5. typefloat64이면,
    1. valuerawBytes의 바이트 요소들이 연결되어 IEEE 754-2019 binary64 값의 리틀 엔디언 비트 문자열 인코딩으로 해석된 것이라고 하자.
    2. value가 NaN이면, NaN을 반환한다.
    3. value에 대응하는 Number 값을 반환한다.
  6. IsUnsignedElementType(type)가 true이면,
    1. intValuerawBytes의 바이트 요소들이 연결되어 부호 없는 리틀 엔디언 이진수의 비트 문자열 인코딩으로 해석된 것이라고 하자.
  7. 그렇지 않으면,
    1. intValuerawBytes의 바이트 요소들이 연결되어 비트 길이가 elementSize × 8인 이진 리틀 엔디언 2의 보수 수의 비트 문자열 인코딩으로 해석된 것이라고 하자.
  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. elementSize를 요소 타입 type에 대해 Table 70에 지정된 Element Size 값이라고 하자.
  2. agentRecord를 주변 agent의 Agent Record라고 하자.
  3. executionagentRecord.[[CandidateExecution]]이라고 하자.
  4. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier()인 Agent Events Record라고 하자.
  5. isTypedArraytrue이고 IsNoTearConfiguration(type, order)가 true이면 noTeartrue라고 하자; 그렇지 않으면 noTearfalse라고 하자.
  6. rawValue를 요소들이 비결정적으로 선택된 바이트 값인 길이 elementSizeList라고 하자.
  7. NOTE: 구현에서 rawValue는 기반 하드웨어의 비원자적 또는 원자적 읽기 명령의 결과이다. 비결정성은 약한 일관성을 가진 하드웨어의 관찰 가능한 동작을 설명하기 위한 메모리 모델의 의미론적 규정이다.
  8. readEventReadSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize }라고 하자.
  9. readEventeventsRecord.[[EventList]]에 추가한다.
  10. Chosen Value Record { [[Event]]: readEvent, [[ChosenValue]]: rawValue }를 execution.[[ChosenValues]]에 추가한다.
  11. 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. Assert: IsDetachedBuffer(arrayBuffer)는 false이다.
  2. Assert: arrayBufferbyteIndex에서 시작하여 type의 값을 나타내기에 충분한 바이트가 있다.
  3. blockarrayBuffer.[[ArrayBufferData]]라고 하자.
  4. elementSize를 요소 타입 type에 대해 Table 70에 지정된 Element Size 값이라고 하자.
  5. IsSharedArrayBuffer(arrayBuffer)가 true이면,
    1. Assert: blockShared Data Block이다.
    2. rawValueGetRawBytesFromSharedBlock(block, byteIndex, type, isTypedArray, order)라고 하자.
  6. 그렇지 않으면,
    1. rawValueblock에서 byteIndex(포함)부터 byteIndex + elementSize(제외)까지의 구간에 있는 인덱스의 바이트를 요소로 가지는 List라고 하자.
  7. Assert: rawValue의 요소 개수는 elementSize이다.
  8. isLittleEndian이 존재하지 않으면,
    1. agentRecord를 주변 agent의 Agent Record라고 하자.
    2. isLittleEndianagentRecord.[[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. rawBytesvalue를 roundTiesToEven 모드를 사용하여 IEEE 754-2019 binary16 형식으로 변환한 결과인 2바이트를 요소로 가지는 List라고 하자. 바이트들은 리틀 엔디언 순서로 배치된다. valueNaN이면, rawBytes는 구현이 선택한 임의의 IEEE 754-2019 binary16 형식 NaN 인코딩으로 설정될 수 있다. 구현은 구현이 구별할 수 있는 각 NaN 값에 대해 항상 같은 인코딩을 선택해야 한다.
  2. 그렇지 않고 typefloat32이면,
    1. rawBytesvalue를 roundTiesToEven 모드를 사용하여 IEEE 754-2019 binary32 형식으로 변환한 결과인 4바이트를 요소로 가지는 List라고 하자. 바이트들은 리틀 엔디언 순서로 배치된다. valueNaN이면, rawBytes는 구현이 선택한 임의의 IEEE 754-2019 binary32 형식 NaN 인코딩으로 설정될 수 있다. 구현은 구현이 구별할 수 있는 각 NaN 값에 대해 항상 같은 인코딩을 선택해야 한다.
  3. 그렇지 않고 typefloat64이면,
    1. rawBytesvalueIEEE 754-2019 binary64 형식 인코딩인 8바이트를 요소로 가지는 List라고 하자. 바이트들은 리틀 엔디언 순서로 배치된다. valueNaN이면, rawBytes는 구현이 선택한 임의의 IEEE 754-2019 binary64 형식 NaN 인코딩으로 설정될 수 있다. 구현은 구현이 구별할 수 있는 각 NaN 값에 대해 항상 같은 인코딩을 선택해야 한다.
  4. 그렇지 않으면,
    1. n을 요소 타입 type에 대해 Table 70에 지정된 Element Size 값이라고 하자.
    2. conversionOperation을 요소 타입 type에 대해 Table 70의 “Conversion Operation” 열에 이름이 지정된 추상 연산이라고 하자.
    3. intValue(! conversionOperation(value))라고 하자.
    4. intValue ≥ 0이면,
      1. rawBytesintValuen-바이트 이진 인코딩을 요소로 가지는 List라고 하자. 바이트들은 리틀 엔디언 순서로 정렬된다.
    5. 그렇지 않으면,
      1. rawBytesintValuen-바이트 이진 2의 보수 인코딩을 요소로 가지는 List라고 하자. 바이트들은 리틀 엔디언 순서로 정렬된다.
  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. Assert: IsDetachedBuffer(arrayBuffer)는 false이다.
  2. Assert: arrayBufferbyteIndex에서 시작하여 type의 값을 나타내기에 충분한 바이트가 있다.
  3. Assert: IsBigIntElementType(type)가 true이면 value는 BigInt이고, 그렇지 않으면 value는 Number이다.
  4. blockarrayBuffer.[[ArrayBufferData]]라고 하자.
  5. elementSize를 요소 타입 type에 대해 Table 70에 지정된 Element Size 값이라고 하자.
  6. agentRecord를 주변 agent의 Agent Record라고 하자.
  7. isLittleEndian이 존재하지 않으면,
    1. isLittleEndianagentRecord.[[LittleEndian]]으로 설정한다.
  8. rawBytesNumericToRawBytes(type, value, isLittleEndian)라고 하자.
  9. IsSharedArrayBuffer(arrayBuffer)가 true이면,
    1. executionagentRecord.[[CandidateExecution]]이라고 하자.
    2. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier()인 Agent Events Record라고 하자.
    3. isTypedArraytrue이고 IsNoTearConfiguration(type, order)가 true이면 noTeartrue라고 하자; 그렇지 않으면 noTearfalse라고 하자.
    4. WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes }를 eventsRecord.[[EventList]]에 추가한다.
  10. 그렇지 않으면,
    1. rawBytes의 개별 바이트들을 block[byteIndex]에서 시작하여 block에 저장한다.
  11. 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. Assert: IsDetachedBuffer(arrayBuffer)는 false이다.
  2. Assert: arrayBufferbyteIndex에서 시작하여 type의 값을 나타내기에 충분한 바이트가 있다.
  3. Assert: IsBigIntElementType(type)가 true이면 value는 BigInt이고, 그렇지 않으면 value는 Number이다.
  4. blockarrayBuffer.[[ArrayBufferData]]라고 하자.
  5. elementSize를 요소 타입 type에 대해 Table 70에 지정된 Element Size 값이라고 하자.
  6. agentRecord를 주변 agent의 Agent Record라고 하자.
  7. isLittleEndianagentRecord.[[LittleEndian]]이라고 하자.
  8. rawBytesNumericToRawBytes(type, value, isLittleEndian)라고 하자.
  9. IsSharedArrayBuffer(arrayBuffer)가 true이면,
    1. executionagentRecord.[[CandidateExecution]]이라고 하자.
    2. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier()인 Agent Events Record라고 하자.
    3. rawBytesRead를 요소들이 비결정적으로 선택된 바이트 값인 길이 elementSizeList라고 하자.
    4. NOTE: 구현에서 rawBytesRead는 기반 하드웨어에서 load-link, load-exclusive 또는 read-modify-write 명령의 피연산자 결과이다. 비결정성은 약한 일관성을 가진 하드웨어의 관찰 가능한 동작을 설명하기 위한 메모리 모델의 의미론적 규정이다.
    5. rmwEventReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }라고 하자.
    6. rmwEventeventsRecord.[[EventList]]에 추가한다.
    7. Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead }를 execution.[[ChosenValues]]에 추가한다.
  10. 그렇지 않으면,
    1. rawBytesReadblock[byteIndex]로 시작하는 elementSize개의 바이트 시퀀스를 요소로 가지는 길이 elementSizeList라고 하자.
    2. rawBytesModifiedop(rawBytesRead, rawBytes)라고 하자.
    3. rawBytesModified의 개별 바이트들을 block[byteIndex]에서 시작하여 block에 저장한다.
  11. RawBytesToNumeric(type, rawBytesRead, isLittleEndian)를 반환한다.

25.1.4 ArrayBuffer 생성자

ArrayBuffer 생성자는:

  • %ArrayBuffer%이다.
  • 전역 객체"ArrayBuffer" 속성의 초기값이다.
  • 생성자로 호출될 때 새로운 ArrayBuffer를 생성하고 초기화한다.
  • 함수로 호출되도록 의도되지 않았으며, 그런 방식으로 호출되면 예외를 던진다.
  • 클래스 정의의 extends 절의 값으로 사용될 수 있다. 지정된 ArrayBuffer 동작을 상속하려는 서브클래스 생성자는 ArrayBuffer.prototype 내장 메서드를 지원하는 데 필요한 내부 상태로 서브클래스 인스턴스를 생성하고 초기화하기 위해 ArrayBuffer 생성자에 대한 super 호출을 포함해야 한다.

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 생성자는:

  • 값이 %Function.prototype%[[Prototype]] 내부 슬롯을 가진다.
  • 다음 속성들을 가진다:

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%이다.
  • 값이 %Object.prototype%[[Prototype]] 내부 슬롯을 가진다.
  • 보통 객체이다.
  • [[ArrayBufferData]] 또는 [[ArrayBufferByteLength]] 내부 슬롯을 가지지 않는다.

25.1.6.1 get ArrayBuffer.prototype.byteLength

ArrayBuffer.prototype.byteLength는 set 접근자 함수가 undefined인 접근자 속성이다. 그 get 접근자 함수는 호출될 때 다음 단계를 수행한다:

  1. objthis 값이라고 하자.
  2. RequireInternalSlot(obj, [[ArrayBufferData]])를 수행한다.
  3. IsSharedArrayBuffer(obj)가 true이면, TypeError 예외를 던진다.
  4. IsDetachedBuffer(obj)가 true이면, +0𝔽을 반환한다.
  5. lengthobj.[[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. objthis 값이라고 하자.
  2. RequireInternalSlot(obj, [[ArrayBufferData]])를 수행한다.
  3. IsSharedArrayBuffer(obj)가 true이면, TypeError 예외를 던진다.
  4. IsDetachedBuffer(obj)를 반환한다.

25.1.6.4 get ArrayBuffer.prototype.maxByteLength

ArrayBuffer.prototype.maxByteLength는 set 접근자 함수가 undefined인 접근자 속성이다. 그 get 접근자 함수는 호출될 때 다음 단계를 수행한다:

  1. objthis 값이라고 하자.
  2. RequireInternalSlot(obj, [[ArrayBufferData]])를 수행한다.
  3. IsSharedArrayBuffer(obj)가 true이면, TypeError 예외를 던진다.
  4. IsDetachedBuffer(obj)가 true이면, +0𝔽을 반환한다.
  5. IsFixedLengthArrayBuffer(obj)가 true이면,
    1. lengthobj.[[ArrayBufferByteLength]]라고 하자.
  6. 그렇지 않으면,
    1. lengthobj.[[ArrayBufferMaxByteLength]]라고 하자.
  7. 𝔽(length)를 반환한다.

25.1.6.5 get ArrayBuffer.prototype.resizable

ArrayBuffer.prototype.resizable은 set 접근자 함수가 undefined인 접근자 속성이다. 그 get 접근자 함수는 호출될 때 다음 단계를 수행한다:

  1. objthis 값이라고 하자.
  2. RequireInternalSlot(obj, [[ArrayBufferData]])를 수행한다.
  3. IsSharedArrayBuffer(obj)가 true이면, TypeError 예외를 던진다.
  4. IsFixedLengthArrayBuffer(obj)가 false이면, true를 반환한다.
  5. false를 반환한다.

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

이 메서드는 호출될 때 다음 단계를 수행한다:

  1. objthis 값이라고 하자.
  2. RequireInternalSlot(obj, [[ArrayBufferMaxByteLength]])를 수행한다.
  3. IsSharedArrayBuffer(obj)가 true이면, TypeError 예외를 던진다.
  4. newByteLength를 ? ToIndex(newLength)라고 하자.
  5. IsDetachedBuffer(obj)가 true이면, TypeError 예외를 던진다.
  6. newByteLength > obj.[[ArrayBufferMaxByteLength]]이면, RangeError 예외를 던진다.
  7. hostHandled를 ? HostResizeArrayBuffer(obj, newByteLength)라고 하자.
  8. hostHandledhandled이면, undefined를 반환한다.
  9. oldBlockobj.[[ArrayBufferData]]라고 하자.
  10. newBlock을 ? CreateByteDataBlock(newByteLength)라고 하자.
  11. copyLengthmin(newByteLength, obj.[[ArrayBufferByteLength]])라고 하자.
  12. CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength)를 수행한다.
  13. NOTE: 새 Data Block 생성과 이전 Data Block에서의 복사는 모두 관찰 가능하지 않다. 구현은 이 메서드를 제자리 증가 또는 축소로 구현할 수 있다.
  14. obj.[[ArrayBufferData]]newBlock으로 설정한다.
  15. obj.[[ArrayBufferByteLength]]newByteLength로 설정한다.
  16. undefined를 반환한다.

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

이 메서드는 호출될 때 다음 단계를 수행한다:

  1. objthis 값이라고 하자.
  2. RequireInternalSlot(obj, [[ArrayBufferData]])를 수행한다.
  3. IsSharedArrayBuffer(obj)가 true이면, TypeError 예외를 던진다.
  4. IsDetachedBuffer(obj)가 true이면, TypeError 예외를 던진다.
  5. lenobj.[[ArrayBufferByteLength]]라고 하자.
  6. relativeStart를 ? ToIntegerOrInfinity(start)라고 하자.
  7. relativeStart = -∞이면, first를 0이라고 하자.
  8. 그렇지 않고 relativeStart < 0이면, firstmax(len + relativeStart, 0)이라고 하자.
  9. 그렇지 않으면, firstmin(relativeStart, len)이라고 하자.
  10. endundefined이면 relativeEndlen이라고 하자; 그렇지 않으면 relativeEnd를 ? ToIntegerOrInfinity(end)라고 하자.
  11. relativeEnd = -∞이면, final을 0이라고 하자.
  12. 그렇지 않고 relativeEnd < 0이면, finalmax(len + relativeEnd, 0)이라고 하자.
  13. 그렇지 않으면, finalmin(relativeEnd, len)이라고 하자.
  14. newLenmax(final - first, 0)이라고 하자.
  15. ctor를 ? SpeciesConstructor(obj, %ArrayBuffer%)라고 하자.
  16. new를 ? Construct(ctor, « 𝔽(newLen) »)라고 하자.
  17. RequireInternalSlot(new, [[ArrayBufferData]])를 수행한다.
  18. IsSharedArrayBuffer(new)가 true이면, TypeError 예외를 던진다.
  19. IsDetachedBuffer(new)가 true이면, TypeError 예외를 던진다.
  20. SameValue(new, obj)가 true이면, TypeError 예외를 던진다.
  21. new.[[ArrayBufferByteLength]] < newLen이면, TypeError 예외를 던진다.
  22. NOTE: 위 단계들의 부수 효과로 obj가 detach되었거나 크기가 조절되었을 수 있다.
  23. IsDetachedBuffer(obj)가 true이면, TypeError 예외를 던진다.
  24. fromBufobj.[[ArrayBufferData]]라고 하자.
  25. toBufnew.[[ArrayBufferData]]라고 하자.
  26. currentLenobj.[[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. objthis 값이라고 하자.
  2. ArrayBufferCopyAndDetach(obj, newLength, preserve-resizability)를 반환한다.

25.1.6.9 ArrayBuffer.prototype.transferToFixedLength ( [ newLength ] )

이 메서드는 호출될 때 다음 단계를 수행한다:

  1. objthis 값이라고 하자.
  2. ArrayBufferCopyAndDetach(obj, newLength, fixed-length)를 반환한다.

25.1.6.10 ArrayBuffer.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 속성의 초기값은 String 값 "ArrayBuffer"이다.

이 속성은 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true } 속성 특성을 가진다.

25.1.7 ArrayBuffer 인스턴스의 속성

ArrayBuffer 인스턴스는 ArrayBuffer 프로토타입 객체로부터 속성을 상속한다. 각 ArrayBuffer 인스턴스는 [[ArrayBufferData]] 내부 슬롯, [[ArrayBufferByteLength]] 내부 슬롯, 그리고 [[ArrayBufferDetachKey]] 내부 슬롯을 가진다. 크기 조절 가능 ArrayBuffer 인스턴스는 각각 [[ArrayBufferMaxByteLength]] 내부 슬롯을 가진다.

[[ArrayBufferData]]null인 ArrayBuffer 인스턴스는 detached된 것으로 간주되며, ArrayBuffer 인스턴스에 포함된 데이터에 접근하거나 수정하는 모든 연산자는 실패한다.

[[ArrayBufferDetachKey]]undefined 이외의 값으로 설정된 ArrayBuffer 인스턴스는 모든 DetachArrayBuffer 호출이 동일한 "detach key"를 인자로 전달해야 하며, 그렇지 않으면 TypeError가 발생한다. 이 내부 슬롯은 이 명세의 알고리즘이 아니라 특정 임베딩 환경에 의해서만 설정된다.

25.1.8 크기 조절 가능 ArrayBuffer 지침

Note 1

다음은 크기 조절 가능 ArrayBuffer를 사용하는 ECMAScript 프로그래머를 위한 지침이다.

가능한 경우 프로그램은 배포 환경에서 테스트할 것을 권장한다. 사용 가능한 물리 메모리의 양은 하드웨어 장치마다 크게 다르다. 마찬가지로 가상 메모리 서브시스템도 하드웨어 장치와 운영 체제마다 크게 다르다. 64비트 데스크톱 웹 브라우저에서 메모리 부족 오류 없이 실행되는 애플리케이션이 32비트 모바일 웹 브라우저에서는 메모리가 부족해질 수 있다.

크기 조절 가능 ArrayBuffer에 대한 "maxByteLength" 옵션 값을 선택할 때는 애플리케이션에 가능한 가장 작은 크기를 선택할 것을 권장한다. "maxByteLength"가 1,073,741,824(230 바이트 또는 1GiB)를 초과하지 않을 것을 권장한다.

특정 최대 크기에 대해 크기 조절 가능 ArrayBuffer를 성공적으로 생성했다고 해서 향후 resize가 성공한다는 보장은 없다는 점에 유의하라.

Note 2

다음은 크기 조절 가능 ArrayBuffer를 구현하는 ECMAScript 구현자를 위한 지침이다.

크기 조절 가능 ArrayBuffer는 resize 시 복사, 가상 메모리를 미리 예약하는 제자리 증가, 또는 생성자의 "maxByteLength" 옵션의 서로 다른 값에 대해 두 방식을 조합하여 구현할 수 있다.

웹 브라우저와 같이 호스트가 멀티 테넌트(즉, 많은 ECMAScript 애플리케이션을 동시에 실행)이고 구현이 가상 메모리를 예약하여 제자리 증가를 구현하기로 선택한 경우, 단일 애플리케이션이 가상 메모리 주소 공간을 고갈시킬 가능성을 줄이고 상호 운용성 위험을 줄이기 위해 32비트와 64비트 구현 모두 "maxByteLength" ≥ 1GiB에서 1.5GiB 사이의 값에 대해 예외를 던질 것을 권장한다.

임베디드 장치처럼 MMU가 없는 환경에서 실행되는 호스트와 같이 가상 메모리가 없거나, 호스트가 복사를 통해서만 크기 조절을 구현하는 경우, "maxByteLength" 옵션에 대해 어떤 Number 값도 허용할 수 있다. 그러나 요청된 크기의 메모리 블록을 결코 할당할 수 없다면 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 either a normal completion containing a SharedArrayBuffer or a throw completion. SharedArrayBuffer를 생성하는 데 사용된다. It performs the following steps when called:

  1. Let slots be « [[ArrayBufferData]] ».
  2. If maxByteLength is present and maxByteLength is not empty, let allocatingGrowableBuffer be true; else let allocatingGrowableBuffer be false.
  3. If allocatingGrowableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferByteLengthData]] and [[ArrayBufferMaxByteLength]] to slots.
  4. Else,
    1. Append [[ArrayBufferByteLength]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%SharedArrayBuffer.prototype%", slots).
  6. If allocatingGrowableBuffer is true, let allocLength be maxByteLength; else let allocLength be byteLength.
  7. Let block be ? CreateSharedByteDataBlock(allocLength).
  8. Set obj.[[ArrayBufferData]] to block.
  9. If allocatingGrowableBuffer is true, then
    1. Assert: byteLengthmaxByteLength.
    2. Let byteLengthBlock be ? CreateSharedByteDataBlock(8).
    3. Perform SetValueInBuffer(byteLengthBlock, 0, biguint64, (byteLength), true, seq-cst).
    4. Set obj.[[ArrayBufferByteLengthData]] to byteLengthBlock.
    5. Set obj.[[ArrayBufferMaxByteLength]] to maxByteLength.
  10. Else,
    1. Set obj.[[ArrayBufferByteLength]] to byteLength.
  11. Return obj.

25.2.2.2 IsSharedArrayBuffer ( obj )

The abstract operation IsSharedArrayBuffer takes argument obj (an ArrayBuffer or a SharedArrayBuffer) and returns a Boolean. 객체가 SharedArrayBuffer인지 테스트한다. It performs the following steps when called:

  1. obj.[[ArrayBufferData]]Shared Data Block이면, true를 반환한다.
  2. false를 반환한다.

25.2.2.3 IsGrowableSharedArrayBuffer ( obj )

The abstract operation IsGrowableSharedArrayBuffer takes argument obj (an ArrayBuffer or a SharedArrayBuffer) and returns a Boolean. 객체가 증가 가능 SharedArrayBuffer인지 테스트한다. It performs the following steps when called:

  1. IsSharedArrayBuffer(obj)가 true이고 obj[[ArrayBufferByteLengthData]] 내부 슬롯을 가지면, true를 반환한다.
  2. false를 반환한다.

25.2.2.4 HostGrowSharedArrayBuffer ( buffer, newByteLength )

The host-defined abstract operation HostGrowSharedArrayBuffer takes arguments buffer (a SharedArrayBuffer) and newByteLength (a non-negative integer) and returns either a normal completion containing either handled or unhandled, or a throw completion. 호스트에게 buffer구현 정의 증가를 수행할 기회를 제공한다. 호스트buffer의 증가를 처리하지 않기로 선택하면, 기본 동작을 위해 unhandled를 반환할 수 있다.

HostGrowSharedArrayBuffer의 구현은 다음 요구사항을 준수해야 한다:

  • 추상 연산unhandled와 함께 정상 완료하지 않고, newByteLength < buffer의 현재 바이트 길이이거나 newByteLength > buffer.[[ArrayBufferMaxByteLength]]이면, RangeError 예외를 던진다.
  • agentRecord를 주변 agent의 Agent Record라고 하자. isLittleEndianagentRecord.[[LittleEndian]]이라고 하자. 이 추상 연산handled와 함께 정상 완료하면, [[Order]]seq-cst, [[Payload]]NumericToRawBytes(biguint64, newByteLength, isLittleEndian), [[Block]]buffer.[[ArrayBufferByteLengthData]], [[ByteIndex]]가 0, 그리고 [[ElementSize]]가 8인 WriteSharedMemory 또는 ReadModifyWriteSharedMemory 이벤트가 주변 agent의 candidate execution에 추가되어, SharedArrayBuffer.prototype.grow ( newLength )에 대한 경쟁 호출이 "lost", 즉 조용히 아무것도 하지 않는 일이 없도록 한다.
Note

위 두 번째 요구사항은 buffer의 현재 바이트 길이를 어떻게 또는 언제 읽는지에 대해 의도적으로 모호하다. 바이트 길이는 기반 하드웨어에서 원자적 read-modify-write 연산을 통해 갱신되어야 하므로, load-link/store-conditional 또는 load-exclusive/store-exclusive 명령 쌍을 사용하는 아키텍처는 쌍을 이루는 명령들을 명령 스트림에서 가깝게 유지하고자 할 수 있다. 따라서 SharedArrayBuffer.prototype.grow ( newLength ) 자체는 HostGrowSharedArrayBuffer를 호출하기 전에 newByteLength에 대한 경계 검사를 수행하지 않으며, 현재 바이트 길이가 언제 읽히는지에 대한 요구사항도 없다.

이는 0 ≤ newByteLengthbuffer.[[ArrayBufferMaxByteLength]]가 보장되는 HostResizeArrayBuffer와 대조된다.

HostGrowSharedArrayBuffer의 기본 구현은 NormalCompletion(unhandled)를 반환하는 것이다.

25.2.3 SharedArrayBuffer 생성자

SharedArrayBuffer 생성자는:

  • %SharedArrayBuffer%이다.
  • 해당 속성이 존재한다면(아래 참조), 전역 객체"SharedArrayBuffer" 속성의 초기값이다.
  • 생성자로 호출될 때 새로운 SharedArrayBuffer를 생성하고 초기화한다.
  • 함수로 호출되도록 의도되지 않았으며, 그런 방식으로 호출되면 예외를 던진다.
  • 클래스 정의의 extends 절의 값으로 사용될 수 있다. 지정된 SharedArrayBuffer 동작을 상속하려는 서브클래스 생성자는 SharedArrayBuffer.prototype 내장 메서드를 지원하는 데 필요한 내부 상태로 서브클래스 인스턴스를 생성하고 초기화하기 위해 SharedArrayBuffer 생성자에 대한 super 호출을 포함해야 한다.

호스트가 SharedArrayBuffer에 대한 동시 접근을 제공하지 않을 때마다 전역 객체"SharedArrayBuffer" 속성을 생략할 수 있다.

Note

ArrayBuffer와 달리, SharedArrayBuffer는 detached될 수 없으며 그 내부 [[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 생성자는:

  • 값이 %Function.prototype%[[Prototype]] 내부 슬롯을 가진다.
  • 다음 속성들을 가진다:

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%이다.
  • 값이 %Object.prototype%[[Prototype]] 내부 슬롯을 가진다.
  • 보통 객체이다.
  • [[ArrayBufferData]] 또는 [[ArrayBufferByteLength]] 내부 슬롯을 가지지 않는다.

25.2.5.1 get SharedArrayBuffer.prototype.byteLength

SharedArrayBuffer.prototype.byteLength는 set 접근자 함수가 undefined인 접근자 속성이다. 그 get 접근자 함수는 호출될 때 다음 단계를 수행한다:

  1. objthis 값이라고 하자.
  2. RequireInternalSlot(obj, [[ArrayBufferData]])를 수행한다.
  3. IsSharedArrayBuffer(obj)가 false이면, TypeError 예외를 던진다.
  4. lengthArrayBufferByteLength(obj, seq-cst)라고 하자.
  5. 𝔽(length)를 반환한다.

25.2.5.2 SharedArrayBuffer.prototype.constructor

SharedArrayBuffer.prototype.constructor의 초기값은 %SharedArrayBuffer%이다.

25.2.5.3 SharedArrayBuffer.prototype.grow ( newLength )

이 메서드는 호출될 때 다음 단계를 수행한다:

  1. objthis 값이라고 하자.
  2. RequireInternalSlot(obj, [[ArrayBufferMaxByteLength]])를 수행한다.
  3. IsSharedArrayBuffer(obj)가 false이면, TypeError 예외를 던진다.
  4. newByteLength를 ? ToIndex(newLength)라고 하자.
  5. hostHandled를 ? HostGrowSharedArrayBuffer(obj, newByteLength)라고 하자.
  6. hostHandledhandled이면, undefined를 반환한다.
  7. agentRecord를 주변 agent의 Agent Record라고 하자.
  8. isLittleEndianagentRecord.[[LittleEndian]]이라고 하자.
  9. byteLengthBlockobj.[[ArrayBufferByteLengthData]]라고 하자.
  10. currentByteLengthRawBytesGetRawBytesFromSharedBlock(byteLengthBlock, 0, biguint64, true, seq-cst)라고 하자.
  11. newByteLengthRawBytesNumericToRawBytes(biguint64, (newByteLength), isLittleEndian)라고 하자.
  12. 반복한다,
    1. NOTE: 이는 동일한 버퍼에 대한 병렬적이고 경쟁하는 grow가 전체 순서화되고, lost되지 않으며, 조용히 아무것도 하지 않는 일이 없도록 보장하는 compare-and-exchange 루프이다. 루프는 경쟁 없이 증가를 시도할 수 있었을 때 종료된다.
    2. currentByteLength(RawBytesToNumeric(biguint64, currentByteLengthRawBytes, isLittleEndian))라고 하자.
    3. newByteLength = currentByteLength이면, undefined를 반환한다.
    4. newByteLength < currentByteLength이거나 newByteLength > obj.[[ArrayBufferMaxByteLength]]이면, RangeError 예외를 던진다.
    5. byteLengthDeltanewByteLength - currentByteLength라고 하자.
    6. byteLengthDelta 바이트로 구성된 새로운 Shared Data Block 값을 생성하는 것이 불가능하면, RangeError 예외를 던진다.
    7. NOTE: 여기서는 새로운 Shared Data Block이 생성되어 사용되지 않는다. 증가 가능 SharedArrayBuffer의 관찰 가능한 동작은 생성 시 최대 크기의 Shared Data Block을 할당함으로써 지정되며, 이 단계는 메모리가 부족한 구현이 RangeError를 던져야 한다는 요구사항을 포착한다.
    8. readByteLengthRawBytesAtomicCompareExchangeInSharedBlock(byteLengthBlock, 0, 8, currentByteLengthRawBytes, newByteLengthRawBytes)라고 하자.
    9. ByteListEqual(readByteLengthRawBytes, currentByteLengthRawBytes)가 true이면, undefined를 반환한다.
    10. currentByteLengthRawBytesreadByteLengthRawBytes로 설정한다.
Note

길이를 갱신하는 compare-exchange의 허위 실패는 금지된다. 새 길이에 대한 경계 검사가 통과하고 구현에 메모리 부족이 없다면, ReadModifyWriteSharedMemory 이벤트(즉 성공적인 compare-exchange)가 항상 candidate execution에 추가된다.

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. objthis 값이라고 하자.
  2. RequireInternalSlot(obj, [[ArrayBufferData]])를 수행한다.
  3. IsSharedArrayBuffer(obj)가 false이면, TypeError 예외를 던진다.
  4. IsFixedLengthArrayBuffer(obj)가 false이면, true를 반환한다.
  5. false를 반환한다.

25.2.5.5 get SharedArrayBuffer.prototype.maxByteLength

SharedArrayBuffer.prototype.maxByteLength는 set 접근자 함수가 undefined인 접근자 속성이다. 그 get 접근자 함수는 호출될 때 다음 단계를 수행한다:

  1. objthis 값이라고 하자.
  2. RequireInternalSlot(obj, [[ArrayBufferData]])를 수행한다.
  3. IsSharedArrayBuffer(obj)가 false이면, TypeError 예외를 던진다.
  4. IsFixedLengthArrayBuffer(obj)가 true이면,
    1. lengthobj.[[ArrayBufferByteLength]]라고 하자.
  5. 그렇지 않으면,
    1. lengthobj.[[ArrayBufferMaxByteLength]]라고 하자.
  6. 𝔽(length)를 반환한다.

25.2.5.6 SharedArrayBuffer.prototype.slice ( start, end )

이 메서드는 호출될 때 다음 단계를 수행한다:

  1. objthis 값이라고 하자.
  2. RequireInternalSlot(obj, [[ArrayBufferData]])를 수행한다.
  3. IsSharedArrayBuffer(obj)가 false이면, TypeError 예외를 던진다.
  4. lenArrayBufferByteLength(obj, seq-cst)라고 하자.
  5. relativeStart를 ? ToIntegerOrInfinity(start)라고 하자.
  6. relativeStart = -∞이면, first를 0이라고 하자.
  7. 그렇지 않고 relativeStart < 0이면, firstmax(len + relativeStart, 0)이라고 하자.
  8. 그렇지 않으면, firstmin(relativeStart, len)이라고 하자.
  9. endundefined이면 relativeEndlen이라고 하자; 그렇지 않으면 relativeEnd를 ? ToIntegerOrInfinity(end)라고 하자.
  10. relativeEnd = -∞이면, final을 0이라고 하자.
  11. 그렇지 않고 relativeEnd < 0이면, finalmax(len + relativeEnd, 0)이라고 하자.
  12. 그렇지 않으면, finalmin(relativeEnd, len)이라고 하자.
  13. newLenmax(final - first, 0)이라고 하자.
  14. ctor를 ? SpeciesConstructor(obj, %SharedArrayBuffer%)라고 하자.
  15. new를 ? Construct(ctor, « 𝔽(newLen) »)라고 하자.
  16. RequireInternalSlot(new, [[ArrayBufferData]])를 수행한다.
  17. IsSharedArrayBuffer(new)가 false이면, TypeError 예외를 던진다.
  18. new.[[ArrayBufferData]]obj.[[ArrayBufferData]]이면, TypeError 예외를 던진다.
  19. ArrayBufferByteLength(new, seq-cst) < newLen이면, TypeError 예외를 던진다.
  20. fromBufobj.[[ArrayBufferData]]라고 하자.
  21. toBufnew.[[ArrayBufferData]]라고 하자.
  22. CopyDataBlockBytes(toBuf, 0, fromBuf, first, newLen)를 수행한다.
  23. new를 반환한다.

25.2.5.7 SharedArrayBuffer.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 속성의 초기값은 String 값 "SharedArrayBuffer"이다.

이 속성은 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true } 속성 특성을 가진다.

25.2.6 SharedArrayBuffer 인스턴스의 속성

SharedArrayBuffer 인스턴스는 SharedArrayBuffer 프로토타입 객체로부터 속성을 상속한다. 각 SharedArrayBuffer 인스턴스는 [[ArrayBufferData]] 내부 슬롯을 가진다. 증가 가능하지 않은 SharedArrayBuffer 인스턴스는 각각 [[ArrayBufferByteLength]] 내부 슬롯을 가진다. 증가 가능한 SharedArrayBuffer 인스턴스는 각각 [[ArrayBufferByteLengthData]] 내부 슬롯과 [[ArrayBufferMaxByteLength]] 내부 슬롯을 가진다.

Note

SharedArrayBuffer 인스턴스는 ArrayBuffer 인스턴스와 달리 결코 detached되지 않는다.

25.2.7 증가 가능 SharedArrayBuffer 지침

Note 1

다음은 증가 가능 SharedArrayBuffer를 사용하는 ECMAScript 프로그래머를 위한 지침이다.

가능한 경우 프로그램은 배포 환경에서 테스트할 것을 권장한다. 사용 가능한 물리 메모리의 양은 하드웨어 장치마다 크게 다르다. 마찬가지로 가상 메모리 서브시스템도 하드웨어 장치와 운영 체제마다 크게 다르다. 64비트 데스크톱 웹 브라우저에서 메모리 부족 오류 없이 실행되는 애플리케이션이 32비트 모바일 웹 브라우저에서는 메모리가 부족해질 수 있다.

증가 가능 SharedArrayBuffer에 대한 "maxByteLength" 옵션 값을 선택할 때는 애플리케이션에 가능한 가장 작은 크기를 선택할 것을 권장한다. "maxByteLength"가 1073741824, 즉 1GiB를 초과하지 않을 것을 권장한다.

특정 최대 크기에 대해 증가 가능 SharedArrayBuffer를 성공적으로 생성했다고 해서 향후 grow가 성공한다는 보장은 없다는 점에 유의하라.

증가 가능 SharedArrayBuffer 길이의 모든 로드가 동기화하는 seq-cst 로드는 아니다. 정수 인덱스 속성 접근, 예를 들어 u8[idx]의 경계 검사를 위한 길이 로드는 동기화하지 않는다. 일반적으로 명시적 동기화가 없으면, 한 속성 접근이 in-bound였다는 사실이 같은 agent의 후속 속성 접근도 in-bound임을 의미하지 않는다. 반대로 SharedArrayBuffer, %TypedArray%.prototype, 그리고 DataView.prototype의 lengthbyteLength getter를 통한 길이의 명시적 로드는 동기화한다. TypedArray가 완전히 out-of-bounds인지 확인하기 위해 내장 메서드가 수행하는 길이 로드도 동기화한다.

Note 2

다음은 증가 가능 SharedArrayBuffer를 구현하는 ECMAScript 구현자를 위한 지침이다.

증가 가능 SharedArrayBuffer는 가상 메모리를 미리 예약하는 제자리 증가로 구현할 것을 권장한다.

증가 연산은 증가 가능 SharedArrayBuffer에 대한 메모리 접근과 병렬로 발생할 수 있으므로, 메모리 모델의 제약은 unordered 접근조차도 "tear"하지 않을 것(값의 비트가 섞이지 않을 것)을 요구한다. 실제로 이는 증가 가능 SharedArrayBuffer의 기반 데이터 블록이 세계를 멈추지 않고는 복사 방식으로 증가될 수 없음을 의미한다. 세계를 멈추는 방식은 직렬화 지점을 도입하고 느리기 때문에 구현 전략으로 권장하지 않는다.

증가된 메모리는 병렬로 발생하는 모든 racy 접근을 포함하여, 생성 순간부터 0으로 채워진 것처럼 보여야 한다. 이는 zero-filled-on-demand 가상 메모리 페이지를 통해 달성하거나, 메모리를 수동으로 0으로 채우는 경우 신중한 동기화를 통해 달성할 수 있다.

증가 가능 SharedArrayBufferTypedArray 뷰에 대한 정수 인덱스 속성 접근은, 기반 버퍼의 길이에 대해 정수 인덱스 속성 로드가 동기화하지 않기 때문에(위 프로그래머 지침 참조), 증가 불가능 SharedArrayBuffer의 TypedArray 뷰에 대한 접근과 유사하게 최적화 가능하도록 의도되어 있다. 예를 들어 속성 접근에 대한 경계 검사는 여전히 루프 밖으로 끌어올려질 수 있다.

실제로 임베디드 장치처럼 MMU가 없는 환경에서 실행되는 호스트와 같이 가상 메모리가 없는 호스트에서 증가 가능 SharedArrayBuffer를 복사 방식으로 구현하는 것은 어렵다. 그러한 호스트에서 증가 가능 SharedArrayBuffer의 메모리 사용 동작은 가상 메모리가 있는 호스트와 크게 다를 수 있다. 그러한 호스트는 사용자에게 메모리 사용 기대치를 명확히 전달해야 한다.

25.3 DataView 객체

25.3.1 DataView 객체를 위한 추상 연산

25.3.1.1 DataView With Buffer Witness Records

DataView With Buffer Witness Record는 DataView와 함께 viewed buffer의 캐시된 바이트 길이를 캡슐화하는 데 사용되는 Record 값이다. 이는 viewed buffer가 증가 가능 SharedArrayBuffer일 때 바이트 길이 데이터 블록에 대해 단일 ReadSharedMemory 이벤트만 있도록 보장하는 데 도움을 주기 위해 사용된다.

DataView With Buffer Witness Records는 Table 72에 나열된 필드를 가진다.

Table 72: DataView With Buffer Witness Record 필드
필드 이름 의미
[[Object]] DataView 그 버퍼의 바이트 길이가 로드되는 DataView 객체.
[[CachedBufferByteLength]] 음이 아닌 정수 또는 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. Assert: IsViewOutOfBounds(viewRecord)는 false이다.
  2. viewviewRecord.[[Object]]라고 하자.
  3. view.[[ByteLength]]auto가 아니면, view.[[ByteLength]]를 반환한다.
  4. Assert: IsFixedLengthArrayBuffer(view.[[ViewedArrayBuffer]])는 false이다.
  5. byteOffsetview.[[ByteOffset]]이라고 하자.
  6. byteLengthviewRecord.[[CachedBufferByteLength]]라고 하자.
  7. Assert: byteLengthdetached가 아니다.
  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이면,
    1. Assert: bufferByteLengthdetached이다.
    2. true를 반환한다.
  4. Assert: bufferByteLength는 음이 아닌 정수이다.
  5. byteOffsetStartview.[[ByteOffset]]이라고 하자.
  6. view.[[ByteLength]]auto이면,
    1. byteOffsetEndbufferByteLength라고 하자.
  7. 그렇지 않으면,
    1. byteOffsetEndbyteOffsetStart + view.[[ByteLength]]라고 하자.
  8. NOTE: [[ByteOffset]]bufferByteLength인 0길이 DataView는 out-of-bounds로 간주되지 않는다.
  9. byteOffsetStart > bufferByteLength이거나 byteOffsetEnd > bufferByteLength이면, true를 반환한다.
  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 either a normal completion containing either a Number or a BigInt, or a throw completion. DataView 인스턴스의 함수가 뷰의 버퍼에서 값을 가져오는 데 사용된다. It performs the following steps when called:

  1. RequireInternalSlot(view, [[DataView]])를 수행한다.
  2. Assert: view[[ViewedArrayBuffer]] 내부 슬롯을 가진다.
  3. getIndex를 ? ToIndex(requestIndex)라고 하자.
  4. isLittleEndianToBoolean(isLittleEndian)으로 설정한다.
  5. viewOffsetview.[[ByteOffset]]이라고 하자.
  6. viewRecordMakeDataViewWithBufferWitnessRecord(view, unordered)라고 하자.
  7. NOTE: view의 backing buffer가 증가 가능 SharedArrayBuffer일 때 경계 검사는 동기화 연산이 아니다.
  8. IsViewOutOfBounds(viewRecord)가 true이면, TypeError 예외를 던진다.
  9. viewSizeGetViewByteLength(viewRecord)라고 하자.
  10. elementSize를 요소 타입 type에 대해 Table 70에 지정된 Element Size 값이라고 하자.
  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 either a normal completion containing undefined or a throw completion. DataView 인스턴스의 함수가 값을 뷰의 버퍼에 저장하는 데 사용된다. It performs the following steps when called:

  1. RequireInternalSlot(view, [[DataView]])를 수행한다.
  2. Assert: 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. NOTE: view의 backing buffer가 증가 가능 SharedArrayBuffer일 때 경계 검사는 동기화 연산이 아니다.
  10. IsViewOutOfBounds(viewRecord)가 true이면, TypeError 예외를 던진다.
  11. viewSizeGetViewByteLength(viewRecord)라고 하자.
  12. elementSize를 요소 타입 type에 대해 Table 70에 지정된 Element Size 값이라고 하자.
  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.prototype 내장 메서드를 지원하는 데 필요한 내부 상태로 서브클래스 인스턴스를 생성하고 초기화하기 위해 DataView 생성자에 대한 super 호출을 포함해야 한다.

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. obj를 ? OrdinaryCreateFromConstructor(NewTarget, "%DataView.prototype%", « [[DataView]], [[ViewedArrayBuffer]], [[ByteLength]], [[ByteOffset]] »)라고 하자.
  11. IsDetachedBuffer(buffer)가 true이면, TypeError 예외를 던진다.
  12. bufferByteLengthArrayBufferByteLength(buffer, seq-cst)로 설정한다.
  13. offset > bufferByteLength이면, RangeError 예외를 던진다.
  14. byteLengthundefined가 아니면,
    1. offset + viewByteLength > bufferByteLength이면, RangeError 예외를 던진다.
  15. obj.[[ViewedArrayBuffer]]buffer로 설정한다.
  16. obj.[[ByteLength]]viewByteLength로 설정한다.
  17. obj.[[ByteOffset]]offset으로 설정한다.
  18. obj를 반환한다.

25.3.3 DataView 생성자의 속성

DataView 생성자는:

  • 값이 %Function.prototype%[[Prototype]] 내부 슬롯을 가진다.
  • 다음 속성들을 가진다:

25.3.3.1 DataView.prototype

DataView.prototype의 초기값은 DataView 프로토타입 객체이다.

이 속성은 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false } 속성 특성을 가진다.

25.3.4 DataView 프로토타입 객체의 속성

DataView 프로토타입 객체는:

  • %DataView.prototype%이다.
  • 값이 %Object.prototype%[[Prototype]] 내부 슬롯을 가진다.
  • 보통 객체이다.
  • [[DataView]], [[ViewedArrayBuffer]], [[ByteLength]], 또는 [[ByteOffset]] 내부 슬롯을 가지지 않는다.

25.3.4.1 get DataView.prototype.buffer

DataView.prototype.buffer는 set 접근자 함수가 undefined인 접근자 속성이다. 그 get 접근자 함수는 호출될 때 다음 단계를 수행한다:

  1. objthis 값이라고 하자.
  2. RequireInternalSlot(obj, [[DataView]])를 수행한다.
  3. Assert: obj[[ViewedArrayBuffer]] 내부 슬롯을 가진다.
  4. bufferobj.[[ViewedArrayBuffer]]라고 하자.
  5. buffer를 반환한다.

25.3.4.2 get DataView.prototype.byteLength

DataView.prototype.byteLength는 set 접근자 함수가 undefined인 접근자 속성이다. 그 get 접근자 함수는 호출될 때 다음 단계를 수행한다:

  1. objthis 값이라고 하자.
  2. RequireInternalSlot(obj, [[DataView]])를 수행한다.
  3. Assert: obj[[ViewedArrayBuffer]] 내부 슬롯을 가진다.
  4. viewRecordMakeDataViewWithBufferWitnessRecord(obj, 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. objthis 값이라고 하자.
  2. RequireInternalSlot(obj, [[DataView]])를 수행한다.
  3. Assert: obj[[ViewedArrayBuffer]] 내부 슬롯을 가진다.
  4. viewRecordMakeDataViewWithBufferWitnessRecord(obj, seq-cst)라고 하자.
  5. IsViewOutOfBounds(viewRecord)가 true이면, TypeError 예외를 던진다.
  6. offsetobj.[[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% 속성의 초기값은 String 값 "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" 속성의 초기값이다.
  • 보통 객체이다.
  • 값이 %Object.prototype%[[Prototype]] 내부 슬롯을 가진다.
  • [[Construct]] 내부 메서드를 가지지 않는다. new 연산자와 함께 생성자로 사용할 수 없다.
  • [[Call]] 내부 메서드를 가지지 않는다. 함수로 호출될 수 없다.

Atomics 객체는 공유 메모리 배열 셀에 대해 분할 불가능하게(원자적으로) 동작하는 함수와, agent가 primitive 이벤트를 기다리고 dispatch할 수 있게 하는 함수를 제공한다. 규율 있게 사용하면, Atomics 함수는 공유 메모리를 통해 통신하는 multi-agent 프로그램이 병렬 CPU에서도 잘 이해된 순서로 실행될 수 있게 한다. 공유 메모리 통신을 지배하는 규칙은 아래에 정의된 메모리 모델에 의해 제공된다.

Note

ECMAScript에서 공유 메모리를 프로그래밍하고 구현하기 위한 정보성 지침은 메모리 모델 절 끝의 노트를 보라.

25.4.1 Waiter Record

Waiter RecordAtomics.wait 또는 Atomics.waitAsync의 특정 호출을 나타내는 데 사용되는 Record 값이다.

Waiter Record는 Table 73에 나열된 필드를 가진다.

Table 73: Waiter Record 필드
필드 이름 의미
[[AgentSignifier]] agent signifier Atomics.wait 또는 Atomics.waitAsync를 호출한 agent.
[[PromiseCapability]] PromiseCapability Record 또는 blocking Atomics.waitAsync 호출을 나타내는 경우 결과 promise이고, 그렇지 않으면 blocking.
[[TimeoutTime]] 음이 아닌 확장 수학 값 timeout이 트리거될 수 있는 가장 이른 시간. time value를 사용해 계산된다.
[[Result]] "ok" 또는 "timed-out" 호출의 반환값.

25.4.2 WaiterList Records

WaiterList RecordAtomics.wait, Atomics.waitAsync, 그리고 Atomics.notify를 통한 agent의 대기와 알림을 설명하는 데 사용된다.

WaiterList Record는 Table 74에 나열된 필드를 가진다.

Table 74: WaiterList Record 필드
필드 이름 의미
[[Waiters]] Waiter RecordList 이 WaiterList가 연결된 위치에서 대기 중인 Atomics.wait 또는 Atomics.waitAsync 호출들.
[[MostRecentLeaveEvent]] Synchronize 이벤트 또는 empty 자신의 critical section을 가장 최근에 떠난 이벤트, 또는 그 critical section에 한 번도 진입한 적이 없으면 empty.

WaiterList 안에는 같은 agent signifier를 가진 여러 Waiter Record가 있을 수 있다.

agent cluster는 WaiterList Record들의 저장소를 가진다. 이 저장소는 (block, i)로 색인되며, 여기서 blockShared Data Block이고 iblock의 메모리 안의 바이트 오프셋이다. WaiterList Record는 agent와 독립적이다. agent cluster 안의 어떤 agent에서든 (block, i)로 WaiterList Record 저장소를 조회하면 같은 WaiterList Record가 결과로 나온다.

각 WaiterList Record는 평가 중 그 WaiterList Record에 대한 독점 접근을 제어하는 critical section을 가진다. 한 번에 하나의 agent만 WaiterList Record의 critical section에 들어갈 수 있다. WaiterList Record의 critical section에 들어가고 나오는 것은 추상 연산 EnterCriticalSectionLeaveCriticalSection에 의해 제어된다. WaiterList Record에 대한 연산—대기 중인 agent 추가 및 제거, agent 목록 순회, 목록의 agent 일시 중단 및 알림, Synchronize 이벤트 설정 및 검색—은 WaiterList Record의 critical section에 들어간 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 either a normal completion containing a TypedArray With Buffer Witness Record, or a throw completion. It performs the following steps when called:

  1. taRecord를 ? ValidateTypedArray(typedArray, unordered)라고 하자.
  2. NOTE: typedArray의 backing buffer가 증가 가능 SharedArrayBuffer일 때 경계 검사는 동기화 연산이 아니다.
  3. waitabletrue이면,
    1. typedArray.[[TypedArrayName]]"Int32Array""BigInt64Array"도 아니면, TypeError 예외를 던진다.
  4. 그렇지 않으면,
    1. typeTypedArrayElementType(typedArray)이라고 하자.
    2. IsUnclampedIntegerElementType(type)가 false이고 IsBigIntElementType(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 either a normal completion containing a non-negative integer or a throw completion. It performs the following steps when called:

  1. lengthTypedArrayLength(taRecord)라고 하자.
  2. accessIndex를 ? ToIndex(requestIndex)라고 하자.
  3. Assert: 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 either a normal completion containing a non-negative integer or a throw completion. 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 (a non-negative integer) and returns either a normal completion containing unused or a throw completion. 이 연산은 Atomics 메서드에서 모든 인자 강제가 수행된 뒤 atomic 연산을 위한 backing buffer 내의 인덱스를 다시 검증한다. 인자 강제는 임의의 부수 효과를 가질 수 있고, 이로 인해 버퍼가 out of bounds가 될 수 있기 때문이다. 이 연산은 typedArray의 backing buffer가 SharedArrayBuffer일 때 예외를 던지지 않는다. It performs the following steps when called:

  1. taRecordMakeTypedArrayWithBufferWitnessRecord(typedArray, unordered)라고 하자.
  2. NOTE: typedArray의 backing buffer가 증가 가능 SharedArrayBuffer일 때 경계 검사는 동기화 연산이 아니다.
  3. IsTypedArrayOutOfBounds(taRecord)가 true이면, TypeError 예외를 던진다.
  4. Assert: 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. Assert: ii + 3은 block의 메모리 안에서 유효한 바이트 오프셋이다.
  2. 쌍 (block, i)가 참조하는 WaiterList Record를 반환한다.

25.4.3.6 EnterCriticalSection ( waiterList )

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

  1. Assert: 주변 agent는 어떤 WaiterList Recordcritical section에도 있지 않다.
  2. 어떤 agent도 waiterListcritical section 안에 있지 않을 때까지 기다린 다음, waiterListcritical section에 들어간다(다른 agent가 들어오도록 허용하지 않고).
  3. waiterList.[[MostRecentLeaveEvent]]empty가 아니면,
    1. NOTE: critical section에 적어도 한 번 들어간 waiterListLeaveCriticalSection에 의해 설정된 Synchronize 이벤트를 가진다.
    2. agentRecord를 주변 agent의 Agent Record라고 하자.
    3. executionagentRecord.[[CandidateExecution]]이라고 하자.
    4. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier()인 Agent Events Record라고 하자.
    5. enterEvent를 새로운 Synchronize 이벤트라고 하자.
    6. enterEventeventsRecord.[[EventList]]에 추가한다.
    7. (waiterList.[[MostRecentLeaveEvent]], enterEvent)를 eventsRecord.[[AgentSynchronizesWith]]에 추가한다.
  4. unused를 반환한다.

EnterCriticalSection은 critical section에 들어가려는 agent가 다른 agent가 그것을 떠날 때까지 기다려야 할 때 contention을 가진다. contention이 없을 때 EnterCriticalSection 호출의 FIFO 순서는 관찰 가능하다. contention이 있을 때 구현은 임의의 순서를 선택할 수 있지만, agent가 무기한 기다리게 해서는 안 된다.

25.4.3.7 LeaveCriticalSection ( waiterList )

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

  1. Assert: 주변 agent는 waiterListcritical section 안에 있다.
  2. agentRecord를 주변 agent의 Agent Record라고 하자.
  3. executionagentRecord.[[CandidateExecution]]이라고 하자.
  4. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier()인 Agent Events Record라고 하자.
  5. leaveEvent를 새로운 Synchronize 이벤트라고 하자.
  6. leaveEventeventsRecord.[[EventList]]에 추가한다.
  7. waiterList.[[MostRecentLeaveEvent]]leaveEvent로 설정한다.
  8. waiterListcritical section을 떠난다.
  9. unused를 반환한다.

25.4.3.8 AddWaiter ( waiterList, waiterRecord )

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

  1. Assert: 주변 agent는 waiterListcritical section 안에 있다.
  2. Assert: waiterList.[[Waiters]] 안에는 [[PromiseCapability]] 필드가 waiterRecord.[[PromiseCapability]]이고 [[AgentSignifier]] 필드가 waiterRecord.[[AgentSignifier]]Waiter Record가 없다.
  3. waiterRecordwaiterList.[[Waiters]]에 추가한다.
  4. unused를 반환한다.

25.4.3.9 RemoveWaiter ( waiterList, waiterRecord )

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

  1. Assert: 주변 agent는 waiterListcritical section 안에 있다.
  2. Assert: waiterList.[[Waiters]]waiterRecord를 포함한다.
  3. waiterRecordwaiterList.[[Waiters]]에서 제거한다.
  4. unused를 반환한다.

25.4.3.10 RemoveWaiters ( waiterList, count )

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

  1. Assert: 주변 agent는 waiterListcritical section 안에 있다.
  2. lenwaiterList.[[Waiters]]의 요소 개수라고 하자.
  3. countmin(count, len)으로 설정한다.
  4. waiterswaiterList.[[Waiters]]의 처음 count개 요소를 요소로 가지는 List라고 하자.
  5. waiterList.[[Waiters]]의 처음 count개 요소를 제거한다.
  6. waiters를 반환한다.

25.4.3.11 SuspendThisAgent ( waiterList, waiterRecord )

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

  1. Assert: 주변 agent는 waiterListcritical section 안에 있다.
  2. Assert: waiterList.[[Waiters]]waiterRecord를 포함한다.
  3. thisAgentAgentSignifier()라고 하자.
  4. Assert: waiterRecord.[[AgentSignifier]]thisAgent이다.
  5. Assert: waiterRecord.[[PromiseCapability]]blocking이다.
  6. Assert: AgentCanSuspend()는 true이다.
  7. LeaveCriticalSection(waiterList)를 수행하고 waiterRecord.[[TimeoutTime]] 시간이 될 때까지 주변 agent를 일시 중단하되, critical section을 나간 뒤 suspension이 효력을 발생하기 전에 도착한 알림이 lost되지 않는 방식으로 결합 연산을 수행한다. 주변 agent는 timeout으로 인해 또는 다른 agent가 waiterListthisAgent를 인자로 NotifyWaiter를 호출하는 것(즉 Atomics.notify 호출을 통해)으로만 suspension에서 깨어날 수 있다.
  8. EnterCriticalSection(waiterList)를 수행한다.
  9. unused를 반환한다.

25.4.3.12 NotifyWaiter ( waiterList, waiterRecord )

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

  1. Assert: 주변 agent는 waiterListcritical section 안에 있다.
  2. waiterRecord.[[PromiseCapability]]blocking이면,
    1. signifier가 waiterRecord.[[AgentSignifier]]인 agent를 suspension에서 깨운다.
    2. NOTE: 이는 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. resolveJobagentSignifier, promiseCapability, 그리고 resolution을 캡처하고 호출될 때 다음 단계를 수행하는, 매개변수가 없는 새로운 Job Abstract Closure라고 하자:
    1. Assert: AgentSignifier()는 agentSignifier이다.
    2. Call(promiseCapability.[[Resolve]], undefined, « resolution »)를 수행한다.
    3. unused를 반환한다.
  2. realmInTargetAgent를 ! GetFunctionRealm(promiseCapability.[[Resolve]])라고 하자.
  3. Assert: 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 either a normal completion containing either an Object, "not-equal", "timed-out", or "ok", or a throw completion. It performs the following steps when called:

  1. taRecord를 ? ValidateIntegerTypedArray(typedArray, true)라고 하자.
  2. buffertaRecord.[[Object]].[[ViewedArrayBuffer]]라고 하자.
  3. IsSharedArrayBuffer(buffer)가 false이면, TypeError 예외를 던진다.
  4. byteIndexInBuffer를 ? ValidateAtomicAccess(taRecord, index)라고 하자.
  5. arrayTypeNametypedArray.[[TypedArrayName]]이라고 하자.
  6. arrayTypeName"BigInt64Array"이면, expected를 ? ToBigInt64(value)라고 하자.
  7. 그렇지 않으면, expected를 ? ToInt32(value)라고 하자.
  8. timeoutNumber를 ? ToNumber(timeout)라고 하자.
  9. timeoutNumberNaN 또는 +∞𝔽이면, realTimeout을 +∞라고 하자.
  10. 그렇지 않고 timeoutNumber-∞𝔽이면, realTimeout을 0이라고 하자.
  11. 그렇지 않으면, realTimeoutmax((timeoutNumber), 0)이라고 하자.
  12. modesync이고 AgentCanSuspend()가 false이면, TypeError 예외를 던진다.
  13. blockbuffer.[[ArrayBufferData]]라고 하자.
  14. waiterListGetWaiterList(block, byteIndexInBuffer)라고 하자.
  15. modesync이면,
    1. promiseCapabilityblocking이라고 하자.
    2. resultObjectundefined라고 하자.
  16. 그렇지 않으면,
    1. promiseCapability를 ! NewPromiseCapability(%Promise%)라고 하자.
    2. resultObjectOrdinaryObjectCreate(%Object.prototype%)라고 하자.
  17. EnterCriticalSection(waiterList)를 수행한다.
  18. elementTypeTypedArrayElementType(typedArray)이라고 하자.
  19. witnessGetValueFromBuffer(buffer, byteIndexInBuffer, elementType, true, seq-cst)라고 하자.
  20. expectedwitness이면,
    1. LeaveCriticalSection(waiterList)를 수행한다.
    2. modesync이면, "not-equal"을 반환한다.
    3. CreateDataPropertyOrThrow(resultObject, "async", false)를 수행한다.
    4. CreateDataPropertyOrThrow(resultObject, "value", "not-equal")를 수행한다.
    5. resultObject를 반환한다.
  21. realTimeout = 0이고 modeasync이면,
    1. NOTE: 동기적 즉시 timeout에 대한 특별한 처리는 없다. 비동기적 즉시 timeout은 빠르게 실패하고 불필요한 Promise job을 피하기 위해 특별한 처리를 가진다.
    2. LeaveCriticalSection(waiterList)를 수행한다.
    3. CreateDataPropertyOrThrow(resultObject, "async", false)를 수행한다.
    4. CreateDataPropertyOrThrow(resultObject, "value", "timed-out")를 수행한다.
    5. resultObject를 반환한다.
  22. thisAgentAgentSignifier()라고 하자.
  23. now를 현재 시간을 식별하는 time value(UTC)라고 하자.
  24. additionalTimeout구현 정의 음이 아닌 수학 값이라고 하자.
  25. timeoutTime(now) + realTimeout + additionalTimeout이라고 하자.
  26. NOTE: realTimeout이 +∞이면, timeoutTime도 +∞이다.
  27. waiterRecord를 새로운 Waiter Record { [[AgentSignifier]]: thisAgent, [[PromiseCapability]]: promiseCapability, [[TimeoutTime]]: timeoutTime, [[Result]]: "ok" }라고 하자.
  28. AddWaiter(waiterList, waiterRecord)를 수행한다.
  29. modesync이면,
    1. SuspendThisAgent(waiterList, waiterRecord)를 수행한다.
  30. 그렇지 않고 timeoutTime유한하면,
    1. EnqueueAtomicsWaitAsyncTimeoutJob(waiterList, waiterRecord)를 수행한다.
  31. LeaveCriticalSection(waiterList)를 수행한다.
  32. modesync이면, waiterRecord.[[Result]]를 반환한다.
  33. CreateDataPropertyOrThrow(resultObject, "async", true)를 수행한다.
  34. CreateDataPropertyOrThrow(resultObject, "value", promiseCapability.[[Promise]])를 수행한다.
  35. resultObject를 반환한다.
Note

additionalTimeout은 구현이 전력 소비를 줄이거나 timing attack을 완화하기 위해 타이머 해상도를 거칠게 만드는 것처럼 필요에 따라 timeout을 padding할 수 있게 한다. 이 값은 DoWait 호출마다 다를 수 있다.

25.4.3.15 EnqueueAtomicsWaitAsyncTimeoutJob ( waiterList, waiterRecord )

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

  1. timeoutJobwaiterListwaiterRecord를 캡처하고 호출될 때 다음 단계를 수행하는, 매개변수가 없는 새로운 Job Abstract Closure라고 하자:
    1. EnterCriticalSection(waiterList)를 수행한다.
    2. waiterList.[[Waiters]]waiterRecord를 포함하면,
      1. timeOfJobExecution을 현재 시간을 식별하는 time value(UTC)라고 하자.
      2. Assert: (time value의 잠재적 비단조성을 무시하면) (timeOfJobExecution) ≥ waiterRecord.[[TimeoutTime]]이다.
      3. waiterRecord.[[Result]]"timed-out"으로 설정한다.
      4. RemoveWaiter(waiterList, waiterRecord)를 수행한다.
      5. NotifyWaiter(waiterList, waiterRecord)를 수행한다.
    3. LeaveCriticalSection(waiterList)를 수행한다.
    4. unused를 반환한다.
  2. now를 현재 시간을 식별하는 time value(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. agentRecord를 주변 agent의 Agent Record라고 하자.
  2. executionagentRecord.[[CandidateExecution]]이라고 하자.
  3. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier()인 Agent Events Record라고 하자.
  4. rawBytesRead를 요소들이 비결정적으로 선택된 바이트 값인 길이 elementSizeList라고 하자.
  5. NOTE: 구현에서 rawBytesRead는 기반 하드웨어에서 load-link, load-exclusive 또는 read-modify-write 명령의 피연산자 결과이다. 비결정성은 약한 일관성을 가진 하드웨어의 관찰 가능한 동작을 설명하기 위한 메모리 모델의 의미론적 규정이다.
  6. NOTE: 기대 값과 읽은 값의 비교는 기대 값이 읽은 값과 같지 않을 때 불필요하게 강한 동기화를 피하기 위해 read-modify-write 수정 함수 바깥에서 수행된다.
  7. ByteListEqual(rawBytesRead, expectedBytes)가 true이면,
    1. second를 아무것도 캡처하지 않고 호출될 때 원자적으로 다음 단계를 수행하는, 매개변수 (oldBytes, newBytes)를 가진 새로운 read-modify-write 수정 함수라고 하자:
      1. newBytes를 반환한다.
    2. eventReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndexInBuffer, [[ElementSize]]: elementSize, [[Payload]]: replacementBytes, [[ModifyOp]]: second }라고 하자.
  8. 그렇지 않으면,
    1. eventReadSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndexInBuffer, [[ElementSize]]: elementSize }라고 하자.
  9. eventeventsRecord.[[EventList]]에 추가한다.
  10. Chosen Value Record { [[Event]]: event, [[ChosenValue]]: rawBytesRead }를 execution.[[ChosenValues]]에 추가한다.
  11. 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 either a normal completion containing either a Number or a BigInt, or a throw completion. op는 바이트 값의 두 List 인자를 받아 바이트 값의 List를 반환한다. 이 연산은 값을 원자적으로 로드하고, 다른 값과 결합한 뒤, 그 결합을 저장한다. 로드된 값을 반환한다. It performs the following steps when called:

  1. byteIndexInBuffer를 ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index)라고 하자.
  2. typedArray.[[ContentType]]bigint이면 coerced를 ? ToBigInt(value)라고 하자.
  3. 그렇지 않으면, coerced𝔽(? ToIntegerOrInfinity(value))라고 하자.
  4. RevalidateAtomicAccess(typedArray, byteIndexInBuffer)를 수행한다.
  5. buffertypedArray.[[ViewedArrayBuffer]]라고 하자.
  6. elementTypeTypedArrayElementType(typedArray)이라고 하자.
  7. GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, coerced, 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. Assert: xBytesyBytes는 같은 수의 요소를 가진다.
  2. result를 새로운 빈 List라고 하자.
  3. i를 0이라고 하자.
  4. xBytes의 각 요소 xByte에 대해, 다음을 수행한다.
    1. yByteyBytes[i]라고 하자.
    2. op&이면,
      1. resultBytexByteyByte에 비트 AND 연산을 적용한 결과라고 하자.
    3. 그렇지 않고 op^이면,
      1. resultBytexByteyByte에 비트 배타적 OR(XOR) 연산을 적용한 결과라고 하자.
    4. 그렇지 않으면,
      1. Assert: op|이다.
      2. resultBytexByteyByte에 비트 포함 OR 연산을 적용한 결과라고 하자.
    5. ii + 1로 설정한다.
    6. resultByteresult에 추가한다.
  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. addtypedArray를 캡처하고 호출될 때 원자적으로 다음 단계를 수행하는, 매개변수 (xBytes, yBytes)를 가진 새로운 read-modify-write 수정 함수라고 하자:
    1. typeTypedArrayElementType(typedArray)이라고 하자.
    2. agentRecord를 주변 agent의 Agent Record라고 하자.
    3. isLittleEndianagentRecord.[[LittleEndian]]이라고 하자.
    4. xRawBytesToNumeric(type, xBytes, isLittleEndian)라고 하자.
    5. yRawBytesToNumeric(type, yBytes, isLittleEndian)라고 하자.
    6. x가 Number이면,
      1. sumNumber::add(x, y)라고 하자.
    7. 그렇지 않으면,
      1. Assert: x는 BigInt이다.
      2. sumBigInt::add(x, y)라고 하자.
    8. sumBytesNumericToRawBytes(type, sum, isLittleEndian)라고 하자.
    9. Assert: sumBytes, xBytes, 그리고 yBytes는 같은 수의 요소를 가진다.
    10. sumBytes를 반환한다.
  2. AtomicReadModifyWrite(typedArray, index, value, add)를 반환한다.

25.4.5 Atomics.and ( typedArray, index, value )

이 함수는 호출될 때 다음 단계를 수행한다:

  1. and를 아무것도 캡처하지 않고 호출될 때 원자적으로 다음 단계를 수행하는, 매개변수 (xBytes, yBytes)를 가진 새로운 read-modify-write 수정 함수라고 하자:
    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. agentRecord를 주변 agent의 Agent Record라고 하자.
  10. isLittleEndianagentRecord.[[LittleEndian]]이라고 하자.
  11. expectedBytesNumericToRawBytes(elementType, expected, isLittleEndian)라고 하자.
  12. replacementBytesNumericToRawBytes(elementType, replacement, isLittleEndian)라고 하자.
  13. IsSharedArrayBuffer(buffer)가 true이면,
    1. rawBytesReadAtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes)라고 하자.
  14. 그렇지 않으면,
    1. rawBytesReadblock[byteIndexInBuffer]로 시작하는 elementSize개의 바이트 시퀀스를 요소로 가지는 길이 elementSizeList라고 하자.
    2. ByteListEqual(rawBytesRead, expectedBytes)가 true이면,
      1. replacementBytes의 개별 바이트들을 block[byteIndexInBuffer]에서 시작하여 block에 저장한다.
  15. RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian)를 반환한다.

25.4.7 Atomics.exchange ( typedArray, index, value )

이 함수는 호출될 때 다음 단계를 수행한다:

  1. second를 아무것도 캡처하지 않고 호출될 때 원자적으로 다음 단계를 수행하는, 매개변수 (oldBytes, newBytes)를 가진 새로운 read-modify-write 수정 함수라고 하자:
    1. newBytes를 반환한다.
  2. AtomicReadModifyWrite(typedArray, index, value, second)를 반환한다.

25.4.8 Atomics.isLockFree ( size )

이 함수는 호출될 때 다음 단계를 수행한다:

  1. n을 ? ToIntegerOrInfinity(size)라고 하자.
  2. agentRecord를 주변 agent의 Agent Record라고 하자.
  3. n = 1이면, agentRecord.[[IsLockFree1]]을 반환한다.
  4. n = 2이면, agentRecord.[[IsLockFree2]]를 반환한다.
  5. n = 4이면, true를 반환한다.
  6. n = 8이면, agentRecord.[[IsLockFree8]]을 반환한다.
  7. false를 반환한다.
Note

이 함수는 최적화 primitive이다. 직관은 크기 n 바이트의 datum에 대한 atomic primitive(compareExchange, load, store, add, sub, and, or, xor, 또는 exchange)의 원자적 단계가 주변 agent가 그 datum을 구성하는 n 바이트 외부의 lock을 획득하지 않고 수행된다면, Atomics.isLockFree(n)가 true를 반환한다는 것이다. 고성능 알고리즘은 이 함수를 사용하여 critical section에서 lock을 사용할지 atomic 연산을 사용할지 결정한다. atomic primitive가 lock-free가 아니면 알고리즘이 자체 locking을 제공하는 것이 종종 더 효율적이다.

Atomics.isLockFree(4)는 알려진 모든 관련 하드웨어에서 지원될 수 있으므로 항상 true를 반환한다. 이를 가정할 수 있으면 일반적으로 프로그램이 단순해진다.

이 함수가 반환하는 값과 관계없이 모든 atomic 연산은 원자적임이 보장된다. 예를 들어 연산 도중에 visible operation이 발생하는 일은 결코 없다(예: "tearing").

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)를 가진 새로운 read-modify-write 수정 함수라고 하자:
    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이면 coerced를 ? ToBigInt(value)라고 하자.
  3. 그렇지 않으면, coerced𝔽(? ToIntegerOrInfinity(value))라고 하자.
  4. RevalidateAtomicAccess(typedArray, byteIndexInBuffer)를 수행한다.
  5. buffertypedArray.[[ViewedArrayBuffer]]라고 하자.
  6. elementTypeTypedArrayElementType(typedArray)이라고 하자.
  7. SetValueInBuffer(buffer, byteIndexInBuffer, elementType, coerced, true, seq-cst)를 수행한다.
  8. coerced를 반환한다.

25.4.12 Atomics.sub ( typedArray, index, value )

이 함수는 호출될 때 다음 단계를 수행한다:

  1. subtracttypedArray를 캡처하고 호출될 때 원자적으로 다음 단계를 수행하는, 매개변수 (xBytes, yBytes)를 가진 새로운 read-modify-write 수정 함수라고 하자:
    1. typeTypedArrayElementType(typedArray)이라고 하자.
    2. agentRecord를 주변 agent의 Agent Record라고 하자.
    3. isLittleEndianagentRecord.[[LittleEndian]]이라고 하자.
    4. xRawBytesToNumeric(type, xBytes, isLittleEndian)라고 하자.
    5. yRawBytesToNumeric(type, yBytes, isLittleEndian)라고 하자.
    6. x가 Number이면,
      1. differenceNumber::subtract(x, y)라고 하자.
    7. 그렇지 않으면,
      1. Assert: x는 BigInt이다.
      2. differenceBigInt::subtract(x, y)라고 하자.
    8. differenceBytesNumericToRawBytes(type, difference, isLittleEndian)라고 하자.
    9. Assert: differenceBytes, xBytes, 그리고 yBytes는 같은 수의 요소를 가진다.
    10. differenceBytes를 반환한다.
  2. AtomicReadModifyWrite(typedArray, index, value, subtract)를 반환한다.

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

이 함수는 주변 agent를 wait queue에 넣고 알림을 받거나 wait가 timeout될 때까지 일시 중단하며, 그 경우들을 구별하는 String을 반환한다.

호출될 때 다음 단계를 수행한다:

  1. DoWait(sync, typedArray, index, value, timeout)를 반환한다.

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

이 함수는 호출하는 agent가 알림을 받거나 timeout에 도달하면 resolve되는 Promise를 반환한다.

호출될 때 다음 단계를 수행한다:

  1. DoWait(async, typedArray, index, value, timeout)를 반환한다.

25.4.15 Atomics.notify ( typedArray, index, count )

이 함수는 wait queue에서 잠자고 있는 일부 agent들에게 알린다.

호출될 때 다음 단계를 수행한다:

  1. taRecord를 ? ValidateIntegerTypedArray(typedArray, true)라고 하자.
  2. byteIndexInBuffer를 ? ValidateAtomicAccess(taRecord, index)라고 하자.
  3. countundefined이면,
    1. count를 +∞로 설정한다.
  4. 그렇지 않으면,
    1. intCount를 ? ToIntegerOrInfinity(count)라고 하자.
    2. countmax(intCount, 0)으로 설정한다.
  5. buffertypedArray.[[ViewedArrayBuffer]]라고 하자.
  6. blockbuffer.[[ArrayBufferData]]라고 하자.
  7. IsSharedArrayBuffer(buffer)가 false이면, +0𝔽을 반환한다.
  8. waiterListGetWaiterList(block, byteIndexInBuffer)라고 하자.
  9. EnterCriticalSection(waiterList)를 수행한다.
  10. waitersRemoveWaiters(waiterList, count)라고 하자.
  11. waiters의 각 요소 waiterRecord에 대해, 다음을 수행한다.
    1. NotifyWaiter(waiterList, waiterRecord)를 수행한다.
  12. LeaveCriticalSection(waiterList)를 수행한다.
  13. nwaiters의 요소 개수라고 하자.
  14. 𝔽(n)를 반환한다.

25.4.16 Atomics.xor ( typedArray, index, value )

이 함수는 호출될 때 다음 단계를 수행한다:

  1. xor를 아무것도 캡처하지 않고 호출될 때 원자적으로 다음 단계를 수행하는, 매개변수 (xBytes, yBytes)를 가진 새로운 read-modify-write 수정 함수라고 하자:
    1. ByteListBitwiseOp(^, xBytes, yBytes)를 반환한다.
  2. AtomicReadModifyWrite(typedArray, index, value, xor)를 반환한다.

25.4.17 Atomics [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 속성의 초기값은 String 값 "Atomics"이다.

이 속성은 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true } 속성 특성을 가진다.

25.5 JSON 객체

JSON 객체는:

  • %JSON%이다.
  • 전역 객체"JSON" 속성의 초기값이다.
  • 보통 객체이다.
  • JSON 텍스트를 구문 분석하고 구성하는 데 사용되는 두 함수 parsestringify를 포함한다.
  • 값이 %Object.prototype%[[Prototype]] 내부 슬롯을 가진다.
  • [[Construct]] 내부 메서드를 가지지 않는다. new 연산자와 함께 생성자로 사용할 수 없다.
  • [[Call]] 내부 메서드를 가지지 않는다. 함수로 호출될 수 없다.

JSON Data Interchange Format은 ECMA-404에 정의되어 있다. 이 명세에서 사용되는 JSON interchange format은 ECMA-404에 설명된 것과 정확히 같다. JSON.parseJSON.stringify의 적합한 구현은 형식에서 어떤 삭제나 확장도 없이 ECMA-404 명세에 설명된 정확한 interchange format을 지원해야 한다.

25.5.1 JSON.isRawJSON ( obj )

이 함수는 호출될 때 다음 단계를 수행한다:

  1. obj가 Object이고 obj[[IsRawJSON]] 내부 슬롯을 가지면, true를 반환한다.
  2. false를 반환한다.

25.5.2 JSON.parse ( text [ , reviver ] )

이 함수는 JSON 텍스트(JSON 형식의 String)를 구문 분석하고 ECMAScript 언어 값을 생성한다. JSON 형식은 ECMAScript 리터럴, Array Initializer, Object Initializer의 구문과 유사한 구문으로 리터럴, 배열, 객체를 표현한다. 구문 분석 후 JSON 객체는 ECMAScript 객체로 실현된다. JSON 배열은 ECMAScript Array 인스턴스로 실현된다. JSON 문자열, 숫자, 불리언, null은 ECMAScript String, Number, Boolean, 그리고 null로 실현된다.

선택적 reviver 매개변수는 결과를 필터링하고 변환할 수 있는 함수이다. parse에 의해 생성된 각 값에 대해, reviver는 세 인자(연관된 속성 키, 값, 그리고 context 객체)와 함께 호출된다. 속성이 수정되지 않았고 그 값이 primitive이면, 제공된 context 객체는 대응하는 Parse Node의 소스 텍스트를 포함하는 "source" 속성을 가진다. 호출이 undefined를 반환하면, 속성은 삭제된다. 그렇지 않으면, 속성은 반환값을 사용하도록 재정의된다.

  1. jsonString을 ? ToString(text)라고 하자.
  2. parseResult를 ? ParseJSON(jsonString)라고 하자.
  3. unfilteredparseResult.[[Value]]라고 하자.
  4. IsCallable(reviver)가 false이면, unfiltered를 반환한다.
  5. rootOrdinaryObjectCreate(%Object.prototype%)라고 하자.
  6. rootName을 빈 String이라고 하자.
  7. CreateDataPropertyOrThrow(root, rootName, unfiltered)를 수행한다.
  8. snapshotCreateJSONParseRecord(parseResult.[[ParseNode]], rootName, unfiltered)라고 하자.
  9. InternalizeJSONProperty(root, rootName, reviver, snapshot)를 반환한다.

이 함수의 "length" 속성은 2𝔽이다.

25.5.2.1 ParseJSON ( text )

The abstract operation ParseJSON takes argument text (a String) and returns either a normal completion containing a Record with fields [[ParseNode]] (a Parse Node) and [[Value]] (an ECMAScript language value), or a throw completion. It performs the following steps when called:

  1. StringToCodePoints(text)가 ECMA-404에 지정된 유효한 JSON 텍스트가 아니면, SyntaxError 예외를 던진다.
  2. scriptString"(", text, 그리고 ");"의 문자열 연결이라고 하자.
  3. scriptParseText(scriptString, Script)라고 하자.
  4. NOTE: 13.2.5.1에 정의된 early error 규칙은 위 ParseText 호출에 대해 특별한 처리를 가진다.
  5. Assert: script는 Parse Node이다.
  6. result를 ! scriptEvaluation이라고 하자.
  7. NOTE: 13.2.5.6에 정의된 PropertyDefinitionEvaluation 의미론은 위 평가에 대해 특별한 처리를 가진다.
  8. Assert: result는 String, Number, Boolean, ArrayLiteral 또는 ObjectLiteral 중 하나에 의해 정의되는 Object, 또는 null 중 하나이다.
  9. Record { [[ParseNode]]: script, [[Value]]: result }를 반환한다.

JSON.parse의 적합한 구현이 JSON 문법을 확장하는 것은 허용되지 않는다. 구현이 수정되거나 확장된 JSON interchange format을 지원하고자 한다면, 다른 parse 함수를 정의하여 그렇게 해야 한다.

Note 1

유효한 JSON 텍스트는 ECMAScript PrimaryExpression 구문의 부분집합이다. 단계 1jsonString이 그 부분집합에 부합하는지 검증하고, 단계 8는 평가가 적절한 타입의 값을 반환함을 단언한다.

그러나 13.2.5.6가 ParseJSON 동안 다르게 동작하기 때문에, 동일한 소스 텍스트가 JSON으로 평가될 때와 PrimaryExpression으로 평가될 때 서로 다른 결과를 생성할 수 있다. 더 나아가, 객체 리터럴에서 중복 "__proto__" 속성에 대한 Early Error 역시 ParseJSON 동안 적용되지 않으므로, ParseJSON이 받아들이는 모든 텍스트가 문법과 일치함에도 PrimaryExpression으로 유효한 것은 아니다.

Note 2

객체 안에 중복 name String이 있는 경우, 같은 키에 대해 어휘적으로 앞서는 값은 덮어써진다.

25.5.2.2 JSON Parse Record

JSON Parse Record는 JSON 텍스트에서 구문 분석된 값의 초기 상태를 설명하는 데 사용되는 Record 값이다.

JSON Parse Record는 Table 75에 나열된 필드를 가진다.

Table 75: JSON Parse Record 필드
필드 이름 의미
[[ParseNode]] Parse Node context Parse Node.
[[Key]] 속성 이름 [[Value]]와 연관된 속성 이름.
[[Value]] ECMAScript 언어 값 [[ParseNode]]의 평가에 의해 생성된 값.
[[Elements]] JSON Parse RecordList [[Value]]가 Array이면, 이는 [[Value]]의 요소에 대응하는 JSON Parse Record들을 포함한다. 그렇지 않으면, 이는 빈 List이다.
[[Entries]] JSON Parse RecordList [[Value]]가 Array가 아닌 Object이면, 이는 [[Value]]의 엔트리에 대응하는 JSON Parse Record들을 포함한다. 그렇지 않으면, 이는 빈 List이다.

25.5.2.3 CreateJSONParseRecord ( parseNode, key, val )

The abstract operation CreateJSONParseRecord takes arguments parseNode (a Parse Node), key (a property name), and val (an ECMAScript language value) and returns a JSON Parse Record. JSON 텍스트에서 구문 분석된 parseNode와 그 평가에 의해 생성된 val을 재귀적으로 결합한다. It performs the following steps when called:

  1. typedValNodeShallowestContainedJSONValue(parseNode)라고 하자.
  2. Assert: typedValNodeempty가 아니다.
  3. elements를 새로운 빈 List라고 하자.
  4. entries를 새로운 빈 List라고 하자.
  5. val이 Object이면,
    1. isArray를 ! IsArray(val)라고 하자.
    2. isArraytrue이면,
      1. Assert: typedValNodeArrayLiteral Parse Node이다.
      2. contentNodestypedValNodeJSONArrayLiteralContentNodes라고 하자.
      3. lencontentNodes의 요소 개수라고 하자.
      4. valLen을 ! LengthOfArrayLike(val)라고 하자.
      5. Assert: valLenlen이다.
      6. index를 0이라고 하자.
      7. index < len인 동안 반복한다,
        1. propName을 ! ToString(𝔽(index))라고 하자.
        2. elementParseRecordCreateJSONParseRecord(contentNodes[index], propName, ! Get(val, propName))라고 하자.
        3. elementParseRecordelements에 추가한다.
        4. indexindex + 1로 설정한다.
    3. 그렇지 않으면,
      1. Assert: typedValNodeObjectLiteral Parse Node이다.
      2. propertyNodestypedValNodePropertyDefinitionNodes라고 하자.
      3. NOTE: val은 JSON 텍스트에서 생성되었고 수정되지 않았으므로, 그 모든 속성 키는 String이며 완전히 열거된다.
      4. keys를 ! EnumerableOwnProperties(val, key)라고 하자.
      5. keys의 각 String propertyKey에 대해, 다음을 수행한다.
        1. NOTE: JSON 텍스트가 단일 객체에 대해 같은 이름을 가진 여러 name/value 쌍(예: {"a":"lost","a":"kept"})을 지정하는 경우, 결과 ECMAScript 객체의 대응 속성 값은 그 이름을 가진 마지막 쌍에 의해 지정된다.
        2. propertyDefinitionempty라고 하자.
        3. propertyNodes의 각 Parse Node propertyNode에 대해, 다음을 수행한다.
          1. propNamepropertyNodePropName이라고 하자.
          2. propNamepropertyKey이면, propertyDefinitionpropertyNode로 설정한다.
        4. Assert: propertyDefinition PropertyDefinition : PropertyName : AssignmentExpression 이다.
        5. propertyValueNodepropertyDefinitionAssignmentExpression이라고 하자.
        6. entryParseRecordCreateJSONParseRecord(propertyValueNode, propertyKey, ! Get(val, propertyKey))라고 하자.
        7. entryParseRecordentries에 추가한다.
  6. 그렇지 않으면,
    1. Assert: typedValNodeArrayLiteral Parse Node도 ObjectLiteral Parse Node도 아니다.
  7. JSON Parse Record { [[ParseNode]]: typedValNode, [[Key]]: key, [[Value]]: val, [[Elements]]: elements, [[Entries]]: entries }를 반환한다.

25.5.2.4 InternalizeJSONProperty ( holder, name, reviver, parseRecord )

The abstract operation InternalizeJSONProperty takes arguments holder (an Object), name (a String), reviver (a function object), and parseRecord (a JSON Parse Record or empty) and returns either a normal completion containing an ECMAScript language value or a throw completion.

Note

이 알고리즘은 [[Delete]] 또는 CreateDataPropertyfalse를 반환해도 의도적으로 예외를 던지지 않는다.

호출될 때 다음 단계를 수행한다:

  1. val을 ? Get(holder, name)라고 하자.
  2. contextOrdinaryObjectCreate(%Object.prototype%)라고 하자.
  3. parseRecordJSON Parse Record이고 SameValue(parseRecord.[[Value]], val)가 true이면,
    1. val이 Object가 아니면,
      1. parseNodeparseRecord.[[ParseNode]]라고 하자.
      2. Assert: parseNodeArrayLiteral Parse Node도 ObjectLiteral Parse Node도 아니다.
      3. sourceTextparseNode일치한 소스 텍스트라고 하자.
      4. CreateDataPropertyOrThrow(context, "source", CodePointsToString(sourceText))를 수행한다.
    2. elementRecordsparseRecord.[[Elements]]라고 하자.
    3. entryRecordsparseRecord.[[Entries]]라고 하자.
  4. 그렇지 않으면,
    1. elementRecords를 새로운 빈 List라고 하자.
    2. entryRecords를 새로운 빈 List라고 하자.
  5. val이 Object이면,
    1. isArray를 ? IsArray(val)라고 하자.
    2. isArraytrue이면,
      1. elementRecordsLenelementRecords의 요소 개수라고 하자.
      2. len을 ? LengthOfArrayLike(val)라고 하자.
      3. index를 0이라고 하자.
      4. index < len인 동안 반복한다,
        1. propertyKey를 ! ToString(𝔽(index))라고 하자.
        2. index < elementRecordsLen이면 elementRecordelementRecords[index]라고 하자; 그렇지 않으면 elementRecordempty라고 하자.
        3. newElement를 ? InternalizeJSONProperty(val, propertyKey, reviver, elementRecord)라고 하자.
        4. newElementundefined이면,
          1. val.[[Delete]](propertyKey)를 수행한다.
        5. 그렇지 않으면,
          1. CreateDataProperty(val, propertyKey, newElement)를 수행한다.
        6. indexindex + 1로 설정한다.
    3. 그렇지 않으면,
      1. keys를 ? EnumerableOwnProperties(val, key)라고 하자.
      2. keys의 각 String propertyKey에 대해, 다음을 수행한다.
        1. entryRecords의 요소 entryentry.[[Key]]propertyKey인 것이 존재하면 entryRecordentry라고 하자; 그렇지 않으면 entryRecordempty라고 하자.
        2. newElement를 ? InternalizeJSONProperty(val, propertyKey, reviver, entryRecord)라고 하자.
        3. newElementundefined이면,
          1. val.[[Delete]](propertyKey)를 수행한다.
        4. 그렇지 않으면,
          1. CreateDataProperty(val, propertyKey, newElement)를 수행한다.
  6. Call(reviver, holder, « name, val, context »)를 반환한다.

25.5.2.5 Static Semantics: ShallowestContainedJSONValue ( root )

The abstract operation ShallowestContainedJSONValue takes argument root (a Parse Node) and returns a Parse Node or empty. root에 뿌리를 둔 parse tree에 대해 breadth-first search를 수행하고, JSON 값에 대응하는 nonterminal의 인스턴스인 첫 번째 노드를 반환하거나, 그러한 노드가 없으면 empty를 반환한다. It performs the following steps when called:

  1. activeFuncactive function object라고 하자.
  2. Assert: activeFuncJSON.parse 내장 함수 객체이다(JSON.parse 참조).
  3. types를 « NullLiteral, BooleanLiteral, NumericLiteral, StringLiteral, ArrayLiteral, ObjectLiteral, UnaryExpression »라고 하자.
  4. unaryExpressionempty라고 하자.
  5. queue를 « root »라고 하자.
  6. queue가 비어 있지 않은 동안 반복한다,
    1. candidatequeue의 첫 번째 요소라고 하자.
    2. queue에서 첫 번째 요소를 제거한다.
    3. queuedChildrenfalse라고 하자.
    4. types의 각 nonterminal type에 대해, 다음을 수행한다.
      1. candidatetype의 인스턴스이면,
        1. NOTE: JSON 문법에서 number 토큰은 음수 값을 나타낼 수 있다. ECMAScript에서 부정은 UnaryExpression- 뒤에 파생 UnaryExpression이 오는 것으로 구문 분석되는 단항 연산으로 표현된다.
        2. typeUnaryExpression이면,
          1. candidate의 부모가 UnaryExpression Parse Node가 아니면, unaryExpressioncandidate로 설정한다.
        3. 그렇지 않고 typeNumericLiteral이면,
          1. Assert: candidateunaryExpression 안에 포함되어 있다.
          2. unaryExpression을 반환한다.
        4. 그렇지 않으면,
          1. candidate를 반환한다.
      2. queuedChildrenfalse이고, candidate가 nonterminal의 인스턴스이며, candidate Contains typetrue이면,
        1. childrencandidate의 각 child node를 순서대로 포함하는 List라고 하자.
        2. queuequeuechildren의 리스트 연결로 설정한다.
        3. queuedChildrentrue로 설정한다.
  7. empty를 반환한다.

25.5.2.6 Static Semantics: JSONArrayLiteralContentNodes

The syntax-directed operation JSONArrayLiteralContentNodes takes no arguments and returns a List of Parse Nodes. It is defined piecewise over the following productions:

ArrayLiteral : [ Elisionopt ] [ ElementList ] [ ElementList , Elisionopt ]
  1. Assert: Elision은 존재하지 않는다.
  2. ElementList가 존재하지 않으면, 새로운 빈 List를 반환한다.
  3. ElementListJSONArrayLiteralContentNodes를 반환한다.
ElementList : Elisionopt AssignmentExpression
  1. Assert: Elision은 존재하지 않는다.
  2. « AssignmentExpression »를 반환한다.
ElementList : ElementList , Elisionopt AssignmentExpression
  1. Assert: Elision은 존재하지 않는다.
  2. elements를 파생된 ElementListJSONArrayLiteralContentNodes라고 하자.
  3. elements와 « AssignmentExpression »의 리스트 연결을 반환한다.
ElementList : Elisionopt SpreadElement ElementList , Elisionopt SpreadElement
  1. NOTE: ECMA-404에 지정된 JSON 텍스트는 SpreadElement를 포함하지 않는다.
  2. Assert: 이 단계에는 결코 도달하지 않는다.

25.5.3 JSON.rawJSON ( text )

이 함수는 string, number, boolean, 또는 null 값의 raw JSON 텍스트를 나타내는 객체를 반환한다.

  1. jsonString을 ? ToString(text)라고 하자.
  2. jsonString이 빈 String이면, SyntaxError 예외를 던진다.
  3. jsonString의 첫 번째 코드 단위가 ASCII 소문자 코드 단위(0x0061부터 0x007A까지 포함), ASCII 숫자 코드 단위(0x0030부터 0x0039까지 포함), 0x0022 (QUOTATION MARK), 또는 0x002D (HYPHEN-MINUS) 중 어느 것도 아니면, SyntaxError 예외를 던진다.
  4. jsonString의 마지막 코드 단위가 ASCII 소문자 코드 단위(0x0061부터 0x007A까지 포함), ASCII 숫자 코드 단위(0x0030부터 0x0039까지 포함), 또는 0x0022 (QUOTATION MARK) 중 어느 것도 아니면, SyntaxError 예외를 던진다.
  5. parseResult를 ? ParseJSON(jsonString)라고 하자.
  6. Assert: parseResult.[[Value]]는 String, Number, Boolean, 또는 null 중 하나이다.
  7. internalSlotsList를 « [[IsRawJSON]] »라고 하자.
  8. objOrdinaryObjectCreate(null, internalSlotsList)라고 하자.
  9. CreateDataPropertyOrThrow(obj, "rawJSON", jsonString)를 수행한다.
  10. SetIntegrityLevel(obj, frozen)를 수행한다.
  11. obj를 반환한다.

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

이 함수는 ECMAScript 언어 값을 나타내는 UTF-16 인코딩 JSON 형식의 String 또는 undefined를 반환한다. 세 매개변수를 받을 수 있다. value 매개변수는 ECMAScript 언어 값으로, 보통 객체나 배열이지만 String, Boolean, Number 또는 null일 수도 있다. 선택적 replacer 매개변수는 객체와 배열이 stringified되는 방식을 변경하는 함수이거나, stringified될 객체 속성을 선택하기 위한 포함 목록으로 동작하는 String과 Number의 배열이다. 선택적 space 매개변수는 결과에 공백을 삽입하여 사람이 읽기 쉽게 할 수 있는 String 또는 Number이다.

호출될 때 다음 단계를 수행한다:

  1. stack을 새로운 빈 List라고 하자.
  2. indent를 빈 String이라고 하자.
  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. propertyKey를 ! ToString(𝔽(k))라고 하자.
          2. propertyValue를 ? Get(replacer, propertyKey)라고 하자.
          3. itemundefined라고 하자.
          4. propertyValue가 String이면,
            1. itempropertyValue로 설정한다.
          5. 그렇지 않고 propertyValue가 Number이면,
            1. item을 ! ToString(propertyValue)으로 설정한다.
          6. 그렇지 않고 propertyValue가 Object이면,
            1. propertyValue[[StringData]] 또는 [[NumberData]] 내부 슬롯을 가지면, item을 ? ToString(propertyValue)로 설정한다.
          7. itemundefined가 아니고 propertyListitem을 포함하지 않으면,
            1. itempropertyList에 추가한다.
          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을 빈 String이라고 하자; 그렇지 않으면 gap을 코드 단위 0x0020 (SPACE)의 spaceMV회 발생을 포함하는 String 값이라고 하자.
  8. 그렇지 않고 space가 String이면,
    1. space의 길이가 ≤ 10이면 gapspace라고 하자; 그렇지 않으면 gapspace의 0부터 10까지의 부분 문자열이라고 하자.
  9. 그렇지 않으면,
    1. gap을 빈 String이라고 하자.
  10. wrapperOrdinaryObjectCreate(%Object.prototype%)라고 하자.
  11. CreateDataPropertyOrThrow(wrapper, 빈 String, value)를 수행한다.
  12. stateJSON Serialization Record { [[ReplacerFunction]]: replacerFunction, [[Stack]]: stack, [[Indent]]: indent, [[Gap]]: gap, [[PropertyList]]: propertyList }라고 하자.
  13. SerializeJSONProperty(state, 빈 String, wrapper)를 반환한다.

이 함수의 "length" 속성은 3𝔽이다.

Note 1

JSON 구조는 임의의 깊이로 중첩될 수 있지만, 비순환이어야 한다. value가 순환 구조이거나 순환 구조를 포함하면, 이 함수는 TypeError 예외를 던져야 한다. 다음은 stringify할 수 없는 값의 예이다:

a = [];
a[0] = a;
my_text = JSON.stringify(a); // 이는 TypeError를 던져야 한다.
Note 2

Symbolic primitive 값은 다음과 같이 렌더링된다:

  • null 값은 JSON 텍스트에서 String 값 "null"로 렌더링된다.
  • undefined 값은 렌더링되지 않는다.
  • true 값은 JSON 텍스트에서 String 값 "true"로 렌더링된다.
  • false 값은 JSON 텍스트에서 String 값 "false"로 렌더링된다.
Note 3

String 값은 QUOTATION MARK (") 코드 단위로 감싸진다. 코드 단위 "\\ 접두사로 escape된다. 제어 문자 코드 단위는 escape sequence \uHHHH 또는 더 짧은 형식 \b (BACKSPACE), \f (FORM FEED), \n (LINE FEED), \r (CARRIAGE RETURN), \t (CHARACTER TABULATION)로 대체된다.

Note 4

유한한 숫자는 ToString(number)을 호출한 것처럼 stringify된다. 부호와 관계없이 NaNInfinity는 String 값 "null"로 표현된다.

Note 5

JSON 표현을 가지지 않는 값(예: undefined 및 함수)은 String을 생성하지 않는다. 대신 undefined 값을 생성한다. 배열에서 이러한 값은 String 값 "null"로 표현된다. 객체에서는 표현 불가능한 값으로 인해 해당 속성이 stringification에서 제외된다.

Note 6

객체는 U+007B (LEFT CURLY BRACKET) 뒤에 U+002C (COMMA)로 구분된 0개 이상의 속성이 오고, U+007D (RIGHT CURLY BRACKET)로 닫히는 방식으로 렌더링된다. 속성은 속성 이름을 나타내는 따옴표로 감싼 String, U+003A (COLON), 그리고 stringified된 속성 값이다. 배열은 여는 U+005B (LEFT SQUARE BRACKET) 뒤에 U+002C (COMMA)로 구분된 0개 이상의 값이 오고, 닫는 U+005D (RIGHT SQUARE BRACKET)로 렌더링된다.

25.5.4.1 JSON Serialization Record

JSON Serialization Record는 JSON 형식으로의 직렬화를 가능하게 하는 데 사용되는 Record 값이다.

JSON Serialization Record는 Table 76에 나열된 필드를 가진다.

Table 76: JSON Serialization Record 필드
필드 이름 의미
[[ReplacerFunction]] 함수 객체 또는 undefined 객체 속성에 대한 대체 값을 제공할 수 있는 함수(JSON.stringify의 replacer 매개변수에서 옴).
[[PropertyList]] String의 List 또는 undefined 배열이 아닌 객체를 직렬화할 때 포함할 속성의 이름(JSON.stringify의 replacer 매개변수에서 옴).
[[Gap]] String 들여쓰기의 단위(JSON.stringify의 space 매개변수에서 옴).
[[Stack]] Object의 List 직렬화가 진행 중인 중첩 객체들의 집합. 순환 구조를 감지하는 데 사용된다.
[[Indent]] String 현재 들여쓰기.

25.5.4.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 either a normal completion containing either a String or undefined, or a throw completion. It performs the following steps when called:

  1. value를 ? Get(holder, key)이라고 하라.
  2. value가 Object이거나 value가 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[[IsRawJSON]] 내부 슬롯이 있으면,
      1. rawJSON을 ! Get(value, "rawJSON")이라고 하라.
      2. Assert: rawJSON은 String이다.
      3. rawJSON을 반환하라.
    2. value[[NumberData]] 내부 슬롯이 있으면,
      1. value를 ? ToNumber(value)로 설정하라.
    3. 그렇지 않고 value[[StringData]] 내부 슬롯이 있으면,
      1. value를 ? ToString(value)로 설정하라.
    4. 그렇지 않고 value[[BooleanData]] 내부 슬롯이 있으면,
      1. valuevalue.[[BooleanData]]로 설정하라.
    5. 그렇지 않고 value[[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가 Object이고 IsCallable(value)이 false이면,
    1. isArray를 ? IsArray(value)라고 하라.
    2. isArraytrue이면,
      1. SerializeJSONArray(state, value)를 반환하라.
    3. SerializeJSONObject(state, value)를 반환하라.
  12. undefined를 반환하라.

25.5.4.3 QuoteJSONString ( value )

The abstract operation QuoteJSONString takes argument value (a String) and returns a String. value를 0x0022 (QUOTATION MARK) 코드 단위로 감싸고 그 안의 특정 다른 코드 단위를 escape한다. 이 연산은 6.1.4에 설명된 대로 value를 UTF-16으로 인코딩된 코드 포인트의 시퀀스로 해석한다. It performs the following steps when called:

  1. product를 코드 단위 0x0022 (QUOTATION MARK)만으로 구성된 String 값이라고 하자.
  2. StringToCodePoints(value)의 각 코드 포인트 cp에 대해, 다음을 수행한다.
    1. cpTable 77의 “Code Point” 열에 나열되어 있으면,
      1. productproduct와 대응하는 행의 “Escape Sequence” 열에 지정된 cp에 대한 escape sequence의 문자열 연결로 설정한다.
    2. 그렇지 않고 cp의 숫자 값이 0x0020 (SPACE)보다 작거나 cpleading surrogate 또는 trailing surrogate와 같은 숫자 값을 가지면,
      1. unitcp의 숫자 값과 같은 숫자 값을 가진 코드 단위라고 하자.
      2. productproductUnicodeEscape(unit)의 문자열 연결로 설정한다.
    3. 그렇지 않으면,
      1. productproductUTF16EncodeCodePoint(cp)의 문자열 연결로 설정한다.
  3. productproduct와 코드 단위 0x0022 (QUOTATION MARK)의 문자열 연결로 설정한다.
  4. product를 반환한다.
Table 77: JSON 단일 문자 escape sequence
코드 포인트 Unicode 문자 이름 Escape Sequence
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.4.4 UnicodeEscape ( constructor )

The abstract operation UnicodeEscape takes argument constructor (a code unit) and returns a String. constructor를 Unicode escape sequence로 나타낸다. It performs the following steps when called:

  1. nconstructor의 숫자 값이라고 하자.
  2. Assert: n ≤ 0xFFFF.
  3. hex를 소문자 16진수로 형식화한 n의 String 표현이라고 하자.
  4. 코드 단위 0x005C (REVERSE SOLIDUS), "u", 그리고 StringPad(hex, 4, "0", start)의 문자열 연결을 반환한다.

25.5.4.5 SerializeJSONObject ( state, value )

The abstract operation SerializeJSONObject takes arguments state (a JSON Serialization Record) and value (an Object) and returns either a normal completion containing a String or a throw completion. 객체를 직렬화한다. It performs the following steps when called:

  1. state.[[Stack]]value를 포함하면, 구조가 순환적이므로 TypeError 예외를 던진다.
  2. valuestate.[[Stack]]에 추가한다.
  3. stepBackstate.[[Indent]]라고 하자.
  4. state.[[Indent]]state.[[Indent]]state.[[Gap]]의 문자열 연결로 설정한다.
  5. state.[[PropertyList]]undefined가 아니면,
    1. keysstate.[[PropertyList]]라고 하자.
  6. 그렇지 않으면,
    1. keys를 ? EnumerableOwnProperties(value, key)라고 하자.
  7. partial을 새로운 빈 List라고 하자.
  8. keys의 각 요소 propertyKey에 대해, 다음을 수행한다.
    1. strP를 ? SerializeJSONProperty(state, propertyKey, value)라고 하자.
    2. strPundefined가 아니면,
      1. memberQuoteJSONString(propertyKey)라고 하자.
      2. membermember":"의 문자열 연결로 설정한다.
      3. state.[[Gap]]이 빈 String이 아니면,
        1. membermember와 코드 단위 0x0020 (SPACE)의 문자열 연결로 설정한다.
      4. membermemberstrP의 문자열 연결로 설정한다.
      5. memberpartial에 추가한다.
  9. partial이 비어 있으면,
    1. final"{}"라고 하자.
  10. 그렇지 않으면,
    1. state.[[Gap]]이 빈 String이면,
      1. propertiespartial의 모든 요소 String을 연결하되 인접한 각 String 쌍 사이에 코드 단위 0x002C (COMMA)를 넣어 형성된 String 값이라고 하자. 첫 번째 String 앞이나 마지막 String 뒤에는 쉼표를 삽입하지 않는다.
      2. final"{", properties, 그리고 "}"의 문자열 연결이라고 하자.
    2. 그렇지 않으면,
      1. separator를 코드 단위 0x002C (COMMA), 코드 단위 0x000A (LINE FEED), 그리고 state.[[Indent]]의 문자열 연결이라고 하자.
      2. propertiespartial의 모든 요소 String을 연결하되 인접한 각 String 쌍 사이에 separator를 넣어 형성된 String 값이라고 하자. separator String은 첫 번째 String 앞이나 마지막 String 뒤에는 삽입하지 않는다.
      3. final"{", 코드 단위 0x000A (LINE FEED), state.[[Indent]], properties, 코드 단위 0x000A (LINE FEED), stepBack, 그리고 "}"의 문자열 연결이라고 하자.
  11. state.[[Stack]]의 마지막 요소를 제거한다.
  12. state.[[Indent]]stepBack으로 설정한다.
  13. final을 반환한다.

25.5.4.6 SerializeJSONArray ( state, value )

The abstract operation SerializeJSONArray takes arguments state (a JSON Serialization Record) and value (an Object) and returns either a normal completion containing a String or a throw completion. 배열을 직렬화한다. It performs the following steps when called:

  1. state.[[Stack]]value를 포함하면, 구조가 순환적이므로 TypeError 예외를 던진다.
  2. valuestate.[[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. strPpartial에 추가한다.
    4. indexindex + 1로 설정한다.
  9. partial이 비어 있으면,
    1. final"[]"라고 하자.
  10. 그렇지 않으면,
    1. state.[[Gap]]이 빈 String이면,
      1. propertiespartial의 모든 요소 String을 연결하되 인접한 각 String 쌍 사이에 코드 단위 0x002C (COMMA)를 넣어 형성된 String 값이라고 하자. 첫 번째 String 앞이나 마지막 String 뒤에는 쉼표를 삽입하지 않는다.
      2. final"[", properties, 그리고 "]"의 문자열 연결이라고 하자.
    2. 그렇지 않으면,
      1. separator를 코드 단위 0x002C (COMMA), 코드 단위 0x000A (LINE FEED), 그리고 state.[[Indent]]의 문자열 연결이라고 하자.
      2. propertiespartial의 모든 요소 String을 연결하되 인접한 각 String 쌍 사이에 separator를 넣어 형성된 String 값이라고 하자. separator String은 첫 번째 String 앞이나 마지막 String 뒤에는 삽입하지 않는다.
      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(제외)까지의 구간에 있는 요소만 포함된다. 키가 배열 인덱스가 아닌 속성은 stringification에서 제외된다. 배열은 여는 LEFT SQUARE BRACKET, COMMA로 구분된 요소들, 그리고 닫는 RIGHT SQUARE BRACKET으로 stringified된다.

25.5.5 JSON [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 속성의 초기값은 String 값 "JSON"이다.

이 속성은 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true } 속성 특성을 가진다.