21 |
22 | ArrayBufferCopyAndDetach (
23 | _arrayBuffer_: an ECMAScript language value,
24 | _newLength_: an ECMAScript language value,
25 | _preserveResizability_: ~preserve-resizability~ or ~fixed-length~,
26 | ): either a normal completion containing an ArrayBuffer or a throw completion
27 |
28 |
29 |
30 |
31 |
32 |
33 | 1. Perform ? RequireInternalSlot(_arrayBuffer_, [[ArrayBufferData]]).
34 | 1. If IsSharedArrayBuffer(_arrayBuffer_) is *true*, throw a *TypeError* exception.
35 | 1. If _newLength_ is *undefined*, then
36 | 1. Let _newByteLength_ be _arrayBuffer_.[[ArrayBufferByteLength]].
37 | 1. Else,
38 | 1. Let _newByteLength_ be ? ToIndex(_newLength_).
39 | 1. If IsDetachedBuffer(_arrayBuffer_) is *true*, throw a *TypeError* exception.
40 | 1. If _preserveResizability_ is ~preserve-resizability~ and IsResizableArrayBuffer(_arrayBuffer_) is *true*, then
41 | 1. Let _newMaxByteLength_ be _arrayBuffer_.[[ArrayBufferMaxByteLength]].
42 | 1. Else,
43 | 1. Let _newMaxByteLength_ be ~empty~.
44 | 1. If _arrayBuffer_.[[ArrayBufferDetachKey]] is not *undefined*, throw a *TypeError* exception.
45 | 1. Let _newBuffer_ be ? AllocateArrayBuffer(%ArrayBuffer%, _newByteLength_, _newMaxByteLength_).
46 | 1. Let _copyLength_ be min(_newByteLength_, _arrayBuffer_.[[ArrayBufferByteLength]]).
47 | 1. Let _fromBlock_ be _arrayBuffer_.[[ArrayBufferData]].
48 | 1. Let _toBlock_ be _newBuffer_.[[ArrayBufferData]].
49 | 1. Perform CopyDataBlockBytes(_toBlock_, 0, _fromBlock_, 0, _copyLength_).
50 | 1. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as a zero-copy move or a `realloc`.
51 | 1. Perform ! DetachArrayBuffer(_arrayBuffer_).
52 | 1. Return _newBuffer_.
53 |
54 |
55 |
56 |
57 |
58 |
59 |
Properties of the ArrayBuffer Prototype Object
60 |
61 |
62 |
get ArrayBuffer.prototype.detached
63 |
`ArrayBuffer.prototype.detached` is an accessor property whose set accessor function is *undefined*. Its get accessor function performs the following steps:
64 |
65 | 1. Let _O_ be the *this* value.
66 | 1. Perform ? RequireInternalSlot(_O_, [[ArrayBufferData]]).
67 | 1. If IsSharedArrayBuffer(_O_) is *true*, throw a *TypeError* exception.
68 | 1. Return IsDetachedBuffer(_O_).
69 |
70 |
71 |
72 |
73 |
This method performs the following steps when called:
84 |
85 | 1. Let _O_ be the *this* value.
86 | 1. Return ? ArrayBufferCopyAndDetach(_O_, _newLength_, ~fixed-length~).
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # `ArrayBuffer.prototype.transfer` and friends
2 |
3 | Stage: 4 ([included in ES2024](https://github.com/tc39/ecma262/pull/3175)). **This repository is no longer active.**
4 |
5 | Author: Shu-yu Guo (@syg)
6 |
7 | Champion: Shu-yu Guo (@syg), Jordan Harband (@ljharb), Yagiz Nizipli (@anonrig)
8 |
9 | ## Introduction
10 |
11 | `ArrayBuffer`s may be transferred and detached by HTML's serialization algorithms, but there lacks a programmatic JS API for the same expressivity. A programmatic API is useful for programming patterns such as transferring ownership of `ArrayBuffer`s, optimized reallocations (i.e. `realloc` semantics), and fixing resizable `ArrayBuffer`s into fixed-length ones. This proposal fills out this expressivity by adding new methods to `ArrayBuffer.prototype`.
12 |
13 | This proposal is spun out of the [resizable buffers proposal](https://github.com/tc39/proposal-resizablearraybuffer/issues/113). At the time of spinning out, resizable buffers was Stage 3, and this proposal was demoted to Stage 2.
14 |
15 |
16 | ## API
17 |
18 | ```javascript
19 | class ArrayBuffer {
20 | // ... existing stuff
21 |
22 | // Returns a new ArrayBuffer with the same byte content
23 | // as this buffer for [0, min(this.byteLength, newByteLength)],
24 | // then detaches this buffer.
25 | //
26 | // The maximum byte length and thus the resizability of this buffer
27 | // is preserved in the new ArrayBuffer.
28 | //
29 | // Any new memory is zeroed.
30 | //
31 | // If newByteLength is undefined, it is set to this.bytelength.
32 | //
33 | // Designed to be implementable as a copy-free move or a realloc.
34 | //
35 | // Throws a RangeError unless all of the following are satisfied:
36 | // - 0 <= newByteLength
37 | // - If this buffer is resizable, newByteLength <= this.maxByteLength
38 | transfer(newByteLength);
39 |
40 | // Like transfer, except always returns a non-resizable ArrayBuffer.
41 | transferToFixedLength(newByteLength);
42 |
43 | // Returns whether this ArrayBuffer is detached.
44 | get detached();
45 | }
46 | ```
47 |
48 | ## Motivation and use cases
49 |
50 | ### Ownership
51 |
52 | A "move and detach original `ArrayBuffer`" method can be used to implement ownership semantics when working with `ArrayBuffer`s. This is useful in many situations, such as disallowing other users from modifying a buffer when writing into it.
53 |
54 | For example, consider the following example from @domenic from the original transfer proposal:
55 |
56 | ```javascript
57 | function validateAndWrite(arrayBuffer) {
58 | // Do some asynchronous validation.
59 | await validate(arrayBuffer);
60 |
61 | // Assuming we've got here, it's valid; write it to disk.
62 | await fs.writeFile("data.bin", arrayBuffer);
63 | }
64 |
65 | const data = new Uint8Array([0x01, 0x02, 0x03]);
66 | validateAndWrite(data.buffer);
67 | setTimeout(() => {
68 | data[0] = data[1] = data[2] = 0x00;
69 | }, 50);
70 | ```
71 |
72 | Depending on the time taken for `await validate(arrayBuffer)`, the validation result may be stale due to the callback passed to `setTimeout`. A defensive approach would copy the input first, but this is markedly less performant:
73 |
74 | ```javascript
75 | function validateAndWriteSafeButSlow(arrayBuffer) {
76 | // Copy first!
77 | const copy = arrayBuffer.slice();
78 |
79 | await validate(copy);
80 | await fs.writeFile("data.bin", copy);
81 | }
82 | ```
83 |
84 | With `transfer`, the ownership transfer can be succinctly expressed:
85 |
86 | ```javascript
87 | function validateAndWriteSafeAndFast(arrayBuffer) {
88 | // Transfer to take ownership, which implementations can choose to
89 | // implement as a zero-copy move.
90 | const owned = arrayBuffer.transfer();
91 |
92 | // arrayBuffer is detached after this point.
93 | assert(arrayBuffer.detached);
94 |
95 | await validate(owned);
96 | await fs.writeFile("data.bin", owned);
97 | }
98 | ```
99 |
100 | ### Realloc
101 |
102 | The same `transfer` API, when passing a `newByteLength` argument, can double to have the same expressivity as [`realloc`](https://en.cppreference.com/w/c/memory/realloc). Operating systems often implement `realloc` more efficiently than a copy.
103 |
104 | ### Fixing resizable buffers to be fixed-length
105 |
106 | The `transferToFixedLength` method is a variant of `transfer` that always returns a fixed-length `ArrayBuffer`. This is useful in cases when the new buffer no longers needs resizability, allowing implementations to free up virtual memory if resizable buffers were implemented in-place (i.e. address space is reserved up front).
107 |
108 | ### Checking detachedness
109 |
110 | Owing to the [messy history](https://esdiscuss.org/topic/arraybuffer-neutering) of TypedArray and `ArrayBuffer` standardization, and preservation of web compatibility, TypedArray views on detached buffers throw for some operations (e.g. prototype methods), and return sentinel values (`0` or `undefined`) for others (e.g. indexed access and length).
111 |
112 | The `detached` getter is added to authoritatively determine whether an `ArrayBuffer` is detached.
113 |
114 | Currently, there isn't any performant way of detecting whether an `ArrayBuffer` is detached. The following implementation is an example of how the detachedness can be detected, but has some flaws in V8: functions with try catch blocks are not inlined in V8. See also [this Node internal comment](https://github.com/nodejs/node/blob/main/lib/querystring.js#L472).
115 |
116 | ```javascript
117 | const assert = require('node:assert')
118 |
119 | function isBufferDetached(buffer) {
120 | if (buffer.byteLength === 0) {
121 | try {
122 | new Uint8Array(buffer);
123 | } catch (error) {
124 | assert(error.name === 'TypeError');
125 | return true;
126 | }
127 | }
128 | return false
129 | }
130 | ```
131 |
132 | ## FAQ and design rationale tradeoffs
133 |
134 | ### Why do both `transfer` and `transferToFixedLength` exist instead of a single, more flexible method?
135 |
136 | Most folks seem to have the intuition that the move semantics, being the primary use case, ought to preserve resizability. Transferring `ArrayBuffer`s in HTML serialization preserves resizability, and symmetry with that is good for intuition.
137 |
138 | A flexible `transfer` also complicates the API design for a more minority use case, thus the separate `transferToFixedLength` method.
139 |
140 | ### Why can't I pass a new `maxByteLength` to `transfer`?
141 |
142 | One of the goals of `transfer`, in addition to detach semantics, is to be more efficiently implementable than a copy in user code. It is not clear to the author that for resizable buffers implemented in-place, reallocation of the virtual memory pages is possible and efficient on all popular operating systems.
143 |
144 | And besides it adds complexity in service of a more minority use case. Resizable buffers ought to be allocated with sufficient maximum size from the start.
145 |
146 | ### If performance is the goal, why add new methods instead of implementing copy-on-write (CoW) as a transparent optimization?
147 |
148 | In a word, security.
149 |
150 | `ArrayBuffer`s are a very popular attack vector for exploiting JavaScript engines. An important security mitigation engines employ is to ensure the `ArrayBuffer`'s data pointer is constant and does not move. For this same reason, resizable buffers are specified to allow in-place implementation.
151 |
152 | CoW `ArrayBuffer`s may be implemented by moving the data pointer. When the CoW `ArrayBuffer` is modified, new memory is allocated and the backing store is updated. However, this conflicts with the security mitigation.
153 |
154 | It is possible to both implement copy-on-write `ArrayBuffer`s and keep the "fixed data pointer" security mitigation only with additional help from the underlying operating system: by mapping new virtual memory that is marked as CoW and initially point to the same physical pages as the source buffer. This technique is, however, not portable.
155 |
156 | At this time, Google Chrome deems this mitigation important enough for security to not implement CoW `ArrayBuffer`s.
157 |
158 | ### How is `get detached()` used in browsers and in runtimes?
159 |
160 | - Node.js [discussed adding a public API](https://github.com/nodejs/node/pull/45512) for `get detached()`
161 | - WebKit has [`isDetached`](https://github.com/WebKit/WebKit/blob/6545977030f491dd87b3ae9fd666f6b949ae8a74/Source/JavaScriptCore/runtime/ArrayBuffer.h#L308) in internal `ArrayBuffer` class
162 | - V8 added [`v8::ArrayBuffer::WasDetached`](https://github.com/v8/v8/commit/9df5ef70ff18977b157028fc55ced5af4bcee535) which was later [backported to Node.js](https://github.com/nodejs/node/pull/45568) and used in Node webstreams.
163 |
164 | ### How is `transfer` used in browsers and in runtimes?
165 |
166 | Most browsers use `detach()` as the name for detaching `ArrayBuffer`s.
167 |
168 | - V8 has `Detach()` as [`v8::ArrayBuffer::Detach()`](https://v8docs.nodesource.com/node-18.2/d5/d6e/classv8_1_1_array_buffer.html#abb7a2b60240651d16e17d02eb6f636cf)
169 | - WebKit has [`void detach()`](https://github.com/WebKit/WebKit/blob/6545977030f491dd87b3ae9fd666f6b949ae8a74/Source/JavaScriptCore/runtime/ArrayBuffer.h#L307)
170 | - Node.js [has an internal implementation](https://github.com/nodejs/node/blob/22c645d411b7cba9e7b0d578a3e7108147a5d89e/lib/internal/webstreams/util.js#L131) to support detaching internal buffers called `transferArrayBuffer`, and used in Node webstream.
171 |
172 | ## Open questions
173 |
174 | ### Do we really need `transferToFixedLength`?
175 |
176 | Feels nice to round out the expressivity, but granted the use case here isn't as compelling as `transfer`.
177 |
178 | ## History and acknowledgment
179 |
180 | Thanks to:
181 | - @domenic for https://github.com/domenic/proposal-arraybuffer-transfer/tree/HEAD~1
182 |
--------------------------------------------------------------------------------
/resizable-buffer-biblio.json:
--------------------------------------------------------------------------------
1 | {"location":"https://tc39.es/proposal-resizablearraybuffer/","entries":[{"type":"clause","id":"intro","aoid":null,"title":"Resizable ArrayBuffer and growable SharedArrayBuffer","titleHTML":"Resizable ArrayBuffer and growable SharedArrayBuffer","number":""},{"type":"op","aoid":"DetachArrayBuffer","refId":"sec-detacharraybuffer","kind":"abstract operation","signature":{"parameters":[{"name":"_arrayBuffer_","type":{"kind":"opaque","type":"an ArrayBuffer"}}],"optionalParameters":[{"name":"_key_","type":{"kind":"opaque","type":"anything"}}],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"unused"}}},"effects":[]},{"type":"clause","id":"sec-detacharraybuffer","aoid":"DetachArrayBuffer","title":"DetachArrayBuffer ( arrayBuffer [ , key ] )","titleHTML":"DetachArrayBuffer ( arrayBuffer [ , key ] )","number":"1.1.1"},{"type":"op","aoid":"AllocateArrayBuffer","refId":"sec-allocatearraybuffer","kind":"abstract operation","signature":{"parameters":[{"name":"_constructor_","type":{"kind":"opaque","type":"a constructor"}},{"name":"_byteLength_","type":{"kind":"opaque","type":"a non-negative integer"}}],"optionalParameters":[{"name":"_maxByteLength_","type":{"kind":"union","types":[{"kind":"opaque","type":"a non-negative integer"},{"kind":"opaque","type":"~empty~"}]}}],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"opaque","type":"an ArrayBuffer"}}},"effects":[]},{"type":"clause","id":"sec-allocatearraybuffer","aoid":"AllocateArrayBuffer","title":"AllocateArrayBuffer ( constructor, byteLength [ , maxByteLength ] )","titleHTML":"AllocateArrayBuffer ( constructor, byteLength [ , maxByteLength ] )","number":"1.1.2"},{"type":"op","aoid":"ArrayBufferByteLength","refId":"sec-arraybufferlength","kind":"abstract operation","signature":{"parameters":[{"name":"_arrayBuffer_","type":{"kind":"opaque","type":"an ArrayBuffer"}},{"name":"_order_","type":{"kind":"union","types":[{"kind":"opaque","type":"~SeqCst~"},{"kind":"opaque","type":"~Unordered~"}]}}],"optionalParameters":[],"return":{"kind":"opaque","type":"a non-negative integer"}},"effects":[]},{"type":"clause","id":"sec-arraybufferlength","aoid":"ArrayBufferByteLength","title":"ArrayBufferByteLength ( arrayBuffer, order )","titleHTML":"ArrayBufferByteLength ( arrayBuffer, order )","number":"1.1.3"},{"type":"op","aoid":"MakeIdempotentArrayBufferByteLengthGetter","refId":"sec-makeidempotentarraybufferbytelengthgetter","kind":"abstract operation","signature":{"parameters":[{"name":"_order_","type":{"kind":"union","types":[{"kind":"opaque","type":"~SeqCst~"},{"kind":"opaque","type":"~Unordered~"}]}}],"optionalParameters":[],"return":{"kind":"opaque","type":"an Abstract Closure with one parameter"}},"effects":[]},{"type":"clause","id":"sec-makeidempotentarraybufferbytelengthgetter","aoid":"MakeIdempotentArrayBufferByteLengthGetter","title":"MakeIdempotentArrayBufferByteLengthGetter ( order )","titleHTML":"MakeIdempotentArrayBufferByteLengthGetter ( order )","number":"1.1.4"},{"type":"op","aoid":"IsResizableArrayBuffer","refId":"sec-isresizablearraybuffer","kind":"abstract operation","signature":{"parameters":[{"name":"_arrayBuffer_","type":{"kind":"opaque","type":"an ArrayBuffer"}}],"optionalParameters":[],"return":{"kind":"opaque","type":"a Boolean"}},"effects":[]},{"type":"clause","id":"sec-isresizablearraybuffer","aoid":"IsResizableArrayBuffer","title":"IsResizableArrayBuffer ( arrayBuffer )","titleHTML":"IsResizableArrayBuffer ( arrayBuffer )","number":"1.1.5"},{"type":"op","aoid":"GetArrayBufferMaxByteLengthOption","refId":"sec-getarraybuffermaxbytelengthoption","kind":"abstract operation","signature":{"parameters":[{"name":"_options_","type":{"kind":"opaque","type":"an ECMAScript language value"}}],"optionalParameters":[],"return":{"kind":"completion","typeOfValueIfNormal":{"kind":"union","types":[{"kind":"opaque","type":"a non-negative integer"},{"kind":"opaque","type":"~empty~"}]},"completionType":"normal"}},"effects":["user-code"]},{"type":"clause","id":"sec-getarraybuffermaxbytelengthoption","aoid":"GetArrayBufferMaxByteLengthOption","title":"GetArrayBufferMaxByteLengthOption ( options )","titleHTML":"GetArrayBufferMaxByteLengthOption ( options )","number":"1.1.6"},{"type":"op","aoid":"HostResizeArrayBuffer","refId":"sec-hostresizearraybuffer","kind":"host-defined abstract operation","signature":{"parameters":[{"name":"_buffer_","type":{"kind":"opaque","type":"an ArrayBuffer"}},{"name":"_newByteLength_","type":{"kind":"opaque","type":"a non-negative integer"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"union","types":[{"kind":"opaque","type":"~handled~"},{"kind":"opaque","type":"~unhandled~"}]}}},"effects":[]},{"type":"clause","id":"sec-hostresizearraybuffer","aoid":"HostResizeArrayBuffer","title":"HostResizeArrayBuffer ( buffer, newByteLength )","titleHTML":"HostResizeArrayBuffer ( buffer, newByteLength )","number":"1.1.7"},{"type":"clause","id":"sec-abstract-operations-for-arraybuffer-objects-mods","aoid":null,"title":"Modifications to Abstract Operations for ArrayBuffer Objects","titleHTML":"Modifications to Abstract Operations for ArrayBuffer Objects","number":"1.1"},{"type":"clause","id":"sec-arraybuffer-length","aoid":null,"title":"ArrayBuffer ( length [ , options ] )","titleHTML":"ArrayBuffer ( length [ , options ] )","number":"1.2.1"},{"type":"clause","id":"sec-arraybuffer-constructor","aoid":null,"title":"The ArrayBuffer Constructor","titleHTML":"The ArrayBuffer Constructor","number":"1.2"},{"type":"clause","id":"sec-get-arraybuffer-@@species","aoid":null,"title":"get ArrayBuffer [ @@species ]","titleHTML":"get ArrayBuffer [ @@species ]","number":"1.3.1"},{"type":"clause","id":"sec-get-arraybuffer.prototype.maxbytelength","aoid":null,"title":"get ArrayBuffer.prototype.maxByteLength","titleHTML":"get ArrayBuffer.prototype.maxByteLength","number":"1.3.2"},{"type":"clause","id":"sec-get-arraybuffer.prototype.resizable","aoid":null,"title":"get ArrayBuffer.prototype.resizable","titleHTML":"get ArrayBuffer.prototype.resizable","number":"1.3.3"},{"type":"clause","id":"sec-arraybuffer.prototype.slice","aoid":null,"title":"ArrayBuffer.prototype.slice ( start, end )","titleHTML":"ArrayBuffer.prototype.slice ( start, end )","number":"1.3.4"},{"type":"clause","id":"sec-arraybuffer.prototype.resize","aoid":null,"title":"ArrayBuffer.prototype.resize ( newLength )","titleHTML":"ArrayBuffer.prototype.resize ( newLength )","number":"1.3.5"},{"type":"clause","id":"sec-properties-of-the-arraybuffer-prototype-object-mods","aoid":null,"title":"Modifications to the Properties of the ArrayBuffer Prototype Object","titleHTML":"Modifications to the Properties of the ArrayBuffer Prototype Object","number":"1.3"},{"type":"clause","id":"sec-arraybuffer-objects-mods","aoid":null,"title":"Modifications to ArrayBuffer Objects","titleHTML":"Modifications to ArrayBuffer Objects","number":"1"},{"type":"op","aoid":"AllocateSharedArrayBuffer","refId":"sec-allocatesharedarraybuffer","kind":"abstract operation","signature":{"parameters":[{"name":"_constructor_","type":{"kind":"opaque","type":"a constructor"}},{"name":"_byteLength_","type":{"kind":"opaque","type":"a non-negative integer"}}],"optionalParameters":[{"name":"_maxByteLength_","type":{"kind":"union","types":[{"kind":"opaque","type":"a non-negative integer"},{"kind":"opaque","type":"~empty~"}]}}],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"opaque","type":"a SharedArrayBuffer"}}},"effects":[]},{"type":"clause","id":"sec-allocatesharedarraybuffer","aoid":"AllocateSharedArrayBuffer","title":"AllocateSharedArrayBuffer ( constructor, byteLength [ , maxByteLength ] )","titleHTML":"AllocateSharedArrayBuffer ( constructor, byteLength [ , maxByteLength ] )","number":"2.1.1"},{"type":"op","aoid":"HostGrowSharedArrayBuffer","refId":"sec-hostgrowsharedarraybuffer","kind":"host-defined abstract operation","signature":{"parameters":[{"name":"_buffer_","type":{"kind":"opaque","type":"a SharedArrayBuffer"}},{"name":"_newByteLength_","type":{"kind":"opaque","type":"a non-negative integer"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"union","types":[{"kind":"opaque","type":"~handled~"},{"kind":"opaque","type":"~unhandled~"}]}}},"effects":[]},{"type":"clause","id":"sec-hostgrowsharedarraybuffer","aoid":"HostGrowSharedArrayBuffer","title":"HostGrowSharedArrayBuffer ( buffer, newByteLength )","titleHTML":"HostGrowSharedArrayBuffer ( buffer, newByteLength )","number":"2.1.2"},{"type":"clause","id":"sec-abstract-operations-for-sharedarraybuffer-objects-mods","aoid":null,"title":"Modifications to Abstract Operations for SharedArrayBuffer Objects","titleHTML":"Modifications to Abstract Operations for SharedArrayBuffer Objects","number":"2.1"},{"type":"clause","id":"sec-sharedarraybuffer-length","aoid":null,"title":"SharedArrayBuffer ( length [ , options ] )","titleHTML":"SharedArrayBuffer ( length [ , options ] )","number":"2.2.1"},{"type":"clause","id":"sec-sharedarraybuffer-constructor","aoid":null,"title":"The SharedArrayBuffer Constructor","titleHTML":"The SharedArrayBuffer Constructor","number":"2.2"},{"type":"clause","id":"sec-get-sharedarraybuffer.prototype.bytelength","aoid":null,"title":"get SharedArrayBuffer.prototype.byteLength","titleHTML":"get SharedArrayBuffer.prototype.byteLength","number":"2.3.1"},{"type":"clause","id":"sec-get-sharedarraybuffer.prototype.growable","aoid":null,"title":"get SharedArrayBuffer.prototype.growable","titleHTML":"get SharedArrayBuffer.prototype.growable","number":"2.3.2"},{"type":"clause","id":"sec-get-sharedarraybuffer.prototype.maxbytelength","aoid":null,"title":"get SharedArrayBuffer.prototype.maxByteLength","titleHTML":"get SharedArrayBuffer.prototype.maxByteLength","number":"2.3.3"},{"type":"clause","id":"sec-sharedarraybuffer.prototype.grow","aoid":null,"title":"SharedArrayBuffer.prototype.grow ( newLength )","titleHTML":"SharedArrayBuffer.prototype.grow ( newLength )","number":"2.3.4"},{"type":"clause","id":"sec-sharedarraybuffer.prototype.slice","aoid":null,"title":"SharedArrayBuffer.prototype.slice ( start, end )","titleHTML":"SharedArrayBuffer.prototype.slice ( start, end )","number":"2.3.5"},{"type":"clause","id":"sec-properties-of-the-sharedarraybuffer-prototype-object-mods","aoid":null,"title":"Modifications to the Properties of the SharedArrayBuffer Prototype Object","titleHTML":"Modifications to the Properties of the SharedArrayBuffer Prototype Object","number":"2.3"},{"type":"clause","id":"sec-sharedarraybuffer-objects-mods","aoid":null,"title":"Modifications to SharedArrayBuffer Objects","titleHTML":"Modifications to SharedArrayBuffer Objects","number":"2"},{"type":"clause","id":"sec-integer-indexed-exotic-objects-ownpropertykeys","aoid":null,"title":"[[OwnPropertyKeys]] ( )","titleHTML":"[[OwnPropertyKeys]] ( )","number":"3.1"},{"type":"op","aoid":"IsValidIntegerIndex","refId":"sec-isvalidintegerindex","kind":"abstract operation","signature":{"parameters":[{"name":"_O_","type":{"kind":"opaque","type":"an Integer-Indexed exotic object"}},{"name":"_index_","type":{"kind":"opaque","type":"a Number"}}],"optionalParameters":[],"return":{"kind":"opaque","type":"a Boolean"}},"effects":[]},{"type":"clause","id":"sec-isvalidintegerindex","aoid":"IsValidIntegerIndex","title":"IsValidIntegerIndex ( O, index )","titleHTML":"IsValidIntegerIndex ( O, index )","number":"3.2"},{"type":"op","aoid":"IntegerIndexedObjectByteLength","refId":"sec-integerindexedobjectbytelength","kind":"abstract operation","signature":{"parameters":[{"name":"_O_","type":{"kind":"opaque","type":"an Integer-Indexed exotic object"}},{"name":"_getBufferByteLength_","type":{"kind":"opaque","type":"an Abstract Closure"}}],"optionalParameters":[],"return":{"kind":"opaque","type":"a non-negative integer"}},"effects":[]},{"type":"clause","id":"sec-integerindexedobjectbytelength","aoid":"IntegerIndexedObjectByteLength","title":"IntegerIndexedObjectByteLength ( O, getBufferByteLength )","titleHTML":"IntegerIndexedObjectByteLength ( O, getBufferByteLength )","number":"3.3"},{"type":"op","aoid":"IntegerIndexedObjectLength","refId":"sec-integerindexedobjectlength","kind":"abstract operation","signature":{"parameters":[{"name":"_O_","type":{"kind":"opaque","type":"an Integer-Indexed exotic object"}},{"name":"_getBufferByteLength_","type":{"kind":"opaque","type":"an Abstract Closure"}}],"optionalParameters":[],"return":{"kind":"union","types":[{"kind":"opaque","type":"a non-negative integer"},{"kind":"opaque","type":"~out-of-bounds~"}]}},"effects":[]},{"type":"clause","id":"sec-integerindexedobjectlength","aoid":"IntegerIndexedObjectLength","title":"IntegerIndexedObjectLength ( O, getBufferByteLength )","titleHTML":"IntegerIndexedObjectLength ( O, getBufferByteLength )","number":"3.4"},{"type":"op","aoid":"IsIntegerIndexedObjectOutOfBounds","refId":"sec-isintegerindexedobjectoutofbounds","kind":"abstract operation","signature":{"parameters":[{"name":"_O_","type":{"kind":"opaque","type":"an Integer-Indexed exotic object"}},{"name":"_getBufferByteLength_","type":{"kind":"opaque","type":"an Abstract Closure"}}],"optionalParameters":[],"return":{"kind":"opaque","type":"a Boolean"}},"effects":[]},{"type":"clause","id":"sec-isintegerindexedobjectoutofbounds","aoid":"IsIntegerIndexedObjectOutOfBounds","title":"IsIntegerIndexedObjectOutOfBounds ( O, getBufferByteLength )","titleHTML":"IsIntegerIndexedObjectOutOfBounds ( O, getBufferByteLength )","number":"3.5"},{"type":"op","aoid":"IsArrayBufferViewOutOfBounds","refId":"sec-isarraybufferviewoutofbounds","kind":"abstract operation","signature":{"parameters":[{"name":"_O_","type":{"kind":"union","types":[{"kind":"opaque","type":"an Integer-Indexed exotic object"},{"kind":"opaque","type":"a DataView"}]}}],"optionalParameters":[],"return":{"kind":"opaque","type":"a Boolean"}},"effects":[]},{"type":"clause","id":"sec-isarraybufferviewoutofbounds","aoid":"IsArrayBufferViewOutOfBounds","title":"IsArrayBufferViewOutOfBounds ( O )","titleHTML":"IsArrayBufferViewOutOfBounds ( O )","number":"3.6"},{"type":"clause","id":"sec-integer-indexed-exotic-objects-mods","aoid":null,"title":"Modifications to Integer-Indexed Exotic Objects","titleHTML":"Modifications to Integer-Indexed Exotic Objects","number":"3"},{"type":"op","aoid":"ValidateTypedArray","refId":"sec-validatetypedarray","kind":"abstract operation","signature":{"parameters":[{"name":"_O_","type":{"kind":"opaque","type":"an ECMAScript language value"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"unused"}}},"effects":[]},{"type":"clause","id":"sec-validatetypedarray","aoid":"ValidateTypedArray","title":"ValidateTypedArray ( O )","titleHTML":"ValidateTypedArray ( O )","number":"4.1.1"},{"type":"clause","id":"sec-get-%typedarray%.prototype.bytelength","aoid":null,"title":"get %TypedArray%.prototype.byteLength","titleHTML":"get %TypedArray%.prototype.byteLength","number":"4.1.2"},{"type":"clause","id":"sec-get-%typedarray%.prototype.byteoffset","aoid":null,"title":"get %TypedArray%.prototype.byteOffset","titleHTML":"get %TypedArray%.prototype.byteOffset","number":"4.1.3"},{"type":"clause","id":"sec-get-%typedarray%.prototype.length","aoid":null,"title":"get %TypedArray%.prototype.length","titleHTML":"get %TypedArray%.prototype.length","number":"4.1.4"},{"type":"clause","id":"sec-%typedarray%.prototype.copywithin","aoid":null,"title":"%TypedArray%.prototype.copyWithin ( target, start [ , end ] )","titleHTML":"%TypedArray%.prototype.copyWithin ( target, start [ , end ] )","number":"4.1.5"},{"type":"clause","id":"sec-%typedarray%.prototype.fill","aoid":null,"title":"%TypedArray%.prototype.fill ( value [ , start [ , end ] ] )","titleHTML":"%TypedArray%.prototype.fill ( value [ , start [ , end ] ] )","number":"4.1.6"},{"type":"clause","id":"sec-%typedarray%.prototype.slice","aoid":null,"title":"%TypedArray%.prototype.slice ( start, end )","titleHTML":"%TypedArray%.prototype.slice ( start, end )","number":"4.1.7"},{"type":"clause","id":"sec-%typedarray%.prototype.subarray","aoid":null,"title":"%TypedArray%.prototype.subarray ( begin, end )","titleHTML":"%TypedArray%.prototype.subarray ( begin, end )","number":"4.1.8"},{"type":"op","aoid":"SetTypedArrayFromTypedArray","refId":"sec-settypedarrayfromtypedarray","kind":"abstract operation","signature":{"parameters":[{"name":"_target_","type":{"kind":"opaque","type":"a TypedArray"}},{"name":"_targetOffset_","type":{"kind":"union","types":[{"kind":"opaque","type":"a non-negative integer"},{"kind":"opaque","type":"+∞"}]}},{"name":"_source_","type":{"kind":"opaque","type":"a TypedArray"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"unused"}}},"effects":[]},{"type":"clause","id":"sec-settypedarrayfromtypedarray","aoid":"SetTypedArrayFromTypedArray","title":"SetTypedArrayFromTypedArray ( target, targetOffset, source )","titleHTML":"SetTypedArrayFromTypedArray ( target, targetOffset, source )","number":"4.1.9"},{"type":"clause","id":"sec-properties-of-the-%typedarrayprototype%-object-mods","aoid":null,"title":"Modifications to Properties of the %TypedArray.prototype% Object","titleHTML":"Modifications to Properties of the %TypedArray.prototype% Object","number":"4.1"},{"type":"op","aoid":"InitializeTypedArrayFromTypedArray","refId":"sec-initializetypedarrayfromtypedarray","kind":"abstract operation","signature":{"parameters":[{"name":"_O_","type":{"kind":"opaque","type":"a TypedArray"}},{"name":"_srcArray_","type":{"kind":"opaque","type":"a TypedArray"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"unused"}}},"effects":[]},{"type":"clause","id":"sec-initializetypedarrayfromtypedarray","aoid":"InitializeTypedArrayFromTypedArray","title":"InitializeTypedArrayFromTypedArray ( O, srcArray )","titleHTML":"InitializeTypedArrayFromTypedArray ( O, srcArray )","number":"4.2.1"},{"type":"op","aoid":"InitializeTypedArrayFromArrayBuffer","refId":"sec-initializetypedarrayfromarraybuffer","kind":"abstract operation","signature":{"parameters":[{"name":"_O_","type":{"kind":"opaque","type":"a TypedArray"}},{"name":"_buffer_","type":{"kind":"union","types":[{"kind":"opaque","type":"an ArrayBuffer"},{"kind":"opaque","type":"a SharedArrayBuffer"}]}},{"name":"_byteOffset_","type":{"kind":"opaque","type":"an ECMAScript language value"}},{"name":"_length_","type":{"kind":"opaque","type":"an ECMAScript language value"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"unused"}}},"effects":[]},{"type":"clause","id":"sec-initializetypedarrayfromarraybuffer","aoid":"InitializeTypedArrayFromArrayBuffer","title":"InitializeTypedArrayFromArrayBuffer ( O, buffer, byteOffset, length )","titleHTML":"InitializeTypedArrayFromArrayBuffer ( O, buffer, byteOffset, length )","number":"4.2.2"},{"type":"clause","id":"sec-typedarray-constructors-mods","aoid":null,"title":"Modifications to the TypedArray Constructors","titleHTML":"Modifications to the TypedArray Constructors","number":"4.2"},{"type":"clause","id":"sec-typedarray-objects-mods","aoid":null,"title":"Modifications to TypedArray Objects","titleHTML":"Modifications to TypedArray Objects","number":"4"},{"type":"op","aoid":"GetViewByteLength","refId":"sec-getviewbytelength","kind":"abstract operation","signature":{"parameters":[{"name":"_view_","type":{"kind":"opaque","type":"a DataView"}},{"name":"_getBufferByteLength_","type":{"kind":"opaque","type":"an Abstract Closure"}}],"optionalParameters":[],"return":{"kind":"union","types":[{"kind":"opaque","type":"a non-negative integer"},{"kind":"opaque","type":"~out-of-bounds~"}]}},"effects":[]},{"type":"clause","id":"sec-getviewbytelength","aoid":"GetViewByteLength","title":"GetViewByteLength ( view, getBufferByteLength )","titleHTML":"GetViewByteLength ( view, getBufferByteLength )","number":"5.1.1"},{"type":"op","aoid":"IsViewOutOfBounds","refId":"sec-isviewoutofbounds","kind":"abstract operation","signature":{"parameters":[{"name":"_view_","type":{"kind":"opaque","type":"a DataView"}},{"name":"_getBufferByteLength_","type":{"kind":"opaque","type":"an Abstract Closure"}}],"optionalParameters":[],"return":{"kind":"opaque","type":"a Boolean"}},"effects":[]},{"type":"clause","id":"sec-isviewoutofbounds","aoid":"IsViewOutOfBounds","title":"IsViewOutOfBounds ( view, getBufferByteLength )","titleHTML":"IsViewOutOfBounds ( view, getBufferByteLength )","number":"5.1.2"},{"type":"op","aoid":"GetViewValue","refId":"sec-getviewvalue","kind":"abstract operation","signature":{"parameters":[{"name":"_view_","type":{"kind":"opaque","type":"an ECMAScript language value"}},{"name":"_requestIndex_","type":{"kind":"opaque","type":"an ECMAScript language value"}},{"name":"_isLittleEndian_","type":{"kind":"opaque","type":"an ECMAScript language value"}},{"name":"_type_","type":{"kind":"opaque","type":"a TypedArray element type"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"union","types":[{"kind":"opaque","type":"a Number"},{"kind":"opaque","type":"a BigInt"}]}}},"effects":[]},{"type":"clause","id":"sec-getviewvalue","aoid":"GetViewValue","title":"GetViewValue ( view, requestIndex, isLittleEndian, type )","titleHTML":"GetViewValue ( view, requestIndex, isLittleEndian, type )","number":"5.1.3"},{"type":"op","aoid":"SetViewValue","refId":"sec-setviewvalue","kind":"abstract operation","signature":{"parameters":[{"name":"_view_","type":{"kind":"opaque","type":"an ECMAScript language value"}},{"name":"_requestIndex_","type":{"kind":"opaque","type":"an ECMAScript language value"}},{"name":"_isLittleEndian_","type":{"kind":"opaque","type":"an ECMAScript language value"}},{"name":"_type_","type":{"kind":"opaque","type":"a TypedArray element type"}},{"name":"_value_","type":{"kind":"opaque","type":"an ECMAScript language value"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"opaque","type":"*undefined*"}}},"effects":[]},{"type":"clause","id":"sec-setviewvalue","aoid":"SetViewValue","title":"SetViewValue ( view, requestIndex, isLittleEndian, type, value )","titleHTML":"SetViewValue ( view, requestIndex, isLittleEndian, type, value )","number":"5.1.4"},{"type":"clause","id":"sec-abstract-operations-for-dataview-objects-mods","aoid":null,"title":"Modifications to Abstract Operations For DataView Objects","titleHTML":"Modifications to Abstract Operations For DataView Objects","number":"5.1"},{"type":"clause","id":"sec-dataview-buffer-byteoffset-bytelength","aoid":null,"title":"DataView ( buffer [ , byteOffset [ , byteLength ] ] )","titleHTML":"DataView ( buffer [ , byteOffset [ , byteLength ] ] )","number":"5.2.1"},{"type":"clause","id":"sec-dataview-constructor-mods","aoid":null,"title":"Modifications to the DataView Constructor","titleHTML":"Modifications to the DataView Constructor","number":"5.2"},{"type":"clause","id":"sec-get-dataview.prototype.bytelength","aoid":null,"title":"get DataView.prototype.byteLength","titleHTML":"get DataView.prototype.byteLength","number":"5.3.1"},{"type":"clause","id":"sec-get-dataview.prototype.byteoffset","aoid":null,"title":"get DataView.prototype.byteOffset","titleHTML":"get DataView.prototype.byteOffset","number":"5.3.2"},{"type":"clause","id":"sec-properties-of-the-dataview-prototype-object-mods","aoid":null,"title":"Modifications to Properties of the DataView Prototype Object","titleHTML":"Modifications to Properties of the DataView Prototype Object","number":"5.3"},{"type":"clause","id":"sec-dataview-objects-mods","aoid":null,"title":"Modifications to DataView Objects","titleHTML":"Modifications to DataView Objects","number":"5"},{"type":"clause","id":"sec-atomics.compareexchange","aoid":null,"title":"Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue )","titleHTML":"Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue )","number":"6.1.1"},{"type":"clause","id":"sec-atomics.store","aoid":null,"title":"Atomics.store ( typedArray, index, value )","titleHTML":"Atomics.store ( typedArray, index, value )","number":"6.1.2"},{"type":"clause","id":"sec-properties-of-the-atomics-object-mods","aoid":null,"title":"Modifications to Properties of the Atomics Object","titleHTML":"Modifications to Properties of the Atomics Object","number":"6.1"},{"type":"op","aoid":"AtomicReadModifyWrite","refId":"sec-atomicreadmodifywrite","kind":"abstract operation","signature":{"parameters":[{"name":"_typedArray_","type":{"kind":"opaque","type":"an ECMAScript language value"}},{"name":"_index_","type":{"kind":"opaque","type":"an ECMAScript language value"}},{"name":"_value_","type":{"kind":"opaque","type":"an ECMAScript language value"}},{"name":"_op_","type":{"kind":"opaque","type":"a read-modify-write modification function"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"union","types":[{"kind":"opaque","type":"a Number"},{"kind":"opaque","type":"a BigInt"}]}}},"effects":[]},{"type":"clause","id":"sec-atomicreadmodifywrite","aoid":"AtomicReadModifyWrite","title":"AtomicReadModifyWrite ( typedArray, index, value, op )","titleHTML":"AtomicReadModifyWrite ( typedArray, index, value, op )","number":"6.2.1"},{"type":"op","aoid":"ValidateAtomicAccess","refId":"sec-validateatomicaccess","kind":"abstract operation","signature":{"parameters":[{"name":"_typedArray_","type":{"kind":"opaque","type":"a TypedArray"}},{"name":"_requestIndex_","type":{"kind":"opaque","type":"an ECMAScript language value"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"opaque","type":"an integer"}}},"effects":[]},{"type":"clause","id":"sec-validateatomicaccess","aoid":"ValidateAtomicAccess","title":"ValidateAtomicAccess ( typedArray, requestIndex )","titleHTML":"ValidateAtomicAccess ( typedArray, requestIndex )","number":"6.2.2"},{"type":"clause","id":"sec-abstract-operations-for-atomics-mods","aoid":null,"title":"Modifications to Abstract Operations for Atomics","titleHTML":"Modifications to Abstract Operations for Atomics","number":"6.2"},{"type":"clause","id":"sec-atomics-mods","aoid":null,"title":"Modifications to Atomics","titleHTML":"Modifications to Atomics","number":"6"},{"type":"clause","id":"sec-maxbytelength-guidelines","aoid":null,"title":"Resizable ArrayBuffer and growable SharedArrayBuffer Guidelines","titleHTML":"Resizable ArrayBuffer and growable SharedArrayBuffer Guidelines","number":"7"},{"type":"clause","id":"omitted-for-brevity","aoid":null,"title":"Mechanical Changes Omitted for Brevity","titleHTML":"Mechanical Changes Omitted for Brevity","number":"8"}]}
--------------------------------------------------------------------------------