Skip to content

Conversation

@MattiasBuelens
Copy link
Contributor

@MattiasBuelens MattiasBuelens commented Oct 8, 2025

Previously, many BufferSource algorithms were using internal slots such as [[ByteOffset]] and [[ByteLength]] directly. However, with the addition of SharedArrayBuffer (#353, #1311) and [AllowResizable] (#982), this comes with extra caveats:

Transferring an ArrayBuffer must also take into account whether it should remain resizable or not. Fortunately, we can use the new ArrayBufferCopyAndDetach operation for that.

  • I added an optional preserveResizability parameter to "transfer an ArrayBuffer", so specifications can choose whether to preserve resizability or not. By default, this is not preserved. (Most specs aren't using [AllowResizable] yet anyway.)
  • I removed the realm parameter of that algorithm, since ArrayBufferCopyAndDetach doesn't accept such a parameter. According to WebDex, no specs were actually using that parameter anyway.

Open questions:

Fixes #1312.
Fixes #1385.

  • At least two implementers are interested (and none opposed):
  • Tests are written and can be reviewed and commented upon at:
  • Implementation bugs are filed:
    • Chromium: …
    • Gecko: …
    • WebKit: …
    • Deno: …
    • Node.js: …
    • webidl2.js: …
    • widlparser: …
  • MDN issue is filed: …
  • The top of this comment includes a clear commit message to use.

(See WHATWG Working Mode: Changes for more details.)


Preview | Diff

@MattiasBuelens MattiasBuelens marked this pull request as ready for review October 13, 2025 08:14
@MattiasBuelens
Copy link
Contributor Author

@annevk Could you assign reviewer(s) to this? Thanks! 🙏

@annevk
Copy link
Member

annevk commented Nov 24, 2025

Thanks for tackling this!

Hopefully @syg and @bakkot can help or appoint someone?

Copy link
Member

@annevk annevk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did an editorial pass.

Copy link
Contributor Author

@MattiasBuelens MattiasBuelens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick self-review.

index.bs Outdated
1. [=/Assert=]: |arrayBuffer| is an {{ArrayBuffer}} or {{SharedArrayBuffer}} object.
1. Let |jsArrayBuffer| be the result of [=converted to a JavaScript value|converting=]
|arrayBuffer| to a JavaScript value.
1. If [$IsDetachedBuffer$](|jsArrayBuffer|) is true, then return the empty
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you pass a TA backed by a detached buffer, then the Set |offset| to |bufferSource|'s [=ArrayBufferView/byte offset=]. step above will throw. It's weird that passing a TA backed by a detached buffer throws while passing the detached buffer itself returns the empty byte sequence (in this step). It doesn't fundamentally break anything, but it's inconsistent.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, we should check if bufferSource's underlying buffer is detached before we try to read bufferSource's byte offset.

I'll move this to the preceding "if bufferSource is a buffer view type instance" step.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved the detached check all the way to the top. I also check if length is zero, so reading byte offset later on won't throw.

Funnily enough, reading bufferSource's byte length itself can still throw for an out-of-bounds DataView (as you already reported)... Do we want "get a copy of the bytes held" to propagate that error? Or should we return an empty byte sequence in that case? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it so we read both byte length and byte offset before we check if length is zero. That way, any exceptions from reading those properties will be thrown first.

@syg
Copy link
Contributor

syg commented Jan 15, 2026

When dealing with views backed by a SharedArrayBuffer, what memory ordering should we use? ECMAScript seems to use SEQ-CST pretty much everywhere (e.g. %TypedArray%.prototype.byteLength), but "get a copy of the bytes" uses UNORDERED for GetValueFromBuffer.

The rules of thumb here are:

  • Explicit accesses of the length, like via .length, or a particular builtin reading the length, of a growable SAB are seq-cst (intended to be synchronizing)
  • Implicit accesses of the length for the sake of bounds checking are unordered (intended to be fast)
  • Access of SAB (growable or otherwise) contents themselves are unordered (intended to be fast)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

"byte length of a buffer source type" needs updating for resizable and detached buffers Buffer source types infrastructure

4 participants