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

Add immutable array buffer awareness to structuredClone #11033

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
31 changes: 29 additions & 2 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -3047,6 +3047,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<li>The <dfn data-x-href="https://tc39.es/ecma262/#sec-isconstructor">IsConstructor</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.es/ecma262/#sec-isdatadescriptor">IsDataDescriptor</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.es/ecma262/#sec-isdetachedbuffer">IsDetachedBuffer</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.es/ecma262/#sec-isimmutablebuffer">IsImmutableBuffer</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.es/ecma262/#sec-issharedarraybuffer">IsSharedArrayBuffer</dfn> abstract operation</li>
<li>The <dfn data-x="js-NewObjectEnvironment" data-x-href="https://tc39.es/ecma262/#sec-newobjectenvironment">NewObjectEnvironment</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.es/ecma262/#sec-normalcompletion">NormalCompletion</dfn> abstract operation</li>
Expand Down Expand Up @@ -9744,6 +9745,16 @@ interface <dfn interface>DOMStringList</dfn> {
</ol>
</li>

<li>
<p>Otherwise, if <span>IsImmutableBuffer</span>(<var>value</var>) is true, then:</p>

<ol>
<li><p>Set <var>serialized</var> to { [[Type]]: "ImmutableArrayBuffer", [[ArrayBufferData]]:
<var>value</var>.[[ArrayBufferData]], [[ArrayBufferByteLength]]:
<var>value</var>.[[ArrayBufferByteLength]] }.</p></li>
Copy link
Member

@andreubotella andreubotella Feb 17, 2025

Choose a reason for hiding this comment

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

Is value.[[ArrayBufferData]] supposed to be able to be kept alive in the serialization? Unlike for SABs, serializing immutable ArrayBuffers doesn't throw if forStorage is true, meaning that the serialization could be deserialized at some future time in a different process that doesn't share any memory with the current one.

At the very least we should have a note saying that implementations should make sure that a forStorage serialization actually serializes the buffer's contents, but a non-for-storage one might serialize a pointer to the buffer data instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is value.[[ArrayBufferData]] supposed to be able to be kept alive in the serialization? Unlike for SABs, serializing immutable ArrayBuffers doesn't throw if forStorage is true, meaning that the serialization could be deserialized at some future time in a different process that doesn't share any memory with the current one.

That's a good question. I'm not very well versed in the particulars here, but my instinct is that I've got it correct—an immutable array buffer should behave like any other non-shared array buffer when forStorage is true, such that it could be deserialized into a new immutable array buffer with identical contents by a completely independent process at some point in the future.

I like your idea of a note, and have attempted to update accordingly.

</ol>
</li>

<li>
<p>Otherwise:</p>

Expand Down Expand Up @@ -9791,7 +9802,8 @@ interface <dfn interface>DOMStringList</dfn> {
<var>memory</var>).</p></li>

<li><p><span>Assert</span>: <var>bufferSerialized</var>.[[Type]] is "ArrayBuffer",
"ResizableArrayBuffer", "SharedArrayBuffer", or "GrowableSharedArrayBuffer".</p></li>
"ImmutableArrayBuffer", "ResizableArrayBuffer", "SharedArrayBuffer", or
"GrowableSharedArrayBuffer".</p></li>

<li><p>If <var>value</var> has a [[DataView]] internal slot, then set <var>serialized</var> to
{ [[Type]]: "ArrayBufferView", [[Constructor]]: "DataView", [[ArrayBufferSerialized]]:
Expand Down Expand Up @@ -10186,6 +10198,20 @@ o.myself = o;</code></pre>
</ol>
</li>

<li>
<p>Otherwise, if <var>serialized</var>.[[Type]] is "ImmutableArrayBuffer", then:</p>

<ol>
<li><p>Set <var>value</var> to a new ArrayBuffer object in <var>targetRealm</var> whose
[[ArrayBufferData]] internal slot value is <var>serialized</var>.[[ArrayBufferData]], whose
[[ArrayBufferByteLength]] internal slot value is
<var>serialized</var>.[[ArrayBufferByteLength]], and whose [[ArrayBufferIsImmutable]] internal
slot is present.</p></li>

<li><p><span>Assert</span>: <span>IsImmutableBuffer</span>(<var>value</var>) is true.</p></li>
</ol>
</li>

<li>
<p>Otherwise, if <var>serialized</var>.[[Type]] is "ArrayBuffer", then set <var>value</var> to a
new ArrayBuffer object in <var>targetRealm</var> whose [[ArrayBufferData]] internal slot value
Copy link
Member

Choose a reason for hiding this comment

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

Is it possible for a slot to not have a value in this way?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Technically yes, but it's obviously not great and I see now that things are moving away from it. I've updated accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But for the record, the document.all HTMLAllCollection seems to be another example—it has an [[IsHTMLDDA]] internal slot for which no value is ever specified AFAICT.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And in ECMAScript, Object Internal Methods and Internal Slots defines the initial value of an internal slot to be undefined.

Copy link
Contributor

Choose a reason for hiding this comment

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

True although see also tc39/ecma262#3399

Expand Down Expand Up @@ -10463,7 +10489,8 @@ o.myself = o;</code></pre>
<span>"<code>DataCloneError</code>"</span> <code>DOMException</code>.</p></li>

<li><p>If <var>transferable</var> has an [[ArrayBufferData]] internal slot and
<span>IsSharedArrayBuffer</span>(<var>transferable</var>) is true, then throw a
<span>IsSharedArrayBuffer</span>(<var>transferable</var>) is true or
either <span>IsImmutableBuffer</span>(<var>transferable</var>) is true, then throw a
<span>"<code>DataCloneError</code>"</span> <code>DOMException</code>.</p></li>

<li><p>If <var>memory</var>[<var>transferable</var>] <span data-x="map exists">exists</span>,
Expand Down