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

Expose structuredClone #3414

Merged
merged 1 commit into from Jul 27, 2021
Merged

Expose structuredClone #3414

merged 1 commit into from Jul 27, 2021

Conversation

@surma
Copy link
Contributor

@surma surma commented Jan 27, 2018

This is in connection to #793, to make the discussion a bit more tangible.

This is my first time touching the HTML spec and also my first time writing a spec section from scratch. I probably didn’t do everything right, so please be thorough in your review.

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


/common-dom-interfaces.html ( diff )
/index.html ( diff )
/structured-data.html ( diff )
/web-messaging.html ( diff )
/webappapis.html ( diff )
/window-object.html ( diff )
/workers.html ( diff )

source Outdated Show resolved Hide resolved
Loading
source Outdated Show resolved Hide resolved
Loading
source Outdated Show resolved Hide resolved
Loading
source Outdated Show resolved Hide resolved
Loading
source Outdated Show resolved Hide resolved
Loading
source Outdated Show resolved Hide resolved
Loading
source Outdated Show resolved Hide resolved
Loading
Copy link
Member

@annevk annevk left a comment

Some additional nits from me. Thanks for taking this on. If you can convince the powers that be at Chrome (and add some tests) we can move forward with this. (Potentially after adding transferables.)

Loading

source Outdated Show resolved Hide resolved
Loading
source Outdated Show resolved Hide resolved
Loading
source Outdated Show resolved Hide resolved
Loading
source Outdated Show resolved Hide resolved
Loading
source Outdated Show resolved Hide resolved
Loading
source Outdated Show resolved Hide resolved
Loading
source Outdated Show resolved Hide resolved
Loading
source Outdated Show resolved Hide resolved
Loading
source Outdated Show resolved Hide resolved
Loading
source Outdated Show resolved Hide resolved
Loading
@TimothyGu TimothyGu dismissed their stale review Jan 28, 2018

Other than the comment, the spec text LGTM. However, this will need tests (and of course, browser support).

source Outdated Show resolved Hide resolved
Loading
@surma
Copy link
Contributor Author

@surma surma commented Jan 28, 2018

Loading

@domenic
Copy link
Member

@domenic domenic commented Jan 28, 2018

I think this section is misplaced. It should be part of https://html.spec.whatwg.org/multipage/structured-data.html#safe-passing-of-structured-data, probably a new sub-section at the end.

For the dev edition, the contents of this new subsection (not including its heading) should be the only content of the "Safe passing of structured data" section.

Loading

Copy link
Member

@mathiasbynens mathiasbynens left a comment

Thanks for getting the ball rolling on this, Surma! 👍🏻

Loading

source Outdated Show resolved Hide resolved
Loading
source Outdated Show resolved Hide resolved
Loading
@surma
Copy link
Contributor Author

@surma surma commented Jan 30, 2018

@domenic I hope I understood your feedback right. PTAL

Loading

@tobireif
Copy link

@tobireif tobireif commented Feb 1, 2018

As a web developer / JS API user I don't care so much about how the object gets cloned (whether the "structural clone algorithm" is used or a different way of deep cloning). The name of the method doesn't have to reflect the choice of algorithm used by the implementation.

Could the method be called clone() instead of structuredClone() ? or eg deepClone() or completeClone() or completeCopy() -
or perhaps just simply copy() ? (I haven't gone through all existing names)

Loading

@surma
Copy link
Contributor Author

@surma surma commented Feb 1, 2018

The name of the method doesn't have to reflect the choice of algorithm

I disagree. The name should to convey what kind of clone the result is. The method structuredClone give you a, well, structured clone. Meaning it directly implies what will be cloned and what will not be cloned (e.g. methods and prototypes are not cloned).

A name like deepClone or completeCopy could set expectations with the developer that are not being fulfilled. That’s how we end up with misnomers on the platform.

Loading

@tobireif
Copy link

@tobireif tobireif commented Feb 1, 2018

I see, thanks for your reply.

Perhaps we do need a method deepClone() or completeCopy()?

Loading

@surma
Copy link
Contributor Author

@surma surma commented Feb 1, 2018

Yeah, we have talked about that. But cloning functions is not trivial. Please continue discussing that matter in #793 :)

Loading

@annevk
Copy link
Member

@annevk annevk commented Feb 16, 2018

To reiterate, my main problem with this proposal is that it doesn't expose the full underlying primitive, but rather a subset, and it's unclear how to extend it to expose it fully. The primitive we have is one that takes a value and a transfer list, and returns a value and a transfer list. And the transfer list can be independent from the value. This API just drops the return transfer list on the floor.

Loading

@surma
Copy link
Contributor Author

@surma surma commented Feb 16, 2018

Thanks for re-iterating, I didn’t get that before. That’s fair, I guess. I don’t see a problem with changing the returned value to {cloned, transferredValues}.

Loading

@domenic
Copy link
Member

@domenic domenic commented Feb 16, 2018

I'm not sure that primitive is terribly important. I think it's more for handling cases where for whatever reason you don't put the transferred values inside the cloned data, and for spec convenience in not making you dig through to find those values, but IMO such cases are not an important part of the primitive...

Loading

@surma
Copy link
Contributor Author

@surma surma commented Feb 16, 2018

I agree, but I’m also not sure if we are thinking of everything that could be needed in the future. I’ll leave that decision up to you all, I don’t have very strong feelings either way, although in terms of developer ergonomics and arguably the current 99% use-case, returning just the clone seems more desirable.

Loading

@jeremyroman
Copy link
Contributor

@jeremyroman jeremyroman commented Mar 21, 2018

FWIW, +1 for just returning the deserialized values. It'd be really easy for a caller to get if they wanted, be serializing {data, transferList} themselves. Currently [[TransferredValues]] is only exposed insofar as MessagePort objects are extracted from there and separately exposed. As a result, Blink doesn't actually keep the original transfer list in order at present (we have separate lists for ports, buffers, etc.).

Loading

@surma
Copy link
Contributor Author

@surma surma commented May 18, 2018

The original PR for tests got side-tracked and the actual PR for adding tests for structuredClone() now lives in web-platform-tests/wpt#11069.

Loading

@surma
Copy link
Contributor Author

@surma surma commented May 21, 2018

Just wondering: I am not sure what the result of the conversation so far is. Have we reached some sort of consensus weather transferList should be exposed by structuredClone()? What are we missing to qualify for “implementer interest”?

Loading

@domenic
Copy link
Member

@domenic domenic commented May 21, 2018

I don't know about consensus, but I feel it should definitely be there, and my read of @annevk was that he didn't feel too strongly against it...

What we're missing in terms of implementer interest is outlined in https://whatwg.org/working-mode#additions. So far I don't see any browser engineers saying "we would like to implement this soon" on this thread.

Loading

@annevk
Copy link
Member

@annevk annevk commented May 22, 2018

I suspect Firefox would adopt this pretty quickly, but it'd be good if someone could go over #793 (comment) and work through @wanderview's concern.

Loading

Copy link
Member

@annevk annevk left a comment

I added the PR template to OP.

Mozilla supports adding this.

Loading

source Outdated
<dt><var>result</var> = self . <code subdfn data-x="dom-structuredClone">structuredClone</code>( <var>value</var>
[, { <code data-x="dom-PostMessageOptions-transfer">transfer</code> } ] )</dt>
<dd>
<p>Takes the input value and returns a deep copy by performing the structured clone algorithm. <span>Transferable
Copy link
Member

@annevk annevk Jul 21, 2021

Choose a reason for hiding this comment

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

I think this is confusing as elsewhere we say that this is an algorithm the specification used to define.

Loading

Copy link
Member

@domenic domenic Jul 21, 2021

Choose a reason for hiding this comment

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

What phrasing would you suggest? Maybe "returns a deep copy by performing the structured serialization and then deserialization algorithms"? That seems a bit technical for web devs who might be more familiar with https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm ...

Loading

Copy link
Member

@domenic domenic Jul 21, 2021

Choose a reason for hiding this comment

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

Maybe just "by performing a structured clone".

Loading

Copy link
Member

@annevk annevk Jul 21, 2021

Choose a reason for hiding this comment

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

Either simply: "and returns a deep clone of it"

Or: "and returns a deep clone of it (technically, by serializing and then deserializing the input)"

And I guess we should flag @whatwg/documentation to see if there is interest in aligning the documentation more with the current state of things.

Loading

Copy link
Member

@domenic domenic Jul 21, 2021

Choose a reason for hiding this comment

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

I guess I find it important to have some phrasing here that distinguishes this kind of deep clone from other meanings JS developers might be used to, such as https://lodash.com/docs/4.17.15#cloneDeep .

Loading

Copy link
Member

@annevk annevk Jul 26, 2021

Choose a reason for hiding this comment

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

Okay, maybe the answer here is that we update the note that starts with

This specification used to define a "structured clone" algorithm

to instead say that is the colloquial name and also the name of the API (xref)?

Loading

Copy link
Member

@domenic domenic Jul 26, 2021

Choose a reason for hiding this comment

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

Done, although in a slightly more elaborate form; let me know what you think.

Loading

source Outdated Show resolved Hide resolved
Loading
source Outdated
<dt><var>result</var> = self . <code subdfn data-x="dom-structuredClone">structuredClone</code>( <var>value</var>
[, { <code data-x="dom-PostMessageOptions-transfer">transfer</code> } ] )</dt>
<dd>
<p>Takes the input value and returns a deep copy by performing the structured clone algorithm. <span>Transferable
Copy link
Member

@annevk annevk Jul 26, 2021

Choose a reason for hiding this comment

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

Okay, maybe the answer here is that we update the note that starts with

This specification used to define a "structured clone" algorithm

to instead say that is the colloquial name and also the name of the API (xref)?

Loading

source Outdated Show resolved Hide resolved
Loading
@domenic domenic force-pushed the structuredclone branch from ef3c548 to b8d156c Jul 26, 2021
annevk
annevk approved these changes Jul 27, 2021
Copy link
Member

@annevk annevk left a comment

Looks great, thanks!

Loading

transferring the underlying data instead of copying it. Collectively this
serialization/deserialization process is known as "structured cloning", although most APIs perform
separate serialization and deserialization steps. (With the notable exception being the <code
data-x="dom-structuredClone">structuredClone()</code> function.)</p>
Copy link
Member

@annevk annevk Jul 27, 2021

Choose a reason for hiding this comment

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

Suggested change
data-x="dom-structuredClone">structuredClone()</code> function.)</p>
data-x="dom-structuredClone">structuredClone()</code> method.)</p>

Loading

@domenic domenic force-pushed the structuredclone branch from b8d156c to a09e2f4 Jul 27, 2021
@domenic domenic merged commit 1e610d4 into whatwg:main Jul 27, 2021
2 checks passed
Loading
@domenic domenic deleted the structuredclone branch Jul 27, 2021
domenic pushed a commit to web-platform-tests/wpt that referenced this issue Jul 27, 2021
@domenic
Copy link
Member

@domenic domenic commented Jul 27, 2021

Hooray! 6+ years after the original feature request, and 3.5 years after the original PR, this is finally merged!

I've updated the OP with implementation bug links for all browsers.

Loading

@sideshowbarker
Copy link
Member

@sideshowbarker sideshowbarker commented Jul 27, 2021

Hooray! 6+ years after the original feature request, and 3.5 years after the original PR, this is finally merged!

🎉 I’ll make time to update the related MDN docs

Loading

domenic added a commit to WICG/portals that referenced this issue Jul 30, 2021
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Jul 31, 2021
Automatic update from web-platform-tests
Add tests for structuredClone

Follows whatwg/html#3414.
--

wpt-commits: 7cfc0be8d4d4c3ae374e1f8444a2309c0eefc563
wpt-pr: 11069
jakearchibald pushed a commit to w3c/ServiceWorker that referenced this issue Aug 2, 2021
jamienicol pushed a commit to jamienicol/gecko that referenced this issue Aug 4, 2021
Automatic update from web-platform-tests
Add tests for structuredClone

Follows whatwg/html#3414.
--

wpt-commits: 7cfc0be8d4d4c3ae374e1f8444a2309c0eefc563
wpt-pr: 11069
andreubotella added a commit to andreubotella/html that referenced this issue Sep 17, 2021
`StructuredDeserialize` expects the first argument to be a record
containing the [[Type]] slot, as would be returned by
`StructuredSerialize` and `StructuredSerializeForStorage`.
`StructuredSerializeWithTransfer` returns instead a record with
[[Serialized]] and [[TransferDataHolders]] slots, which must be
deserialized using the `StructuredDeserializeWithTransfer` operation.

It seems like this was an oversight in whatwg#3414.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Linked issues

Successfully merging this pull request may close these issues.

None yet