diff --git a/.github/workflows/publish-main.yml b/.github/workflows/publish-main.yml deleted file mode 100644 index 704b5b5..0000000 --- a/.github/workflows/publish-main.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Publish main - -on: - push: - branches: [main] - -jobs: - publish: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: '[node LTS] npm install' - uses: ljharb/actions/node/install@main - with: - node-version: lts/* - - run: npm run build - - name: Publish to gh-pages - uses: JamesIves/github-pages-deploy-action@v4.3.3 - with: - branch: gh-pages - folder: build - clean-exclude: | - pr diff --git a/.github/workflows/publish-pr.yml b/.github/workflows/publish-pr.yml deleted file mode 100644 index cd5decd..0000000 --- a/.github/workflows/publish-pr.yml +++ /dev/null @@ -1,113 +0,0 @@ -name: Publish PR -run-name: ${{ github.event.workflow_run.display_title }} - -on: - workflow_run: - workflows: ['Render PR'] - types: [completed] - -jobs: - publish: - runs-on: ubuntu-latest - if: > - ${{ - !github.event.repository.fork && - github.event.workflow_run.event == 'pull_request' && - github.event.workflow_run.conclusion == 'success' - }} - steps: - - uses: actions/checkout@v4 - - name: '[node LTS] npm install' - uses: ljharb/actions/node/install@main - with: - node-version: lts/* - - name: Print event info - uses: actions/github-script@v7 - with: - script: 'console.log(${{ toJson(github.event) }});' - - name: Download zipball - uses: actions/github-script@v7 - with: - script: | - const { owner, repo } = context.repo; - const run_id = ${{ github.event.workflow_run.id }}; - const listArtifactsQuery = { owner, repo, run_id, name: 'result' }; - const listArtifactsResponse = - await github.rest.actions.listWorkflowRunArtifacts(listArtifactsQuery); - const { total_count, artifacts } = listArtifactsResponse.data; - if (total_count !== 1) { - const summary = artifacts?.map(artifact => { - const { name, size_in_bytes, url } = artifact; - return { name, size_in_bytes, url }; - }); - const repr = value => JSON.stringify(value); - throw Error(`Expected 1 artifact, got ${total_count} ${repr(summary ?? [])}`); - } - const artifact_id = artifacts[0].id; - console.log(`downloading artifact ${artifact_id}`); - const downloadResponse = await github.rest.actions.downloadArtifact({ - owner, - repo, - artifact_id, - archive_format: 'zip', - }); - const fs = require('fs'); - fs.writeFileSync('${{ github.workspace }}/result.zip', Buffer.from(downloadResponse.data)); - - name: Provide result directory - run: rm -rf result && mkdir -p result - - run: unzip -o result.zip -d result - - run: ls result - - name: Extract PR data - id: extract-pr-data - run: | - cd result - awk -v ok=1 ' - NR == 1 && match($0, /^[1-9][0-9]* [0-9a-fA-F]{7,}$/) { - print "number=" $1; - print "commit=" $2; - next; - } - { ok = 0; } - END { exit !ok; } - ' pr-data.txt >> $GITHUB_OUTPUT - rm pr-data.txt - - name: Insert preview warning - env: - PR: ${{ steps.extract-pr-data.outputs.number }} - COMMIT: ${{ steps.extract-pr-data.outputs.commit }} - run: | - tmp="$(mktemp -u XXXXXXXX.json)" - repo_url="https://github.com/$GITHUB_REPOSITORY" - jq -n --arg repo_url "$repo_url" --arg PR "$PR" --arg commit "$COMMIT" ' - def repo_link($args): $args as [$path, $contents] - | ($repo_url + ($path // "")) as $url - | "\($contents // $url)"; - { - SUMMARY: "PR #\($PR)", - REPO_LINK: repo_link([]), - PR_LINK: repo_link(["/pull/" + $PR, "PR #\($PR)"]), - COMMIT_LINK: ("commit " + repo_link(["/commit/" + $commit, "\($commit)"])), - } - ' > "$tmp" - find result -name '*.html' -exec \ - node scripts/insert_warning.mjs scripts/pr_preview_warning.html "$tmp" '{}' '+' - - name: Publish to gh-pages - uses: JamesIves/github-pages-deploy-action@v4.3.3 - with: - branch: gh-pages - folder: result - target-folder: pr/${{ steps.extract-pr-data.outputs.number }} - - name: Determine gh-pages url - id: get-pages-url - run: | - gh_pages_url="https://$(printf '%s' "$GITHUB_REPOSITORY" \ - | sed 's#/#.github.io/#; s#^tc39.github.io/#tc39.es/#')" - echo "url=$gh_pages_url" >> $GITHUB_OUTPUT - - name: Provide PR comment - uses: phulsechinmay/rewritable-pr-comment@v0.3.0 - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - ISSUE_ID: ${{ steps.extract-pr-data.outputs.number }} - message: > - The rendered spec for this PR is available at - ${{ steps.get-pages-url.outputs.url }}/pr/${{ steps.extract-pr-data.outputs.number }}. diff --git a/.github/workflows/render-pr.yml b/.github/workflows/render-pr.yml deleted file mode 100644 index 9cc0f2c..0000000 --- a/.github/workflows/render-pr.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Render PR - -on: [pull_request] - -jobs: - render: - runs-on: ubuntu-latest - if: ${{ github.event.pull_request }} - steps: - - uses: actions/checkout@v4 - - name: '[node LTS] npm install' - uses: ljharb/actions/node/install@main - with: - node-version: lts/* - - run: npm run build - - name: Save PR data - env: - PR: ${{ github.event.number }} - run: echo "$PR $(git rev-parse --verify HEAD)" > build/pr-data.txt - - uses: actions/upload-artifact@v4 - id: upload - if: ${{ !github.event.repository.fork }} - with: - name: result - path: build/ - - name: Echo artifact ID - run: echo 'Artifact ID is ${{ steps.upload.outputs.artifact-id }}' - - name: Verify artifact discoverability - uses: actions/github-script@v7 - with: - script: | - const { owner, repo } = context.repo; - const run_id = ${{ github.run_id }}; - const listArtifactsResponse = - await github.rest.actions.listWorkflowRunArtifacts({ owner, repo, run_id }); - console.log(`artifacts for run id ${run_id}`, listArtifactsResponse?.data); diff --git a/.gitignore b/.gitignore deleted file mode 100644 index d3cae16..0000000 --- a/.gitignore +++ /dev/null @@ -1,46 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* - -# Runtime data -pids -*.pid -*.seed - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules -jspm_packages - -# Optional npm cache directory -.npm - -# Optional REPL history -.node_repl_history - -# Only apps should have lockfiles -yarn.lock -package-lock.json -npm-shrinkwrap.json -pnpm-lock.yaml - -# Build directory -build diff --git a/.npmrc b/.npmrc deleted file mode 100644 index 43c97e7..0000000 --- a/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 6e78ec9..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 ECMA TC39 and contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index 268d12b..0000000 --- a/README.md +++ /dev/null @@ -1,202 +0,0 @@ -# Immutable ArrayBuffers - -A TC39 proposal for immutable ArrayBuffers. - -## Status - -[The TC39 Process](https://tc39.es/process-document/) - -**Stage**: 2.7 - -**Champions**: -- Mark S. Miller (@erights) -- Peter Hoddie (@phoddie) -- Richard Gibson (@gibson042) -- Jack-Works (@Jack-Works) - -**Specification**: https://tc39.es/proposal-immutable-arraybuffer/ - -## Presentation history - -- ***for stage 1*** - October 2024 tc39 plenary ([slides.key](./immu-arraybuffer-talks/immu-arrayBuffers-stage1-as-recorded.key), [slides.pdf](./immu-arraybuffer-talks/immu-arrayBuffers-stage1.pdf), [video](https://www.youtube.com/watch?v=CP_5Yo9h84k)) -- ***for stage 2*** - December 2024 tc39 plenary ([slides.key](./immu-arraybuffer-talks/immu-arrayBuffers-stage2.key), [slides.pdf](./immu-arraybuffer-talks/immu-arrayBuffers-stage2.pdf), [docs slides](https://docs.google.com/presentation/d/1S1ixC7AVg3s_p4ZNhu3zBMcIcKbFkmp6umnsQUKOIqw/edit?usp=sharing), [video](https://www.youtube.com/watch?v=Fy_AnIbAAm8)) -- ***for stage 2.7*** - February 2025 plenary ([slides.key](./immu-arraybuffer-talks/immu-arrayBuffers-stage2-7-as-presented.key), [slides.pdf](./immu-arraybuffer-talks/immu-arrayBuffers-stage2-7-as-presented.pdf)) -- ***for stage 3, take 1*** - April 2025 Plenary ([slides.key](./immu-arraybuffer-talks/immu-arrayBuffers-stage3.key), [slides.pdf](./immu-arraybuffer-talks/immu-arrayBuffers-stage3.pdf), [incomplete video](https://www.youtube.com/watch?v=DOB7IHqSRUU&list=PLzDw4TTug5O3vIAd4IR1Gp5t_46co_dv9)) - -## Background - -Prior proposals [In-Place Resizable and Growable `ArrayBuffer`s](https://github.com/tc39/proposal-resizablearraybuffer) and [ArrayBuffer.prototype.transfer and friends](https://github.com/tc39/proposal-arraybuffer-transfer) have both reached stage 4, and so are now an official part of JavaScript. Altogether, `ArrayBuffer.prototype` now has the following methods: -- `transfer(newByteLength?: number) :ArrayBuffer` -- move the contents of the original buffer to a new buffer, detach the original buffer, and return the new buffer. The new buffer will be as resizable as the original was. -- `transferToFixedLength(newByteLength?: number) :ArrayBuffer` -- like `transfer` but the new buffer is not resizable. -- `resize(newByteLength: number) :void` -- change the size of this buffer if possible, or throw otherwise. -- `slice(start?: number, end?: number) :ArrayBuffer` -- Return a new buffer whose initial contents are a copy of that region of the original buffer. The original buffer is unmodified. - -and the following read-only accessor properties -- `detached: boolean` -- is this buffer detached, or are its contents still available from this buffer object? -- `resizable: boolean` -- can this buffer be resized, or is it fixed-length? -- `byteLength: number` -- how big are the current contents of this buffer? -- `maxByteLength: number` -- how big could this buffer be resized to be? - -None of the operations above enable the creation of an immutable buffer, i.e., a non-detached buffer whose contents cannot be changed, resized, or detached. - -Both a `DataView` object and a `TypedArray` object are views into a buffer backing store. For a `TypedArray` object, the contents of the backing store appear as indexed data properties of the `TypeArray` object that reflect the current contents of this backing store. Currently, because there is no way to prevent the contents of the backing store from being changed, `TypedArray`s cannot be frozen. - -## Motivation - -Some JavaScript implementations, like Moddable XS, bring JavaScript to embedded systems, like device controllers, where ROM is much more plentiful and cheaper than RAM. These systems need to place voluminous fixed data into ROM, and currently do so using semantics outside the official JavaScript standard. - -APIs that accept ArrayBuffers and/or objects backed by them could also benefit from performance improvement by avoiding defensive copies when the input buffers are immutable (see [Generic zero-copy ArrayBuffer usage](https://gist.github.com/domenic/a9343fa787ba54b4ba3a60882c49cc32) for a proposed alternative solution to this problem in the Web Platform). - -The [OCapN](https://ocapn.org/) network protocol treats strings and byte-arrays as distinct forms of bulk data to be transmitted by copy. At JavaScript endpoints speaking OCapN such as [@endo/pass-style](https://www.npmjs.com/package/@endo/pass-style) + [@endo/marshal](https://www.npmjs.com/package/@endo/marshal), JavaScript strings represent OCapN strings. The immutability of strings in the JavaScript language reflects their by-copy nature in the protocol. Likewise, to reflect an OCapN byte-array well into the JavaScript language, an immutable container of bulk binary data is required. There currently are none, but an Immutable `ArrayBuffer` would provide exactly the necessary low-level machinery. - -## Prior proposals or issues with overlapping goals - -[Limited ArrayBuffer](https://github.com/tc39/proposal-limited-arraybuffer), especially [issue #16](https://github.com/tc39/proposal-limited-arraybuffer/issues/16) - -[Readonly Collections](https://github.com/tc39/proposal-readonly-collections), especially [issue #10](https://github.com/tc39/proposal-readonly-collections/issues/10) - -wasm zero copy [issue #1162 comment](https://github.com/WebAssembly/design/issues/1162#issuecomment-2666958705) - -w3c TPAC talk [Zero-copy operations on the web](https://www.w3.org/2020/Talks/TPAC/unconference/zerocopy.pdf) - -web-bluetooth [read-only ArrayBuffer](https://webbluetoothcg.github.io/web-bluetooth/#read-only-arraybuffer), especially [issue #300](https://github.com/WebBluetoothCG/web-bluetooth/issues/300#issuecomment-2560251857) - -gpuweb [issue #2072](https://github.com/gpuweb/gpuweb/issues/2072#issuecomment-2560291036), [issue #747](https://github.com/gpuweb/gpuweb/issues/747#issuecomment-2560254816), and [SharedValueTable proposal](https://hackmd.io/@webgpu/S1f56dN8s) - - [likely should use](https://github.com/tc39/proposal-immutable-arraybuffer/issues/25) [Limited ArrayBuffer](https://github.com/tc39/proposal-limited-arraybuffer) instead of Immutable ArrayBuffer because Immutable ArrayBuffers cannot be detached. - - Note that [`WebAssembly.Memory` also can't be detached (except via other WebAssembly methods,...)](https://github.com/tc39/proposal-immutable-arraybuffer/issues/20#issuecomment-2562075230). - -webidl [Frozen Array](https://webidl.spec.whatwg.org/#idl-frozen-array) - -webcodecs [issue #80](https://github.com/w3c/webcodecs/issues/80#issuecomment-2560331900), [issue #104](https://github.com/w3c/webcodecs/issues/104#issuecomment-2560334782), and [issue #212](https://github.com/w3c/webcodecs/issues/212#issuecomment-2560348504) - -web transport [issue #131](https://github.com/w3c/webtransport/issues/131#issuecomment-2560357416) - - [unlikely](https://github.com/w3c/webtransport/issues/131#issuecomment-2662013436) because Chrome (and likely others) copy when crossing address spaces. - - But possible: see [Even when talking between different processes, each with their own address space, for a huge enough buffer ...](https://github.com/tc39/proposal-immutable-arraybuffer/issues/30#issuecomment-2652223749) - -whatwg streams [issue #495](https://github.com/whatwg/streams/issues/495#issuecomment-2560361444) - - [unlikely](https://github.com/whatwg/streams/issues/495#issuecomment-2662375750) because, well, they are streams, not buffers. - -w3c machine learning workshop [issue #93](https://github.com/w3c/machine-learning-workshop/issues/93#issuecomment-2560365962) - -[Deno intends to support](https://deno.com/blog/updates-from-tc39#immutable-arraybuffer) - -[Proposal Import Buffer](https://github.com/styfle/proposal-import-buffer) relies on Immutable ArrayBuffer - -## Solution - -This proposal introduces additional methods and read-only accessor properties to `ArrayBuffer.prototype` that fit naturally into those explained above. Just as a buffer can be resizable or not, and detached or not, this proposal enables buffers to be immutable or not. Just as `transferToFixedSize` moves the contents of a original buffer into a newly created non-resizable buffer, this proposal provides a transfer operation that moves the contents of an original original buffer into a newly created immutable buffer. Altogether, this proposal only adds to `ArrayBuffer.prototype` one read-only accessor - -- `immutable: boolean` -- is this buffer immutable, or can its contents be changed? - -and two methods - -- `transferToImmutable(newByteLength?: number) :ArrayBuffer` -- move the contents of the original buffer into a new immutable buffer, detach the original buffer, and return the new buffer. -- `sliceToImmutable(start?: number, end?: number) :ArrayBuffer` -- create a new immutable buffer from a range of the original buffer's contents in a way that allows implementations to easily minimize and sometimes even eliminate copying them. - -An immutable buffer cannot be detached, resized, or further transferred. Its `maxByteLength` is the same as its `byteLength`. A `DataView` or `TypedArray` using an immutable buffer as its backing store can be frozen and immutable. `ArrayBuffer`s, `DataView`s, and `TypedArray`s that are frozen and immutable could be placed in ROM without going beyond JavaScript's official semantics. - -The ArrayBuffer `slice` method and TypedArray methods that create new ArrayBuffers (`filter`, `map`, `slice`, `toReversed`, etc.) make no effort to preserve immutability, just like they make no effort to preserve resizability (although use of SpeciesConstructor in those methods means that _lack_ of resizability/immutability in the result cannot be guaranteed for the latter). - -Immutable buffers also [intuitively integrate with HTML `structuredClone`](https://github.com/whatwg/html/pull/11033)—they are not transferable, but cloning preserves both immutability and the underlying data block. - -## Use cases - -### Represent arbitrary binary data as an immutable [netstring](https://en.wikipedia.org/wiki/Netstring) - -```js -const consumeIntoNetstring = data => { - // Transfer to a new ArrayBuffer with room for the netstring framing. - // https://en.wikipedia.org/wiki/Netstring - const prefix = new TextEncoder().encode(`${data.length}:`); - const buf = data.buffer.transfer(prefix.length + data.length + 1); - - // Frame the data. - const tmpArr = new Uint8Array(buf); - tmpArr.copyWithin(prefix.length, 0); - tmpArr.set(prefix); - tmpArr[tmpArr.length - 1] = 0x2C; - - // Transfer to an immutable ArrayBuffer backing a frozen Uint8Array. - const frozenNetstring = Object.freeze(new Uint8Array(buf.transferToImmutable())); - assert(buf.detached); - return frozenNetstring; -}; - -const input = new TextEncoder().encode('hello world!'); -const result = consumeIntoNetstring(input); -assert(Object.isFrozen(result)); -try { result[0] = 0; } catch (_err) {} -try { new Uint8Array(result.buffer)[0] = 1; } catch (_err) {} -try { result.buffer.transferToImmutable(); } catch (_err) {} -assert(String.fromCharCode(...result) === '12:hello world!,'); -``` - -## Implementations - -### Polyfill/transpiler implementations - -* [endo immutable-arraybuffer](https://github.com/endojs/endo/tree/master/packages/immutable-arraybuffer) - -### Native implementations - -Tracking issues to be added: -- [ ] JavaScriptCore -- [ ] SpiderMonkey -- [x] XS -- [ ] V8 - -## Q&A - -
- - - -
- -Why can't an immutable ArrayBuffer be detached/transferred? -
-
- -Because that would result in observable changes to any TypedArray or DataView backed by it. -
- - -
- -Should the index properties of a TypedArray backed by an immutable ArrayBuffer be configurable and writable? -
-
- -No, TypedArray index properties should continue to track the state of the underlying buffer without individual bookkeeping. -
- - -
- -Should ArrayBuffers support zero-copy slices (e.g., `arrayBuffer.sliceToImmutable()`)? https://github.com/tc39/proposal-immutable-arraybuffer/issues/9 -
-
- -Yes. As agreed at the December tc39 plenary, we won't specify that the implementation be zero-copy. But providing this operation ***enables*** some implementations to easily implement it as zero-copy. -
- -
- -Should the new getter be named `immutable` or `mutable`? https://github.com/tc39/proposal-immutable-arraybuffer/issues/10 -
-
- -`immutable`. As agreed at the December tc39 plenary, by following the defaults-to-false principle, feature tests such as `if (buf.immutable) {` will be falsy on engines that have not yet implemented this proposal. -
- -
- -Order of operations, when to throw or silently do nothing? https://github.com/tc39/proposal-immutable-arraybuffer/issues/16 - -
-
- -We will drive the resolution to this from implementor feedback. But when this by itself is not a deciding factor, we prefer failure to throw rather than be silent. This existing XS implementation follows that principle. -
- -
diff --git a/immu-arraybuffer-talks/images/cover.jpg b/immu-arraybuffer-talks/images/cover.jpg deleted file mode 100644 index 718dfcd..0000000 Binary files a/immu-arraybuffer-talks/images/cover.jpg and /dev/null differ diff --git a/immu-arraybuffer-talks/immu-arrayBuffers-stage1-as-recorded.key b/immu-arraybuffer-talks/immu-arrayBuffers-stage1-as-recorded.key deleted file mode 100644 index c0472d0..0000000 Binary files a/immu-arraybuffer-talks/immu-arrayBuffers-stage1-as-recorded.key and /dev/null differ diff --git a/immu-arraybuffer-talks/immu-arrayBuffers-stage1.pdf b/immu-arraybuffer-talks/immu-arrayBuffers-stage1.pdf deleted file mode 100644 index dc5cda5..0000000 Binary files a/immu-arraybuffer-talks/immu-arrayBuffers-stage1.pdf and /dev/null differ diff --git a/immu-arraybuffer-talks/immu-arrayBuffers-stage2-7-as-presented.key b/immu-arraybuffer-talks/immu-arrayBuffers-stage2-7-as-presented.key deleted file mode 100644 index ff588fa..0000000 Binary files a/immu-arraybuffer-talks/immu-arrayBuffers-stage2-7-as-presented.key and /dev/null differ diff --git a/immu-arraybuffer-talks/immu-arrayBuffers-stage2-7-as-presented.pdf b/immu-arraybuffer-talks/immu-arrayBuffers-stage2-7-as-presented.pdf deleted file mode 100644 index 70e11e6..0000000 Binary files a/immu-arraybuffer-talks/immu-arrayBuffers-stage2-7-as-presented.pdf and /dev/null differ diff --git a/immu-arraybuffer-talks/immu-arrayBuffers-stage2-7.key b/immu-arraybuffer-talks/immu-arrayBuffers-stage2-7.key deleted file mode 100644 index 822a30d..0000000 Binary files a/immu-arraybuffer-talks/immu-arrayBuffers-stage2-7.key and /dev/null differ diff --git a/immu-arraybuffer-talks/immu-arrayBuffers-stage2-7.pdf b/immu-arraybuffer-talks/immu-arrayBuffers-stage2-7.pdf deleted file mode 100644 index d555b05..0000000 Binary files a/immu-arraybuffer-talks/immu-arrayBuffers-stage2-7.pdf and /dev/null differ diff --git a/immu-arraybuffer-talks/immu-arrayBuffers-stage2.key b/immu-arraybuffer-talks/immu-arrayBuffers-stage2.key deleted file mode 100644 index abd62e3..0000000 Binary files a/immu-arraybuffer-talks/immu-arrayBuffers-stage2.key and /dev/null differ diff --git a/immu-arraybuffer-talks/immu-arrayBuffers-stage2.pdf b/immu-arraybuffer-talks/immu-arrayBuffers-stage2.pdf deleted file mode 100644 index aa716da..0000000 Binary files a/immu-arraybuffer-talks/immu-arrayBuffers-stage2.pdf and /dev/null differ diff --git a/immu-arraybuffer-talks/immu-arrayBuffers-stage3-as-presented.key b/immu-arraybuffer-talks/immu-arrayBuffers-stage3-as-presented.key deleted file mode 100644 index 98b0903..0000000 Binary files a/immu-arraybuffer-talks/immu-arrayBuffers-stage3-as-presented.key and /dev/null differ diff --git a/immu-arraybuffer-talks/immu-arrayBuffers-stage3-as-presented.mov b/immu-arraybuffer-talks/immu-arrayBuffers-stage3-as-presented.mov deleted file mode 100644 index 91f93ab..0000000 Binary files a/immu-arraybuffer-talks/immu-arrayBuffers-stage3-as-presented.mov and /dev/null differ diff --git a/immu-arraybuffer-talks/immu-arrayBuffers-stage3.key b/immu-arraybuffer-talks/immu-arrayBuffers-stage3.key deleted file mode 100644 index 206e2ab..0000000 Binary files a/immu-arraybuffer-talks/immu-arrayBuffers-stage3.key and /dev/null differ diff --git a/immu-arraybuffer-talks/immu-arrayBuffers-stage3.pdf b/immu-arraybuffer-talks/immu-arrayBuffers-stage3.pdf deleted file mode 100644 index b6e9670..0000000 Binary files a/immu-arraybuffer-talks/immu-arrayBuffers-stage3.pdf and /dev/null differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..cb6da5c --- /dev/null +++ b/index.html @@ -0,0 +1,4341 @@ + + + + + +Immutable ArrayBuffers
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to the nth pin1-9
  • +
  • Jump to the 10th pin0
  • +
  • Jump to the most recent link target`
  • +

Proposal proposal-immutable-arraybuffer

Stage 2.7 Draft / September 20, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, then
        1. Let current be ! O.[[GetOwnProperty]](P).
        2. Assert: current.[[Configurable]] and current.[[Writable]] are both false.
        3. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        4. Return ValidateAndApplyPropertyDescriptor(O, P, false, Desc, current).
      3. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false, return false.
      4. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      5. If IsAccessorDescriptor(Desc) is true, return false.
      6. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, return false.
      7. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      8. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.2 Properties of the %TypedArray% Intrinsic Object

+

The %TypedArray% intrinsic object:

+
    +
  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • +
  • has a "name" property whose value is "TypedArray".
  • +
  • has the following properties:
  • +
+ + +

23.2.2.1 %TypedArray%.from ( source [ , mapper [ , thisArg ] ] )

+

This method performs the following steps when called:

+
  1. Let C be the this value.
  2. If IsConstructor(C) is false, throw a TypeError exception.
  3. If mapper is undefined, then
    1. Let mapping be false.
  4. Else,
    1. If IsCallable(mapper) is false, throw a TypeError exception.
    2. Let mapping be true.
  5. Let usingIterator be ? GetMethod(source, %Symbol.iterator%).
  6. If usingIterator is not undefined, then
    1. Let values be ? IteratorToList(? GetIteratorFromMethod(source, usingIterator)).
    2. Let len be the number of elements in values.
    3. Let targetObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
    4. Let k be 0.
    5. Repeat, while k < len,
      1. Let Pk be ! ToString(𝔽(k)).
      2. Let kValue be the first element of values.
      3. Remove the first element from values.
      4. If mapping is true, then
        1. Let mappedValue be ? Call(mapper, thisArg, « kValue, 𝔽(k) »).
      5. Else,
        1. Let mappedValue be kValue.
      6. Perform ? Set(targetObj, Pk, mappedValue, true).
      7. Set k to k + 1.
    6. Assert: values is now an empty List.
    7. Return targetObj.
  7. NOTE: source is not an iterable object, so assume it is already an array-like object.
  8. Let arrayLike be ! ToObject(source).
  9. Let len be ? LengthOfArrayLike(arrayLike).
  10. Let targetObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
  11. Let k be 0.
  12. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ? Get(arrayLike, Pk).
    3. If mapping is true, then
      1. Let mappedValue be ? Call(mapper, thisArg, « kValue, 𝔽(k) »).
    4. Else,
      1. Let mappedValue be kValue.
    5. Perform ? Set(targetObj, Pk, mappedValue, true).
    6. Set k to k + 1.
  13. Return targetObj.
+
+ + +

23.2.2.2 %TypedArray%.of ( ...items )

+

This method performs the following steps when called:

+
  1. Let len be the number of elements in items.
  2. Let C be the this value.
  3. If IsConstructor(C) is false, throw a TypeError exception.
  4. Let newObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
  5. Let k be 0.
  6. Repeat, while k < len,
    1. Let kValue be items[k].
    2. Let Pk be ! ToString(𝔽(k)).
    3. Perform ? Set(newObj, Pk, kValue, true).
    4. Set k to k + 1.
  7. Return newObj.
+
+
+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.10 %TypedArray%.prototype.filter ( callback [ , thisArg ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.filter as defined in 23.1.3.8.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let len be TypedArrayLength(taRecord).
  4. If IsCallable(callback) is false, throw a TypeError exception.
  5. Let kept be a new empty List.
  6. Let captured be 0.
  7. Let k be 0.
  8. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ! Get(O, Pk).
    3. Let selected be ToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »)).
    4. If selected is true, then
      1. Append kValue to kept.
      2. Set captured to captured + 1.
    5. Set k to k + 1.
  9. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(captured) », write).
  10. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  11. Let n be 0.
  12. For each element e of kept, do
    1. Perform ! Set(A, ! ToString(𝔽(n)), e, true).
    2. Set n to n + 1.
  13. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.22 %TypedArray%.prototype.map ( callback [ , thisArg ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.map as defined in 23.1.3.21.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let len be TypedArrayLength(taRecord).
  4. If IsCallable(callback) is false, throw a TypeError exception.
  5. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(len) », write).
  6. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  7. Let k be 0.
  8. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ! Get(O, Pk).
    3. Let mappedValue be ? Call(callback, thisArg, « kValue, 𝔽(k), O »).
    4. Perform ? Set(A, Pk, mappedValue, true).
    5. Set k to k + 1.
  9. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.27 %TypedArray%.prototype.slice ( start, end )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.slice as defined in 23.1.3.28.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let srcArrayLength be TypedArrayLength(taRecord).
  4. Let relativeStart be ? ToIntegerOrInfinity(start).
  5. If relativeStart = -∞, let startIndex be 0.
  6. Else if relativeStart < 0, let startIndex be max(srcArrayLength + relativeStart, 0).
  7. Else, let startIndex be min(relativeStart, srcArrayLength).
  8. If end is undefined, let relativeEnd be srcArrayLength; else let relativeEnd be ? ToIntegerOrInfinity(end).
  9. If relativeEnd = -∞, let endIndex be 0.
  10. Else if relativeEnd < 0, let endIndex be max(srcArrayLength + relativeEnd, 0).
  11. Else, let endIndex be min(relativeEnd, srcArrayLength).
  12. Let countBytes be max(endIndex - startIndex, 0).
  13. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(countBytes) », write).
  14. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  15. If countBytes > 0, then
    1. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    2. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    3. Set endIndex to min(endIndex, TypedArrayLength(taRecord)).
    4. Set countBytes to max(endIndex - startIndex, 0).
    5. Let srcType be TypedArrayElementType(O).
    6. Let targetType be TypedArrayElementType(A).
    7. If srcType is targetType, then
      1. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data.
      2. Let srcBuffer be O.[[ViewedArrayBuffer]].
      3. Let targetBuffer be A.[[ViewedArrayBuffer]].
      4. Let elementSize be TypedArrayElementSize(O).
      5. Let srcByteOffset be O.[[ByteOffset]].
      6. Let srcByteIndex be (startIndex × elementSize) + srcByteOffset.
      7. Let targetByteIndex be A.[[ByteOffset]].
      8. Let endByteIndex be targetByteIndex + (countBytes × elementSize).
      9. Repeat, while targetByteIndex < endByteIndex,
        1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered).
        3. Set srcByteIndex to srcByteIndex + 1.
        4. Set targetByteIndex to targetByteIndex + 1.
    8. Else,
      1. Let n be 0.
      2. Let k be startIndex.
      3. Repeat, while k < endIndex,
        1. Let Pk be ! ToString(𝔽(k)).
        2. Let kValue be ! Get(O, Pk).
        3. Perform ! Set(A, ! ToString(𝔽(n)), kValue, true).
        4. Set k to k + 1.
        5. Set n to n + 1.
  16. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.1 TypedArraySpeciesCreate ( exemplar, argumentList [ , accessMode ] )

+

The abstract operation TypedArraySpeciesCreate takes arguments exemplar (a TypedArray) and argumentList (a List of ECMAScript language values) and optional argument accessMode (read or write) and returns either a normal completion containing a TypedArray or a throw completion. It is used to specify the creation of a new TypedArray using a constructor function that is derived from exemplar. Unlike ArraySpeciesCreate, which can create non-Array objects through the use of %Symbol.species%, this operation enforces that the constructor function creates an actual TypedArray. It performs the following steps when called:

+
  1. If accessMode is not present, set accessMode to read.
  2. Let defaultConstructor be the intrinsic object associated with the constructor name exemplar.[[TypedArrayName]] in Table 73.
  3. Let constructor be ? SpeciesConstructor(exemplar, defaultConstructor).
  4. Let result be ? TypedArrayCreateFromConstructor(constructor, argumentList, accessMode).
  5. Assert: result has [[TypedArrayName]] and [[ContentType]] internal slots.
  6. Assert: result has all of the internal slots of a TypedArray instance (23.2.8).
  7. If result.[[ContentType]] is not exemplar.[[ContentType]], throw a TypeError exception.
  8. Return result.
+
+ + +

23.2.4.2 TypedArrayCreateFromConstructor ( constructor, argumentList [ , accessMode ] )

+

The abstract operation TypedArrayCreateFromConstructor takes arguments constructor (a constructor) and argumentList (a List of ECMAScript language values) and optional argument accessMode (read or write) and returns either a normal completion containing a TypedArray or a throw completion. It is used to specify the creation of a new TypedArray using a constructor function. It performs the following steps when called:

+
  1. If accessMode is not present, set accessMode to read.
  2. Let newTypedArray be ? Construct(constructor, argumentList).
  3. Let taRecord be ? ValidateTypedArray(newTypedArray, seq-cst, accessMode).
  4. If the number of elements in argumentList is 1 and argumentList[0] is a Number, then
    1. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    2. Let length be TypedArrayLength(taRecord).
    3. If length < (argumentList[0]), throw a TypeError exception.
  5. Return newTypedArray.
+
+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. The contents of an immutable ArrayBuffer's Data Block are constrained to be permanently stable, and may not be modified by either ECMAScript code or by other activities inside an implementation or observable by it. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion.

+ Editor's Note
The current name of parameter preserveResizability is preserved for the benefit of diff readability, but may be subject to change (to e.g. mode) before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  8. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  9. If preserveResizability is immutable, then
    1. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  10. Else,
    1. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
      1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
    2. Else,
      1. Let newMaxByteLength be empty.
    3. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
    4. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
    5. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
    6. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
    7. Let toBlock be newBuffer.[[ArrayBufferData]].
    8. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
    9. 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.
  11. Perform ! DetachArrayBuffer(arrayBuffer).
  12. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return 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) is false.
  2. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If key is not present, set key to undefined.
  4. If arrayBuffer.[[ArrayBufferDetachKey]] is not key, throw a TypeError exception.
  5. Set arrayBuffer.[[ArrayBufferData]] to null.
  6. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
  7. Return unused.
+ Note
+

Detaching an ArrayBuffer instance disassociates the Data Block used as its backing store from the instance and sets the byte length of the buffer to 0.

+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. Assert: IsImmutableBuffer(O) is false.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be max(final - first, 0).
  10. NOTE: Side-effects of the above steps may have detached or resized O.
  11. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  12. Let fromBuf be O.[[ArrayBufferData]].
  13. Let currentLen be O.[[ArrayBufferByteLength]].
  14. If currentLen < final, throw a RangeError exception.
  15. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  16. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot whose value is always undefined.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let getIndex be ? ToIndex(requestIndex).
  5. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  6. Otherwise, let numberValue be ? ToNumber(value).
  7. Set isLittleEndian to ToBoolean(isLittleEndian).
  8. Let viewOffset be view.[[ByteOffset]].
  9. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  10. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  11. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

Copyright & Software License

+ + +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/package.json b/package.json deleted file mode 100644 index add00f7..0000000 --- a/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "private": true, - "name": "template-for-proposals", - "description": "A repository template for ECMAScript proposals.", - "scripts": { - "build": "npm run build-loose -- --strict", - "build-loose": "node -e 'fs.mkdirSync(\"build\", { recursive: true })' && ecmarkup --load-biblio @tc39/ecma262-biblio --verbose spec.emu build/index.html --lint-spec", - "clean": "rm -rf out", - "format": "emu-format --write spec.emu", - "watch": "npm run build-loose -- --watch" - }, - "homepage": "https://github.com/tc39/template-for-proposals#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/tc39/template-for-proposals.git" - }, - "license": "MIT", - "devDependencies": { - "@tc39/ecma262-biblio": "2.1.2862", - "ecmarkup": "^21.2.0", - "jsdom": "^25.0.1", - "parse5-html-rewriting-stream": "^7.0.0", - "tmp": "^0.2.3" - }, - "engines": { - "node": ">= 12" - } -} diff --git a/pr/21/index.html b/pr/21/index.html new file mode 100644 index 0000000..041ed5f --- /dev/null +++ b/pr/21/index.html @@ -0,0 +1,3673 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #21 +

+ This document is a preview of merging PR #21, resulting in commit e52a2d16d982618b70f8cc281eb55997c4412d75. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / January 9, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. Let mutable be true.
      3. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      4. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false not mutable, return false.
      5. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      6. If IsAccessorDescriptor(Desc) is true, return false.
      7. If Desc has a [[Writable]] field and Desc.[[Writable]] is false not mutable, return false.
      8. If Desc has a [[Value]] field and mutable is false and SameValue(Desc.[[Value]], TypedArrayGetElement(O, numericIndex)) is false, return false.
      9. If Desc has a [[Value]] field and mutable is true, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      10. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If SameValue(O, Receiver) is true, then
        1. IsValidIntegerIndex(O, numericIndex) is true and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
        2. Perform ? TypedArraySetElement(O, numericIndex, V).
        3. Return true.
      2. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  2. Otherwise, let numValue be ? ToNumber(value).
  3. If IsValidIntegerIndex(O, index) is true and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  4. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached or immutable ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+ + +

23.2.3.26.1 SetTypedArrayFromTypedArray ( target, targetOffset, source )

+

The abstract operation SetTypedArrayFromTypedArray takes arguments target (a TypedArray), targetOffset (a non-negative integer or +∞), and source (a TypedArray) and returns either a normal completion containing unused or a throw completion. It sets multiple values in target, starting at index targetOffset, reading the values from source. It performs the following steps when called:

+
  1. Let targetBuffer be target.[[ViewedArrayBuffer]].
  2. Let targetRecord be MakeTypedArrayWithBufferWitnessRecord(target, seq-cst).
  3. If IsTypedArrayOutOfBounds(targetRecord) is true, throw a TypeError exception.
  4. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let targetLength be TypedArrayLength(targetRecord).
  6. Let srcBuffer be source.[[ViewedArrayBuffer]].
  7. Let srcRecord be MakeTypedArrayWithBufferWitnessRecord(source, seq-cst).
  8. If IsTypedArrayOutOfBounds(srcRecord) is true, throw a TypeError exception.
  9. Let srcLength be TypedArrayLength(srcRecord).
  10. Let targetType be TypedArrayElementType(target).
  11. Let targetElementSize be TypedArrayElementSize(target).
  12. Let targetByteOffset be target.[[ByteOffset]].
  13. Let srcType be TypedArrayElementType(source).
  14. Let srcElementSize be TypedArrayElementSize(source).
  15. Let srcByteOffset be source.[[ByteOffset]].
  16. If targetOffset = +∞, throw a RangeError exception.
  17. If srcLength + targetOffset > targetLength, throw a RangeError exception.
  18. If target.[[ContentType]] is not source.[[ContentType]], throw a TypeError exception.
  19. If IsSharedArrayBuffer(srcBuffer) is true, IsSharedArrayBuffer(targetBuffer) is true, and srcBuffer.[[ArrayBufferData]] is targetBuffer.[[ArrayBufferData]], let sameSharedArrayBuffer be true; otherwise, let sameSharedArrayBuffer be false.
  20. If SameValue(srcBuffer, targetBuffer) is true or sameSharedArrayBuffer is true, then
    1. Let srcByteLength be TypedArrayByteLength(srcRecord).
    2. Set srcBuffer to ? CloneArrayBuffer(srcBuffer, srcByteOffset, srcByteLength).
    3. Let srcByteIndex be 0.
  21. Else,
    1. Let srcByteIndex be srcByteOffset.
  22. Let targetByteIndex be (targetOffset × targetElementSize) + targetByteOffset.
  23. Let limit be targetByteIndex + (targetElementSize × srcLength).
  24. If srcType is targetType, then
    1. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Repeat, while targetByteIndex < limit,
      1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered).
      2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered).
      3. Set srcByteIndex to srcByteIndex + 1.
      4. Set targetByteIndex to targetByteIndex + 1.
  25. Else,
    1. Repeat, while targetByteIndex < limit,
      1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, srcType, true, unordered).
      2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, targetType, value, true, unordered).
      3. Set srcByteIndex to srcByteIndex + srcElementSize.
      4. Set targetByteIndex to targetByteIndex + targetElementSize.
  26. Return unused.
+
+ + +

23.2.3.26.2 SetTypedArrayFromArrayLike ( target, targetOffset, source )

+

The abstract operation SetTypedArrayFromArrayLike takes arguments target (a TypedArray), targetOffset (a non-negative integer or +∞), and source (an ECMAScript language value, but not a TypedArray) and returns either a normal completion containing unused or a throw completion. It sets multiple values in target, starting at index targetOffset, reading the values from source. It performs the following steps when called:

+
  1. Let targetRecord be MakeTypedArrayWithBufferWitnessRecord(target, seq-cst).
  2. If IsTypedArrayOutOfBounds(targetRecord) is true, throw a TypeError exception.
  3. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let targetLength be TypedArrayLength(targetRecord).
  5. Let src be ? ToObject(source).
  6. Let srcLength be ? LengthOfArrayLike(src).
  7. If targetOffset = +∞, throw a RangeError exception.
  8. If srcLength + targetOffset > targetLength, throw a RangeError exception.
  9. Let k be 0.
  10. Repeat, while k < srcLength,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let value be ? Get(src, Pk).
    3. Let targetIndex be 𝔽(targetOffset + k).
    4. Perform ? TypedArraySetElement(target, targetIndex, value).
    5. Set k to k + 1.
  11. Return unused.
+
+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , use ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument use (read or write) 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. If use is not present, set use to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If use is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an 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 an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, count).
  6. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  8. If preserveResizability is immutable, then
    1. Return ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  9. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
    1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
  10. Else,
    1. Let newMaxByteLength be empty.
  11. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  12. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
  13. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  14. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
  15. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  16. Let toBlock be newBuffer.[[ArrayBufferData]].
  17. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
  18. 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.
  19. Perform ! DetachArrayBuffer(arrayBuffer).
  20. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return false.
+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. TODO: Confirm inclusion of this redundant check.
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. Let len be O.[[ArrayBufferByteLength]].
  7. Let bounds be ? ResolveBounds(len, start, end).
  8. Let first be bounds.[[From]].
  9. Let final be bounds.[[To]].
  10. TODO: Confirm this strictness vs. the conventional max(_final_ - _first_, 0).
  11. Let newLen be final - first.
  12. If newLen < 0, throw a RangeError exception.
  13. Let copyLen be min(newLen, len).
  14. NOTE: Side-effects of the above steps may have detached or resized O. This algorithm proceeds only when O is not detached, even if newLen is 0.
  15. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  16. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, O.[[ArrayBufferData]], first, copyLen).
  17. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. Let getIndex be ? ToIndex(requestIndex).
  4. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  5. Otherwise, let numberValue be ? ToNumber(value).
  6. Set isLittleEndian to ToBoolean(isLittleEndian).
  7. Let viewOffset be view.[[ByteOffset]].
  8. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  9. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  10. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  11. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , use ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument use (read or write) 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. If use is not present, set use to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, use).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , use ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and use (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If use is not present, set use to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, use).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/23/index.html b/pr/23/index.html new file mode 100644 index 0000000..83494f8 --- /dev/null +++ b/pr/23/index.html @@ -0,0 +1,3570 @@ + + + + + +Immutable ArrayBuffers
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / December 27, 2024

Immutable ArrayBuffers

+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. Let mutable be true.
      3. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      4. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false not mutable, return false.
      5. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      6. If IsAccessorDescriptor(Desc) is true, return false.
      7. If Desc has a [[Writable]] field and Desc.[[Writable]] is false not mutable, return false.
      8. If Desc has a [[Value]] field and mutable is false and SameValue(Desc.[[Value]], TypedArrayGetElement(O, numericIndex)) is false, return false.
      9. If Desc has a [[Value]] field and mutable is true, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      10. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If SameValue(O, Receiver) is true, then
        1. IsValidIntegerIndex(O, numericIndex) is true and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
        2. Perform ? TypedArraySetElement(O, numericIndex, V).
        3. Return true.
      2. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  2. Otherwise, let numValue be ? ToNumber(value).
  3. If IsValidIntegerIndex(O, index) is true and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  4. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached or immutable ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+ + +

23.2.3.26.1 SetTypedArrayFromTypedArray ( target, targetOffset, source )

+

The abstract operation SetTypedArrayFromTypedArray takes arguments target (a TypedArray), targetOffset (a non-negative integer or +∞), and source (a TypedArray) and returns either a normal completion containing unused or a throw completion. It sets multiple values in target, starting at index targetOffset, reading the values from source. It performs the following steps when called:

+
  1. Let targetBuffer be target.[[ViewedArrayBuffer]].
  2. Let targetRecord be MakeTypedArrayWithBufferWitnessRecord(target, seq-cst).
  3. If IsTypedArrayOutOfBounds(targetRecord) is true, throw a TypeError exception.
  4. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let targetLength be TypedArrayLength(targetRecord).
  6. Let srcBuffer be source.[[ViewedArrayBuffer]].
  7. Let srcRecord be MakeTypedArrayWithBufferWitnessRecord(source, seq-cst).
  8. If IsTypedArrayOutOfBounds(srcRecord) is true, throw a TypeError exception.
  9. Let srcLength be TypedArrayLength(srcRecord).
  10. Let targetType be TypedArrayElementType(target).
  11. Let targetElementSize be TypedArrayElementSize(target).
  12. Let targetByteOffset be target.[[ByteOffset]].
  13. Let srcType be TypedArrayElementType(source).
  14. Let srcElementSize be TypedArrayElementSize(source).
  15. Let srcByteOffset be source.[[ByteOffset]].
  16. If targetOffset = +∞, throw a RangeError exception.
  17. If srcLength + targetOffset > targetLength, throw a RangeError exception.
  18. If target.[[ContentType]] is not source.[[ContentType]], throw a TypeError exception.
  19. If IsSharedArrayBuffer(srcBuffer) is true, IsSharedArrayBuffer(targetBuffer) is true, and srcBuffer.[[ArrayBufferData]] is targetBuffer.[[ArrayBufferData]], let sameSharedArrayBuffer be true; otherwise, let sameSharedArrayBuffer be false.
  20. If SameValue(srcBuffer, targetBuffer) is true or sameSharedArrayBuffer is true, then
    1. Let srcByteLength be TypedArrayByteLength(srcRecord).
    2. Set srcBuffer to ? CloneArrayBuffer(srcBuffer, srcByteOffset, srcByteLength).
    3. Let srcByteIndex be 0.
  21. Else,
    1. Let srcByteIndex be srcByteOffset.
  22. Let targetByteIndex be (targetOffset × targetElementSize) + targetByteOffset.
  23. Let limit be targetByteIndex + (targetElementSize × srcLength).
  24. If srcType is targetType, then
    1. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Repeat, while targetByteIndex < limit,
      1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered).
      2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered).
      3. Set srcByteIndex to srcByteIndex + 1.
      4. Set targetByteIndex to targetByteIndex + 1.
  25. Else,
    1. Repeat, while targetByteIndex < limit,
      1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, srcType, true, unordered).
      2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, targetType, value, true, unordered).
      3. Set srcByteIndex to srcByteIndex + srcElementSize.
      4. Set targetByteIndex to targetByteIndex + targetElementSize.
  26. Return unused.
+
+ + +

23.2.3.26.2 SetTypedArrayFromArrayLike ( target, targetOffset, source )

+

The abstract operation SetTypedArrayFromArrayLike takes arguments target (a TypedArray), targetOffset (a non-negative integer or +∞), and source (an ECMAScript language value, but not a TypedArray) and returns either a normal completion containing unused or a throw completion. It sets multiple values in target, starting at index targetOffset, reading the values from source. It performs the following steps when called:

+
  1. Let targetRecord be MakeTypedArrayWithBufferWitnessRecord(target, seq-cst).
  2. If IsTypedArrayOutOfBounds(targetRecord) is true, throw a TypeError exception.
  3. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let targetLength be TypedArrayLength(targetRecord).
  5. Let src be ? ToObject(source).
  6. Let srcLength be ? LengthOfArrayLike(src).
  7. If targetOffset = +∞, throw a RangeError exception.
  8. If srcLength + targetOffset > targetLength, throw a RangeError exception.
  9. Let k be 0.
  10. Repeat, while k < srcLength,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let value be ? Get(src, Pk).
    3. Let targetIndex be 𝔽(targetOffset + k).
    4. Perform ? TypedArraySetElement(target, targetIndex, value).
    5. Set k to k + 1.
  11. Return unused.
+
+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , use ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument use (read or write) 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. If use is not present, set use to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If use is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an 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 an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
    1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
  8. Else if preserveResizability is immutable, then
    1. Let newMaxByteLength be immutable.
  9. Else,
    1. Let newMaxByteLength be empty.
  10. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  11. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
  12. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  13. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
  14. Let toBlock be newBuffer.[[ArrayBufferData]].
  15. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  16. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
  17. 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.
  18. Perform ! DetachArrayBuffer(arrayBuffer).
  19. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return false.
+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. Let getIndex be ? ToIndex(requestIndex).
  4. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  5. Otherwise, let numberValue be ? ToNumber(value).
  6. Set isLittleEndian to ToBoolean(isLittleEndian).
  7. Let viewOffset be view.[[ByteOffset]].
  8. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  9. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  10. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  11. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , use ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument use (read or write) 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. If use is not present, set use to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, use).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , use ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and use (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If use is not present, set use to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, use).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2024 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/24/index.html b/pr/24/index.html new file mode 100644 index 0000000..753b7b3 --- /dev/null +++ b/pr/24/index.html @@ -0,0 +1,3637 @@ + + + + +Immutable ArrayBuffers + +
+ PR #24 +

+ This document is a preview of merging PR #24, resulting in commit aefb4d7fff2b3a941176d5484ada161734f84e47. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / January 1, 2025

Immutable ArrayBuffers

+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. Let mutable be true.
      3. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      4. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false not mutable, return false.
      5. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      6. If IsAccessorDescriptor(Desc) is true, return false.
      7. If Desc has a [[Writable]] field and Desc.[[Writable]] is false not mutable, return false.
      8. If Desc has a [[Value]] field and mutable is false and SameValue(Desc.[[Value]], TypedArrayGetElement(O, numericIndex)) is false, return false.
      9. If Desc has a [[Value]] field and mutable is true, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      10. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If SameValue(O, Receiver) is true, then
        1. IsValidIntegerIndex(O, numericIndex) is true and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
        2. Perform ? TypedArraySetElement(O, numericIndex, V).
        3. Return true.
      2. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  2. Otherwise, let numValue be ? ToNumber(value).
  3. If IsValidIntegerIndex(O, index) is true and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  4. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached or immutable ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+ + +

23.2.3.26.1 SetTypedArrayFromTypedArray ( target, targetOffset, source )

+

The abstract operation SetTypedArrayFromTypedArray takes arguments target (a TypedArray), targetOffset (a non-negative integer or +∞), and source (a TypedArray) and returns either a normal completion containing unused or a throw completion. It sets multiple values in target, starting at index targetOffset, reading the values from source. It performs the following steps when called:

+
  1. Let targetBuffer be target.[[ViewedArrayBuffer]].
  2. Let targetRecord be MakeTypedArrayWithBufferWitnessRecord(target, seq-cst).
  3. If IsTypedArrayOutOfBounds(targetRecord) is true, throw a TypeError exception.
  4. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let targetLength be TypedArrayLength(targetRecord).
  6. Let srcBuffer be source.[[ViewedArrayBuffer]].
  7. Let srcRecord be MakeTypedArrayWithBufferWitnessRecord(source, seq-cst).
  8. If IsTypedArrayOutOfBounds(srcRecord) is true, throw a TypeError exception.
  9. Let srcLength be TypedArrayLength(srcRecord).
  10. Let targetType be TypedArrayElementType(target).
  11. Let targetElementSize be TypedArrayElementSize(target).
  12. Let targetByteOffset be target.[[ByteOffset]].
  13. Let srcType be TypedArrayElementType(source).
  14. Let srcElementSize be TypedArrayElementSize(source).
  15. Let srcByteOffset be source.[[ByteOffset]].
  16. If targetOffset = +∞, throw a RangeError exception.
  17. If srcLength + targetOffset > targetLength, throw a RangeError exception.
  18. If target.[[ContentType]] is not source.[[ContentType]], throw a TypeError exception.
  19. If IsSharedArrayBuffer(srcBuffer) is true, IsSharedArrayBuffer(targetBuffer) is true, and srcBuffer.[[ArrayBufferData]] is targetBuffer.[[ArrayBufferData]], let sameSharedArrayBuffer be true; otherwise, let sameSharedArrayBuffer be false.
  20. If SameValue(srcBuffer, targetBuffer) is true or sameSharedArrayBuffer is true, then
    1. Let srcByteLength be TypedArrayByteLength(srcRecord).
    2. Set srcBuffer to ? CloneArrayBuffer(srcBuffer, srcByteOffset, srcByteLength).
    3. Let srcByteIndex be 0.
  21. Else,
    1. Let srcByteIndex be srcByteOffset.
  22. Let targetByteIndex be (targetOffset × targetElementSize) + targetByteOffset.
  23. Let limit be targetByteIndex + (targetElementSize × srcLength).
  24. If srcType is targetType, then
    1. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Repeat, while targetByteIndex < limit,
      1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered).
      2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered).
      3. Set srcByteIndex to srcByteIndex + 1.
      4. Set targetByteIndex to targetByteIndex + 1.
  25. Else,
    1. Repeat, while targetByteIndex < limit,
      1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, srcType, true, unordered).
      2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, targetType, value, true, unordered).
      3. Set srcByteIndex to srcByteIndex + srcElementSize.
      4. Set targetByteIndex to targetByteIndex + targetElementSize.
  26. Return unused.
+
+ + +

23.2.3.26.2 SetTypedArrayFromArrayLike ( target, targetOffset, source )

+

The abstract operation SetTypedArrayFromArrayLike takes arguments target (a TypedArray), targetOffset (a non-negative integer or +∞), and source (an ECMAScript language value, but not a TypedArray) and returns either a normal completion containing unused or a throw completion. It sets multiple values in target, starting at index targetOffset, reading the values from source. It performs the following steps when called:

+
  1. Let targetRecord be MakeTypedArrayWithBufferWitnessRecord(target, seq-cst).
  2. If IsTypedArrayOutOfBounds(targetRecord) is true, throw a TypeError exception.
  3. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let targetLength be TypedArrayLength(targetRecord).
  5. Let src be ? ToObject(source).
  6. Let srcLength be ? LengthOfArrayLike(src).
  7. If targetOffset = +∞, throw a RangeError exception.
  8. If srcLength + targetOffset > targetLength, throw a RangeError exception.
  9. Let k be 0.
  10. Repeat, while k < srcLength,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let value be ? Get(src, Pk).
    3. Let targetIndex be 𝔽(targetOffset + k).
    4. Perform ? TypedArraySetElement(target, targetIndex, value).
    5. Set k to k + 1.
  11. Return unused.
+
+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , use ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument use (read or write) 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. If use is not present, set use to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If use is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an 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 an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
    1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
  8. Else if preserveResizability is immutable, then
    1. Let newMaxByteLength be immutable.
  9. Else,
    1. Let newMaxByteLength be empty.
  10. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  11. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
  12. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  13. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
  14. Let toBlock be newBuffer.[[ArrayBufferData]].
  15. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  16. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
  17. 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.
  18. Perform ! DetachArrayBuffer(arrayBuffer).
  19. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return false.
+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. Let getIndex be ? ToIndex(requestIndex).
  4. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  5. Otherwise, let numberValue be ? ToNumber(value).
  6. Set isLittleEndian to ToBoolean(isLittleEndian).
  7. Let viewOffset be view.[[ByteOffset]].
  8. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  9. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  10. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  11. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , use ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument use (read or write) 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. If use is not present, set use to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, use).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , use ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and use (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If use is not present, set use to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, use).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/28/index.html b/pr/28/index.html new file mode 100644 index 0000000..2da9a19 --- /dev/null +++ b/pr/28/index.html @@ -0,0 +1,3673 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #28 +

+ This document is a preview of merging PR #28, resulting in commit 6382eb078cd6213ac52b22ef8315745de350234d. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / January 12, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. Let mutable be true.
      3. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      4. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false not mutable, return false.
      5. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      6. If IsAccessorDescriptor(Desc) is true, return false.
      7. If Desc has a [[Writable]] field and Desc.[[Writable]] is false not mutable, return false.
      8. If Desc has a [[Value]] field and mutable is false and SameValue(Desc.[[Value]], TypedArrayGetElement(O, numericIndex)) is false, return false.
      9. If Desc has a [[Value]] field and mutable is true, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      10. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If SameValue(O, Receiver) is true, then
        1. IsValidIntegerIndex(O, numericIndex) is true and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
        2. Perform ? TypedArraySetElement(O, numericIndex, V).
        3. Return true.
      2. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  2. Otherwise, let numValue be ? ToNumber(value).
  3. If IsValidIntegerIndex(O, index) is true and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  4. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached or immutable ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+ + +

23.2.3.26.1 SetTypedArrayFromTypedArray ( target, targetOffset, source )

+

The abstract operation SetTypedArrayFromTypedArray takes arguments target (a TypedArray), targetOffset (a non-negative integer or +∞), and source (a TypedArray) and returns either a normal completion containing unused or a throw completion. It sets multiple values in target, starting at index targetOffset, reading the values from source. It performs the following steps when called:

+
  1. Let targetBuffer be target.[[ViewedArrayBuffer]].
  2. Let targetRecord be MakeTypedArrayWithBufferWitnessRecord(target, seq-cst).
  3. If IsTypedArrayOutOfBounds(targetRecord) is true, throw a TypeError exception.
  4. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let targetLength be TypedArrayLength(targetRecord).
  6. Let srcBuffer be source.[[ViewedArrayBuffer]].
  7. Let srcRecord be MakeTypedArrayWithBufferWitnessRecord(source, seq-cst).
  8. If IsTypedArrayOutOfBounds(srcRecord) is true, throw a TypeError exception.
  9. Let srcLength be TypedArrayLength(srcRecord).
  10. Let targetType be TypedArrayElementType(target).
  11. Let targetElementSize be TypedArrayElementSize(target).
  12. Let targetByteOffset be target.[[ByteOffset]].
  13. Let srcType be TypedArrayElementType(source).
  14. Let srcElementSize be TypedArrayElementSize(source).
  15. Let srcByteOffset be source.[[ByteOffset]].
  16. If targetOffset = +∞, throw a RangeError exception.
  17. If srcLength + targetOffset > targetLength, throw a RangeError exception.
  18. If target.[[ContentType]] is not source.[[ContentType]], throw a TypeError exception.
  19. If IsSharedArrayBuffer(srcBuffer) is true, IsSharedArrayBuffer(targetBuffer) is true, and srcBuffer.[[ArrayBufferData]] is targetBuffer.[[ArrayBufferData]], let sameSharedArrayBuffer be true; otherwise, let sameSharedArrayBuffer be false.
  20. If SameValue(srcBuffer, targetBuffer) is true or sameSharedArrayBuffer is true, then
    1. Let srcByteLength be TypedArrayByteLength(srcRecord).
    2. Set srcBuffer to ? CloneArrayBuffer(srcBuffer, srcByteOffset, srcByteLength).
    3. Let srcByteIndex be 0.
  21. Else,
    1. Let srcByteIndex be srcByteOffset.
  22. Let targetByteIndex be (targetOffset × targetElementSize) + targetByteOffset.
  23. Let limit be targetByteIndex + (targetElementSize × srcLength).
  24. If srcType is targetType, then
    1. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Repeat, while targetByteIndex < limit,
      1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered).
      2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered).
      3. Set srcByteIndex to srcByteIndex + 1.
      4. Set targetByteIndex to targetByteIndex + 1.
  25. Else,
    1. Repeat, while targetByteIndex < limit,
      1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, srcType, true, unordered).
      2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, targetType, value, true, unordered).
      3. Set srcByteIndex to srcByteIndex + srcElementSize.
      4. Set targetByteIndex to targetByteIndex + targetElementSize.
  26. Return unused.
+
+ + +

23.2.3.26.2 SetTypedArrayFromArrayLike ( target, targetOffset, source )

+

The abstract operation SetTypedArrayFromArrayLike takes arguments target (a TypedArray), targetOffset (a non-negative integer or +∞), and source (an ECMAScript language value, but not a TypedArray) and returns either a normal completion containing unused or a throw completion. It sets multiple values in target, starting at index targetOffset, reading the values from source. It performs the following steps when called:

+
  1. Let targetRecord be MakeTypedArrayWithBufferWitnessRecord(target, seq-cst).
  2. If IsTypedArrayOutOfBounds(targetRecord) is true, throw a TypeError exception.
  3. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let targetLength be TypedArrayLength(targetRecord).
  5. Let src be ? ToObject(source).
  6. Let srcLength be ? LengthOfArrayLike(src).
  7. If targetOffset = +∞, throw a RangeError exception.
  8. If srcLength + targetOffset > targetLength, throw a RangeError exception.
  9. Let k be 0.
  10. Repeat, while k < srcLength,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let value be ? Get(src, Pk).
    3. Let targetIndex be 𝔽(targetOffset + k).
    4. Perform ? TypedArraySetElement(target, targetIndex, value).
    5. Set k to k + 1.
  11. Return unused.
+
+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , use ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument use (read or write) 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. If use is not present, set use to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If use is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an 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 an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  8. If preserveResizability is immutable, then
    1. Return ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  9. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
    1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
  10. Else,
    1. Let newMaxByteLength be empty.
  11. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  12. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
  13. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  14. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
  15. Let toBlock be newBuffer.[[ArrayBufferData]].
  16. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
  17. 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.
  18. Perform ! DetachArrayBuffer(arrayBuffer).
  19. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return false.
+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be final - first.
  10. TODO: Confirm this strictness vs. slice (rejecting negative newLen rather than clamping to 0).
  11. If newLen < 0, throw a RangeError exception.
  12. NOTE: Side-effects of the above steps may have detached or resized O.
  13. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  14. Let fromBuf be O.[[ArrayBufferData]].
  15. Let currentLen be O.[[ArrayBufferByteLength]].
  16. If currentLen < final, throw a RangeError exception.
  17. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  18. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. Let getIndex be ? ToIndex(requestIndex).
  4. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  5. Otherwise, let numberValue be ? ToNumber(value).
  6. Set isLittleEndian to ToBoolean(isLittleEndian).
  7. Let viewOffset be view.[[ByteOffset]].
  8. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  9. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  10. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  11. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , use ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument use (read or write) 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. If use is not present, set use to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, use).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , use ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and use (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If use is not present, set use to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, use).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/29/index.html b/pr/29/index.html new file mode 100644 index 0000000..cb5112b --- /dev/null +++ b/pr/29/index.html @@ -0,0 +1,3665 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #29 +

+ This document is a preview of merging PR #29, resulting in commit 45bee9ecdc0b81261bfb6587d5a9d88bce585b7e. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / January 14, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. Let mutable be true.
      3. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      4. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false not mutable, return false.
      5. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      6. If IsAccessorDescriptor(Desc) is true, return false.
      7. If Desc has a [[Writable]] field and Desc.[[Writable]] is false not mutable, return false.
      8. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      9. If Desc has a [[Value]] field, then
        1. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        2. If mutable is false and SameValue(Desc.[[Value]], TypedArrayGetElement(O, numericIndex)) is false, return false.
        3. If mutable is true, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      10. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , use ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument use (read or write) 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. If use is not present, set use to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If use is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an 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 an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  8. If preserveResizability is immutable, then
    1. Return ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  9. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
    1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
  10. Else,
    1. Let newMaxByteLength be empty.
  11. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  12. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
  13. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  14. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
  15. Let toBlock be newBuffer.[[ArrayBufferData]].
  16. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
  17. 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.
  18. Perform ! DetachArrayBuffer(arrayBuffer).
  19. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return false.
+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be final - first.
  10. TODO: Confirm this strictness vs. slice (rejecting negative newLen rather than clamping to 0).
  11. If newLen < 0, throw a RangeError exception.
  12. NOTE: Side-effects of the above steps may have detached or resized O.
  13. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  14. Let fromBuf be O.[[ArrayBufferData]].
  15. Let currentLen be O.[[ArrayBufferByteLength]].
  16. If currentLen < final, throw a RangeError exception.
  17. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  18. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. Let getIndex be ? ToIndex(requestIndex).
  4. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  5. Otherwise, let numberValue be ? ToNumber(value).
  6. Set isLittleEndian to ToBoolean(isLittleEndian).
  7. Let viewOffset be view.[[ByteOffset]].
  8. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  9. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  10. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  11. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , use ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument use (read or write) 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. If use is not present, set use to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, use).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , use ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and use (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If use is not present, set use to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, use).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/32/index.html b/pr/32/index.html new file mode 100644 index 0000000..acac5ca --- /dev/null +++ b/pr/32/index.html @@ -0,0 +1,3665 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #32 +

+ This document is a preview of merging PR #32, resulting in commit f0fde7a2ea645b08d615171779e9290099bc4b4f. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / February 15, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, then
        1. Let current be ! O.[[GetOwnProperty]](P).
        2. Assert: current.[[Configurable]] and current.[[Writable]] are both false.
        3. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        4. Return ValidateAndApplyPropertyDescriptor(O, P, false, Desc, current).
      3. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false, return false.
      4. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      5. If IsAccessorDescriptor(Desc) is true, return false.
      6. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, return false.
      7. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      8. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , use ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument use (read or write) 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. If use is not present, set use to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If use is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an 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 an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  8. If preserveResizability is immutable, then
    1. Return ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  9. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
    1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
  10. Else,
    1. Let newMaxByteLength be empty.
  11. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  12. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
  13. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  14. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
  15. Let toBlock be newBuffer.[[ArrayBufferData]].
  16. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
  17. 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.
  18. Perform ! DetachArrayBuffer(arrayBuffer).
  19. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return false.
+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be final - first.
  10. TODO: Confirm this strictness vs. slice (rejecting negative newLen rather than clamping to 0).
  11. If newLen < 0, throw a RangeError exception.
  12. NOTE: Side-effects of the above steps may have detached or resized O.
  13. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  14. Let fromBuf be O.[[ArrayBufferData]].
  15. Let currentLen be O.[[ArrayBufferByteLength]].
  16. If currentLen < final, throw a RangeError exception.
  17. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  18. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. Let getIndex be ? ToIndex(requestIndex).
  4. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  5. Otherwise, let numberValue be ? ToNumber(value).
  6. Set isLittleEndian to ToBoolean(isLittleEndian).
  7. Let viewOffset be view.[[ByteOffset]].
  8. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  9. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  10. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  11. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , use ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument use (read or write) 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. If use is not present, set use to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, use).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , use ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and use (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If use is not present, set use to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, use).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/33/index.html b/pr/33/index.html new file mode 100644 index 0000000..569b41e --- /dev/null +++ b/pr/33/index.html @@ -0,0 +1,3667 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #33 +

+ This document is a preview of merging PR #33, resulting in commit e04608acdf0f4923a34395640fd3657ec8c7d8c8. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / February 15, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. Let mutable be true.
      3. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      4. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false not mutable, return false.
      5. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      6. If IsAccessorDescriptor(Desc) is true, return false.
      7. If Desc has a [[Writable]] field and Desc.[[Writable]] is false not mutable, return false.
      8. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      9. If Desc has a [[Value]] field, then
        1. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        2. If mutable is false and SameValue(Desc.[[Value]], TypedArrayGetElement(O, numericIndex)) is false, return false.
        3. If mutable is true, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      10. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  8. If preserveResizability is immutable, then
    1. Return ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  9. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
    1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
  10. Else,
    1. Let newMaxByteLength be empty.
  11. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  12. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
  13. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  14. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
  15. Let toBlock be newBuffer.[[ArrayBufferData]].
  16. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
  17. 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.
  18. Perform ! DetachArrayBuffer(arrayBuffer).
  19. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return false.
+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be final - first.
  10. TODO: Confirm this strictness vs. slice (rejecting negative newLen rather than clamping to 0).
  11. If newLen < 0, throw a RangeError exception.
  12. NOTE: Side-effects of the above steps may have detached or resized O.
  13. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  14. Let fromBuf be O.[[ArrayBufferData]].
  15. Let currentLen be O.[[ArrayBufferByteLength]].
  16. If currentLen < final, throw a RangeError exception.
  17. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  18. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. Let getIndex be ? ToIndex(requestIndex).
  4. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  5. Otherwise, let numberValue be ? ToNumber(value).
  6. Set isLittleEndian to ToBoolean(isLittleEndian).
  7. Let viewOffset be view.[[ByteOffset]].
  8. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  9. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  10. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  11. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/34/index.html b/pr/34/index.html new file mode 100644 index 0000000..46102c2 --- /dev/null +++ b/pr/34/index.html @@ -0,0 +1,3667 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #34 +

+ This document is a preview of merging PR #34, resulting in commit f7661f55488d5a72350634fcfaa6e62a22e9b24c. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / February 15, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. Let mutable be true.
      3. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      4. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false not mutable, return false.
      5. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      6. If IsAccessorDescriptor(Desc) is true, return false.
      7. If Desc has a [[Writable]] field and Desc.[[Writable]] is false not mutable, return false.
      8. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      9. If Desc has a [[Value]] field, then
        1. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        2. If mutable is false and SameValue(Desc.[[Value]], TypedArrayGetElement(O, numericIndex)) is false, return false.
        3. If mutable is true, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      10. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  8. If preserveResizability is immutable, then
    1. Return ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  9. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
    1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
  10. Else,
    1. Let newMaxByteLength be empty.
  11. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  12. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
  13. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  14. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
  15. Let toBlock be newBuffer.[[ArrayBufferData]].
  16. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
  17. 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.
  18. Perform ! DetachArrayBuffer(arrayBuffer).
  19. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return false.
+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be final - first.
  10. NOTE: This differs from ArrayBuffer.prototype.slice ( start, end ), which instead clamps newLen to be non-negative.
  11. If newLen < 0, throw a RangeError exception.
  12. NOTE: Side-effects of the above steps may have detached or resized O.
  13. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  14. Let fromBuf be O.[[ArrayBufferData]].
  15. Let currentLen be O.[[ArrayBufferByteLength]].
  16. If currentLen < final, throw a RangeError exception.
  17. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  18. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. Let getIndex be ? ToIndex(requestIndex).
  4. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  5. Otherwise, let numberValue be ? ToNumber(value).
  6. Set isLittleEndian to ToBoolean(isLittleEndian).
  7. Let viewOffset be view.[[ByteOffset]].
  8. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  9. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  10. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  11. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/35/index.html b/pr/35/index.html new file mode 100644 index 0000000..eac6991 --- /dev/null +++ b/pr/35/index.html @@ -0,0 +1,3669 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #35 +

+ This document is a preview of merging PR #35, resulting in commit 5c635d270203e1eac5b3183b69314a434e0db3ee. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / February 15, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. Let mutable be true.
      3. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      4. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false not mutable, return false.
      5. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      6. If IsAccessorDescriptor(Desc) is true, return false.
      7. If Desc has a [[Writable]] field and Desc.[[Writable]] is false not mutable, return false.
      8. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      9. If Desc has a [[Value]] field, then
        1. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        2. If mutable is false and SameValue(Desc.[[Value]], TypedArrayGetElement(O, numericIndex)) is false, return false.
        3. If mutable is true, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      10. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion.

+ Editor's Note
The current name of parameter preserveResizability is preserved for the benefit of diff readability, but may be subject to change (to e.g. mode) before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  8. If preserveResizability is immutable, then
    1. Return ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  9. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
    1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
  10. Else,
    1. Let newMaxByteLength be empty.
  11. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  12. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
  13. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  14. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
  15. Let toBlock be newBuffer.[[ArrayBufferData]].
  16. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
  17. 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.
  18. Perform ! DetachArrayBuffer(arrayBuffer).
  19. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return false.
+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be final - first.
  10. NOTE: This differs from ArrayBuffer.prototype.slice ( start, end ), which instead clamps newLen to be non-negative.
  11. If newLen < 0, throw a RangeError exception.
  12. NOTE: Side-effects of the above steps may have detached or resized O.
  13. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  14. Let fromBuf be O.[[ArrayBufferData]].
  15. Let currentLen be O.[[ArrayBufferByteLength]].
  16. If currentLen < final, throw a RangeError exception.
  17. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  18. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. Let getIndex be ? ToIndex(requestIndex).
  4. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  5. Otherwise, let numberValue be ? ToNumber(value).
  6. Set isLittleEndian to ToBoolean(isLittleEndian).
  7. Let viewOffset be view.[[ByteOffset]].
  8. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  9. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  10. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  11. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/36/index.html b/pr/36/index.html new file mode 100644 index 0000000..2589a39 --- /dev/null +++ b/pr/36/index.html @@ -0,0 +1,3669 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #36 +

+ This document is a preview of merging PR #36, resulting in commit 6b423a05f83fd9da2b6e7235ff71d09515f70356. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / February 15, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. Let mutable be true.
      3. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      4. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false not mutable, return false.
      5. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      6. If IsAccessorDescriptor(Desc) is true, return false.
      7. If Desc has a [[Writable]] field and Desc.[[Writable]] is false not mutable, return false.
      8. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      9. If Desc has a [[Value]] field, then
        1. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        2. If mutable is false and SameValue(Desc.[[Value]], TypedArrayGetElement(O, numericIndex)) is false, return false.
        3. If mutable is true, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      10. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion.

+ Editor's Note
The current name of parameter preserveResizability is preserved for the benefit of diff readability, but may be subject to change (to e.g. mode) before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  8. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  9. If preserveResizability is immutable, then
    1. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  10. Else,
    1. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
      1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
    2. Else,
      1. Let newMaxByteLength be empty.
    3. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
    4. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
    5. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
    6. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
    7. Let toBlock be newBuffer.[[ArrayBufferData]].
    8. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
    9. 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.
  11. Perform ! DetachArrayBuffer(arrayBuffer).
  12. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return false.
+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be final - first.
  10. NOTE: This differs from ArrayBuffer.prototype.slice ( start, end ), which instead clamps newLen to be non-negative.
  11. If newLen < 0, throw a RangeError exception.
  12. NOTE: Side-effects of the above steps may have detached or resized O.
  13. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  14. Let fromBuf be O.[[ArrayBufferData]].
  15. Let currentLen be O.[[ArrayBufferByteLength]].
  16. If currentLen < final, throw a RangeError exception.
  17. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  18. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. Let getIndex be ? ToIndex(requestIndex).
  4. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  5. Otherwise, let numberValue be ? ToNumber(value).
  6. Set isLittleEndian to ToBoolean(isLittleEndian).
  7. Let viewOffset be view.[[ByteOffset]].
  8. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  9. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  10. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  11. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/37/index.html b/pr/37/index.html new file mode 100644 index 0000000..437fc16 --- /dev/null +++ b/pr/37/index.html @@ -0,0 +1,3669 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #37 +

+ This document is a preview of merging PR #37, resulting in commit 4e3705a67f4a2e3ab4525f4741601cfce9925e22. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / February 15, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. Let mutable be true.
      3. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      4. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false not mutable, return false.
      5. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      6. If IsAccessorDescriptor(Desc) is true, return false.
      7. If Desc has a [[Writable]] field and Desc.[[Writable]] is false not mutable, return false.
      8. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      9. If Desc has a [[Value]] field, then
        1. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        2. If mutable is false and SameValue(Desc.[[Value]], TypedArrayGetElement(O, numericIndex)) is false, return false.
        3. If mutable is true, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      10. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion.

+ Editor's Note
The current name of parameter preserveResizability is preserved for the benefit of diff readability, but may be subject to change (to e.g. mode) before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  8. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  9. If preserveResizability is immutable, then
    1. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  10. Else,
    1. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
      1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
    2. Else,
      1. Let newMaxByteLength be empty.
    3. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
    4. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
    5. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
    6. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
    7. Let toBlock be newBuffer.[[ArrayBufferData]].
    8. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
    9. 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.
  11. Perform ! DetachArrayBuffer(arrayBuffer).
  12. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return false.
+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be final - first.
  10. NOTE: This differs from ArrayBuffer.prototype.slice ( start, end ), which instead clamps newLen to be non-negative.
  11. If newLen < 0, throw a RangeError exception.
  12. NOTE: Side-effects of the above steps may have detached or resized O.
  13. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  14. Let fromBuf be O.[[ArrayBufferData]].
  15. Let currentLen be O.[[ArrayBufferByteLength]].
  16. If currentLen < final, throw a RangeError exception.
  17. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  18. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let getIndex be ? ToIndex(requestIndex).
  5. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  6. Otherwise, let numberValue be ? ToNumber(value).
  7. Set isLittleEndian to ToBoolean(isLittleEndian).
  8. Let viewOffset be view.[[ByteOffset]].
  9. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  10. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  11. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/38/index.html b/pr/38/index.html new file mode 100644 index 0000000..2d40dce --- /dev/null +++ b/pr/38/index.html @@ -0,0 +1,3678 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #38 +

+ This document is a preview of merging PR #38, resulting in commit f7891ea25efd7ba3eb6aef64e21b4ee2dab34d45. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / February 15, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. Let mutable be true.
      3. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      4. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false not mutable, return false.
      5. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      6. If IsAccessorDescriptor(Desc) is true, return false.
      7. If Desc has a [[Writable]] field and Desc.[[Writable]] is false not mutable, return false.
      8. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      9. If Desc has a [[Value]] field, then
        1. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        2. If mutable is false and SameValue(Desc.[[Value]], TypedArrayGetElement(O, numericIndex)) is false, return false.
        3. If mutable is true, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      10. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion.

+ Editor's Note
The current name of parameter preserveResizability is preserved for the benefit of diff readability, but may be subject to change (to e.g. mode) before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  8. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  9. If preserveResizability is immutable, then
    1. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  10. Else,
    1. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
      1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
    2. Else,
      1. Let newMaxByteLength be empty.
    3. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
    4. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
    5. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
    6. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
    7. Let toBlock be newBuffer.[[ArrayBufferData]].
    8. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
    9. 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.
  11. Perform ! DetachArrayBuffer(arrayBuffer).
  12. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return 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) is false.
  2. If key is not present, set key to undefined.
  3. If arrayBuffer.[[ArrayBufferDetachKey]] is not key, throw a TypeError exception.
  4. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  5. Set arrayBuffer.[[ArrayBufferData]] to null.
  6. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
  7. Return unused.
+ Note
+

Detaching an ArrayBuffer instance disassociates the Data Block used as its backing store from the instance and sets the byte length of the buffer to 0.

+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be final - first.
  10. NOTE: This differs from ArrayBuffer.prototype.slice ( start, end ), which instead clamps newLen to be non-negative.
  11. If newLen < 0, throw a RangeError exception.
  12. NOTE: Side-effects of the above steps may have detached or resized O.
  13. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  14. Let fromBuf be O.[[ArrayBufferData]].
  15. Let currentLen be O.[[ArrayBufferByteLength]].
  16. If currentLen < final, throw a RangeError exception.
  17. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  18. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let getIndex be ? ToIndex(requestIndex).
  5. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  6. Otherwise, let numberValue be ? ToNumber(value).
  7. Set isLittleEndian to ToBoolean(isLittleEndian).
  8. Let viewOffset be view.[[ByteOffset]].
  9. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  10. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  11. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/39/index.html b/pr/39/index.html new file mode 100644 index 0000000..67ca406 --- /dev/null +++ b/pr/39/index.html @@ -0,0 +1,3678 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #39 +

+ This document is a preview of merging PR #39, resulting in commit 265d383433d1cb93e239d7505f6c70874d3f8d4c. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / February 17, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, then
        1. Let current be ! O.[[GetOwnProperty]](P).
        2. Assert: current.[[Configurable]] and current.[[Writable]] are both false.
        3. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        4. Return ValidateAndApplyPropertyDescriptor(O, P, false, Desc, current).
      3. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false, return false.
      4. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      5. If IsAccessorDescriptor(Desc) is true, return false.
      6. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, return false.
      7. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      8. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion.

+ Editor's Note
The current name of parameter preserveResizability is preserved for the benefit of diff readability, but may be subject to change (to e.g. mode) before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  8. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  9. If preserveResizability is immutable, then
    1. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  10. Else,
    1. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
      1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
    2. Else,
      1. Let newMaxByteLength be empty.
    3. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
    4. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
    5. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
    6. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
    7. Let toBlock be newBuffer.[[ArrayBufferData]].
    8. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
    9. 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.
  11. Perform ! DetachArrayBuffer(arrayBuffer).
  12. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return 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) is false.
  2. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If key is not present, set key to undefined.
  4. If arrayBuffer.[[ArrayBufferDetachKey]] is not key, throw a TypeError exception.
  5. Set arrayBuffer.[[ArrayBufferData]] to null.
  6. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
  7. Return unused.
+ Note
+

Detaching an ArrayBuffer instance disassociates the Data Block used as its backing store from the instance and sets the byte length of the buffer to 0.

+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be final - first.
  10. NOTE: This differs from ArrayBuffer.prototype.slice ( start, end ), which instead clamps newLen to be non-negative.
  11. If newLen < 0, throw a RangeError exception.
  12. NOTE: Side-effects of the above steps may have detached or resized O.
  13. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  14. Let fromBuf be O.[[ArrayBufferData]].
  15. Let currentLen be O.[[ArrayBufferByteLength]].
  16. If currentLen < final, throw a RangeError exception.
  17. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  18. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let getIndex be ? ToIndex(requestIndex).
  5. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  6. Otherwise, let numberValue be ? ToNumber(value).
  7. Set isLittleEndian to ToBoolean(isLittleEndian).
  8. Let viewOffset be view.[[ByteOffset]].
  9. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  10. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  11. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/40/index.html b/pr/40/index.html new file mode 100644 index 0000000..0573e95 --- /dev/null +++ b/pr/40/index.html @@ -0,0 +1,3678 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #40 +

+ This document is a preview of merging PR #40, resulting in commit 2f82eca5232bdf1926b8edd7444169ac90b449bf. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / February 18, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, then
        1. Let current be ! O.[[GetOwnProperty]](P).
        2. Assert: current.[[Configurable]] and current.[[Writable]] are both false.
        3. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        4. Return ValidateAndApplyPropertyDescriptor(O, P, false, Desc, current).
      3. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false, return false.
      4. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      5. If IsAccessorDescriptor(Desc) is true, return false.
      6. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, return false.
      7. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      8. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion.

+ Editor's Note
The current name of parameter preserveResizability is preserved for the benefit of diff readability, but may be subject to change (to e.g. mode) before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  8. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  9. If preserveResizability is immutable, then
    1. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  10. Else,
    1. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
      1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
    2. Else,
      1. Let newMaxByteLength be empty.
    3. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
    4. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
    5. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
    6. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
    7. Let toBlock be newBuffer.[[ArrayBufferData]].
    8. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
    9. 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.
  11. Perform ! DetachArrayBuffer(arrayBuffer).
  12. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return 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) is false.
  2. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If key is not present, set key to undefined.
  4. If arrayBuffer.[[ArrayBufferDetachKey]] is not key, throw a TypeError exception.
  5. Set arrayBuffer.[[ArrayBufferData]] to null.
  6. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
  7. Return unused.
+ Note
+

Detaching an ArrayBuffer instance disassociates the Data Block used as its backing store from the instance and sets the byte length of the buffer to 0.

+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be final - first.
  10. NOTE: This differs from ArrayBuffer.prototype.slice ( start, end ), which instead clamps newLen to be non-negative.
  11. If newLen < 0, throw a RangeError exception.
  12. NOTE: Side-effects of the above steps may have detached or resized O.
  13. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  14. Let fromBuf be O.[[ArrayBufferData]].
  15. Let currentLen be O.[[ArrayBufferByteLength]].
  16. If currentLen < final, throw a RangeError exception.
  17. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  18. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot whose value is always undefined.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let getIndex be ? ToIndex(requestIndex).
  5. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  6. Otherwise, let numberValue be ? ToNumber(value).
  7. Set isLittleEndian to ToBoolean(isLittleEndian).
  8. Let viewOffset be view.[[ByteOffset]].
  9. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  10. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  11. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/41/index.html b/pr/41/index.html new file mode 100644 index 0000000..70cedbc --- /dev/null +++ b/pr/41/index.html @@ -0,0 +1,3678 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #41 +

+ This document is a preview of merging PR #41, resulting in commit 586f0764a5b29b05d6be820a61bf9be758a134cd. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / February 19, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, then
        1. Let current be ! O.[[GetOwnProperty]](P).
        2. Assert: current.[[Configurable]] and current.[[Writable]] are both false.
        3. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        4. Return ValidateAndApplyPropertyDescriptor(O, P, false, Desc, current).
      3. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false, return false.
      4. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      5. If IsAccessorDescriptor(Desc) is true, return false.
      6. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, return false.
      7. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      8. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion.

+ Editor's Note
The current name of parameter preserveResizability is preserved for the benefit of diff readability, but may be subject to change (to e.g. mode) before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  8. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  9. If preserveResizability is immutable, then
    1. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  10. Else,
    1. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
      1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
    2. Else,
      1. Let newMaxByteLength be empty.
    3. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
    4. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
    5. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
    6. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
    7. Let toBlock be newBuffer.[[ArrayBufferData]].
    8. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
    9. 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.
  11. Perform ! DetachArrayBuffer(arrayBuffer).
  12. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return 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) is false.
  2. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If key is not present, set key to undefined.
  4. If arrayBuffer.[[ArrayBufferDetachKey]] is not key, throw a TypeError exception.
  5. Set arrayBuffer.[[ArrayBufferData]] to null.
  6. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
  7. Return unused.
+ Note
+

Detaching an ArrayBuffer instance disassociates the Data Block used as its backing store from the instance and sets the byte length of the buffer to 0.

+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be max(final - first, 0).
  10. NOTE: Side-effects of the above steps may have detached or resized O.
  11. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  12. Let fromBuf be O.[[ArrayBufferData]].
  13. Let currentLen be O.[[ArrayBufferByteLength]].
  14. If currentLen < final, throw a RangeError exception.
  15. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  16. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot whose value is always undefined.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let getIndex be ? ToIndex(requestIndex).
  5. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  6. Otherwise, let numberValue be ? ToNumber(value).
  7. Set isLittleEndian to ToBoolean(isLittleEndian).
  8. Let viewOffset be view.[[ByteOffset]].
  9. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  10. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  11. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 69 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/44/index.html b/pr/44/index.html new file mode 100644 index 0000000..7b3a3ea --- /dev/null +++ b/pr/44/index.html @@ -0,0 +1,3678 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #44 +

+ This document is a preview of merging PR #44, resulting in commit 46a078c530ea415fa253fc4d143028cb764c6d3a. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / February 19, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, then
        1. Let current be ! O.[[GetOwnProperty]](P).
        2. Assert: current.[[Configurable]] and current.[[Writable]] are both false.
        3. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        4. Return ValidateAndApplyPropertyDescriptor(O, P, false, Desc, current).
      3. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false, return false.
      4. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      5. If IsAccessorDescriptor(Desc) is true, return false.
      6. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, return false.
      7. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      8. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. The contents of an immutable ArrayBuffer's Data Block are constrained to be permanently stable, and may not be modified by either ECMAScript code or by other activities inside an implementation or observable by it. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion.

+ Editor's Note
The current name of parameter preserveResizability is preserved for the benefit of diff readability, but may be subject to change (to e.g. mode) before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  8. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  9. If preserveResizability is immutable, then
    1. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  10. Else,
    1. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
      1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
    2. Else,
      1. Let newMaxByteLength be empty.
    3. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
    4. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
    5. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
    6. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
    7. Let toBlock be newBuffer.[[ArrayBufferData]].
    8. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
    9. 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.
  11. Perform ! DetachArrayBuffer(arrayBuffer).
  12. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return 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) is false.
  2. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If key is not present, set key to undefined.
  4. If arrayBuffer.[[ArrayBufferDetachKey]] is not key, throw a TypeError exception.
  5. Set arrayBuffer.[[ArrayBufferData]] to null.
  6. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
  7. Return unused.
+ Note
+

Detaching an ArrayBuffer instance disassociates the Data Block used as its backing store from the instance and sets the byte length of the buffer to 0.

+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 72 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 72 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be max(final - first, 0).
  10. NOTE: Side-effects of the above steps may have detached or resized O.
  11. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  12. Let fromBuf be O.[[ArrayBufferData]].
  13. Let currentLen be O.[[ArrayBufferByteLength]].
  14. If currentLen < final, throw a RangeError exception.
  15. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  16. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot whose value is always undefined.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let getIndex be ? ToIndex(requestIndex).
  5. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  6. Otherwise, let numberValue be ? ToNumber(value).
  7. Set isLittleEndian to ToBoolean(isLittleEndian).
  8. Let viewOffset be view.[[ByteOffset]].
  9. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  10. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  11. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 72 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/45/index.html b/pr/45/index.html new file mode 100644 index 0000000..6805e96 --- /dev/null +++ b/pr/45/index.html @@ -0,0 +1,3678 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #45 +

+ This document is a preview of merging PR #45, resulting in commit bcfca4c6cd9608d9a85c3f8cb1df74eb4d1c6565. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / February 21, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, then
        1. Let current be ! O.[[GetOwnProperty]](P).
        2. Assert: current.[[Configurable]] and current.[[Writable]] are both false.
        3. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        4. Return ValidateAndApplyPropertyDescriptor(O, P, false, Desc, current).
      3. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false, return false.
      4. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      5. If IsAccessorDescriptor(Desc) is true, return false.
      6. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, return false.
      7. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      8. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. The contents of an immutable ArrayBuffer's Data Block are constrained to be permanently stable, and may not be modified by either ECMAScript code or by other activities inside an implementation or observable by it. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion.

+ Editor's Note
The current name of parameter preserveResizability is preserved for the benefit of diff readability, but may be subject to change (to e.g. mode) before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  8. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  9. If preserveResizability is immutable, then
    1. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  10. Else,
    1. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
      1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
    2. Else,
      1. Let newMaxByteLength be empty.
    3. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
    4. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
    5. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
    6. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
    7. Let toBlock be newBuffer.[[ArrayBufferData]].
    8. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
    9. 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.
  11. Perform ! DetachArrayBuffer(arrayBuffer).
  12. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return 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) is false.
  2. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If key is not present, set key to undefined.
  4. If arrayBuffer.[[ArrayBufferDetachKey]] is not key, throw a TypeError exception.
  5. Set arrayBuffer.[[ArrayBufferData]] to null.
  6. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
  7. Return unused.
+ Note
+

Detaching an ArrayBuffer instance disassociates the Data Block used as its backing store from the instance and sets the byte length of the buffer to 0.

+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be max(final - first, 0).
  10. NOTE: Side-effects of the above steps may have detached or resized O.
  11. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  12. Let fromBuf be O.[[ArrayBufferData]].
  13. Let currentLen be O.[[ArrayBufferByteLength]].
  14. If currentLen < final, throw a RangeError exception.
  15. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  16. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot whose value is always undefined.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let getIndex be ? ToIndex(requestIndex).
  5. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  6. Otherwise, let numberValue be ? ToNumber(value).
  7. Set isLittleEndian to ToBoolean(isLittleEndian).
  8. Let viewOffset be view.[[ByteOffset]].
  9. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  10. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  11. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/47/index.html b/pr/47/index.html new file mode 100644 index 0000000..7a0f520 --- /dev/null +++ b/pr/47/index.html @@ -0,0 +1,3736 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #47 +

+ This document is a preview of merging PR #47, resulting in commit a80ed781c1081980ade9010485389dc9b1e44318. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / March 6, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, then
        1. Let current be ! O.[[GetOwnProperty]](P).
        2. Assert: current.[[Configurable]] and current.[[Writable]] are both false.
        3. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        4. Return ValidateAndApplyPropertyDescriptor(O, P, false, Desc, current).
      3. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false, return false.
      4. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      5. If IsAccessorDescriptor(Desc) is true, return false.
      6. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, return false.
      7. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      8. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.2 Properties of the %TypedArray% Intrinsic Object

+

The %TypedArray% intrinsic object:

+
    +
  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • +
  • has a "name" property whose value is "TypedArray".
  • +
  • has the following properties:
  • +
+ + +

23.2.2.1 %TypedArray%.from ( source [ , mapper [ , thisArg ] ] )

+

This method performs the following steps when called:

+
  1. Let C be the this value.
  2. If IsConstructor(C) is false, throw a TypeError exception.
  3. If mapper is undefined, then
    1. Let mapping be false.
  4. Else,
    1. If IsCallable(mapper) is false, throw a TypeError exception.
    2. Let mapping be true.
  5. Let usingIterator be ? GetMethod(source, %Symbol.iterator%).
  6. If usingIterator is not undefined, then
    1. Let values be ? IteratorToList(? GetIteratorFromMethod(source, usingIterator)).
    2. Let len be the number of elements in values.
    3. Let targetObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
    4. Let k be 0.
    5. Repeat, while k < len,
      1. Let Pk be ! ToString(𝔽(k)).
      2. Let kValue be the first element of values.
      3. Remove the first element from values.
      4. If mapping is true, then
        1. Let mappedValue be ? Call(mapper, thisArg, « kValue, 𝔽(k) »).
      5. Else,
        1. Let mappedValue be kValue.
      6. Perform ? Set(targetObj, Pk, mappedValue, true).
      7. Set k to k + 1.
    6. Assert: values is now an empty List.
    7. Return targetObj.
  7. NOTE: source is not an iterable object, so assume it is already an array-like object.
  8. Let arrayLike be ! ToObject(source).
  9. Let len be ? LengthOfArrayLike(arrayLike).
  10. Let targetObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
  11. Let k be 0.
  12. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ? Get(arrayLike, Pk).
    3. If mapping is true, then
      1. Let mappedValue be ? Call(mapper, thisArg, « kValue, 𝔽(k) »).
    4. Else,
      1. Let mappedValue be kValue.
    5. Perform ? Set(targetObj, Pk, mappedValue, true).
    6. Set k to k + 1.
  13. Return targetObj.
+
+ + +

23.2.2.2 %TypedArray%.of ( ...items )

+

This method performs the following steps when called:

+
  1. Let len be the number of elements in items.
  2. Let C be the this value.
  3. If IsConstructor(C) is false, throw a TypeError exception.
  4. Let newObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
  5. Let k be 0.
  6. Repeat, while k < len,
    1. Let kValue be items[k].
    2. Let Pk be ! ToString(𝔽(k)).
    3. Perform ? Set(newObj, Pk, kValue, true).
    4. Set k to k + 1.
  7. Return newObj.
+
+
+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.10 %TypedArray%.prototype.filter ( callback [ , thisArg ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.filter as defined in 23.1.3.8.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let len be TypedArrayLength(taRecord).
  4. If IsCallable(callback) is false, throw a TypeError exception.
  5. Let kept be a new empty List.
  6. Let captured be 0.
  7. Let k be 0.
  8. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ! Get(O, Pk).
    3. Let selected be ToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »)).
    4. If selected is true, then
      1. Append kValue to kept.
      2. Set captured to captured + 1.
    5. Set k to k + 1.
  9. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(captured) », write).
  10. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  11. Let n be 0.
  12. For each element e of kept, do
    1. Perform ! Set(A, ! ToString(𝔽(n)), e, true).
    2. Set n to n + 1.
  13. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.22 %TypedArray%.prototype.map ( callback [ , thisArg ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.map as defined in 23.1.3.21.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let len be TypedArrayLength(taRecord).
  4. If IsCallable(callback) is false, throw a TypeError exception.
  5. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(len) », write).
  6. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  7. Let k be 0.
  8. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ! Get(O, Pk).
    3. Let mappedValue be ? Call(callback, thisArg, « kValue, 𝔽(k), O »).
    4. Perform ? Set(A, Pk, mappedValue, true).
    5. Set k to k + 1.
  9. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.27 %TypedArray%.prototype.slice ( start, end )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.slice as defined in 23.1.3.28.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let srcArrayLength be TypedArrayLength(taRecord).
  4. Let relativeStart be ? ToIntegerOrInfinity(start).
  5. If relativeStart = -∞, let startIndex be 0.
  6. Else if relativeStart < 0, let startIndex be max(srcArrayLength + relativeStart, 0).
  7. Else, let startIndex be min(relativeStart, srcArrayLength).
  8. If end is undefined, let relativeEnd be srcArrayLength; else let relativeEnd be ? ToIntegerOrInfinity(end).
  9. If relativeEnd = -∞, let endIndex be 0.
  10. Else if relativeEnd < 0, let endIndex be max(srcArrayLength + relativeEnd, 0).
  11. Else, let endIndex be min(relativeEnd, srcArrayLength).
  12. Let countBytes be max(endIndex - startIndex, 0).
  13. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(countBytes) », write).
  14. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  15. If countBytes > 0, then
    1. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    2. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    3. Set endIndex to min(endIndex, TypedArrayLength(taRecord)).
    4. Set countBytes to max(endIndex - startIndex, 0).
    5. Let srcType be TypedArrayElementType(O).
    6. Let targetType be TypedArrayElementType(A).
    7. If srcType is targetType, then
      1. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data.
      2. Let srcBuffer be O.[[ViewedArrayBuffer]].
      3. Let targetBuffer be A.[[ViewedArrayBuffer]].
      4. Let elementSize be TypedArrayElementSize(O).
      5. Let srcByteOffset be O.[[ByteOffset]].
      6. Let srcByteIndex be (startIndex × elementSize) + srcByteOffset.
      7. Let targetByteIndex be A.[[ByteOffset]].
      8. Let endByteIndex be targetByteIndex + (countBytes × elementSize).
      9. Repeat, while targetByteIndex < endByteIndex,
        1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered).
        3. Set srcByteIndex to srcByteIndex + 1.
        4. Set targetByteIndex to targetByteIndex + 1.
    8. Else,
      1. Let n be 0.
      2. Let k be startIndex.
      3. Repeat, while k < endIndex,
        1. Let Pk be ! ToString(𝔽(k)).
        2. Let kValue be ! Get(O, Pk).
        3. Perform ! Set(A, ! ToString(𝔽(n)), kValue, true).
        4. Set k to k + 1.
        5. Set n to n + 1.
  16. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.1 TypedArraySpeciesCreate ( exemplar, argumentList [ , accessMode ] )

+

The abstract operation TypedArraySpeciesCreate takes arguments exemplar (a TypedArray) and argumentList (a List of ECMAScript language values) and optional argument accessMode (read or write) and returns either a normal completion containing a TypedArray or a throw completion. It is used to specify the creation of a new TypedArray using a constructor function that is derived from exemplar. Unlike ArraySpeciesCreate, which can create non-Array objects through the use of %Symbol.species%, this operation enforces that the constructor function creates an actual TypedArray. It performs the following steps when called:

+
  1. If accessMode is not present, set accessMode to read.
  2. Let defaultConstructor be the intrinsic object associated with the constructor name exemplar.[[TypedArrayName]] in Table 73.
  3. Let constructor be ? SpeciesConstructor(exemplar, defaultConstructor).
  4. Let result be ? TypedArrayCreateFromConstructor(constructor, argumentList, accessMode).
  5. Assert: result has [[TypedArrayName]] and [[ContentType]] internal slots.
  6. Assert: result has all of the internal slots of a TypedArray instance (23.2.8).
  7. If result.[[ContentType]] is not exemplar.[[ContentType]], throw a TypeError exception.
  8. Return result.
+
+ + +

23.2.4.2 TypedArrayCreateFromConstructor ( constructor, argumentList [ , accessMode ] )

+

The abstract operation TypedArrayCreateFromConstructor takes arguments constructor (a constructor) and argumentList (a List of ECMAScript language values) and optional argument accessMode (read or write) and returns either a normal completion containing a TypedArray or a throw completion. It is used to specify the creation of a new TypedArray using a constructor function. It performs the following steps when called:

+
  1. If accessMode is not present, set accessMode to read.
  2. Let newTypedArray be ? Construct(constructor, argumentList).
  3. Let taRecord be ? ValidateTypedArray(newTypedArray, seq-cst, accessMode).
  4. If the number of elements in argumentList is 1 and argumentList[0] is a Number, then
    1. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    2. Let length be TypedArrayLength(taRecord).
    3. If length < (argumentList[0]), throw a TypeError exception.
  5. Return newTypedArray.
+
+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. The contents of an immutable ArrayBuffer's Data Block are constrained to be permanently stable, and may not be modified by either ECMAScript code or by other activities inside an implementation or observable by it. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion.

+ Editor's Note
The current name of parameter preserveResizability is preserved for the benefit of diff readability, but may be subject to change (to e.g. mode) before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  8. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  9. If preserveResizability is immutable, then
    1. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  10. Else,
    1. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
      1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
    2. Else,
      1. Let newMaxByteLength be empty.
    3. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
    4. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
    5. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
    6. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
    7. Let toBlock be newBuffer.[[ArrayBufferData]].
    8. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
    9. 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.
  11. Perform ! DetachArrayBuffer(arrayBuffer).
  12. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return 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) is false.
  2. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If key is not present, set key to undefined.
  4. If arrayBuffer.[[ArrayBufferDetachKey]] is not key, throw a TypeError exception.
  5. Set arrayBuffer.[[ArrayBufferData]] to null.
  6. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
  7. Return unused.
+ Note
+

Detaching an ArrayBuffer instance disassociates the Data Block used as its backing store from the instance and sets the byte length of the buffer to 0.

+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be max(final - first, 0).
  10. NOTE: Side-effects of the above steps may have detached or resized O.
  11. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  12. Let fromBuf be O.[[ArrayBufferData]].
  13. Let currentLen be O.[[ArrayBufferByteLength]].
  14. If currentLen < final, throw a RangeError exception.
  15. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  16. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot whose value is always undefined.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let getIndex be ? ToIndex(requestIndex).
  5. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  6. Otherwise, let numberValue be ? ToNumber(value).
  7. Set isLittleEndian to ToBoolean(isLittleEndian).
  8. Let viewOffset be view.[[ByteOffset]].
  9. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  10. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  11. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

A Copyright & Software License

+ +

Copyright Notice

+

© 2025 Mark S. Miller, Richard Gibson

+ +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/50/index.html b/pr/50/index.html new file mode 100644 index 0000000..f5c0971 --- /dev/null +++ b/pr/50/index.html @@ -0,0 +1,4393 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #50 +

+ This document is a preview of merging PR #50, resulting in commit 62fad7c4c4f1924429bdc3e72be33d17fb98a3e3. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / May 2, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, then
        1. Let current be ! O.[[GetOwnProperty]](P).
        2. Assert: current.[[Configurable]] and current.[[Writable]] are both false.
        3. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        4. Return ValidateAndApplyPropertyDescriptor(O, P, false, Desc, current).
      3. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false, return false.
      4. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      5. If IsAccessorDescriptor(Desc) is true, return false.
      6. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, return false.
      7. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      8. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.2 Properties of the %TypedArray% Intrinsic Object

+

The %TypedArray% intrinsic object:

+
    +
  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • +
  • has a "name" property whose value is "TypedArray".
  • +
  • has the following properties:
  • +
+ + +

23.2.2.1 %TypedArray%.from ( source [ , mapper [ , thisArg ] ] )

+

This method performs the following steps when called:

+
  1. Let C be the this value.
  2. If IsConstructor(C) is false, throw a TypeError exception.
  3. If mapper is undefined, then
    1. Let mapping be false.
  4. Else,
    1. If IsCallable(mapper) is false, throw a TypeError exception.
    2. Let mapping be true.
  5. Let usingIterator be ? GetMethod(source, %Symbol.iterator%).
  6. If usingIterator is not undefined, then
    1. Let values be ? IteratorToList(? GetIteratorFromMethod(source, usingIterator)).
    2. Let len be the number of elements in values.
    3. Let targetObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
    4. Let k be 0.
    5. Repeat, while k < len,
      1. Let Pk be ! ToString(𝔽(k)).
      2. Let kValue be the first element of values.
      3. Remove the first element from values.
      4. If mapping is true, then
        1. Let mappedValue be ? Call(mapper, thisArg, « kValue, 𝔽(k) »).
      5. Else,
        1. Let mappedValue be kValue.
      6. Perform ? Set(targetObj, Pk, mappedValue, true).
      7. Set k to k + 1.
    6. Assert: values is now an empty List.
    7. Return targetObj.
  7. NOTE: source is not an iterable object, so assume it is already an array-like object.
  8. Let arrayLike be ! ToObject(source).
  9. Let len be ? LengthOfArrayLike(arrayLike).
  10. Let targetObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
  11. Let k be 0.
  12. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ? Get(arrayLike, Pk).
    3. If mapping is true, then
      1. Let mappedValue be ? Call(mapper, thisArg, « kValue, 𝔽(k) »).
    4. Else,
      1. Let mappedValue be kValue.
    5. Perform ? Set(targetObj, Pk, mappedValue, true).
    6. Set k to k + 1.
  13. Return targetObj.
+
+ + +

23.2.2.2 %TypedArray%.of ( ...items )

+

This method performs the following steps when called:

+
  1. Let len be the number of elements in items.
  2. Let C be the this value.
  3. If IsConstructor(C) is false, throw a TypeError exception.
  4. Let newObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
  5. Let k be 0.
  6. Repeat, while k < len,
    1. Let kValue be items[k].
    2. Let Pk be ! ToString(𝔽(k)).
    3. Perform ? Set(newObj, Pk, kValue, true).
    4. Set k to k + 1.
  7. Return newObj.
+
+
+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.10 %TypedArray%.prototype.filter ( callback [ , thisArg ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.filter as defined in 23.1.3.8.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let len be TypedArrayLength(taRecord).
  4. If IsCallable(callback) is false, throw a TypeError exception.
  5. Let kept be a new empty List.
  6. Let captured be 0.
  7. Let k be 0.
  8. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ! Get(O, Pk).
    3. Let selected be ToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »)).
    4. If selected is true, then
      1. Append kValue to kept.
      2. Set captured to captured + 1.
    5. Set k to k + 1.
  9. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(captured) », write).
  10. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  11. Let n be 0.
  12. For each element e of kept, do
    1. Perform ! Set(A, ! ToString(𝔽(n)), e, true).
    2. Set n to n + 1.
  13. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.22 %TypedArray%.prototype.map ( callback [ , thisArg ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.map as defined in 23.1.3.21.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let len be TypedArrayLength(taRecord).
  4. If IsCallable(callback) is false, throw a TypeError exception.
  5. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(len) », write).
  6. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  7. Let k be 0.
  8. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ! Get(O, Pk).
    3. Let mappedValue be ? Call(callback, thisArg, « kValue, 𝔽(k), O »).
    4. Perform ? Set(A, Pk, mappedValue, true).
    5. Set k to k + 1.
  9. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.27 %TypedArray%.prototype.slice ( start, end )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.slice as defined in 23.1.3.28.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let srcArrayLength be TypedArrayLength(taRecord).
  4. Let relativeStart be ? ToIntegerOrInfinity(start).
  5. If relativeStart = -∞, let startIndex be 0.
  6. Else if relativeStart < 0, let startIndex be max(srcArrayLength + relativeStart, 0).
  7. Else, let startIndex be min(relativeStart, srcArrayLength).
  8. If end is undefined, let relativeEnd be srcArrayLength; else let relativeEnd be ? ToIntegerOrInfinity(end).
  9. If relativeEnd = -∞, let endIndex be 0.
  10. Else if relativeEnd < 0, let endIndex be max(srcArrayLength + relativeEnd, 0).
  11. Else, let endIndex be min(relativeEnd, srcArrayLength).
  12. Let countBytes be max(endIndex - startIndex, 0).
  13. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(countBytes) », write).
  14. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  15. If countBytes > 0, then
    1. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    2. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    3. Set endIndex to min(endIndex, TypedArrayLength(taRecord)).
    4. Set countBytes to max(endIndex - startIndex, 0).
    5. Let srcType be TypedArrayElementType(O).
    6. Let targetType be TypedArrayElementType(A).
    7. If srcType is targetType, then
      1. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data.
      2. Let srcBuffer be O.[[ViewedArrayBuffer]].
      3. Let targetBuffer be A.[[ViewedArrayBuffer]].
      4. Let elementSize be TypedArrayElementSize(O).
      5. Let srcByteOffset be O.[[ByteOffset]].
      6. Let srcByteIndex be (startIndex × elementSize) + srcByteOffset.
      7. Let targetByteIndex be A.[[ByteOffset]].
      8. Let endByteIndex be targetByteIndex + (countBytes × elementSize).
      9. Repeat, while targetByteIndex < endByteIndex,
        1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered).
        3. Set srcByteIndex to srcByteIndex + 1.
        4. Set targetByteIndex to targetByteIndex + 1.
    8. Else,
      1. Let n be 0.
      2. Let k be startIndex.
      3. Repeat, while k < endIndex,
        1. Let Pk be ! ToString(𝔽(k)).
        2. Let kValue be ! Get(O, Pk).
        3. Perform ! Set(A, ! ToString(𝔽(n)), kValue, true).
        4. Set k to k + 1.
        5. Set n to n + 1.
  16. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.1 TypedArraySpeciesCreate ( exemplar, argumentList [ , accessMode ] )

+

The abstract operation TypedArraySpeciesCreate takes arguments exemplar (a TypedArray) and argumentList (a List of ECMAScript language values) and optional argument accessMode (read or write) and returns either a normal completion containing a TypedArray or a throw completion. It is used to specify the creation of a new TypedArray using a constructor function that is derived from exemplar. Unlike ArraySpeciesCreate, which can create non-Array objects through the use of %Symbol.species%, this operation enforces that the constructor function creates an actual TypedArray. It performs the following steps when called:

+
  1. If accessMode is not present, set accessMode to read.
  2. Let defaultConstructor be the intrinsic object associated with the constructor name exemplar.[[TypedArrayName]] in Table 73.
  3. Let constructor be ? SpeciesConstructor(exemplar, defaultConstructor).
  4. Let result be ? TypedArrayCreateFromConstructor(constructor, argumentList, accessMode).
  5. Assert: result has [[TypedArrayName]] and [[ContentType]] internal slots.
  6. Assert: result has all of the internal slots of a TypedArray instance (23.2.8).
  7. If result.[[ContentType]] is not exemplar.[[ContentType]], throw a TypeError exception.
  8. Return result.
+
+ + +

23.2.4.2 TypedArrayCreateFromConstructor ( constructor, argumentList [ , accessMode ] )

+

The abstract operation TypedArrayCreateFromConstructor takes arguments constructor (a constructor) and argumentList (a List of ECMAScript language values) and optional argument accessMode (read or write) and returns either a normal completion containing a TypedArray or a throw completion. It is used to specify the creation of a new TypedArray using a constructor function. It performs the following steps when called:

+
  1. If accessMode is not present, set accessMode to read.
  2. Let newTypedArray be ? Construct(constructor, argumentList).
  3. Let taRecord be ? ValidateTypedArray(newTypedArray, seq-cst, accessMode).
  4. If the number of elements in argumentList is 1 and argumentList[0] is a Number, then
    1. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    2. Let length be TypedArrayLength(taRecord).
    3. If length < (argumentList[0]), throw a TypeError exception.
  5. Return newTypedArray.
+
+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. The contents of an immutable ArrayBuffer's Data Block are constrained to be permanently stable, and may not be modified by either ECMAScript code or by other activities inside an implementation or observable by it. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion.

+ Editor's Note
The current name of parameter preserveResizability is preserved for the benefit of diff readability, but may be subject to change (to e.g. mode) before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  8. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  9. If preserveResizability is immutable, then
    1. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  10. Else,
    1. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
      1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
    2. Else,
      1. Let newMaxByteLength be empty.
    3. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
    4. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
    5. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
    6. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
    7. Let toBlock be newBuffer.[[ArrayBufferData]].
    8. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
    9. 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.
  11. Perform ! DetachArrayBuffer(arrayBuffer).
  12. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return 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) is false.
  2. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If key is not present, set key to undefined.
  4. If arrayBuffer.[[ArrayBufferDetachKey]] is not key, throw a TypeError exception.
  5. Set arrayBuffer.[[ArrayBufferData]] to null.
  6. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
  7. Return unused.
+ Note
+

Detaching an ArrayBuffer instance disassociates the Data Block used as its backing store from the instance and sets the byte length of the buffer to 0.

+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. Assert: IsImmutableBuffer(O) is false.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be max(final - first, 0).
  10. NOTE: Side-effects of the above steps may have detached or resized O.
  11. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  12. Let fromBuf be O.[[ArrayBufferData]].
  13. Let currentLen be O.[[ArrayBufferByteLength]].
  14. If currentLen < final, throw a RangeError exception.
  15. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  16. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot whose value is always undefined.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let getIndex be ? ToIndex(requestIndex).
  5. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  6. Otherwise, let numberValue be ? ToNumber(value).
  7. Set isLittleEndian to ToBoolean(isLittleEndian).
  8. Let viewOffset be view.[[ByteOffset]].
  9. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  10. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  11. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

Copyright & Software License

+ + +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/51/index.html b/pr/51/index.html new file mode 100644 index 0000000..a132969 --- /dev/null +++ b/pr/51/index.html @@ -0,0 +1,4393 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #51 +

+ This document is a preview of merging PR #51, resulting in commit 1fbd0c6875f78e69e8fb1641ae189017ed2924f8. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to nth pin1-9
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / May 2, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, then
        1. Let current be ! O.[[GetOwnProperty]](P).
        2. Assert: current.[[Configurable]] and current.[[Writable]] are both false.
        3. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        4. Return ValidateAndApplyPropertyDescriptor(O, P, false, Desc, current).
      3. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false, return false.
      4. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      5. If IsAccessorDescriptor(Desc) is true, return false.
      6. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, return false.
      7. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      8. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.2 Properties of the %TypedArray% Intrinsic Object

+

The %TypedArray% intrinsic object:

+
    +
  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • +
  • has a "name" property whose value is "TypedArray".
  • +
  • has the following properties:
  • +
+ + +

23.2.2.1 %TypedArray%.from ( source [ , mapper [ , thisArg ] ] )

+

This method performs the following steps when called:

+
  1. Let C be the this value.
  2. If IsConstructor(C) is false, throw a TypeError exception.
  3. If mapper is undefined, then
    1. Let mapping be false.
  4. Else,
    1. If IsCallable(mapper) is false, throw a TypeError exception.
    2. Let mapping be true.
  5. Let usingIterator be ? GetMethod(source, %Symbol.iterator%).
  6. If usingIterator is not undefined, then
    1. Let values be ? IteratorToList(? GetIteratorFromMethod(source, usingIterator)).
    2. Let len be the number of elements in values.
    3. Let targetObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
    4. Let k be 0.
    5. Repeat, while k < len,
      1. Let Pk be ! ToString(𝔽(k)).
      2. Let kValue be the first element of values.
      3. Remove the first element from values.
      4. If mapping is true, then
        1. Let mappedValue be ? Call(mapper, thisArg, « kValue, 𝔽(k) »).
      5. Else,
        1. Let mappedValue be kValue.
      6. Perform ? Set(targetObj, Pk, mappedValue, true).
      7. Set k to k + 1.
    6. Assert: values is now an empty List.
    7. Return targetObj.
  7. NOTE: source is not an iterable object, so assume it is already an array-like object.
  8. Let arrayLike be ! ToObject(source).
  9. Let len be ? LengthOfArrayLike(arrayLike).
  10. Let targetObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
  11. Let k be 0.
  12. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ? Get(arrayLike, Pk).
    3. If mapping is true, then
      1. Let mappedValue be ? Call(mapper, thisArg, « kValue, 𝔽(k) »).
    4. Else,
      1. Let mappedValue be kValue.
    5. Perform ? Set(targetObj, Pk, mappedValue, true).
    6. Set k to k + 1.
  13. Return targetObj.
+
+ + +

23.2.2.2 %TypedArray%.of ( ...items )

+

This method performs the following steps when called:

+
  1. Let len be the number of elements in items.
  2. Let C be the this value.
  3. If IsConstructor(C) is false, throw a TypeError exception.
  4. Let newObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
  5. Let k be 0.
  6. Repeat, while k < len,
    1. Let kValue be items[k].
    2. Let Pk be ! ToString(𝔽(k)).
    3. Perform ? Set(newObj, Pk, kValue, true).
    4. Set k to k + 1.
  7. Return newObj.
+
+
+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.10 %TypedArray%.prototype.filter ( callback [ , thisArg ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.filter as defined in 23.1.3.8.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let len be TypedArrayLength(taRecord).
  4. If IsCallable(callback) is false, throw a TypeError exception.
  5. Let kept be a new empty List.
  6. Let captured be 0.
  7. Let k be 0.
  8. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ! Get(O, Pk).
    3. Let selected be ToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »)).
    4. If selected is true, then
      1. Append kValue to kept.
      2. Set captured to captured + 1.
    5. Set k to k + 1.
  9. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(captured) », write).
  10. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  11. Let n be 0.
  12. For each element e of kept, do
    1. Perform ! Set(A, ! ToString(𝔽(n)), e, true).
    2. Set n to n + 1.
  13. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.22 %TypedArray%.prototype.map ( callback [ , thisArg ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.map as defined in 23.1.3.21.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let len be TypedArrayLength(taRecord).
  4. If IsCallable(callback) is false, throw a TypeError exception.
  5. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(len) », write).
  6. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  7. Let k be 0.
  8. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ! Get(O, Pk).
    3. Let mappedValue be ? Call(callback, thisArg, « kValue, 𝔽(k), O »).
    4. Perform ? Set(A, Pk, mappedValue, true).
    5. Set k to k + 1.
  9. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.27 %TypedArray%.prototype.slice ( start, end )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.slice as defined in 23.1.3.28.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let srcArrayLength be TypedArrayLength(taRecord).
  4. Let relativeStart be ? ToIntegerOrInfinity(start).
  5. If relativeStart = -∞, let startIndex be 0.
  6. Else if relativeStart < 0, let startIndex be max(srcArrayLength + relativeStart, 0).
  7. Else, let startIndex be min(relativeStart, srcArrayLength).
  8. If end is undefined, let relativeEnd be srcArrayLength; else let relativeEnd be ? ToIntegerOrInfinity(end).
  9. If relativeEnd = -∞, let endIndex be 0.
  10. Else if relativeEnd < 0, let endIndex be max(srcArrayLength + relativeEnd, 0).
  11. Else, let endIndex be min(relativeEnd, srcArrayLength).
  12. Let countBytes be max(endIndex - startIndex, 0).
  13. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(countBytes) », write).
  14. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  15. If countBytes > 0, then
    1. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    2. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    3. Set endIndex to min(endIndex, TypedArrayLength(taRecord)).
    4. Set countBytes to max(endIndex - startIndex, 0).
    5. Let srcType be TypedArrayElementType(O).
    6. Let targetType be TypedArrayElementType(A).
    7. If srcType is targetType, then
      1. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data.
      2. Let srcBuffer be O.[[ViewedArrayBuffer]].
      3. Let targetBuffer be A.[[ViewedArrayBuffer]].
      4. Let elementSize be TypedArrayElementSize(O).
      5. Let srcByteOffset be O.[[ByteOffset]].
      6. Let srcByteIndex be (startIndex × elementSize) + srcByteOffset.
      7. Let targetByteIndex be A.[[ByteOffset]].
      8. Let endByteIndex be targetByteIndex + (countBytes × elementSize).
      9. Repeat, while targetByteIndex < endByteIndex,
        1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered).
        3. Set srcByteIndex to srcByteIndex + 1.
        4. Set targetByteIndex to targetByteIndex + 1.
    8. Else,
      1. Let n be 0.
      2. Let k be startIndex.
      3. Repeat, while k < endIndex,
        1. Let Pk be ! ToString(𝔽(k)).
        2. Let kValue be ! Get(O, Pk).
        3. Perform ! Set(A, ! ToString(𝔽(n)), kValue, true).
        4. Set k to k + 1.
        5. Set n to n + 1.
  16. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.1 TypedArraySpeciesCreate ( exemplar, argumentList [ , accessMode ] )

+

The abstract operation TypedArraySpeciesCreate takes arguments exemplar (a TypedArray) and argumentList (a List of ECMAScript language values) and optional argument accessMode (read or write) and returns either a normal completion containing a TypedArray or a throw completion. It is used to specify the creation of a new TypedArray using a constructor function that is derived from exemplar. Unlike ArraySpeciesCreate, which can create non-Array objects through the use of %Symbol.species%, this operation enforces that the constructor function creates an actual TypedArray. It performs the following steps when called:

+
  1. If accessMode is not present, set accessMode to read.
  2. Let defaultConstructor be the intrinsic object associated with the constructor name exemplar.[[TypedArrayName]] in Table 73.
  3. Let constructor be ? SpeciesConstructor(exemplar, defaultConstructor).
  4. Let result be ? TypedArrayCreateFromConstructor(constructor, argumentList, accessMode).
  5. Assert: result has [[TypedArrayName]] and [[ContentType]] internal slots.
  6. Assert: result has all of the internal slots of a TypedArray instance (23.2.8).
  7. If result.[[ContentType]] is not exemplar.[[ContentType]], throw a TypeError exception.
  8. Return result.
+
+ + +

23.2.4.2 TypedArrayCreateFromConstructor ( constructor, argumentList [ , accessMode ] )

+

The abstract operation TypedArrayCreateFromConstructor takes arguments constructor (a constructor) and argumentList (a List of ECMAScript language values) and optional argument accessMode (read or write) and returns either a normal completion containing a TypedArray or a throw completion. It is used to specify the creation of a new TypedArray using a constructor function. It performs the following steps when called:

+
  1. If accessMode is not present, set accessMode to read.
  2. Let newTypedArray be ? Construct(constructor, argumentList).
  3. Let taRecord be ? ValidateTypedArray(newTypedArray, seq-cst, accessMode).
  4. If the number of elements in argumentList is 1 and argumentList[0] is a Number, then
    1. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    2. Let length be TypedArrayLength(taRecord).
    3. If length < (argumentList[0]), throw a TypeError exception.
  5. Return newTypedArray.
+
+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. The contents of an immutable ArrayBuffer's Data Block are constrained to be permanently stable, and may not be modified by either ECMAScript code or by other activities inside an implementation or observable by it. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion.

+ Editor's Note
The current name of parameter preserveResizability is preserved for the benefit of diff readability, but may be subject to change (to e.g. mode) before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  8. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  9. If preserveResizability is immutable, then
    1. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  10. Else,
    1. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
      1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
    2. Else,
      1. Let newMaxByteLength be empty.
    3. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
    4. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
    5. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
    6. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
    7. Let toBlock be newBuffer.[[ArrayBufferData]].
    8. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
    9. 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.
  11. Perform ! DetachArrayBuffer(arrayBuffer).
  12. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return 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) is false.
  2. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If key is not present, set key to undefined.
  4. If arrayBuffer.[[ArrayBufferDetachKey]] is not key, throw a TypeError exception.
  5. Set arrayBuffer.[[ArrayBufferData]] to null.
  6. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
  7. Return unused.
+ Note
+

Detaching an ArrayBuffer instance disassociates the Data Block used as its backing store from the instance and sets the byte length of the buffer to 0.

+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(O) is true, throw a TypeError exception.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be max(final - first, 0).
  10. NOTE: Side-effects of the above steps may have detached or resized O.
  11. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  12. Let fromBuf be O.[[ArrayBufferData]].
  13. Let currentLen be O.[[ArrayBufferByteLength]].
  14. If currentLen < final, throw a RangeError exception.
  15. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  16. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot whose value is always undefined.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let getIndex be ? ToIndex(requestIndex).
  5. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  6. Otherwise, let numberValue be ? ToNumber(value).
  7. Set isLittleEndian to ToBoolean(isLittleEndian).
  8. Let viewOffset be view.[[ByteOffset]].
  9. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  10. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  11. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

Copyright & Software License

+ + +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/53/index.html b/pr/53/index.html new file mode 100644 index 0000000..d40dc5c --- /dev/null +++ b/pr/53/index.html @@ -0,0 +1,4395 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #53 +

+ This document is a preview of merging PR #53, resulting in commit 4214691fa39172d14f8bf24b2668032736411412. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to the nth pin1-9
  • +
  • Jump to the 10th pin0
  • +
  • Jump to the most recent link target`
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / May 29, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, then
        1. Let current be ! O.[[GetOwnProperty]](P).
        2. Assert: current.[[Configurable]] and current.[[Writable]] are both false.
        3. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        4. Return ValidateAndApplyPropertyDescriptor(O, P, false, Desc, current).
      3. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false, return false.
      4. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      5. If IsAccessorDescriptor(Desc) is true, return false.
      6. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, return false.
      7. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      8. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.2 Properties of the %TypedArray% Intrinsic Object

+

The %TypedArray% intrinsic object:

+
    +
  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • +
  • has a "name" property whose value is "TypedArray".
  • +
  • has the following properties:
  • +
+ + +

23.2.2.1 %TypedArray%.from ( source [ , mapper [ , thisArg ] ] )

+

This method performs the following steps when called:

+
  1. Let C be the this value.
  2. If IsConstructor(C) is false, throw a TypeError exception.
  3. If mapper is undefined, then
    1. Let mapping be false.
  4. Else,
    1. If IsCallable(mapper) is false, throw a TypeError exception.
    2. Let mapping be true.
  5. Let usingIterator be ? GetMethod(source, %Symbol.iterator%).
  6. If usingIterator is not undefined, then
    1. Let values be ? IteratorToList(? GetIteratorFromMethod(source, usingIterator)).
    2. Let len be the number of elements in values.
    3. Let targetObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
    4. Let k be 0.
    5. Repeat, while k < len,
      1. Let Pk be ! ToString(𝔽(k)).
      2. Let kValue be the first element of values.
      3. Remove the first element from values.
      4. If mapping is true, then
        1. Let mappedValue be ? Call(mapper, thisArg, « kValue, 𝔽(k) »).
      5. Else,
        1. Let mappedValue be kValue.
      6. Perform ? Set(targetObj, Pk, mappedValue, true).
      7. Set k to k + 1.
    6. Assert: values is now an empty List.
    7. Return targetObj.
  7. NOTE: source is not an iterable object, so assume it is already an array-like object.
  8. Let arrayLike be ! ToObject(source).
  9. Let len be ? LengthOfArrayLike(arrayLike).
  10. Let targetObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
  11. Let k be 0.
  12. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ? Get(arrayLike, Pk).
    3. If mapping is true, then
      1. Let mappedValue be ? Call(mapper, thisArg, « kValue, 𝔽(k) »).
    4. Else,
      1. Let mappedValue be kValue.
    5. Perform ? Set(targetObj, Pk, mappedValue, true).
    6. Set k to k + 1.
  13. Return targetObj.
+
+ + +

23.2.2.2 %TypedArray%.of ( ...items )

+

This method performs the following steps when called:

+
  1. Let len be the number of elements in items.
  2. Let C be the this value.
  3. If IsConstructor(C) is false, throw a TypeError exception.
  4. Let newObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
  5. Let k be 0.
  6. Repeat, while k < len,
    1. Let kValue be items[k].
    2. Let Pk be ! ToString(𝔽(k)).
    3. Perform ? Set(newObj, Pk, kValue, true).
    4. Set k to k + 1.
  7. Return newObj.
+
+
+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.10 %TypedArray%.prototype.filter ( callback [ , thisArg ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.filter as defined in 23.1.3.8.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let len be TypedArrayLength(taRecord).
  4. If IsCallable(callback) is false, throw a TypeError exception.
  5. Let kept be a new empty List.
  6. Let captured be 0.
  7. Let k be 0.
  8. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ! Get(O, Pk).
    3. Let selected be ToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »)).
    4. If selected is true, then
      1. Append kValue to kept.
      2. Set captured to captured + 1.
    5. Set k to k + 1.
  9. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(captured) », write).
  10. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  11. Let n be 0.
  12. For each element e of kept, do
    1. Perform ! Set(A, ! ToString(𝔽(n)), e, true).
    2. Set n to n + 1.
  13. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.22 %TypedArray%.prototype.map ( callback [ , thisArg ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.map as defined in 23.1.3.21.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let len be TypedArrayLength(taRecord).
  4. If IsCallable(callback) is false, throw a TypeError exception.
  5. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(len) », write).
  6. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  7. Let k be 0.
  8. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ! Get(O, Pk).
    3. Let mappedValue be ? Call(callback, thisArg, « kValue, 𝔽(k), O »).
    4. Perform ? Set(A, Pk, mappedValue, true).
    5. Set k to k + 1.
  9. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.27 %TypedArray%.prototype.slice ( start, end )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.slice as defined in 23.1.3.28.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let srcArrayLength be TypedArrayLength(taRecord).
  4. Let relativeStart be ? ToIntegerOrInfinity(start).
  5. If relativeStart = -∞, let startIndex be 0.
  6. Else if relativeStart < 0, let startIndex be max(srcArrayLength + relativeStart, 0).
  7. Else, let startIndex be min(relativeStart, srcArrayLength).
  8. If end is undefined, let relativeEnd be srcArrayLength; else let relativeEnd be ? ToIntegerOrInfinity(end).
  9. If relativeEnd = -∞, let endIndex be 0.
  10. Else if relativeEnd < 0, let endIndex be max(srcArrayLength + relativeEnd, 0).
  11. Else, let endIndex be min(relativeEnd, srcArrayLength).
  12. Let countBytes be max(endIndex - startIndex, 0).
  13. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(countBytes) », write).
  14. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  15. If countBytes > 0, then
    1. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    2. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    3. Set endIndex to min(endIndex, TypedArrayLength(taRecord)).
    4. Set countBytes to max(endIndex - startIndex, 0).
    5. Let srcType be TypedArrayElementType(O).
    6. Let targetType be TypedArrayElementType(A).
    7. If srcType is targetType, then
      1. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data.
      2. Let srcBuffer be O.[[ViewedArrayBuffer]].
      3. Let targetBuffer be A.[[ViewedArrayBuffer]].
      4. Let elementSize be TypedArrayElementSize(O).
      5. Let srcByteOffset be O.[[ByteOffset]].
      6. Let srcByteIndex be (startIndex × elementSize) + srcByteOffset.
      7. Let targetByteIndex be A.[[ByteOffset]].
      8. Let endByteIndex be targetByteIndex + (countBytes × elementSize).
      9. Repeat, while targetByteIndex < endByteIndex,
        1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered).
        3. Set srcByteIndex to srcByteIndex + 1.
        4. Set targetByteIndex to targetByteIndex + 1.
    8. Else,
      1. Let n be 0.
      2. Let k be startIndex.
      3. Repeat, while k < endIndex,
        1. Let Pk be ! ToString(𝔽(k)).
        2. Let kValue be ! Get(O, Pk).
        3. Perform ! Set(A, ! ToString(𝔽(n)), kValue, true).
        4. Set k to k + 1.
        5. Set n to n + 1.
  16. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.1 TypedArraySpeciesCreate ( exemplar, argumentList [ , accessMode ] )

+

The abstract operation TypedArraySpeciesCreate takes arguments exemplar (a TypedArray) and argumentList (a List of ECMAScript language values) and optional argument accessMode (read or write) and returns either a normal completion containing a TypedArray or a throw completion. It is used to specify the creation of a new TypedArray using a constructor function that is derived from exemplar. Unlike ArraySpeciesCreate, which can create non-Array objects through the use of %Symbol.species%, this operation enforces that the constructor function creates an actual TypedArray. It performs the following steps when called:

+
  1. If accessMode is not present, set accessMode to read.
  2. Let defaultConstructor be the intrinsic object associated with the constructor name exemplar.[[TypedArrayName]] in Table 73.
  3. Let constructor be ? SpeciesConstructor(exemplar, defaultConstructor).
  4. Let result be ? TypedArrayCreateFromConstructor(constructor, argumentList, accessMode).
  5. Assert: result has [[TypedArrayName]] and [[ContentType]] internal slots.
  6. Assert: result has all of the internal slots of a TypedArray instance (23.2.8).
  7. If result.[[ContentType]] is not exemplar.[[ContentType]], throw a TypeError exception.
  8. Return result.
+
+ + +

23.2.4.2 TypedArrayCreateFromConstructor ( constructor, argumentList [ , accessMode ] )

+

The abstract operation TypedArrayCreateFromConstructor takes arguments constructor (a constructor) and argumentList (a List of ECMAScript language values) and optional argument accessMode (read or write) and returns either a normal completion containing a TypedArray or a throw completion. It is used to specify the creation of a new TypedArray using a constructor function. It performs the following steps when called:

+
  1. If accessMode is not present, set accessMode to read.
  2. Let newTypedArray be ? Construct(constructor, argumentList).
  3. Let taRecord be ? ValidateTypedArray(newTypedArray, seq-cst, accessMode).
  4. If the number of elements in argumentList is 1 and argumentList[0] is a Number, then
    1. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    2. Let length be TypedArrayLength(taRecord).
    3. If length < (argumentList[0]), throw a TypeError exception.
  5. Return newTypedArray.
+
+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. The contents of an immutable ArrayBuffer's Data Block are constrained to be permanently stable, and may not be modified by either ECMAScript code or by other activities inside an implementation or observable by it. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion.

+ Editor's Note
The current name of parameter preserveResizability is preserved for the benefit of diff readability, but may be subject to change (to e.g. mode) before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  8. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  9. If preserveResizability is immutable, then
    1. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  10. Else,
    1. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
      1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
    2. Else,
      1. Let newMaxByteLength be empty.
    3. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
    4. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
    5. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
    6. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
    7. Let toBlock be newBuffer.[[ArrayBufferData]].
    8. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
    9. 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.
  11. Perform ! DetachArrayBuffer(arrayBuffer).
  12. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return 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) is false.
  2. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If key is not present, set key to undefined.
  4. If arrayBuffer.[[ArrayBufferDetachKey]] is not key, throw a TypeError exception.
  5. Set arrayBuffer.[[ArrayBufferData]] to null.
  6. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
  7. Return unused.
+ Note
+

Detaching an ArrayBuffer instance disassociates the Data Block used as its backing store from the instance and sets the byte length of the buffer to 0.

+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. Assert: IsImmutableBuffer(O) is false.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be max(final - first, 0).
  10. NOTE: Side-effects of the above steps may have detached or resized O.
  11. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  12. Let fromBuf be O.[[ArrayBufferData]].
  13. Let currentLen be O.[[ArrayBufferByteLength]].
  14. If currentLen < final, throw a RangeError exception.
  15. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  16. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot whose value is always undefined.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let getIndex be ? ToIndex(requestIndex).
  5. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  6. Otherwise, let numberValue be ? ToNumber(value).
  7. Set isLittleEndian to ToBoolean(isLittleEndian).
  8. Let viewOffset be view.[[ByteOffset]].
  9. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  10. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  11. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

Copyright & Software License

+ + +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/56/index.html b/pr/56/index.html new file mode 100644 index 0000000..880fa62 --- /dev/null +++ b/pr/56/index.html @@ -0,0 +1,4435 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #56 +

+ This document is a preview of merging PR #56, resulting in commit 493a990e3f1c678bfae79e01dbc6191136a26018. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to the nth pin1-9
  • +
  • Jump to the 10th pin0
  • +
  • Jump to the most recent link target`
  • +

Proposal proposal-immutable-arraybuffer

Stage 2 Draft / July 28, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, then
        1. Let current be ! O.[[GetOwnProperty]](P).
        2. Assert: current.[[Configurable]] and current.[[Writable]] are both false.
        3. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        4. Return ValidateAndApplyPropertyDescriptor(O, P, false, Desc, current).
      3. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false, return false.
      4. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      5. If IsAccessorDescriptor(Desc) is true, return false.
      6. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, return false.
      7. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      8. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.2 Properties of the %TypedArray% Intrinsic Object

+

The %TypedArray% intrinsic object:

+
    +
  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • +
  • has a "name" property whose value is "TypedArray".
  • +
  • has the following properties:
  • +
+ + +

23.2.2.1 %TypedArray%.from ( source [ , mapper [ , thisArg ] ] )

+

This method performs the following steps when called:

+
  1. Let C be the this value.
  2. If IsConstructor(C) is false, throw a TypeError exception.
  3. If mapper is undefined, then
    1. Let mapping be false.
  4. Else,
    1. If IsCallable(mapper) is false, throw a TypeError exception.
    2. Let mapping be true.
  5. Let usingIterator be ? GetMethod(source, %Symbol.iterator%).
  6. If usingIterator is not undefined, then
    1. Let values be ? IteratorToList(? GetIteratorFromMethod(source, usingIterator)).
    2. Let len be the number of elements in values.
    3. Let targetObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
    4. Let k be 0.
    5. Repeat, while k < len,
      1. Let Pk be ! ToString(𝔽(k)).
      2. Let kValue be the first element of values.
      3. Remove the first element from values.
      4. If mapping is true, then
        1. Let mappedValue be ? Call(mapper, thisArg, « kValue, 𝔽(k) »).
      5. Else,
        1. Let mappedValue be kValue.
      6. Perform ? Set(targetObj, Pk, mappedValue, true).
      7. Set k to k + 1.
    6. Assert: values is now an empty List.
    7. Return targetObj.
  7. NOTE: source is not an iterable object, so assume it is already an array-like object.
  8. Let arrayLike be ! ToObject(source).
  9. Let len be ? LengthOfArrayLike(arrayLike).
  10. Let targetObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
  11. Let k be 0.
  12. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ? Get(arrayLike, Pk).
    3. If mapping is true, then
      1. Let mappedValue be ? Call(mapper, thisArg, « kValue, 𝔽(k) »).
    4. Else,
      1. Let mappedValue be kValue.
    5. Perform ? Set(targetObj, Pk, mappedValue, true).
    6. Set k to k + 1.
  13. Return targetObj.
+
+ + +

23.2.2.2 %TypedArray%.of ( ...items )

+

This method performs the following steps when called:

+
  1. Let len be the number of elements in items.
  2. Let C be the this value.
  3. If IsConstructor(C) is false, throw a TypeError exception.
  4. Let newObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
  5. Let k be 0.
  6. Repeat, while k < len,
    1. Let kValue be items[k].
    2. Let Pk be ! ToString(𝔽(k)).
    3. Perform ? Set(newObj, Pk, kValue, true).
    4. Set k to k + 1.
  7. Return newObj.
+
+
+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.10 %TypedArray%.prototype.filter ( callback [ , thisArg ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.filter as defined in 23.1.3.8.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let len be TypedArrayLength(taRecord).
  4. If IsCallable(callback) is false, throw a TypeError exception.
  5. Let kept be a new empty List.
  6. Let captured be 0.
  7. Let k be 0.
  8. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ! Get(O, Pk).
    3. Let selected be ToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »)).
    4. If selected is true, then
      1. Append kValue to kept.
      2. Set captured to captured + 1.
    5. Set k to k + 1.
  9. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(captured) », write).
  10. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  11. Let n be 0.
  12. For each element e of kept, do
    1. Perform ! Set(A, ! ToString(𝔽(n)), e, true).
    2. Set n to n + 1.
  13. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.22 %TypedArray%.prototype.map ( callback [ , thisArg ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.map as defined in 23.1.3.21.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let len be TypedArrayLength(taRecord).
  4. If IsCallable(callback) is false, throw a TypeError exception.
  5. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(len) », write).
  6. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  7. Let k be 0.
  8. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ! Get(O, Pk).
    3. Let mappedValue be ? Call(callback, thisArg, « kValue, 𝔽(k), O »).
    4. Perform ? Set(A, Pk, mappedValue, true).
    5. Set k to k + 1.
  9. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.27 %TypedArray%.prototype.slice ( start, end )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.slice as defined in 23.1.3.28.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let srcArrayLength be TypedArrayLength(taRecord).
  4. Let relativeStart be ? ToIntegerOrInfinity(start).
  5. If relativeStart = -∞, let startIndex be 0.
  6. Else if relativeStart < 0, let startIndex be max(srcArrayLength + relativeStart, 0).
  7. Else, let startIndex be min(relativeStart, srcArrayLength).
  8. If end is undefined, let relativeEnd be srcArrayLength; else let relativeEnd be ? ToIntegerOrInfinity(end).
  9. If relativeEnd = -∞, let endIndex be 0.
  10. Else if relativeEnd < 0, let endIndex be max(srcArrayLength + relativeEnd, 0).
  11. Else, let endIndex be min(relativeEnd, srcArrayLength).
  12. Let countBytes be max(endIndex - startIndex, 0).
  13. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(countBytes) », write).
  14. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  15. If countBytes > 0, then
    1. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    2. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    3. Set endIndex to min(endIndex, TypedArrayLength(taRecord)).
    4. Set countBytes to max(endIndex - startIndex, 0).
    5. Let srcType be TypedArrayElementType(O).
    6. Let targetType be TypedArrayElementType(A).
    7. If srcType is targetType, then
      1. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data.
      2. Let srcBuffer be O.[[ViewedArrayBuffer]].
      3. Let targetBuffer be A.[[ViewedArrayBuffer]].
      4. Let elementSize be TypedArrayElementSize(O).
      5. Let srcByteOffset be O.[[ByteOffset]].
      6. Let srcByteIndex be (startIndex × elementSize) + srcByteOffset.
      7. Let targetByteIndex be A.[[ByteOffset]].
      8. Let endByteIndex be targetByteIndex + (countBytes × elementSize).
      9. Repeat, while targetByteIndex < endByteIndex,
        1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered).
        3. Set srcByteIndex to srcByteIndex + 1.
        4. Set targetByteIndex to targetByteIndex + 1.
    8. Else,
      1. Let n be 0.
      2. Let k be startIndex.
      3. Repeat, while k < endIndex,
        1. Let Pk be ! ToString(𝔽(k)).
        2. Let kValue be ! Get(O, Pk).
        3. Perform ! Set(A, ! ToString(𝔽(n)), kValue, true).
        4. Set k to k + 1.
        5. Set n to n + 1.
  16. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.1 TypedArraySpeciesCreate ( exemplar, argumentList [ , accessMode ] )

+

The abstract operation TypedArraySpeciesCreate takes arguments exemplar (a TypedArray) and argumentList (a List of ECMAScript language values) and optional argument accessMode (read or write) and returns either a normal completion containing a TypedArray or a throw completion. It is used to specify the creation of a new TypedArray using a constructor function that is derived from exemplar. Unlike ArraySpeciesCreate, which can create non-Array objects through the use of %Symbol.species%, this operation enforces that the constructor function creates an actual TypedArray. It performs the following steps when called:

+
  1. If accessMode is not present, set accessMode to read.
  2. Let defaultConstructor be the intrinsic object associated with the constructor name exemplar.[[TypedArrayName]] in Table 73.
  3. Let constructor be ? SpeciesConstructor(exemplar, defaultConstructor).
  4. Let result be ? TypedArrayCreateFromConstructor(constructor, argumentList, accessMode).
  5. Assert: result has [[TypedArrayName]] and [[ContentType]] internal slots.
  6. Assert: result has all of the internal slots of a TypedArray instance (23.2.8).
  7. If result.[[ContentType]] is not exemplar.[[ContentType]], throw a TypeError exception.
  8. Return result.
+
+ + +

23.2.4.2 TypedArrayCreateFromConstructor ( constructor, argumentList [ , accessMode ] )

+

The abstract operation TypedArrayCreateFromConstructor takes arguments constructor (a constructor) and argumentList (a List of ECMAScript language values) and optional argument accessMode (read or write) and returns either a normal completion containing a TypedArray or a throw completion. It is used to specify the creation of a new TypedArray using a constructor function. It performs the following steps when called:

+
  1. If accessMode is not present, set accessMode to read.
  2. Let newTypedArray be ? Construct(constructor, argumentList).
  3. Let taRecord be ? ValidateTypedArray(newTypedArray, seq-cst, accessMode).
  4. If the number of elements in argumentList is 1 and argumentList[0] is a Number, then
    1. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    2. Let length be TypedArrayLength(taRecord).
    3. If length < (argumentList[0]), throw a TypeError exception.
  5. Return newTypedArray.
+
+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. The contents of an immutable ArrayBuffer's Data Block are constrained to be permanently stable, and may not be modified by either ECMAScript code or by other activities inside an implementation or observable by it. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion.

+ Editor's Note
The current name of parameter preserveResizability is preserved for the benefit of diff readability, but may be subject to change (to e.g. mode) before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  8. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  9. If preserveResizability is immutable, then
    1. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  10. Else,
    1. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
      1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
    2. Else,
      1. Let newMaxByteLength be empty.
    3. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
    4. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
    5. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
    6. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
    7. Let toBlock be newBuffer.[[ArrayBufferData]].
    8. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
    9. 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.
  11. Perform ! DetachArrayBuffer(arrayBuffer).
  12. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return 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) is false.
  2. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If key is not present, set key to undefined.
  4. If arrayBuffer.[[ArrayBufferDetachKey]] is not key, throw a TypeError exception.
  5. Set arrayBuffer.[[ArrayBufferData]] to null.
  6. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
  7. Return unused.
+ Note
+

Detaching an ArrayBuffer instance disassociates the Data Block used as its backing store from the instance and sets the byte length of the buffer to 0.

+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. Assert: IsImmutableBuffer(O) is false.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be max(final - first, 0).
  10. NOTE: Side-effects of the above steps may have detached or resized O.
  11. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  12. Let fromBuf be O.[[ArrayBufferData]].
  13. Let currentLen be O.[[ArrayBufferByteLength]].
  14. If currentLen < final, throw a RangeError exception.
  15. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  16. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot whose value is always undefined.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let getIndex be ? ToIndex(requestIndex).
  5. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  6. Otherwise, let numberValue be ? ToNumber(value).
  7. Set isLittleEndian to ToBoolean(isLittleEndian).
  8. Let viewOffset be view.[[ByteOffset]].
  9. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  10. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  11. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

Copyright & Software License

+ + +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/pr/58/index.html b/pr/58/index.html new file mode 100644 index 0000000..8467e8f --- /dev/null +++ b/pr/58/index.html @@ -0,0 +1,4409 @@ + + + + + +Immutable ArrayBuffers + +
+ PR #58 +

+ This document is a preview of merging PR #58, resulting in commit b7c2bbdcf328d99be1b6a5a7588df24e11888cb5. +

+

+ Do not reference it as authoritative in any way. + Instead, see https://github.com/tc39/proposal-immutable-arraybuffer for the living specification. +

+
+ +
+
    +
  • Toggle shortcuts help?
  • +
  • Toggle "can call user code" annotationsu
  • + +
  • Jump to search box/
  • +
  • Toggle pinning of the current clausep
  • +
  • Jump to the nth pin1-9
  • +
  • Jump to the 10th pin0
  • +
  • Jump to the most recent link target`
  • +

Proposal proposal-immutable-arraybuffer

Stage 2.7 Draft / September 17, 2025

Immutable ArrayBuffers

+ + +

6 ECMAScript Data Types and Values

+ + +

6.2.9 Data Blocks

+

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

+
+
+ + +

7 Operations on Objects

+ + + + +

7.1 ResolveBounds ( len, start, end )

+

The abstract operation ResolveBounds takes arguments len (an integer), start (an ECMAScript language value), and end (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion. It performs the following steps when called:

+
  1. Let relativeStart be ? ToIntegerOrInfinity(start).
  2. If relativeStart = -∞, let from be 0.
  3. Else if relativeStart < 0, let from be max(len + relativeStart, 0).
  4. Else, let from be min(relativeStart, len).
  5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  6. If relativeEnd = -∞, let to be 0.
  7. Else if relativeEnd < 0, let to be max(len + relativeEnd, 0).
  8. Else, let to be min(relativeEnd, len).
  9. Return the Record { [[From]]: from, [[To]]: to }.
+
+
+
+ + +

10 Ordinary and Exotic Objects Behaviours

+ + +

10.4 Built-in Exotic Object Internal Methods and Slots

+ + +

10.4.5 TypedArray Exotic Objects

+ + +

10.4.5.1 [[GetOwnProperty]] ( P )

+

The [[GetOwnProperty]] internal method of a TypedArray O takes argument P (a property key) and returns a normal completion containing either a Property Descriptor or undefined. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be TypedArrayGetElement(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Let mutable be true.
      4. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, set mutable to false.
      5. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true mutable, [[Enumerable]]: true, [[Configurable]]: true mutable }.
  2. Return OrdinaryGetOwnProperty(O, P).
+
+ + +

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

+

The [[DefineOwnProperty]] internal method of a TypedArray O takes arguments P (a property key) and Desc (a Property Descriptor) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, then
        1. Let current be ! O.[[GetOwnProperty]](P).
        2. Assert: current.[[Configurable]] and current.[[Writable]] are both false.
        3. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value.
        4. Return ValidateAndApplyPropertyDescriptor(O, P, false, Desc, current).
      3. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is false, return false.
      4. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is false, return false.
      5. If IsAccessorDescriptor(Desc) is true, return false.
      6. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, return false.
      7. If Desc has a [[Value]] field, perform ? TypedArraySetElement(O, numericIndex, Desc.[[Value]]).
      8. Return true.
  2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
+
+ + +

10.4.5.5 [[Set]] ( P, V, Receiver )

+

The [[Set]] internal method of a TypedArray O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

+
  1. If P is a String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable.
      2. If IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
      3. If SameValue(O, Receiver) is true, then
        1. Perform ? TypedArraySetElement(O, numericIndex, V).
        2. Return true.
      4. If IsValidIntegerIndex(O, numericIndex) is false, return true.
  2. Return ? OrdinarySet(O, P, V, Receiver).
+
+ + +

10.4.5.16 TypedArraySetElement ( O, index, value )

+

The abstract operation TypedArraySetElement takes arguments O (a TypedArray), index (a Number), and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

+
  1. Assert: IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is false.
  2. If O.[[ContentType]] is bigint, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let elementSize be TypedArrayElementSize(O).
    3. Let byteIndexInBuffer be ((index) × elementSize) + offset.
    4. Let elementType be TypedArrayElementType(O).
    5. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered).
  5. Return unused.
+ Note
+

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

+
+
+
+
+
+ + +

23 Indexed Collections

+ + +

23.2 TypedArray Objects

+ + +

23.2.2 Properties of the %TypedArray% Intrinsic Object

+

The %TypedArray% intrinsic object:

+
    +
  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • +
  • has a "name" property whose value is "TypedArray".
  • +
  • has the following properties:
  • +
+ + +

23.2.2.1 %TypedArray%.from ( source [ , mapper [ , thisArg ] ] )

+

This method performs the following steps when called:

+
  1. Let C be the this value.
  2. If IsConstructor(C) is false, throw a TypeError exception.
  3. If mapper is undefined, then
    1. Let mapping be false.
  4. Else,
    1. If IsCallable(mapper) is false, throw a TypeError exception.
    2. Let mapping be true.
  5. Let usingIterator be ? GetMethod(source, %Symbol.iterator%).
  6. If usingIterator is not undefined, then
    1. Let values be ? IteratorToList(? GetIteratorFromMethod(source, usingIterator)).
    2. Let len be the number of elements in values.
    3. Let targetObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
    4. Let k be 0.
    5. Repeat, while k < len,
      1. Let Pk be ! ToString(𝔽(k)).
      2. Let kValue be the first element of values.
      3. Remove the first element from values.
      4. If mapping is true, then
        1. Let mappedValue be ? Call(mapper, thisArg, « kValue, 𝔽(k) »).
      5. Else,
        1. Let mappedValue be kValue.
      6. Perform ? Set(targetObj, Pk, mappedValue, true).
      7. Set k to k + 1.
    6. Assert: values is now an empty List.
    7. Return targetObj.
  7. NOTE: source is not an iterable object, so assume it is already an array-like object.
  8. Let arrayLike be ! ToObject(source).
  9. Let len be ? LengthOfArrayLike(arrayLike).
  10. Let targetObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
  11. Let k be 0.
  12. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ? Get(arrayLike, Pk).
    3. If mapping is true, then
      1. Let mappedValue be ? Call(mapper, thisArg, « kValue, 𝔽(k) »).
    4. Else,
      1. Let mappedValue be kValue.
    5. Perform ? Set(targetObj, Pk, mappedValue, true).
    6. Set k to k + 1.
  13. Return targetObj.
+
+ + +

23.2.2.2 %TypedArray%.of ( ...items )

+

This method performs the following steps when called:

+
  1. Let len be the number of elements in items.
  2. Let C be the this value.
  3. If IsConstructor(C) is false, throw a TypeError exception.
  4. Let newObj be ? TypedArrayCreateFromConstructor(C, « 𝔽(len) », write).
  5. Let k be 0.
  6. Repeat, while k < len,
    1. Let kValue be items[k].
    2. Let Pk be ! ToString(𝔽(k)).
    3. Perform ? Set(newObj, Pk, kValue, true).
    4. Set k to k + 1.
  7. Return newObj.
+
+
+ + +

23.2.3 Properties of the %TypedArray% Prototype Object

+ + +

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.copyWithin as defined in 23.1.3.4.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let relativeTarget be ? ToIntegerOrInfinity(target).
  5. If relativeTarget = -∞, let targetIndex be 0.
  6. Else if relativeTarget < 0, let targetIndex be max(len + relativeTarget, 0).
  7. Else, let targetIndex be min(relativeTarget, len).
  8. Let relativeStart be ? ToIntegerOrInfinity(start).
  9. If relativeStart = -∞, let startIndex be 0.
  10. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  11. Else, let startIndex be min(relativeStart, len).
  12. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  13. If relativeEnd = -∞, let endIndex be 0.
  14. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  15. Else, let endIndex be min(relativeEnd, len).
  16. Let count be min(endIndex - startIndex, len - targetIndex).
  17. If count > 0, then
    1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data.
    2. Let buffer be O.[[ViewedArrayBuffer]].
    3. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    5. Set len to TypedArrayLength(taRecord).
    6. Let elementSize be TypedArrayElementSize(O).
    7. Let byteOffset be O.[[ByteOffset]].
    8. Let bufferByteLimit be (len × elementSize) + byteOffset.
    9. Let toByteIndex be (targetIndex × elementSize) + byteOffset.
    10. Let fromByteIndex be (startIndex × elementSize) + byteOffset.
    11. Let countBytes be count × elementSize.
    12. If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
      1. Let direction be -1.
      2. Set fromByteIndex to fromByteIndex + countBytes - 1.
      3. Set toByteIndex to toByteIndex + countBytes - 1.
    13. Else,
      1. Let direction be 1.
    14. Repeat, while countBytes > 0,
      1. If fromByteIndex < bufferByteLimit and toByteIndex < bufferByteLimit, then
        1. Let value be GetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered).
        3. Set fromByteIndex to fromByteIndex + direction.
        4. Set toByteIndex to toByteIndex + direction.
        5. Set countBytes to countBytes - 1.
      2. Else,
        1. Set countBytes to 0.
  18. Return O.
+
+ + +

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.fill as defined in 23.1.3.7.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. If O.[[ContentType]] is bigint, set value to ? ToBigInt(value).
  5. Otherwise, set value to ? ToNumber(value).
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let startIndex be 0.
  8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
  9. Else, let startIndex be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let endIndex be 0.
  12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
  13. Else, let endIndex be min(relativeEnd, len).
  14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
  15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  16. Set len to TypedArrayLength(taRecord).
  17. Set endIndex to min(endIndex, len).
  18. Let k be startIndex.
  19. Repeat, while k < endIndex,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Perform ! Set(O, Pk, value, true).
    3. Set k to k + 1.
  20. Return O.
+
+ + +

23.2.3.10 %TypedArray%.prototype.filter ( callback [ , thisArg ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.filter as defined in 23.1.3.8.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let len be TypedArrayLength(taRecord).
  4. If IsCallable(callback) is false, throw a TypeError exception.
  5. Let kept be a new empty List.
  6. Let captured be 0.
  7. Let k be 0.
  8. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ! Get(O, Pk).
    3. Let selected be ToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »)).
    4. If selected is true, then
      1. Append kValue to kept.
      2. Set captured to captured + 1.
    5. Set k to k + 1.
  9. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(captured) », write).
  10. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  11. Let n be 0.
  12. For each element e of kept, do
    1. Perform ! Set(A, ! ToString(𝔽(n)), e, true).
    2. Set n to n + 1.
  13. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.22 %TypedArray%.prototype.map ( callback [ , thisArg ] )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.map as defined in 23.1.3.21.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let len be TypedArrayLength(taRecord).
  4. If IsCallable(callback) is false, throw a TypeError exception.
  5. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(len) », write).
  6. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  7. Let k be 0.
  8. Repeat, while k < len,
    1. Let Pk be ! ToString(𝔽(k)).
    2. Let kValue be ! Get(O, Pk).
    3. Let mappedValue be ? Call(callback, thisArg, « kValue, 𝔽(k), O »).
    4. Perform ? Set(A, Pk, mappedValue, true).
    5. Set k to k + 1.
  9. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.25 %TypedArray%.prototype.reverse ( )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst, write).
  3. Let len be TypedArrayLength(taRecord).
  4. Let middle be floor(len / 2).
  5. Let lower be 0.
  6. Repeat, while lowermiddle,
    1. Let upper be len - lower - 1.
    2. Let upperP be ! ToString(𝔽(upper)).
    3. Let lowerP be ! ToString(𝔽(lower)).
    4. Let lowerValue be ! Get(O, lowerP).
    5. Let upperValue be ! Get(O, upperP).
    6. Perform ! Set(O, lowerP, upperValue, true).
    7. Perform ! Set(O, upperP, lowerValue, true).
    8. Set lower to lower + 1.
  7. Return O.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

+

This method sets multiple values in this TypedArray, reading the values from source. The details differ based upon the type of source. The optional offset value indicates the first element index in this TypedArray where values are written. If omitted, it is assumed to be 0.

+

It performs the following steps when called:

+
  1. Let target be the this value.
  2. NOTE: The following steps could be simplified by using ? ValidateTypedArray(target, seq-cst, write) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns true and offset is negative. Regardless, such a change is still worth pursuing if possible.
  3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
  4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
  5. If IsImmutableBuffer(target.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  6. Let targetOffset be ? ToIntegerOrInfinity(offset).
  7. If targetOffset < 0, throw a RangeError exception.
  8. If source is an Object that has a [[TypedArrayName]] internal slot, then
    1. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
  9. Else,
    1. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
  10. Return undefined.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.27 %TypedArray%.prototype.slice ( start, end )

+

The interpretation and use of the arguments of this method are the same as for Array.prototype.slice as defined in 23.1.3.28.

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
  3. Let srcArrayLength be TypedArrayLength(taRecord).
  4. Let relativeStart be ? ToIntegerOrInfinity(start).
  5. If relativeStart = -∞, let startIndex be 0.
  6. Else if relativeStart < 0, let startIndex be max(srcArrayLength + relativeStart, 0).
  7. Else, let startIndex be min(relativeStart, srcArrayLength).
  8. If end is undefined, let relativeEnd be srcArrayLength; else let relativeEnd be ? ToIntegerOrInfinity(end).
  9. If relativeEnd = -∞, let endIndex be 0.
  10. Else if relativeEnd < 0, let endIndex be max(srcArrayLength + relativeEnd, 0).
  11. Else, let endIndex be min(relativeEnd, srcArrayLength).
  12. Let countBytes be max(endIndex - startIndex, 0).
  13. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(countBytes) », write).
  14. Assert: IsImmutableBuffer(A.[[ViewedArrayBuffer]]) is false.
  15. If countBytes > 0, then
    1. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
    2. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    3. Set endIndex to min(endIndex, TypedArrayLength(taRecord)).
    4. Set countBytes to max(endIndex - startIndex, 0).
    5. Let srcType be TypedArrayElementType(O).
    6. Let targetType be TypedArrayElementType(A).
    7. If srcType is targetType, then
      1. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data.
      2. Let srcBuffer be O.[[ViewedArrayBuffer]].
      3. Let targetBuffer be A.[[ViewedArrayBuffer]].
      4. Let elementSize be TypedArrayElementSize(O).
      5. Let srcByteOffset be O.[[ByteOffset]].
      6. Let srcByteIndex be (startIndex × elementSize) + srcByteOffset.
      7. Let targetByteIndex be A.[[ByteOffset]].
      8. Let endByteIndex be targetByteIndex + (countBytes × elementSize).
      9. Repeat, while targetByteIndex < endByteIndex,
        1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered).
        2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered).
        3. Set srcByteIndex to srcByteIndex + 1.
        4. Set targetByteIndex to targetByteIndex + 1.
    8. Else,
      1. Let n be 0.
      2. Let k be startIndex.
      3. Repeat, while k < endIndex,
        1. Let Pk be ! ToString(𝔽(k)).
        2. Let kValue be ! Get(O, Pk).
        3. Perform ! Set(A, ! ToString(𝔽(n)), kValue, true).
        4. Set k to k + 1.
        5. Set n to n + 1.
  16. Return A.
+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+
+ + +

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

+

This is a distinct method that, except as described below, implements the same requirements as those of Array.prototype.sort as defined in 23.1.3.30. The implementation of this method may be optimized with the knowledge that the this value is an object that has a fixed length and whose integer-indexed properties are not sparse.

+

This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

+

It performs the following steps when called:

+
  1. If comparator is not undefined and IsCallable(comparator) is false, throw a TypeError exception.
  2. Let obj be the this value.
  3. Let taRecord be ? ValidateTypedArray(obj, seq-cst, write).
  4. Let len be TypedArrayLength(taRecord).
  5. NOTE: The following closure performs a numeric comparison rather than the string comparison used in 23.1.3.30.
  6. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparator and performs the following steps when called:
    1. Return ? CompareTypedArrayElements(x, y, comparator).
  7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
  8. Let j be 0.
  9. Repeat, while j < len,
    1. Perform ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
    2. Set j to j + 1.
  10. Return obj.
+ Note
+

Because NaN always compares greater than any other value (see CompareTypedArrayElements), NaN property values always sort to the end of the result when comparator is not provided.

+
+
+
+ + +

23.2.4 Abstract Operations for TypedArray Objects

+ + +

23.2.4.1 TypedArraySpeciesCreate ( exemplar, argumentList [ , accessMode ] )

+

The abstract operation TypedArraySpeciesCreate takes arguments exemplar (a TypedArray) and argumentList (a List of ECMAScript language values) and optional argument accessMode (read or write) and returns either a normal completion containing a TypedArray or a throw completion. It is used to specify the creation of a new TypedArray using a constructor function that is derived from exemplar. Unlike ArraySpeciesCreate, which can create non-Array objects through the use of %Symbol.species%, this operation enforces that the constructor function creates an actual TypedArray. It performs the following steps when called:

+
  1. If accessMode is not present, set accessMode to read.
  2. Let defaultConstructor be the intrinsic object associated with the constructor name exemplar.[[TypedArrayName]] in Table 73.
  3. Let constructor be ? SpeciesConstructor(exemplar, defaultConstructor).
  4. Let result be ? TypedArrayCreateFromConstructor(constructor, argumentList, accessMode).
  5. Assert: result has [[TypedArrayName]] and [[ContentType]] internal slots.
  6. Assert: result has all of the internal slots of a TypedArray instance (23.2.8).
  7. If result.[[ContentType]] is not exemplar.[[ContentType]], throw a TypeError exception.
  8. Return result.
+
+ + +

23.2.4.2 TypedArrayCreateFromConstructor ( constructor, argumentList [ , accessMode ] )

+

The abstract operation TypedArrayCreateFromConstructor takes arguments constructor (a constructor) and argumentList (a List of ECMAScript language values) and optional argument accessMode (read or write) and returns either a normal completion containing a TypedArray or a throw completion. It is used to specify the creation of a new TypedArray using a constructor function. It performs the following steps when called:

+
  1. If accessMode is not present, set accessMode to read.
  2. Let newTypedArray be ? Construct(constructor, argumentList).
  3. Let taRecord be ? ValidateTypedArray(newTypedArray, seq-cst, accessMode).
  4. If the number of elements in argumentList is 1 and argumentList[0] is a Number, then
    1. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
    2. Let length be TypedArrayLength(taRecord).
    3. If length < (argumentList[0]), throw a TypeError exception.
  5. Return newTypedArray.
+
+ + +

23.2.4.4 ValidateTypedArray ( O, order [ , accessMode ] )

+

The abstract operation ValidateTypedArray takes arguments O (an ECMAScript language value) and order (seq-cst or unordered) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. If accessMode is write and IsImmutableBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  5. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order).
  6. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  7. Return taRecord.
+
+
+
+
+ + +

25 Structured Data

+ + +

25.1 ArrayBuffer Objects

+ + +

25.1.3 Abstract Operations For ArrayBuffer Objects

+ + +

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 or either empty or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer.

+ Editor's Note
The current name and domain of parameter maxByteLength is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty an integer, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Else if maxByteLength is immutable, then
    1. Append [[ArrayBufferIsImmutable]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  6. Let block be ? CreateByteDataBlock(byteLength).
  7. Set obj.[[ArrayBufferData]] to block.
  8. Set obj.[[ArrayBufferByteLength]] to byteLength.
  9. 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.
  10. Return obj.
+
+ + + + +

25.1.3.2 AllocateImmutableArrayBuffer ( constructor, byteLength, fromBlock, fromIndex, count )

+

The abstract operation AllocateImmutableArrayBuffer takes arguments constructor (a constructor), byteLength (a non-negative integer), fromBlock (a Data Block), fromIndex (a non-negative integer), and count (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from fromBlock. The contents of an immutable ArrayBuffer's Data Block are constrained to be permanently stable, and may not be modified by either ECMAScript code or by other activities inside an implementation or observable by it. It performs the following steps when called:

+
  1. Assert: constructor is %ArrayBuffer%.
  2. Assert: countbyteLength.
  3. Let newBuffer be ? AllocateArrayBuffer(constructor, byteLength, immutable).
  4. Let toBlock be newBuffer.[[ArrayBufferData]].
  5. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer.
  6. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, fromIndex, count).
  7. Return newBuffer.
+ Note
+

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when fromBlock is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and count = byteLength.

+
+
+
+ + +

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, fixed-length, or immutable) and returns either a normal completion containing an ArrayBuffer or a throw completion.

+ Editor's Note
The current name of parameter preserveResizability is preserved for the benefit of diff readability, but may be subject to change (to e.g. mode) before acceptance into ECMA-262.
+

It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  7. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  8. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  9. If preserveResizability is immutable, then
    1. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newByteLength, arrayBuffer.[[ArrayBufferData]], 0, copyLength).
  10. Else,
    1. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
      1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
    2. Else,
      1. Let newMaxByteLength be empty.
    3. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
    4. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
    5. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
    6. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
    7. Let toBlock be newBuffer.[[ArrayBufferData]].
    8. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
    9. 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.
  11. Perform ! DetachArrayBuffer(arrayBuffer).
  12. Return newBuffer.
+
+ + + + +

25.1.3.4 IsImmutableBuffer ( arrayBuffer )

+

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

+
  1. If arrayBuffer has an [[ArrayBufferIsImmutable]] internal slot, return true.
  2. Return 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) is false.
  2. If IsImmutableBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If key is not present, set key to undefined.
  4. If arrayBuffer.[[ArrayBufferDetachKey]] is not key, throw a TypeError exception.
  5. Set arrayBuffer.[[ArrayBufferData]] to null.
  6. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
  7. Return unused.
+ Note
+

Detaching an ArrayBuffer instance disassociates the Data Block used as its backing store from the instance and sets the byte length of the buffer to 0.

+
+
+ + +

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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  7. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  10. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  11. Return 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) is false.
  2. Assert: IsImmutableBuffer(arrayBuffer) is false.
  3. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  4. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  5. Let block be arrayBuffer.[[ArrayBufferData]].
  6. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  9. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  11. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).
+
+
+ + +

25.1.6 Properties of the ArrayBuffer Prototype Object

+ + + + +

25.1.6.1 get ArrayBuffer.prototype.immutable

+

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

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Return IsImmutableBuffer(O).
+
+
+ + +

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. Assert: IsImmutableBuffer(O) is false.
  7. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  8. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  9. If hostHandled is handled, return undefined.
  10. Let oldBlock be O.[[ArrayBufferData]].
  11. Let newBlock be ? CreateByteDataBlock(newByteLength).
  12. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  13. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  15. Set O.[[ArrayBufferData]] to newBlock.
  16. Set O.[[ArrayBufferByteLength]] to newByteLength.
  17. Return undefined.
+
+ + +

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

+

This method performs the following steps when called:

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

25.1.6.8 ArrayBuffer.prototype.sliceToImmutable ( start, end )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let bounds be ? ResolveBounds(len, start, end).
  7. Let first be bounds.[[From]].
  8. Let final be bounds.[[To]].
  9. Let newLen be max(final - first, 0).
  10. NOTE: Side-effects of the above steps may have detached or resized O.
  11. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  12. Let fromBuf be O.[[ArrayBufferData]].
  13. Let currentLen be O.[[ArrayBufferByteLength]].
  14. If currentLen < final, throw a RangeError exception.
  15. Let newBuffer be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, newLen, fromBuf, first, newLen).
  16. Return newBuffer.
+
+
+ + + + +

25.1.6.9 ArrayBuffer.prototype.transferToImmutable ( [ newLength ] )

+

This method performs the following steps when called:

+
  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, immutable).
+
+
+
+ + +

25.1.7 Properties of ArrayBuffer Instances

+

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot whose value is always undefined.

+

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

+

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

+
+
+ + +

25.3 DataView Objects

+ + +

25.3.1 Abstract Operations For DataView Objects

+ + +

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. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

+
  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. If IsImmutableBuffer(view.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
  4. Let getIndex be ? ToIndex(requestIndex).
  5. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  6. Otherwise, let numberValue be ? ToNumber(value).
  7. Set isLittleEndian to ToBoolean(isLittleEndian).
  8. Let viewOffset be view.[[ByteOffset]].
  9. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  10. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  11. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  12. Let viewSize be GetViewByteLength(viewRecord).
  13. Let elementSize be the Element Size value specified in Table 73 for Element Type type.
  14. If getIndex + elementSize > viewSize, throw a RangeError exception.
  15. Let bufferIndex be getIndex + viewOffset.
  16. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  17. Return undefined.
+
+
+
+ + +

25.4 The Atomics Object

+ + +

25.4.3 Abstract Operations for Atomics

+ + +

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable [ , accessMode ] )

+

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and optional argument accessMode (read or write) 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. If accessMode is not present, set accessMode to read.
  2. Let taRecord be ? ValidateTypedArray(typedArray, unordered, accessMode).
  3. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  4. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  5. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  6. Return taRecord.
+
+ + +

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex [ , waitable [ , accessMode ] ] )

+

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and optional arguments waitable (a Boolean) and accessMode (read or write) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

+
  1. If waitable is not present, set waitable to false.
  2. If accessMode is not present, set accessMode to read.
  3. Let taRecord be ? ValidateIntegerTypedArray(typedArray, waitable, accessMode).
  4. Return ? ValidateAtomicAccess(taRecord, requestIndex).
+
+ + +

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 takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).
+
+
+ + +

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

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).
+
+ + +

25.4.11 Atomics.store ( typedArray, index, value )

+

This function performs the following steps when called:

+
  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index, false, write).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.
+
+
+
+

Copyright & Software License

+ + +

Software License

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+ +

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

+ +
    +
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. +
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
  6. +
+ +

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ +
+
\ No newline at end of file diff --git a/scripts/insert_warning.mjs b/scripts/insert_warning.mjs deleted file mode 100644 index d26d42b..0000000 --- a/scripts/insert_warning.mjs +++ /dev/null @@ -1,126 +0,0 @@ -import fs from 'node:fs'; -import pathlib from 'node:path'; -import { pipeline } from 'node:stream/promises'; -import { parseArgs } from 'node:util'; -import { JSDOM } from 'jsdom'; -import { RewritingStream } from 'parse5-html-rewriting-stream'; -import tmp from 'tmp'; - -const { positionals: cliArgs } = parseArgs({ - allowPositionals: true, - options: {}, -}); -if (cliArgs.length < 3) { - const self = pathlib.relative(process.cwd(), process.argv[1]); - console.error(`Usage: node ${self} ... - -{{identifier}} substrings in template.html are replaced from data.json, then -the result is inserted into each file.html.`); - process.exit(64); -} - -const main = async args => { - const [templateFile, dataFile, ...files] = args; - - // Substitute data into the template. - const template = fs.readFileSync(templateFile, 'utf8'); - const data = JSON.parse(fs.readFileSync(dataFile, 'utf8')); - const formatErrors = []; - const placeholderPatt = - /[{][{](?:([\p{ID_Start}$_][\p{ID_Continue}$]*)[}][}]|.*?(?:[}][}]|(?=[{][{])|$))/gsu; - const resolved = template.replaceAll(placeholderPatt, (m, name, i) => { - if (!name) { - const trunc = m.replace(/([^\n]{29}(?!$)|[^\n]{,29}(?=\n)).*/s, '$1…'); - formatErrors.push(SyntaxError(`bad placeholder at index ${i}: ${trunc}`)); - } else if (!Object.hasOwn(data, name)) { - formatErrors.push(ReferenceError(`no data for ${m}`)); - } - return data[name]; - }); - if (formatErrors.length > 0) throw AggregateError(formatErrors); - - // Parse the template into DOM nodes for appending to page head (metadata such - // as - -
- {{SUMMARY}} -

- This document is a preview of merging {{PR_LINK}}, resulting in {{COMMIT_LINK}}. -

-

- Do not reference it as authoritative in any way. - Instead, see {{REPO_LINK}} for the living specification. -

-
- diff --git a/spec.emu b/spec.emu deleted file mode 100644 index 1df0c2f..0000000 --- a/spec.emu +++ /dev/null @@ -1,1112 +0,0 @@ - - - - - - - - -

ECMAScript Data Types and Values

- - -

Data Blocks

-

A data block that resides in memory that can be referenced from multiple agents concurrently is designated a Shared Data Block. A Shared Data Block has an identity (for the purposes of equality testing Shared Data Block values) that is address-free: it is tied not to the virtual addresses the block is mapped to in any process, but to the set of locations in memory that the block represents. Two data blocks Shared Data Blocks are equal only if the sets of the locations they contain are equal; otherwise, they are not equal and the intersection of the sets of locations they contain is empty. Finally, Shared Data Blocks can be distinguished from Data Blocks.

-
-
- - -

Operations on Objects

- - - - -

- ResolveBounds ( - _len_: an integer, - _start_: an ECMAScript language value, - _end_: an ECMAScript language value, - ): either a normal completion containing a Record with fields [[From]] (a non-negative integer) and [[To]] (a non-negative integer) or a throw completion -

-
-
- - 1. Let _relativeStart_ be ? ToIntegerOrInfinity(_start_). - 1. If _relativeStart_ = -∞, let _from_ be 0. - 1. Else if _relativeStart_ < 0, let _from_ be max(_len_ + _relativeStart_, 0). - 1. Else, let _from_ be min(_relativeStart_, _len_). - 1. If _end_ is *undefined*, let _relativeEnd_ be _len_; else let _relativeEnd_ be ? ToIntegerOrInfinity(_end_). - 1. If _relativeEnd_ = -∞, let _to_ be 0. - 1. Else if _relativeEnd_ < 0, let _to_ be max(_len_ + _relativeEnd_, 0). - 1. Else, let _to_ be min(_relativeEnd_, _len_). - 1. Return the Record { [[From]]: _from_, [[To]]: _to_ }. - -
-
-
- - -

Ordinary and Exotic Objects Behaviours

- - -

Built-in Exotic Object Internal Methods and Slots

- - -

TypedArray Exotic Objects

- - -

- [[GetOwnProperty]] ( - _P_: a property key, - ): a normal completion containing either a Property Descriptor or *undefined* -

-
-
for
-
a TypedArray _O_
-
- - 1. If _P_ is a String, then - 1. Let _numericIndex_ be CanonicalNumericIndexString(_P_). - 1. If _numericIndex_ is not *undefined*, then - 1. Let _value_ be TypedArrayGetElement(_O_, _numericIndex_). - 1. If _value_ is *undefined*, return *undefined*. - 1. Let _mutable_ be *true*. - 1. If IsImmutableBuffer(_O_.[[ViewedArrayBuffer]]) is *true*, set _mutable_ to *false*. - 1. Return the PropertyDescriptor { [[Value]]: _value_, [[Writable]]: *true* _mutable_, [[Enumerable]]: *true*, [[Configurable]]: *true* _mutable_ }. - 1. Return OrdinaryGetOwnProperty(_O_, _P_). - -
- - -

- [[DefineOwnProperty]] ( - _P_: a property key, - _Desc_: a Property Descriptor, - ): either a normal completion containing a Boolean or a throw completion -

-
-
for
-
a TypedArray _O_
-
- - 1. If _P_ is a String, then - 1. Let _numericIndex_ be CanonicalNumericIndexString(_P_). - 1. If _numericIndex_ is not *undefined*, then - 1. If IsValidIntegerIndex(_O_, _numericIndex_) is *false*, return *false*. - 1. If IsImmutableBuffer(_O_.[[ViewedArrayBuffer]]) is *true*, then - 1. Let _current_ be ! _O_.[[GetOwnProperty]](_P_). - 1. Assert: _current_.[[Configurable]] and _current_.[[Writable]] are both *false*. - 1. NOTE: Attempting to redefine an immutable value always fails, even if the new value would be cast to the current value. - 1. Return ValidateAndApplyPropertyDescriptor(_O_, _P_, *false*, _Desc_, _current_). - 1. If _Desc_ has a [[Configurable]] field and _Desc_.[[Configurable]] is *false*, return *false*. - 1. If _Desc_ has an [[Enumerable]] field and _Desc_.[[Enumerable]] is *false*, return *false*. - 1. If IsAccessorDescriptor(_Desc_) is *true*, return *false*. - 1. If _Desc_ has a [[Writable]] field and _Desc_.[[Writable]] is *false*, return *false*. - 1. If _Desc_ has a [[Value]] field, perform ? TypedArraySetElement(_O_, _numericIndex_, _Desc_.[[Value]]). - 1. Return *true*. - 1. Return ! OrdinaryDefineOwnProperty(_O_, _P_, _Desc_). - -
- - -

- [[Set]] ( - _P_: a property key, - _V_: an ECMAScript language value, - _Receiver_: an ECMAScript language value, - ): either a normal completion containing a Boolean or a throw completion -

-
-
for
-
a TypedArray _O_
-
- - 1. If _P_ is a String, then - 1. Let _numericIndex_ be CanonicalNumericIndexString(_P_). - 1. If _numericIndex_ is not *undefined*, then - 1. NOTE: TypedArray instances restrict own and inherited canonical numeric string properties to integer indices valid for their backing buffers, but assignment failures for canonical numeric string properties are only reported when the buffer is immutable. - 1. If IsImmutableBuffer(_O_.[[ViewedArrayBuffer]]) is *true*, return *false*. - 1. If SameValue(_O_, _Receiver_) is *true*, then - 1. Perform ? TypedArraySetElement(_O_, _numericIndex_, _V_). - 1. Return *true*. - 1. If IsValidIntegerIndex(_O_, _numericIndex_) is *false*, return *true*. - 1. Return ? OrdinarySet(_O_, _P_, _V_, _Receiver_). - -
- - -

- TypedArraySetElement ( - _O_: a TypedArray, - _index_: a Number, - _value_: an ECMAScript language value, - ): either a normal completion containing ~unused~ or a throw completion -

-
-
- - 1. Assert: IsImmutableBuffer(_O_.[[ViewedArrayBuffer]]) is *false*. - 1. If _O_.[[ContentType]] is ~bigint~, let _numValue_ be ? ToBigInt(_value_). - 1. Otherwise, let _numValue_ be ? ToNumber(_value_). - 1. If IsValidIntegerIndex(_O_, _index_) is *true*, then - 1. Let _offset_ be _O_.[[ByteOffset]]. - 1. Let _elementSize_ be TypedArrayElementSize(_O_). - 1. Let _byteIndexInBuffer_ be (ℝ(_index_) × _elementSize_) + _offset_. - 1. Let _elementType_ be TypedArrayElementType(_O_). - 1. Perform SetValueInBuffer(_O_.[[ViewedArrayBuffer]], _byteIndexInBuffer_, _elementType_, _numValue_, *true*, ~unordered~). - 1. Return ~unused~. - - -

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

-
-
-
-
-
- - -

Indexed Collections

- - -

TypedArray Objects

- - -

Properties of the %TypedArray% Intrinsic Object

-

The %TypedArray% intrinsic object:

-
    -
  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • -
  • has a *"name"* property whose value is *"TypedArray"*.
  • -
  • has the following properties:
  • -
- - -

%TypedArray%.from ( _source_ [ , _mapper_ [ , _thisArg_ ] ] )

-

This method performs the following steps when called:

- - 1. Let _C_ be the *this* value. - 1. If IsConstructor(_C_) is *false*, throw a *TypeError* exception. - 1. If _mapper_ is *undefined*, then - 1. Let _mapping_ be *false*. - 1. Else, - 1. If IsCallable(_mapper_) is *false*, throw a *TypeError* exception. - 1. Let _mapping_ be *true*. - 1. Let _usingIterator_ be ? GetMethod(_source_, %Symbol.iterator%). - 1. If _usingIterator_ is not *undefined*, then - 1. Let _values_ be ? IteratorToList(? GetIteratorFromMethod(_source_, _usingIterator_)). - 1. Let _len_ be the number of elements in _values_. - 1. Let _targetObj_ be ? TypedArrayCreateFromConstructor(_C_, « 𝔽(_len_) », ~write~). - 1. Let _k_ be 0. - 1. Repeat, while _k_ < _len_, - 1. Let _Pk_ be ! ToString(𝔽(_k_)). - 1. Let _kValue_ be the first element of _values_. - 1. Remove the first element from _values_. - 1. If _mapping_ is *true*, then - 1. Let _mappedValue_ be ? Call(_mapper_, _thisArg_, « _kValue_, 𝔽(_k_) »). - 1. Else, - 1. Let _mappedValue_ be _kValue_. - 1. Perform ? Set(_targetObj_, _Pk_, _mappedValue_, *true*). - 1. Set _k_ to _k_ + 1. - 1. Assert: _values_ is now an empty List. - 1. Return _targetObj_. - 1. NOTE: _source_ is not an iterable object, so assume it is already an array-like object. - 1. Let _arrayLike_ be ! ToObject(_source_). - 1. Let _len_ be ? LengthOfArrayLike(_arrayLike_). - 1. Let _targetObj_ be ? TypedArrayCreateFromConstructor(_C_, « 𝔽(_len_) », ~write~). - 1. Let _k_ be 0. - 1. Repeat, while _k_ < _len_, - 1. Let _Pk_ be ! ToString(𝔽(_k_)). - 1. Let _kValue_ be ? Get(_arrayLike_, _Pk_). - 1. If _mapping_ is *true*, then - 1. Let _mappedValue_ be ? Call(_mapper_, _thisArg_, « _kValue_, 𝔽(_k_) »). - 1. Else, - 1. Let _mappedValue_ be _kValue_. - 1. Perform ? Set(_targetObj_, _Pk_, _mappedValue_, *true*). - 1. Set _k_ to _k_ + 1. - 1. Return _targetObj_. - -
- - -

%TypedArray%.of ( ..._items_ )

-

This method performs the following steps when called:

- - 1. Let _len_ be the number of elements in _items_. - 1. Let _C_ be the *this* value. - 1. If IsConstructor(_C_) is *false*, throw a *TypeError* exception. - 1. Let _newObj_ be ? TypedArrayCreateFromConstructor(_C_, « 𝔽(_len_) », ~write~). - 1. Let _k_ be 0. - 1. Repeat, while _k_ < _len_, - 1. Let _kValue_ be _items_[_k_]. - 1. Let _Pk_ be ! ToString(𝔽(_k_)). - 1. Perform ? Set(_newObj_, _Pk_, _kValue_, *true*). - 1. Set _k_ to _k_ + 1. - 1. Return _newObj_. - -
-
- - -

Properties of the %TypedArray% Prototype Object

- - -

%TypedArray%.prototype.copyWithin ( _target_, _start_ [ , _end_ ] )

-

The interpretation and use of the arguments of this method are the same as for `Array.prototype.copyWithin` as defined in .

-

This method performs the following steps when called:

- - 1. Let _O_ be the *this* value. - 1. Let _taRecord_ be ? ValidateTypedArray(_O_, ~seq-cst~, ~write~). - 1. Let _len_ be TypedArrayLength(_taRecord_). - 1. Let _relativeTarget_ be ? ToIntegerOrInfinity(_target_). - 1. If _relativeTarget_ = -∞, let _targetIndex_ be 0. - 1. Else if _relativeTarget_ < 0, let _targetIndex_ be max(_len_ + _relativeTarget_, 0). - 1. Else, let _targetIndex_ be min(_relativeTarget_, _len_). - 1. Let _relativeStart_ be ? ToIntegerOrInfinity(_start_). - 1. If _relativeStart_ = -∞, let _startIndex_ be 0. - 1. Else if _relativeStart_ < 0, let _startIndex_ be max(_len_ + _relativeStart_, 0). - 1. Else, let _startIndex_ be min(_relativeStart_, _len_). - 1. If _end_ is *undefined*, let _relativeEnd_ be _len_; else let _relativeEnd_ be ? ToIntegerOrInfinity(_end_). - 1. If _relativeEnd_ = -∞, let _endIndex_ be 0. - 1. Else if _relativeEnd_ < 0, let _endIndex_ be max(_len_ + _relativeEnd_, 0). - 1. Else, let _endIndex_ be min(_relativeEnd_, _len_). - 1. Let _count_ be min(_endIndex_ - _startIndex_, _len_ - _targetIndex_). - 1. If _count_ > 0, then - 1. NOTE: The copying must be performed in a manner that preserves the bit-level encoding of the source data. - 1. Let _buffer_ be _O_.[[ViewedArrayBuffer]]. - 1. Set _taRecord_ to MakeTypedArrayWithBufferWitnessRecord(_O_, ~seq-cst~). - 1. If IsTypedArrayOutOfBounds(_taRecord_) is *true*, throw a *TypeError* exception. - 1. Set _len_ to TypedArrayLength(_taRecord_). - 1. Let _elementSize_ be TypedArrayElementSize(_O_). - 1. Let _byteOffset_ be _O_.[[ByteOffset]]. - 1. Let _bufferByteLimit_ be (_len_ × _elementSize_) + _byteOffset_. - 1. Let _toByteIndex_ be (_targetIndex_ × _elementSize_) + _byteOffset_. - 1. Let _fromByteIndex_ be (_startIndex_ × _elementSize_) + _byteOffset_. - 1. Let _countBytes_ be _count_ × _elementSize_. - 1. If _fromByteIndex_ < _toByteIndex_ and _toByteIndex_ < _fromByteIndex_ + _countBytes_, then - 1. Let _direction_ be -1. - 1. Set _fromByteIndex_ to _fromByteIndex_ + _countBytes_ - 1. - 1. Set _toByteIndex_ to _toByteIndex_ + _countBytes_ - 1. - 1. Else, - 1. Let _direction_ be 1. - 1. Repeat, while _countBytes_ > 0, - 1. If _fromByteIndex_ < _bufferByteLimit_ and _toByteIndex_ < _bufferByteLimit_, then - 1. Let _value_ be GetValueFromBuffer(_buffer_, _fromByteIndex_, ~uint8~, *true*, ~unordered~). - 1. Perform SetValueInBuffer(_buffer_, _toByteIndex_, ~uint8~, _value_, *true*, ~unordered~). - 1. Set _fromByteIndex_ to _fromByteIndex_ + _direction_. - 1. Set _toByteIndex_ to _toByteIndex_ + _direction_. - 1. Set _countBytes_ to _countBytes_ - 1. - 1. Else, - 1. Set _countBytes_ to 0. - 1. Return _O_. - -
- - -

%TypedArray%.prototype.fill ( _value_ [ , _start_ [ , _end_ ] ] )

-

The interpretation and use of the arguments of this method are the same as for `Array.prototype.fill` as defined in .

-

This method performs the following steps when called:

- - 1. Let _O_ be the *this* value. - 1. Let _taRecord_ be ? ValidateTypedArray(_O_, ~seq-cst~, ~write~). - 1. Let _len_ be TypedArrayLength(_taRecord_). - 1. If _O_.[[ContentType]] is ~bigint~, set _value_ to ? ToBigInt(_value_). - 1. Otherwise, set _value_ to ? ToNumber(_value_). - 1. Let _relativeStart_ be ? ToIntegerOrInfinity(_start_). - 1. If _relativeStart_ = -∞, let _startIndex_ be 0. - 1. Else if _relativeStart_ < 0, let _startIndex_ be max(_len_ + _relativeStart_, 0). - 1. Else, let _startIndex_ be min(_relativeStart_, _len_). - 1. If _end_ is *undefined*, let _relativeEnd_ be _len_; else let _relativeEnd_ be ? ToIntegerOrInfinity(_end_). - 1. If _relativeEnd_ = -∞, let _endIndex_ be 0. - 1. Else if _relativeEnd_ < 0, let _endIndex_ be max(_len_ + _relativeEnd_, 0). - 1. Else, let _endIndex_ be min(_relativeEnd_, _len_). - 1. Set _taRecord_ to MakeTypedArrayWithBufferWitnessRecord(_O_, ~seq-cst~). - 1. If IsTypedArrayOutOfBounds(_taRecord_) is *true*, throw a *TypeError* exception. - 1. Set _len_ to TypedArrayLength(_taRecord_). - 1. Set _endIndex_ to min(_endIndex_, _len_). - 1. Let _k_ be _startIndex_. - 1. Repeat, while _k_ < _endIndex_, - 1. Let _Pk_ be ! ToString(𝔽(_k_)). - 1. Perform ! Set(_O_, _Pk_, _value_, *true*). - 1. Set _k_ to _k_ + 1. - 1. Return _O_. - -
- - -

%TypedArray%.prototype.filter ( _callback_ [ , _thisArg_ ] )

-

The interpretation and use of the arguments of this method are the same as for `Array.prototype.filter` as defined in .

-

This method performs the following steps when called:

- - 1. Let _O_ be the *this* value. - 1. Let _taRecord_ be ? ValidateTypedArray(_O_, ~seq-cst~). - 1. Let _len_ be TypedArrayLength(_taRecord_). - 1. If IsCallable(_callback_) is *false*, throw a *TypeError* exception. - 1. Let _kept_ be a new empty List. - 1. Let _captured_ be 0. - 1. Let _k_ be 0. - 1. Repeat, while _k_ < _len_, - 1. Let _Pk_ be ! ToString(𝔽(_k_)). - 1. Let _kValue_ be ! Get(_O_, _Pk_). - 1. Let _selected_ be ToBoolean(? Call(_callback_, _thisArg_, « _kValue_, 𝔽(_k_), _O_ »)). - 1. If _selected_ is *true*, then - 1. Append _kValue_ to _kept_. - 1. Set _captured_ to _captured_ + 1. - 1. Set _k_ to _k_ + 1. - 1. Let _A_ be ? TypedArraySpeciesCreate(_O_, « 𝔽(_captured_) », ~write~). - 1. Assert: IsImmutableBuffer(_A_.[[ViewedArrayBuffer]]) is *false*. - 1. Let _n_ be 0. - 1. For each element _e_ of _kept_, do - 1. Perform ! Set(_A_, ! ToString(𝔽(_n_)), _e_, *true*). - 1. Set _n_ to _n_ + 1. - 1. Return _A_. - -

This method is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.

-
- - -

%TypedArray%.prototype.map ( _callback_ [ , _thisArg_ ] )

-

The interpretation and use of the arguments of this method are the same as for `Array.prototype.map` as defined in .

-

This method performs the following steps when called:

- - 1. Let _O_ be the *this* value. - 1. Let _taRecord_ be ? ValidateTypedArray(_O_, ~seq-cst~). - 1. Let _len_ be TypedArrayLength(_taRecord_). - 1. If IsCallable(_callback_) is *false*, throw a *TypeError* exception. - 1. Let _A_ be ? TypedArraySpeciesCreate(_O_, « 𝔽(_len_) », ~write~). - 1. Assert: IsImmutableBuffer(_A_.[[ViewedArrayBuffer]]) is *false*. - 1. Let _k_ be 0. - 1. Repeat, while _k_ < _len_, - 1. Let _Pk_ be ! ToString(𝔽(_k_)). - 1. Let _kValue_ be ! Get(_O_, _Pk_). - 1. Let _mappedValue_ be ? Call(_callback_, _thisArg_, « _kValue_, 𝔽(_k_), _O_ »). - 1. Perform ? Set(_A_, _Pk_, _mappedValue_, *true*). - 1. Set _k_ to _k_ + 1. - 1. Return _A_. - -

This method is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.

-
- - -

%TypedArray%.prototype.reverse ( )

-

The interpretation and use of the arguments of this method are the same as for `Array.prototype.reverse` as defined in .

-

This method performs the following steps when called:

- - 1. Let _O_ be the *this* value. - 1. Let _taRecord_ be ? ValidateTypedArray(_O_, ~seq-cst~, ~write~). - 1. Let _len_ be TypedArrayLength(_taRecord_). - 1. Let _middle_ be floor(_len_ / 2). - 1. Let _lower_ be 0. - 1. Repeat, while _lower_ ≠ _middle_, - 1. Let _upper_ be _len_ - _lower_ - 1. - 1. Let _upperP_ be ! ToString(𝔽(_upper_)). - 1. Let _lowerP_ be ! ToString(𝔽(_lower_)). - 1. Let _lowerValue_ be ! Get(_O_, _lowerP_). - 1. Let _upperValue_ be ! Get(_O_, _upperP_). - 1. Perform ! Set(_O_, _lowerP_, _upperValue_, *true*). - 1. Perform ! Set(_O_, _upperP_, _lowerValue_, *true*). - 1. Set _lower_ to _lower_ + 1. - 1. Return _O_. - -

This method is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.

-
- - -

%TypedArray%.prototype.set ( _source_ [ , _offset_ ] )

-

This method sets multiple values in this _TypedArray_, reading the values from _source_. The details differ based upon the type of _source_. The optional _offset_ value indicates the first element index in this _TypedArray_ where values are written. If omitted, it is assumed to be 0.

-

It performs the following steps when called:

- - 1. Let _target_ be the *this* value. - 1. NOTE: The following steps could be simplified by using ? ValidateTypedArray(_target_, ~seq-cst~, ~write~) and refactoring SetTypedArrayFromTypedArray and SetTypedArrayFromArrayLike to accept the result as input, but that would observably change the calls into user code and thrown error when IsTypedArrayOutOfBounds returns *true* and _offset_ is negative. Regardless, such a change is still worth pursuing if possible. - 1. Perform ? RequireInternalSlot(_target_, [[TypedArrayName]]). - 1. Assert: _target_ has a [[ViewedArrayBuffer]] internal slot. - 1. If IsImmutableBuffer(_target_.[[ViewedArrayBuffer]]) is *true*, throw a *TypeError* exception. - 1. Let _targetOffset_ be ? ToIntegerOrInfinity(_offset_). - 1. If _targetOffset_ < 0, throw a *RangeError* exception. - 1. If _source_ is an Object that has a [[TypedArrayName]] internal slot, then - 1. Perform ? SetTypedArrayFromTypedArray(_target_, _targetOffset_, _source_). - 1. Else, - 1. Perform ? SetTypedArrayFromArrayLike(_target_, _targetOffset_, _source_). - 1. Return *undefined*. - -

This method is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.

-
- - -

%TypedArray%.prototype.slice ( _start_, _end_ )

-

The interpretation and use of the arguments of this method are the same as for `Array.prototype.slice` as defined in .

-

This method performs the following steps when called:

- - 1. Let _O_ be the *this* value. - 1. Let _taRecord_ be ? ValidateTypedArray(_O_, ~seq-cst~). - 1. Let _srcArrayLength_ be TypedArrayLength(_taRecord_). - 1. Let _relativeStart_ be ? ToIntegerOrInfinity(_start_). - 1. If _relativeStart_ = -∞, let _startIndex_ be 0. - 1. Else if _relativeStart_ < 0, let _startIndex_ be max(_srcArrayLength_ + _relativeStart_, 0). - 1. Else, let _startIndex_ be min(_relativeStart_, _srcArrayLength_). - 1. If _end_ is *undefined*, let _relativeEnd_ be _srcArrayLength_; else let _relativeEnd_ be ? ToIntegerOrInfinity(_end_). - 1. If _relativeEnd_ = -∞, let _endIndex_ be 0. - 1. Else if _relativeEnd_ < 0, let _endIndex_ be max(_srcArrayLength_ + _relativeEnd_, 0). - 1. Else, let _endIndex_ be min(_relativeEnd_, _srcArrayLength_). - 1. Let _countBytes_ be max(_endIndex_ - _startIndex_, 0). - 1. Let _A_ be ? TypedArraySpeciesCreate(_O_, « 𝔽(_countBytes_) », ~write~). - 1. Assert: IsImmutableBuffer(_A_.[[ViewedArrayBuffer]]) is *false*. - 1. If _countBytes_ > 0, then - 1. Set _taRecord_ to MakeTypedArrayWithBufferWitnessRecord(_O_, ~seq-cst~). - 1. If IsTypedArrayOutOfBounds(_taRecord_) is *true*, throw a *TypeError* exception. - 1. Set _endIndex_ to min(_endIndex_, TypedArrayLength(_taRecord_)). - 1. Set _countBytes_ to max(_endIndex_ - _startIndex_, 0). - 1. Let _srcType_ be TypedArrayElementType(_O_). - 1. Let _targetType_ be TypedArrayElementType(_A_). - 1. If _srcType_ is _targetType_, then - 1. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data. - 1. Let _srcBuffer_ be _O_.[[ViewedArrayBuffer]]. - 1. Let _targetBuffer_ be _A_.[[ViewedArrayBuffer]]. - 1. Let _elementSize_ be TypedArrayElementSize(_O_). - 1. Let _srcByteOffset_ be _O_.[[ByteOffset]]. - 1. Let _srcByteIndex_ be (_startIndex_ × _elementSize_) + _srcByteOffset_. - 1. Let _targetByteIndex_ be _A_.[[ByteOffset]]. - 1. Let _endByteIndex_ be _targetByteIndex_ + (_countBytes_ × _elementSize_). - 1. Repeat, while _targetByteIndex_ < _endByteIndex_, - 1. Let _value_ be GetValueFromBuffer(_srcBuffer_, _srcByteIndex_, ~uint8~, *true*, ~unordered~). - 1. Perform SetValueInBuffer(_targetBuffer_, _targetByteIndex_, ~uint8~, _value_, *true*, ~unordered~). - 1. Set _srcByteIndex_ to _srcByteIndex_ + 1. - 1. Set _targetByteIndex_ to _targetByteIndex_ + 1. - 1. Else, - 1. Let _n_ be 0. - 1. Let _k_ be _startIndex_. - 1. Repeat, while _k_ < _endIndex_, - 1. Let _Pk_ be ! ToString(𝔽(_k_)). - 1. Let _kValue_ be ! Get(_O_, _Pk_). - 1. Perform ! Set(_A_, ! ToString(𝔽(_n_)), _kValue_, *true*). - 1. Set _k_ to _k_ + 1. - 1. Set _n_ to _n_ + 1. - 1. Return _A_. - -

This method is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.

-
- - -

%TypedArray%.prototype.sort ( _comparator_ )

-

This is a distinct method that, except as described below, implements the same requirements as those of `Array.prototype.sort` as defined in . The implementation of this method may be optimized with the knowledge that the *this* value is an object that has a fixed length and whose integer-indexed properties are not sparse.

-

This method is not generic. The *this* value must be an object with a [[TypedArrayName]] internal slot.

-

It performs the following steps when called:

- - 1. If _comparator_ is not *undefined* and IsCallable(_comparator_) is *false*, throw a *TypeError* exception. - 1. Let _obj_ be the *this* value. - 1. Let _taRecord_ be ? ValidateTypedArray(_obj_, ~seq-cst~, ~write~). - 1. Let _len_ be TypedArrayLength(_taRecord_). - 1. NOTE: The following closure performs a numeric comparison rather than the string comparison used in . - 1. Let _SortCompare_ be a new Abstract Closure with parameters (_x_, _y_) that captures _comparator_ and performs the following steps when called: - 1. Return ? CompareTypedArrayElements(_x_, _y_, _comparator_). - 1. Let _sortedList_ be ? SortIndexedProperties(_obj_, _len_, _SortCompare_, ~read-through-holes~). - 1. Let _j_ be 0. - 1. Repeat, while _j_ < _len_, - 1. Perform ! Set(_obj_, ! ToString(𝔽(_j_)), _sortedList_[_j_], *true*). - 1. Set _j_ to _j_ + 1. - 1. Return _obj_. - - -

Because *NaN* always compares greater than any other value (see CompareTypedArrayElements), *NaN* property values always sort to the end of the result when _comparator_ is not provided.

-
-
-
- - -

Abstract Operations for TypedArray Objects

- - -

- TypedArraySpeciesCreate ( - _exemplar_: a TypedArray, - _argumentList_: a List of ECMAScript language values, - optional _accessMode_: ~read~ or ~write~, - ): either a normal completion containing a TypedArray or a throw completion -

-
-
description
-
It is used to specify the creation of a new TypedArray using a constructor function that is derived from _exemplar_. Unlike ArraySpeciesCreate, which can create non-Array objects through the use of %Symbol.species%, this operation enforces that the constructor function creates an actual TypedArray.
-
- - 1. If _accessMode_ is not present, set _accessMode_ to ~read~. - 1. Let _defaultConstructor_ be the intrinsic object associated with the constructor name _exemplar_.[[TypedArrayName]] in . - 1. Let _constructor_ be ? SpeciesConstructor(_exemplar_, _defaultConstructor_). - 1. Let _result_ be ? TypedArrayCreateFromConstructor(_constructor_, _argumentList_, _accessMode_). - 1. Assert: _result_ has [[TypedArrayName]] and [[ContentType]] internal slots. - 1. Assert: _result_ has all of the internal slots of a TypedArray instance (). - 1. If _result_.[[ContentType]] is not _exemplar_.[[ContentType]], throw a *TypeError* exception. - 1. Return _result_. - -
- - -

- TypedArrayCreateFromConstructor ( - _constructor_: a constructor, - _argumentList_: a List of ECMAScript language values, - optional _accessMode_: ~read~ or ~write~, - ): either a normal completion containing a TypedArray or a throw completion -

-
-
description
-
It is used to specify the creation of a new TypedArray using a constructor function.
-
- - 1. If _accessMode_ is not present, set _accessMode_ to ~read~. - 1. Let _newTypedArray_ be ? Construct(_constructor_, _argumentList_). - 1. Let _taRecord_ be ? ValidateTypedArray(_newTypedArray_, ~seq-cst~, _accessMode_). - 1. If the number of elements in _argumentList_ is 1 and _argumentList_[0] is a Number, then - 1. If IsTypedArrayOutOfBounds(_taRecord_) is *true*, throw a *TypeError* exception. - 1. Let _length_ be TypedArrayLength(_taRecord_). - 1. If _length_ < ℝ(_argumentList_[0]), throw a *TypeError* exception. - 1. Return _newTypedArray_. - -
- - -

- ValidateTypedArray ( - _O_: an ECMAScript language value, - _order_: ~seq-cst~ or ~unordered~, - optional _accessMode_: ~read~ or ~write~, - ): either a normal completion containing a TypedArray With Buffer Witness Record or a throw completion -

-
-
- - 1. If _accessMode_ is not present, set _accessMode_ to ~read~. - 1. Perform ? RequireInternalSlot(_O_, [[TypedArrayName]]). - 1. Assert: _O_ has a [[ViewedArrayBuffer]] internal slot. - 1. If _accessMode_ is ~write~ and IsImmutableBuffer(_O_.[[ViewedArrayBuffer]]) is *true*, throw a *TypeError* exception. - 1. Let _taRecord_ be MakeTypedArrayWithBufferWitnessRecord(_O_, _order_). - 1. If IsTypedArrayOutOfBounds(_taRecord_) is *true*, throw a *TypeError* exception. - 1. Return _taRecord_. - -
-
-
-
- - -

Structured Data

- - -

ArrayBuffer Objects

- - -

Abstract Operations For ArrayBuffer Objects

- - -

- AllocateArrayBuffer ( - _constructor_: a constructor, - _byteLength_: a non-negative integer, - optional _maxByteLength_: a non-negative integer, or ~empty~ or either ~empty~ or ~immutable~, - ): either a normal completion containing an ArrayBuffer or a throw completion -

-
-
description
-
It is used to create an ArrayBuffer.
-
- The current name and domain of parameter _maxByteLength_ is preserved for the benefit of diff readability, but both may be subject to change before acceptance into ECMA-262. - - 1. Let _slots_ be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ». - 1. If _maxByteLength_ is present and _maxByteLength_ is not ~empty~ an integer, let _allocatingResizableBuffer_ be *true*; otherwise let _allocatingResizableBuffer_ be *false*. - 1. If _allocatingResizableBuffer_ is *true*, then - 1. If _byteLength_ > _maxByteLength_, throw a *RangeError* exception. - 1. Append [[ArrayBufferMaxByteLength]] to _slots_. - 1. Else if _maxByteLength_ is ~immutable~, then - 1. Append [[ArrayBufferIsImmutable]] to _slots_. - 1. Let _obj_ be ? OrdinaryCreateFromConstructor(_constructor_, *"%ArrayBuffer.prototype%"*, _slots_). - 1. Let _block_ be ? CreateByteDataBlock(_byteLength_). - 1. Set _obj_.[[ArrayBufferData]] to _block_. - 1. Set _obj_.[[ArrayBufferByteLength]] to _byteLength_. - 1. 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. - 1. 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. - 1. Set _obj_.[[ArrayBufferMaxByteLength]] to _maxByteLength_. - 1. Return _obj_. - -
- - - - -

- AllocateImmutableArrayBuffer ( - _constructor_: a constructor, - _byteLength_: a non-negative integer, - _fromBlock_: a Data Block, - _fromIndex_: a non-negative integer, - _count_: a non-negative integer, - ): either a normal completion containing an ArrayBuffer or a throw completion -

-
-
description
-
It is used to create an immutable ArrayBuffer (i.e., an ArrayBuffer with a an [[ArrayBufferIsImmutable]] slot) with contents from _fromBlock_. The contents of an immutable ArrayBuffer's Data Block are constrained to be permanently stable, and may not be modified by either ECMAScript code or by other activities inside an implementation or observable by it.
-
- - 1. Assert: _constructor_ is %ArrayBuffer%. - 1. Assert: _count_ ≤ _byteLength_. - 1. Let _newBuffer_ be ? AllocateArrayBuffer(_constructor_, _byteLength_, ~immutable~). - 1. Let _toBlock_ be _newBuffer_.[[ArrayBufferData]]. - 1. NOTE: This is the only step that can write into the Data Block of an immutable ArrayBuffer. - 1. Perform CopyDataBlockBytes(_toBlock_, 0, _fromBlock_, _fromIndex_, _count_). - 1. Return _newBuffer_. - - -

Because neither the identity of a Data Block nor the set of locations in memory represented by it are observable, implementations may implement this operation without allocating new memory locations when _fromBlock_ is the value of the [[ArrayBufferData]] slot for some other immutable ArrayBuffer (and therefore already immutable) and _count_ = _byteLength_.

-
-
-
- - -

- ArrayBufferCopyAndDetach ( - _arrayBuffer_: an ECMAScript language value, - _newLength_: an ECMAScript language value, - _preserveResizability_: ~preserve-resizability~, ~fixed-length~, or ~immutable~, - ): either a normal completion containing an ArrayBuffer or a throw completion -

-
-
- The current name of parameter _preserveResizability_ is preserved for the benefit of diff readability, but may be subject to change (to e.g. _mode_) before acceptance into ECMA-262. - - 1. Perform ? RequireInternalSlot(_arrayBuffer_, [[ArrayBufferData]]). - 1. If IsSharedArrayBuffer(_arrayBuffer_) is *true*, throw a *TypeError* exception. - 1. If _newLength_ is *undefined*, then - 1. Let _newByteLength_ be _arrayBuffer_.[[ArrayBufferByteLength]]. - 1. Else, - 1. Let _newByteLength_ be ? ToIndex(_newLength_). - 1. If IsDetachedBuffer(_arrayBuffer_) is *true*, throw a *TypeError* exception. - 1. If IsImmutableBuffer(_arrayBuffer_) is *true*, throw a *TypeError* exception. - 1. If _arrayBuffer_.[[ArrayBufferDetachKey]] is not *undefined*, throw a *TypeError* exception. - 1. Let _copyLength_ be min(_newByteLength_, _arrayBuffer_.[[ArrayBufferByteLength]]). - 1. If _preserveResizability_ is ~immutable~, then - 1. Let _newBuffer_ be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, _newByteLength_, _arrayBuffer_.[[ArrayBufferData]], 0, _copyLength_). - 1. Else, - 1. If _preserveResizability_ is ~preserve-resizability~ and IsFixedLengthArrayBuffer(_arrayBuffer_) is *false*, then - 1. Let _newMaxByteLength_ be _arrayBuffer_.[[ArrayBufferMaxByteLength]]. - 1. Else, - 1. Let _newMaxByteLength_ be ~empty~. - 1. If _arrayBuffer_.[[ArrayBufferDetachKey]] is not *undefined*, throw a *TypeError* exception. - 1. Let _newBuffer_ be ? AllocateArrayBuffer(%ArrayBuffer%, _newByteLength_, _newMaxByteLength_). - 1. Let _copyLength_ be min(_newByteLength_, _arrayBuffer_.[[ArrayBufferByteLength]]). - 1. Let _fromBlock_ be _arrayBuffer_.[[ArrayBufferData]]. - 1. Let _toBlock_ be _newBuffer_.[[ArrayBufferData]]. - 1. Perform CopyDataBlockBytes(_toBlock_, 0, _fromBlock_, 0, _copyLength_). - 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`. - 1. Perform ! DetachArrayBuffer(_arrayBuffer_). - 1. Return _newBuffer_. - -
- - - - -

- IsImmutableBuffer ( - _arrayBuffer_: an ArrayBuffer or a SharedArrayBuffer, - ): a Boolean -

-
-
- - 1. If _arrayBuffer_ has an [[ArrayBufferIsImmutable]] internal slot, return *true*. - 1. Return *false*. - -
-
- - -

- DetachArrayBuffer ( - _arrayBuffer_: an ArrayBuffer, - optional _key_: anything, - ): either a normal completion containing ~unused~ or a throw completion -

-
-
skip global checks
-
true
-
- - 1. Assert: IsSharedArrayBuffer(_arrayBuffer_) is *false*. - 1. If IsImmutableBuffer(_arrayBuffer_) is *true*, throw a *TypeError* exception. - 1. If _key_ is not present, set _key_ to *undefined*. - 1. If _arrayBuffer_.[[ArrayBufferDetachKey]] is not _key_, throw a *TypeError* exception. - 1. Set _arrayBuffer_.[[ArrayBufferData]] to *null*. - 1. Set _arrayBuffer_.[[ArrayBufferByteLength]] to 0. - 1. Return ~unused~. - - -

Detaching an ArrayBuffer instance disassociates the Data Block used as its backing store from the instance and sets the byte length of the buffer to 0.

-
-
- - -

- SetValueInBuffer ( - _arrayBuffer_: an ArrayBuffer or SharedArrayBuffer, - _byteIndex_: a non-negative integer, - _type_: a TypedArray element type, - _value_: a Number or a BigInt, - _isTypedArray_: a Boolean, - _order_: ~seq-cst~, ~unordered~, or ~init~, - optional _isLittleEndian_: a Boolean, - ): ~unused~ -

-
-
- - 1. Assert: IsDetachedBuffer(_arrayBuffer_) is *false*. - 1. Assert: IsImmutableBuffer(_arrayBuffer_) is *false*. - 1. Assert: There are sufficient bytes in _arrayBuffer_ starting at _byteIndex_ to represent a value of _type_. - 1. Assert: _value_ is a BigInt if IsBigIntElementType(_type_) is *true*; otherwise, _value_ is a Number. - 1. Let _block_ be _arrayBuffer_.[[ArrayBufferData]]. - 1. Let _elementSize_ be the Element Size value specified in for Element Type _type_. - 1. If _isLittleEndian_ is not present, set _isLittleEndian_ to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record. - 1. Let _rawBytes_ be NumericToRawBytes(_type_, _value_, _isLittleEndian_). - 1. If IsSharedArrayBuffer(_arrayBuffer_) is *true*, then - 1. Let _execution_ be the [[CandidateExecution]] field of the surrounding agent's Agent Record. - 1. Let _eventsRecord_ be the Agent Events Record of _execution_.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier(). - 1. If _isTypedArray_ is *true* and IsNoTearConfiguration(_type_, _order_) is *true*, let _noTear_ be *true*; otherwise let _noTear_ be *false*. - 1. Append WriteSharedMemory { [[Order]]: _order_, [[NoTear]]: _noTear_, [[Block]]: _block_, [[ByteIndex]]: _byteIndex_, [[ElementSize]]: _elementSize_, [[Payload]]: _rawBytes_ } to _eventsRecord_.[[EventList]]. - 1. Else, - 1. Store the individual bytes of _rawBytes_ into _block_, starting at _block_[_byteIndex_]. - 1. Return ~unused~. - -
- - -

- GetModifySetValueInBuffer ( - _arrayBuffer_: an ArrayBuffer or a SharedArrayBuffer, - _byteIndex_: a non-negative integer, - _type_: a TypedArray element type, - _value_: a Number or a BigInt, - _op_: a read-modify-write modification function, - ): a Number or a BigInt -

-
-
- - 1. Assert: IsDetachedBuffer(_arrayBuffer_) is *false*. - 1. Assert: IsImmutableBuffer(_arrayBuffer_) is *false*. - 1. Assert: There are sufficient bytes in _arrayBuffer_ starting at _byteIndex_ to represent a value of _type_. - 1. Assert: _value_ is a BigInt if IsBigIntElementType(_type_) is *true*; otherwise, _value_ is a Number. - 1. Let _block_ be _arrayBuffer_.[[ArrayBufferData]]. - 1. Let _elementSize_ be the Element Size value specified in for Element Type _type_. - 1. Let _isLittleEndian_ be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record. - 1. Let _rawBytes_ be NumericToRawBytes(_type_, _value_, _isLittleEndian_). - 1. If IsSharedArrayBuffer(_arrayBuffer_) is *true*, then - 1. Let _execution_ be the [[CandidateExecution]] field of the surrounding agent's Agent Record. - 1. Let _eventsRecord_ be the Agent Events Record of _execution_.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier(). - 1. Let _rawBytesRead_ be a List of length _elementSize_ whose elements are nondeterministically chosen byte values. - 1. NOTE: In implementations, _rawBytesRead_ is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency. - 1. Let _rmwEvent_ be ReadModifyWriteSharedMemory { [[Order]]: ~seq-cst~, [[NoTear]]: *true*, [[Block]]: _block_, [[ByteIndex]]: _byteIndex_, [[ElementSize]]: _elementSize_, [[Payload]]: _rawBytes_, [[ModifyOp]]: _op_ }. - 1. Append _rmwEvent_ to _eventsRecord_.[[EventList]]. - 1. Append Chosen Value Record { [[Event]]: _rmwEvent_, [[ChosenValue]]: _rawBytesRead_ } to _execution_.[[ChosenValues]]. - 1. Else, - 1. Let _rawBytesRead_ be a List of length _elementSize_ whose elements are the sequence of _elementSize_ bytes starting with _block_[_byteIndex_]. - 1. Let _rawBytesModified_ be _op_(_rawBytesRead_, _rawBytes_). - 1. Store the individual bytes of _rawBytesModified_ into _block_, starting at _block_[_byteIndex_]. - 1. Return RawBytesToNumeric(_type_, _rawBytesRead_, _isLittleEndian_). - -
-
- - -

Properties of the ArrayBuffer Prototype Object

- - - - -

get ArrayBuffer.prototype.immutable

-

`ArrayBuffer.prototype.immutable` is an accessor property whose set accessor function is *undefined*. Its get accessor function performs the following steps when called:

- - 1. Let _O_ be the *this* value. - 1. Perform ? RequireInternalSlot(_O_, [[ArrayBufferData]]). - 1. If IsSharedArrayBuffer(_O_) is *true*, throw a *TypeError* exception. - 1. Return IsImmutableBuffer(_O_). - -
-
- - -

ArrayBuffer.prototype.resize ( _newLength_ )

-

This method performs the following steps when called:

- - 1. Let _O_ be the *this* value. - 1. Perform ? RequireInternalSlot(_O_, [[ArrayBufferMaxByteLength]]). - 1. If IsSharedArrayBuffer(_O_) is *true*, throw a *TypeError* exception. - 1. Let _newByteLength_ be ? ToIndex(_newLength_). - 1. If IsDetachedBuffer(_O_) is *true*, throw a *TypeError* exception. - 1. Assert: IsImmutableBuffer(_O_) is *false*. - 1. If _newByteLength_ > _O_.[[ArrayBufferMaxByteLength]], throw a *RangeError* exception. - 1. Let _hostHandled_ be ? HostResizeArrayBuffer(_O_, _newByteLength_). - 1. If _hostHandled_ is ~handled~, return *undefined*. - 1. Let _oldBlock_ be _O_.[[ArrayBufferData]]. - 1. Let _newBlock_ be ? CreateByteDataBlock(_newByteLength_). - 1. Let _copyLength_ be min(_newByteLength_, _O_.[[ArrayBufferByteLength]]). - 1. Perform CopyDataBlockBytes(_newBlock_, 0, _oldBlock_, 0, _copyLength_). - 1. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage. - 1. Set _O_.[[ArrayBufferData]] to _newBlock_. - 1. Set _O_.[[ArrayBufferByteLength]] to _newByteLength_. - 1. Return *undefined*. - -
- - -

ArrayBuffer.prototype.slice ( _start_, _end_ )

-

This method performs the following steps when called:

- - 1. Let _O_ be the *this* value. - 1. Perform ? RequireInternalSlot(_O_, [[ArrayBufferData]]). - 1. If IsSharedArrayBuffer(_O_) is *true*, throw a *TypeError* exception. - 1. If IsDetachedBuffer(_O_) is *true*, throw a *TypeError* exception. - 1. Let _len_ be _O_.[[ArrayBufferByteLength]]. - 1. Let _relativeStart_ be ? ToIntegerOrInfinity(_start_). - 1. If _relativeStart_ = -∞, let _first_ be 0. - 1. Else if _relativeStart_ < 0, let _first_ be max(_len_ + _relativeStart_, 0). - 1. Else, let _first_ be min(_relativeStart_, _len_). - 1. If _end_ is *undefined*, let _relativeEnd_ be _len_; else let _relativeEnd_ be ? ToIntegerOrInfinity(_end_). - 1. If _relativeEnd_ = -∞, let _final_ be 0. - 1. Else if _relativeEnd_ < 0, let _final_ be max(_len_ + _relativeEnd_, 0). - 1. Else, let _final_ be min(_relativeEnd_, _len_). - 1. Let _bounds_ be ? ResolveBounds(_len_, _start_, _end_). - 1. Let _first_ be _bounds_.[[From]]. - 1. Let _final_ be _bounds_.[[To]]. - 1. Let _newLen_ be max(_final_ - _first_, 0). - 1. Let _ctor_ be ? SpeciesConstructor(_O_, %ArrayBuffer%). - 1. Let _new_ be ? Construct(_ctor_, « 𝔽(_newLen_) »). - 1. Perform ? RequireInternalSlot(_new_, [[ArrayBufferData]]). - 1. If IsSharedArrayBuffer(_new_) is *true*, throw a *TypeError* exception. - 1. If IsDetachedBuffer(_new_) is *true*, throw a *TypeError* exception. - 1. If IsImmutableBuffer(_new_) is *true*, throw a *TypeError* exception. - 1. If SameValue(_new_, _O_) is *true*, throw a *TypeError* exception. - 1. If _new_.[[ArrayBufferByteLength]] < _newLen_, throw a *TypeError* exception. - 1. NOTE: Side-effects of the above steps may have detached or resized _O_. - 1. If IsDetachedBuffer(_O_) is *true*, throw a *TypeError* exception. - 1. Let _fromBuf_ be _O_.[[ArrayBufferData]]. - 1. Let _toBuf_ be _new_.[[ArrayBufferData]]. - 1. Let _currentLen_ be _O_.[[ArrayBufferByteLength]]. - 1. If _first_ < _currentLen_, then - 1. Let _count_ be min(_newLen_, _currentLen_ - _first_). - 1. Perform CopyDataBlockBytes(_toBuf_, 0, _fromBuf_, _first_, _count_). - 1. Return _new_. - -
- - - - -

ArrayBuffer.prototype.sliceToImmutable ( _start_, _end_ )

-

This method performs the following steps when called:

- - 1. Let _O_ be the *this* value. - 1. Perform ? RequireInternalSlot(_O_, [[ArrayBufferData]]). - 1. If IsSharedArrayBuffer(_O_) is *true*, throw a *TypeError* exception. - 1. If IsDetachedBuffer(_O_) is *true*, throw a *TypeError* exception. - 1. Let _len_ be _O_.[[ArrayBufferByteLength]]. - 1. Let _bounds_ be ? ResolveBounds(_len_, _start_, _end_). - 1. Let _first_ be _bounds_.[[From]]. - 1. Let _final_ be _bounds_.[[To]]. - 1. Let _newLen_ be max(_final_ - _first_, 0). - 1. NOTE: Side-effects of the above steps may have detached or resized _O_. - 1. If IsDetachedBuffer(_O_) is *true*, throw a *TypeError* exception. - 1. Let _fromBuf_ be _O_.[[ArrayBufferData]]. - 1. Let _currentLen_ be _O_.[[ArrayBufferByteLength]]. - 1. If _currentLen_ < _final_, throw a *RangeError* exception. - 1. Let _newBuffer_ be ? AllocateImmutableArrayBuffer(%ArrayBuffer%, _newLen_, _fromBuf_, _first_, _newLen_). - 1. Return _newBuffer_. - -
-
- - - - -

ArrayBuffer.prototype.transferToImmutable ( [ _newLength_ ] )

-

This method performs the following steps when called:

- - 1. Let _O_ be the *this* value. - 1. Return ? ArrayBufferCopyAndDetach(_O_, _newLength_, ~immutable~). - -
-
-
- - -

Properties of ArrayBuffer Instances

-

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot, and ArrayBuffer instances which are immutable each have an [[ArrayBufferIsImmutable]] internal slot whose value is always *undefined*.

-

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

-

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

-
-
- - -

DataView Objects

- - -

Abstract Operations For DataView Objects

- - -

- SetViewValue ( - _view_: an ECMAScript language value, - _requestIndex_: an ECMAScript language value, - _isLittleEndian_: an ECMAScript language value, - _type_: a TypedArray element type, - _value_: an ECMAScript language value, - ): either a normal completion containing *undefined* or a throw completion -

-
-
description
-
It is used by functions on DataView instances to store values into the view's buffer.
-
- - 1. Perform ? RequireInternalSlot(_view_, [[DataView]]). - 1. Assert: _view_ has a [[ViewedArrayBuffer]] internal slot. - 1. If IsImmutableBuffer(_view_.[[ViewedArrayBuffer]]) is *true*, throw a *TypeError* exception. - 1. Let _getIndex_ be ? ToIndex(_requestIndex_). - 1. If IsBigIntElementType(_type_) is *true*, let _numberValue_ be ? ToBigInt(_value_). - 1. Otherwise, let _numberValue_ be ? ToNumber(_value_). - 1. Set _isLittleEndian_ to ToBoolean(_isLittleEndian_). - 1. Let _viewOffset_ be _view_.[[ByteOffset]]. - 1. Let _viewRecord_ be MakeDataViewWithBufferWitnessRecord(_view_, ~unordered~). - 1. NOTE: Bounds checking is not a synchronizing operation when _view_'s backing buffer is a growable SharedArrayBuffer. - 1. If IsViewOutOfBounds(_viewRecord_) is *true*, throw a *TypeError* exception. - 1. Let _viewSize_ be GetViewByteLength(_viewRecord_). - 1. Let _elementSize_ be the Element Size value specified in for Element Type _type_. - 1. If _getIndex_ + _elementSize_ > _viewSize_, throw a *RangeError* exception. - 1. Let _bufferIndex_ be _getIndex_ + _viewOffset_. - 1. Perform SetValueInBuffer(_view_.[[ViewedArrayBuffer]], _bufferIndex_, _type_, _numberValue_, *false*, ~unordered~, _isLittleEndian_). - 1. Return *undefined*. - -
-
-
- - -

The Atomics Object

- - -

Abstract Operations for Atomics

- - -

- ValidateIntegerTypedArray ( - _typedArray_: an ECMAScript language value, - _waitable_: a Boolean, - optional _accessMode_: ~read~ or ~write~, - ): either a normal completion containing a TypedArray With Buffer Witness Record, or a throw completion -

-
-
- - 1. If _accessMode_ is not present, set _accessMode_ to ~read~. - 1. Let _taRecord_ be ? ValidateTypedArray(_typedArray_, ~unordered~, _accessMode_). - 1. NOTE: Bounds checking is not a synchronizing operation when _typedArray_'s backing buffer is a growable SharedArrayBuffer. - 1. If _waitable_ is *true*, then - 1. If _typedArray_.[[TypedArrayName]] is neither *"Int32Array"* nor *"BigInt64Array"*, throw a *TypeError* exception. - 1. Else, - 1. Let _type_ be TypedArrayElementType(_typedArray_). - 1. If IsUnclampedIntegerElementType(_type_) is *false* and IsBigIntElementType(_type_) is *false*, throw a *TypeError* exception. - 1. Return _taRecord_. - -
- - -

- ValidateAtomicAccessOnIntegerTypedArray ( - _typedArray_: an ECMAScript language value, - _requestIndex_: an ECMAScript language value, - optional _waitable_: a Boolean, - optional _accessMode_: ~read~ or ~write~, - ): either a normal completion containing an integer or a throw completion -

-
-
- - 1. If _waitable_ is not present, set _waitable_ to *false*. - 1. If _accessMode_ is not present, set _accessMode_ to ~read~. - 1. Let _taRecord_ be ? ValidateIntegerTypedArray(_typedArray_, _waitable_, _accessMode_). - 1. Return ? ValidateAtomicAccess(_taRecord_, _requestIndex_). - -
- - -

- AtomicReadModifyWrite ( - _typedArray_: an ECMAScript language value, - _index_: an ECMAScript language value, - _value_: an ECMAScript language value, - _op_: a read-modify-write modification function, - ): either a normal completion containing either a Number or a BigInt, or a throw completion -

-
-
description
-
_op_ takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value.
-
- - 1. Let _byteIndexInBuffer_ be ? ValidateAtomicAccessOnIntegerTypedArray(_typedArray_, _index_, *false*, ~write~). - 1. If _typedArray_.[[ContentType]] is ~bigint~, let _v_ be ? ToBigInt(_value_). - 1. Otherwise, let _v_ be 𝔽(? ToIntegerOrInfinity(_value_)). - 1. Perform ? RevalidateAtomicAccess(_typedArray_, _byteIndexInBuffer_). - 1. Let _buffer_ be _typedArray_.[[ViewedArrayBuffer]]. - 1. Let _elementType_ be TypedArrayElementType(_typedArray_). - 1. Return GetModifySetValueInBuffer(_buffer_, _byteIndexInBuffer_, _elementType_, _v_, _op_). - -
-
- - -

Atomics.compareExchange ( _typedArray_, _index_, _expectedValue_, _replacementValue_ )

-

This function performs the following steps when called:

- - 1. Let _byteIndexInBuffer_ be ? ValidateAtomicAccessOnIntegerTypedArray(_typedArray_, _index_, *false*, ~write~). - 1. Let _buffer_ be _typedArray_.[[ViewedArrayBuffer]]. - 1. Let _block_ be _buffer_.[[ArrayBufferData]]. - 1. If _typedArray_.[[ContentType]] is ~bigint~, then - 1. Let _expected_ be ? ToBigInt(_expectedValue_). - 1. Let _replacement_ be ? ToBigInt(_replacementValue_). - 1. Else, - 1. Let _expected_ be 𝔽(? ToIntegerOrInfinity(_expectedValue_)). - 1. Let _replacement_ be 𝔽(? ToIntegerOrInfinity(_replacementValue_)). - 1. Perform ? RevalidateAtomicAccess(_typedArray_, _byteIndexInBuffer_). - 1. Let _elementType_ be TypedArrayElementType(_typedArray_). - 1. Let _elementSize_ be TypedArrayElementSize(_typedArray_). - 1. Let _isLittleEndian_ be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record. - 1. Let _expectedBytes_ be NumericToRawBytes(_elementType_, _expected_, _isLittleEndian_). - 1. Let _replacementBytes_ be NumericToRawBytes(_elementType_, _replacement_, _isLittleEndian_). - 1. If IsSharedArrayBuffer(_buffer_) is *true*, then - 1. Let _rawBytesRead_ be AtomicCompareExchangeInSharedBlock(_block_, _byteIndexInBuffer_, _elementSize_, _expectedBytes_, _replacementBytes_). - 1. Else, - 1. Let _rawBytesRead_ be a List of length _elementSize_ whose elements are the sequence of _elementSize_ bytes starting with _block_[_byteIndexInBuffer_]. - 1. If ByteListEqual(_rawBytesRead_, _expectedBytes_) is *true*, then - 1. Store the individual bytes of _replacementBytes_ into _block_, starting at _block_[_byteIndexInBuffer_]. - 1. Return RawBytesToNumeric(_elementType_, _rawBytesRead_, _isLittleEndian_). - -
- - -

Atomics.store ( _typedArray_, _index_, _value_ )

-

This function performs the following steps when called:

- - 1. Let _byteIndexInBuffer_ be ? ValidateAtomicAccessOnIntegerTypedArray(_typedArray_, _index_, *false*, ~write~). - 1. If _typedArray_.[[ContentType]] is ~bigint~, let _v_ be ? ToBigInt(_value_). - 1. Otherwise, let _v_ be 𝔽(? ToIntegerOrInfinity(_value_)). - 1. Perform ? RevalidateAtomicAccess(_typedArray_, _byteIndexInBuffer_). - 1. Let _buffer_ be _typedArray_.[[ViewedArrayBuffer]]. - 1. Let _elementType_ be TypedArrayElementType(_typedArray_). - 1. Perform SetValueInBuffer(_buffer_, _byteIndexInBuffer_, _elementType_, _v_, *true*, ~seq-cst~). - 1. Return _v_. - -
-
-