Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reference for stage 3 resizablearraybuffer #24407

Merged

Conversation

chrisdavidmills
Copy link
Contributor

Description

This PR adds content for the new features related to the Resizable ArrayBuffer and growable SharedArrayBuffer Stage 3 draft, which was implemented in Chrome 111+.

See my research document for exact details of what has been added, and other required work.

Motivation

Additional details

Related issues and pull requests

Fixes #24369

@chrisdavidmills chrisdavidmills requested a review from a team as a code owner February 13, 2023 18:47
@chrisdavidmills chrisdavidmills requested review from Josh-Cena and removed request for a team February 13, 2023 18:47
@github-actions github-actions bot added the Content:JS JavaScript docs label Feb 13, 2023
@chrisdavidmills chrisdavidmills marked this pull request as draft February 13, 2023 18:49
@Josh-Cena
Copy link
Member

Lmk when it's ready for review. Content LGTM but I have a lot of editorial suggestions, which I'll probably just commit directly to this branch.

@chrisdavidmills
Copy link
Contributor Author

chrisdavidmills commented Feb 14, 2023

Lmk when it's ready for review. Content LGTM but I have a lot of editorial suggestions, which I'll probably just commit directly to this branch.

You can go ahead with the editorial suggestions; I'm mainly setting it to draft so that it doesn't end up getting merged before the SMEs are able to give it a tech review.

@Josh-Cena
Copy link
Member

Josh-Cena commented Feb 14, 2023

Several thoughts:

  1. How this interacts with WebAssembly.Memory should be documented somewhere.
  2. How this interacts with typed array views should be mentioned. (Can typed arrays cause buffer resizing? Can buffer resize change typed array length?)
  3. There should be some intro on the landing page with an overview of the resize-/grow-related APIs. This is a good place to include motivations like those mentioned in the proposal text.
  4. Mention that new slots are pre-filled with 0 instead of junk values.
  5. Mention some security concerns

We should try to include all information from the proposal that doesn't seem exclusively useful for implementers!

@chrisdavidmills chrisdavidmills marked this pull request as ready for review February 21, 2023 07:03
@github-actions
Copy link
Contributor

This pull request has merge conflicts that must be resolved before it can be merged.

@chrisdavidmills
Copy link
Contributor Author

Let me preface this by saying that I am not as much of an expert with the core JS language as you or Mr @Elchi3 ... but I've got a few questions about your thoughts before I try to make any further changes.

Several thoughts:

1. How this interacts with `WebAssembly.Memory` should be documented somewhere.

There is no mention of WebAssembly/WebAssembly.Memory anywhere in the proposal, so I'm not really sure how I'm supposed to find that out.

2. How this interacts with typed array views should be mentioned. (Can typed arrays cause buffer resizing? Can buffer resize change typed array length?)

I didn't think the typed array view could affect the underlying array buffer. Something like slice() creates a new typed array/buffer.

If you create a resizable ArrayBuffer and then create say a new Float32Array from that buffer, then resize the buffer, it will change the float32's length/bytelength. Do you think that needs to be mentioned somewhere? Just on the TypedArray landing page?

3. There should be some intro on the landing page with an overview of the resize-/grow-related APIs. This is a good place to include motivations like those mentioned in the proposal text.

What landing page? The main ArrayBuffer and SharedArrayBuffer pages? What motivations are you talking about?

4. Mention that new slots are pre-filled with 0 instead of junk values.

In my experience, it is not common practice to document the behavior of internal slots on MDN. Is this useful to web developers?

5. Mention some security concerns

What security concerns were you thinking of specifically, and where would you mention them?

@Josh-Cena
Copy link
Member

There is no mention of WebAssembly/WebAssembly.Memory anywhere in the proposal

There's indeed no direct exposition of how it works, just feel like you may want to explore it, because the proposal quotes WASM as a motivation. See the "Sync up capability with WebAssembly memory.grow" and "WebGPU buffers" sections.

If you create a resizable ArrayBuffer and then create say a new Float32Array from that buffer, then resize the buffer, it will change the float32's length/bytelength. Do you think that needs to be mentioned somewhere? Just on the TypedArray landing page?

Yes, that's what I'm thinking of. Only array buffer resizing can affect typed arrays, but not the other way. The important thing to note is that this only happens when the typed array was created with length of undefined. See the proposal's "Modifications to TypedArray" section. Moreover, it's possible to access a typed array index that corresponds to a non-existent buffer index (because the buffer has shrunk but the TA is not auto-tracking), in which case 0 is returned.

What landing page? The main ArrayBuffer and SharedArrayBuffer pages? What motivations are you talking about?

I'm talking about what APIs you may use to help with buffer resizing (maxByteLength constructor option, resize(), maxByteLength accessor property, etc.). For motivation, you may want to mention WebAssembly.memory, basically whatever motivates this feature's proposal.

it is not common practice to document the behavior of internal slots on MDN

Sorry, when I say "slots", I mean "array buffer indices". For example:

const rab = new ArrayBuffer(0, { maxByteLength: 1024 ** 2 });
const u32a = new Uint32Array(rab);
rab.resize(1000);
console.log(u32a[50]); // 0, not some junk value, as you may expect if the memory is not initialized

What security concerns were you thinking of specifically, and where would you mention them?

Out-of-bounds memory access, etc. Frankly I'm not expert on security either, but you may want to research based on the "Security" section of the proposal. This doesn't have to be in this initial PR.

@marjakh
Copy link

marjakh commented Feb 21, 2023

Yes, that's what I'm thinking of. Only array buffer resizing can affect typed arrays, but not the other way. The important thing to note is that this only happens when the typed array was created with length of undefined

I don't think that's true (the sentence starting with "this only happens").

E.g.,

const ab = new ArrayBuffer(1000, {maxByteLength: 2000});
const ta = new Uint8Array(ab, 0, 10);
console.log(ta[0]); // 0
ab.resize(0);
console.log(ta[0]); // undefined (ta is now out of bounds (behaving as if the backing buffer was detached))

-> I'd say here "the typed array is affected", too.

Moreover, it's possible to access a typed array index that corresponds to a non-existent buffer index (because the buffer has shrunk but the TA is not auto-tracking), in which case 0 is returned.

undefined, not 0, no? See https://tc39.es/ecma262/#sec-integerindexedelementget .

Re: security: I don't think there's anything actionable for JavaScript programmers there. The browsers will make sure the proposal is implemented in a sound way, so that no rogue memory access can occur.

@Josh-Cena
Copy link
Member

RE: only happens when the typed array was created with length of undefined, I'm talking about the ability of auto-tracking byteLength.

image

RE: accessing out-of-bounds memory. Because resizeable buffers are not merged yet, the main spec is not updated. You need to look at the revised AO in the proposal spec. But you are right, out-of-bounds typed arrays act as if they are detached, which means they have byteLength of 0 and return undefined for all indices even when the typed array index corresponds to an existing buffer index.

RE: security, it's okay to just note that "the way the API is designed have got you covered". For example, you are not allowed to shrink shared memory; you are never allowed to access memory not allocated to you; etc. These are the things developers may care about that should be explicitly spelled out.

@chrisdavidmills
Copy link
Contributor Author

@marjakh @Josh-Cena OK, I've had another go, taking on board your new comments. What do you think?

@chrisdavidmills
Copy link
Contributor Author

@marjakh thanks for the further comments. I've made some more changes - let me know what you think.

@@ -78,6 +78,14 @@ Depending on whether the above security measures are taken, the various memory-s

The WebAssembly Threads proposal also defines a new set of [atomic](https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md#atomic-memory-accesses) instructions. Just as `SharedArrayBuffer` and its methods are unconditionally enabled (and only sharing between threads is gated on the new headers), the WebAssembly atomic instructions are also unconditionally allowed.

### Growing SharedArrayBuffers

`SharedArrayBuffer`s can be made growable by including the `maxByteLength` option when calling the {{jsxref("SharedArrayBuffer.SharedArrayBuffer", "constructor", "", "nocode")}}. You can query whether an `ArrayBuffer` is growable and what its maximum size is by accessing its {{jsxref("SharedArrayBuffer.prototype.growable", "growable")}} and {{jsxref("SharedArrayBuffer.prototype.maxByteLength", "maxByteLength")}} properties, respectively. You can assign a new size to a growable `SharedArrayBuffer` with a {{jsxref("SharedArrayBuffer.prototype.grow()", "grow()")}} call.
Copy link

Choose a reason for hiding this comment

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

"You can query whether an ArrayBuffer is growable"

Should this be SharedArrayBuffer?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch — updated in next commit

console.log(float32[0]) // Returns undefined
```

If you then grow `buffer` again, `float32`'s size will increase again. This can potentially bring a typed array that previously became out-of-bounds, back in bounds:
Copy link

Choose a reason for hiding this comment

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

If you then grow buffer again, float32's size will increase again. This can potentially bring [...]

This is also slightly untrue / expressed in an unspecific way: The size will increase only in the case where the growing brings it back in bounds. Now it sounds like the size will always increase if you grow the buffer, and that in addition it might become in-bounds.

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 see what you are getting at. Text updated again.


#### Behavior of length-tracking TypedArrays

In this case, `float32` is created without a specific size so it is non-length-tracking, and will grow to contain `array` as it is grown:
Copy link

Choose a reason for hiding this comment

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

non-length-tracking

Should be: length-tracking

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oops, yup! Updated.

@marjakh
Copy link

marjakh commented Feb 27, 2023

Thanks for working on this so relentlessly through the iterations! This feature has many subtleties and it's tricky to get all the details right. I left a couple of small comments, the rest looks good! Thanks!

@chrisdavidmills
Copy link
Contributor Author

@marjakh no problem! It's really important to have these discussions to make sure we explain things precisely.

Can you have one more quick look, just to make sure things are all OK now?

@marjakh
Copy link

marjakh commented Feb 27, 2023

Everything looks good now, thanks!

@chrisdavidmills
Copy link
Contributor Author

@marjakh Super, thanks!

@chrisdavidmills
Copy link
Contributor Author

@Josh-Cena, @marjakh has now given this the thumbs-up from the SME tech review standpoint. Do you have the privs to merge it? If not, maybe @Elchi3 could have a quick look and give it his stamp?

There is also a set of related interactive examples at mdn/interactive-examples#2434. Can you help me to get these reviewed and approved?

Thanks in advance.

@Josh-Cena
Copy link
Member

I will do a last round of review this week and get it merged. Thank you for the work!

@chrisdavidmills
Copy link
Contributor Author

I will do a last round of review this week and get it merged. Thank you for the work!

Super, cheers!

@Josh-Cena Josh-Cena force-pushed the resizable-arraybuffer-growable-sab branch from 7fbdc24 to bcbbc3c Compare March 1, 2023 04:31
Copy link
Member

@Josh-Cena Josh-Cena left a comment

Choose a reason for hiding this comment

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

This LGTM. I've pushed one little change in bcbbc3c and I'd like to get a thumbs-up from both @chrisdavidmills and @marjakh before I merge this.

@chrisdavidmills
Copy link
Contributor Author

@Josh-Cena LGTM!

@marjakh
Copy link

marjakh commented Mar 1, 2023

The latest edits look good, thanks!

@Josh-Cena
Copy link
Member

Thank you both!

@Josh-Cena Josh-Cena merged commit d42c4bd into mdn:main Mar 1, 2023
@chrisdavidmills chrisdavidmills deleted the resizable-arraybuffer-growable-sab branch March 1, 2023 15:10
@chrisdavidmills
Copy link
Contributor Author

W00t! Thanks for all your hard work on this @Josh-Cena !

@Josh-Cena Josh-Cena changed the title Add docs for resizable ArrayBuffer and growable SAB Reference for stage 3 resizablearraybuffer Aug 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Content:JS JavaScript docs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Intent to document: Resizable ArrayBuffer and growable SharedArrayBuffer
3 participants