@@ -7967,13 +7967,24 @@ interface <dfn interface>DOMStringList</dfn> {
79677967 </div>
79687968
79697969
7970- <div w-nodev>
7971-
79727970 <h3 split-filename="structured-data">Safe passing of structured data</h3>
79737971
7972+ <p id="structuredclone"><span id="structured-clone"></span>To support passing JavaScript objects,
7973+ including <span data-x="platform object">platform objects</span>, across <span data-x="JavaScript
7974+ realm">realm</span> boundaries, this specification defines <span w-nodev>the following
7975+ </span>infrastructure for serializing and deserializing objects, including in some cases
7976+ transferring the underlying data instead of copying it. Collectively this
7977+ serialization/deserialization process is known as "structured cloning", although most APIs perform
7978+ separate serialization and deserialization steps. (With the notable exception being the <code
7979+ data-x="dom-structuredClone">structuredClone()</code> method.)</p>
7980+
7981+ <div w-nodev>
7982+
79747983 <p>This section uses the terminology and typographic conventions from the JavaScript
79757984 specification. <ref spec=JAVASCRIPT></p>
79767985
7986+ </div>
7987+
79777988 <h4><dfn>Serializable objects</dfn></h4>
79787989
79797990 <p><span>Serializable objects</span> support being serialized, and later deserialized, in a way
@@ -7984,6 +7995,8 @@ interface <dfn interface>DOMStringList</dfn> {
79847995 <p>Not all objects are <span>serializable objects</span>, and not all aspects of objects that are
79857996 <span>serializable objects</span> are necessarily preserved when they are serialized.</p>
79867997
7998+ <div w-nodev>
7999+
79878000 <p><span data-x="platform object">Platform objects</span> can be <span>serializable objects</span>
79888001 if their <span>primary interface</span> is decorated with the <dfn extended-attribute
79898002 data-lt="Serializable" data-x="Serializable"><code>[Serializable]</code></dfn> IDL <span>extended
@@ -8091,6 +8104,8 @@ interface <dfn interface>DOMStringList</dfn> {
80918104 However, to better specify the behavior of certain more complex situations, the model was updated
80928105 to make the serialization and deserialization explicit.</p>
80938106
8107+ </div>
8108+
80948109 <h4 export data-lt="transferable object"><dfn>Transferable objects</dfn></h4>
80958110
80968111 <p><span>Transferable objects</span> support being transferred across <span
@@ -8103,6 +8118,8 @@ interface <dfn interface>DOMStringList</dfn> {
81038118 <p class="note">Transferring is an irreversible and non-idempotent operation. Once an object has
81048119 been transferred, it cannot be transferred, or indeed used, again.</p>
81058120
8121+ <div w-nodev>
8122+
81068123 <p><span data-x="platform object">Platform objects</span> can be <span>transferable objects</span>
81078124 if their <span>primary interface</span> is decorated with the <dfn extended-attribute
81088125 data-lt="Transferable" data-x="Transferable"><code>[Transferable]</code></dfn> IDL <span>extended
@@ -9138,11 +9155,6 @@ o.myself = o;</code></pre>
91389155 understood to perform an implicit <span data-x="concept-idl-convert">conversion</span> to the
91399156 JavaScript value before invoking these algorithms.</p>
91409157
9141- <p class="note" id="structuredclone"><span id="structured-clone"></span>This specification used
9142- to define a "structured clone" algorithm, and more recently a StructuredClone abstract operation.
9143- However, in practice all known uses of it were better served by separate serialization and
9144- deserialization steps, so it was removed.</p>
9145-
91469158 <hr>
91479159
91489160 <p>Call sites that are not invoked as a result of author code synchronously calling into a user
@@ -9170,6 +9182,38 @@ o.myself = o;</code></pre>
91709182
91719183 </div>
91729184
9185+ <h4 id="structured-cloning">Structured cloning API</h4>
9186+
9187+ <dl class="domintro">
9188+ <dt><code data-x=""><var>result</var> = self.<code subdfn data-x="dom-structuredClone">structuredClone</code>(<var>value</var>[, { <code data-x="dom-StructuredSerializeOptions-transfer">transfer</code> }])</dt>
9189+ <dd>
9190+ <p>Takes the input value and returns a deep copy by performing the structured clone algorithm.
9191+ <span>Transferable objects</span> listed in the <code
9192+ data-x="dom-StructuredSerializeOptions-transfer">transfer</code> array are transferred, not
9193+ just cloned, meaning that they are no longer usable in the input value.</p>
9194+
9195+ <p>Throws a <span>"<code>DataCloneError</code>"</span> <code>DOMException</code> if any part of
9196+ the input value is not <span data-x="serializable objects">serializable</span>.</p>
9197+ </dd>
9198+ </dl>
9199+
9200+ <div w-nodev>
9201+
9202+ <p>The <dfn method for="WindowOrWorkerGlobalScope"
9203+ data-x="dom-structuredClone"><code>structuredClone(<var>value</var>,
9204+ <var>options</var>)</code></dfn> method steps are:</p>
9205+
9206+ <ol>
9207+ <li><p>Let <var>serialized</var> be ?
9208+ <span>StructuredSerializeWithTransfer</span>(<var>value</var>, <var>options</var>["<code
9209+ data-x="dom-StructuredSerializeOptions-transfer">transfer</code>"]).</p></li>
9210+
9211+ <li><p>Return ? <span>StructuredDeserialize</span>(<var>serialized</var>, <span>this</span>'s
9212+ <span data-x="concept-relevant-realm">relevant Realm</span>).</p></li>
9213+ </ol>
9214+
9215+ </div>
9216+
91739217
91749218 <h2 split-filename="dom" id="dom">Semantics, structure, and APIs of HTML documents</h2>
91759219
@@ -80416,7 +80460,7 @@ interface <dfn interface>Window</dfn> : <span>EventTarget</span> {
8041680460<span>Window</span> includes <span>GlobalEventHandlers</span>;
8041780461<span>Window</span> includes <span>WindowEventHandlers</span>;
8041880462
80419- dictionary <dfn dictionary>WindowPostMessageOptions</dfn> : <span>PostMessageOptions </span> {
80463+ dictionary <dfn dictionary>WindowPostMessageOptions</dfn> : <span>StructuredSerializeOptions </span> {
8042080464 USVString <dfn dict-member for="WindowPostMessageOptions" data-x="dom-WindowPostMessageOptions-targetOrigin">targetOrigin</dfn> = "/";
8042180465};</code></pre>
8042280466
@@ -94809,6 +94853,9 @@ interface mixin <dfn interface>WindowOrWorkerGlobalScope</dfn> {
9480994853 // ImageBitmap
9481094854 Promise<<span>ImageBitmap</span>> <span data-x="dom-createImageBitmap">createImageBitmap</span>(<span>ImageBitmapSource</span> image, optional <span>ImageBitmapOptions</span> options = {});
9481194855 Promise<<span>ImageBitmap</span>> <span data-x="dom-createImageBitmap">createImageBitmap</span>(<span>ImageBitmapSource</span> image, long sx, long sy, long sw, long sh, optional <span>ImageBitmapOptions</span> options = {});
94856+
94857+ // structured cloning
94858+ any <span data-x="dom-structuredClone">structuredClone</span>(any value, optional <span>StructuredSerializeOptions</span> options = {});
9481294859};
9481394860<span>Window</span> includes <span>WindowOrWorkerGlobalScope</span>;
9481494861<span>WorkerGlobalScope</span> includes <span>WindowOrWorkerGlobalScope</span>;</code></pre>
@@ -99740,7 +99787,7 @@ function receiver(e) {
9974099787 and can contain certain data objects such as <code>File</code> <code>Blob</code>,
9974199788 <code>FileList</code>, and <code data-x="idl-ArrayBuffer">ArrayBuffer</code> objects.</p>
9974299789
99743- <p>Objects listed in the <code data-x="dom-PostMessageOptions -transfer">transfer</code> member
99790+ <p>Objects listed in the <code data-x="dom-StructuredSerializeOptions -transfer">transfer</code> member
9974499791 of <var>options</var> are transferred, not just cloned, meaning that they are no longer usable
9974599792 on the sending side.</p>
9974699793
@@ -99816,7 +99863,7 @@ function receiver(e) {
9981699863 </li>
9981799864
9981899865 <li><p>Let <var>transfer</var> be <var>options</var>["<code
99819- data-x="dom-PostMessageOptions -transfer">transfer</code>"].</p></li>
99866+ data-x="dom-StructuredSerializeOptions -transfer">transfer</code>"].</p></li>
9982099867
9982199868 <li><p>Let <var>serializeWithTransferResult</var> be
9982299869 <span>StructuredSerializeWithTransfer</span>(<var>message</var>, <var>transfer</var>). Rethrow
@@ -99892,7 +99939,7 @@ function receiver(e) {
9989299939
9989399940 <li><p>Let <var>options</var> be «[ "<code
9989499941 data-x="dom-WindowPostMessageOptions-targetOrigin">targetOrigin</code>" →
99895- <var>targetOrigin</var>, "<code data-x="dom-PostMessageOptions -transfer">transfer</code>" →
99942+ <var>targetOrigin</var>, "<code data-x="dom-StructuredSerializeOptions -transfer">transfer</code>" →
9989699943 <var>transfer</var> ]».</p></li>
9989799944
9989899945 <li><p>Run the <span>window post message steps</span> providing <var>targetWindow</var>,
@@ -100160,7 +100207,7 @@ interface <dfn interface>MessageChannel</dfn> {
100160100207 <pre><code class="idl">[Exposed=(Window,Worker,AudioWorklet), <span>Transferable</span>]
100161100208interface <dfn interface>MessagePort</dfn> : <span>EventTarget</span> {
100162100209 undefined <span data-x="dom-MessagePort-postMessage">postMessage</span>(any message, sequence<<span data-x="idl-object">object</span>> transfer);
100163- undefined <span data-x="dom-MessagePort-postMessage-options">postMessage</span>(any message, optional <span>PostMessageOptions </span> options = {});
100210+ undefined <span data-x="dom-MessagePort-postMessage-options">postMessage</span>(any message, optional <span>StructuredSerializeOptions </span> options = {});
100164100211 undefined <span data-x="dom-MessagePort-start">start</span>();
100165100212 undefined <span data-x="dom-MessagePort-close">close</span>();
100166100213
@@ -100169,8 +100216,8 @@ interface <dfn interface>MessagePort</dfn> : <span>EventTarget</span> {
100169100216 attribute <span>EventHandler</span> <span data-x="handler-MessagePort-onmessageerror">onmessageerror</span>;
100170100217};
100171100218
100172- dictionary <dfn dictionary>PostMessageOptions </dfn> {
100173- sequence<<span data-x="idl-object">object</span>> <dfn dict-member for="PostMessageOptions " data-x="dom-PostMessageOptions -transfer">transfer</dfn> = [];
100219+ dictionary <dfn dictionary>StructuredSerializeOptions </dfn> {
100220+ sequence<<span data-x="idl-object">object</span>> <dfn dict-member for="StructuredSerializeOptions " data-x="dom-StructuredSerializeOptions -transfer">transfer</dfn> = [];
100174100221};</code></pre>
100175100222
100176100223 <dl class="domintro">
@@ -100313,7 +100360,7 @@ dictionary <dfn dictionary>PostMessageOptions</dfn> {
100313100360
100314100361 <ol> <!-- a lot of this is similar or identical to the window post message steps -->
100315100362 <li><p>Let <var>transfer</var> be <var>options</var>["<code
100316- data-x="dom-PostMessageOptions -transfer">transfer</code>"].</p></li>
100363+ data-x="dom-StructuredSerializeOptions -transfer">transfer</code>"].</p></li>
100317100364
100318100365 <li><p>If <var>transfer</var> <span data-x="list contains">contains</span> this
100319100366 <code>MessagePort</code>, then throw a <span>"<code>DataCloneError</code>"</span>
@@ -100403,7 +100450,8 @@ dictionary <dfn dictionary>PostMessageOptions</dfn> {
100403100450 entangled, if any; otherwise let it be null.</p></li>
100404100451
100405100452 <li><p>Let <var>options</var> be «[ "<code
100406- data-x="dom-PostMessageOptions-transfer">transfer</code>" → <var>transfer</var> ]».</p></li>
100453+ data-x="dom-StructuredSerializeOptions-transfer">transfer</code>" →
100454+ <var>transfer</var> ]».</p></li>
100407100455
100408100456 <li><p>Run the <span>message port post message steps</span> providing <var>targetPort</var>,
100409100457 <var>message</var> and <var>options</var>.</p></li>
@@ -101272,7 +101320,7 @@ interface <dfn interface>DedicatedWorkerGlobalScope</dfn> : <span>WorkerGlobalSc
101272101320 [Replaceable] readonly attribute DOMString <span data-x="dom-DedicatedWorkerGlobalScope-name">name</span>;
101273101321
101274101322 undefined <span data-x="dom-DedicatedWorkerGlobalScope-postMessage">postMessage</span>(any message, sequence<<span data-x="idl-object">object</span>> transfer);
101275- undefined <span data-x="dom-DedicatedWorkerGlobalScope-postMessage-options">postMessage</span>(any message, optional <span>PostMessageOptions </span> options = {});
101323+ undefined <span data-x="dom-DedicatedWorkerGlobalScope-postMessage-options">postMessage</span>(any message, optional <span>StructuredSerializeOptions </span> options = {});
101276101324
101277101325 undefined <span data-x="dom-DedicatedWorkerGlobalScope-close">close</span>();
101278101326
@@ -101294,10 +101342,8 @@ interface <dfn interface>DedicatedWorkerGlobalScope</dfn> : <span>WorkerGlobalSc
101294101342 data-x="concept-WorkerGlobalScope-name">name</span>, i.e. the value given to the
101295101343 <code>Worker</code> constructor. Primarily useful for debugging.</p></dd>
101296101344
101297- <dt><code data-x=""><var>dedicatedWorkerGlobal</var>.<span subdfn data-x="dom-DedicatedWorkerGlobalScope-postMessage">postMessage</span>(<var>message</var> [,
101298- <var>transfer</var> ])</code></dt>
101299- <dt><code data-x=""><var>dedicatedWorkerGlobal</var>.<span subdfn data-x="dom-DedicatedWorkerGlobalScope-postMessage-options">postMessage</span>(<var>message</var>
101300- [, { <span data-x="dom-PostMessageOptions-transfer">transfer</span> } ])</code></dt>
101345+ <dt><code data-x=""><var>dedicatedWorkerGlobal</var>.<span subdfn data-x="dom-DedicatedWorkerGlobalScope-postMessage">postMessage</span>(<var>message</var> [, <var>transfer</var> ])</code></dt>
101346+ <dt><code data-x=""><var>dedicatedWorkerGlobal</var>.<span subdfn data-x="dom-DedicatedWorkerGlobalScope-postMessage-options">postMessage</span>(<var>message</var> [, { <span data-x="dom-StructuredSerializeOptions-transfer">transfer</span> } ])</code></dt>
101301101347 <dd><p>Clones <var>message</var> and transmits it to the <code>Worker</code> object associated
101302101348 with <var>dedicatedWorkerGlobal</var>. <var>transfer</var> can be passed as a list of objects
101303101349 that are to be transferred rather than cloned.</p></dd>
@@ -102007,7 +102053,7 @@ interface <dfn interface>Worker</dfn> : <span>EventTarget</span> {
102007102053 undefined <span data-x="dom-Worker-terminate">terminate</span>();
102008102054
102009102055 undefined <span data-x="dom-Worker-postMessage">postMessage</span>(any message, sequence<<span data-x="idl-object">object</span>> transfer);
102010- undefined <span data-x="dom-Worker-postMessage-options">postMessage</span>(any message, optional <span>PostMessageOptions </span> options = {});
102056+ undefined <span data-x="dom-Worker-postMessage-options">postMessage</span>(any message, optional <span>StructuredSerializeOptions </span> options = {});
102011102057 attribute <span>EventHandler</span> <span data-x="handler-Worker-onmessage">onmessage</span>;
102012102058 attribute <span>EventHandler</span> <span data-x="handler-Worker-onmessageerror">onmessageerror</span>;
102013102059};
@@ -102037,7 +102083,7 @@ enum <dfn enum>WorkerType</dfn> { "classic", "module" };
102037102083 <dd>Aborts <var>worker</var>'s associated global environment.</dd>
102038102084
102039102085 <dt><code data-x=""><var>worker</var>.<span subdfn data-x="dom-Worker-postMessage">postMessage</span>(<var>message</var> [, <var>transfer</var> ])</code></dt>
102040- <dt><code data-x=""><var>worker</var>.<span subdfn data-x="dom-Worker-postMessage-options">postMessage</span>(<var>message</var> [, { <span data-x="dom-PostMessageOptions -transfer">transfer</span> } ])</code></dt>
102086+ <dt><code data-x=""><var>worker</var>.<span subdfn data-x="dom-Worker-postMessage-options">postMessage</span>(<var>message</var> [, { <span data-x="dom-StructuredSerializeOptions -transfer">transfer</span> } ])</code></dt>
102041102087 <dd><p>Clones <var>message</var> and transmits it to <var>worker</var>'s global environment.
102042102088 <var>transfer</var> can be passed as a list of objects that are to be transferred rather than
102043102089 cloned.</p></dd>
0 commit comments