Skip to content

Commit

Permalink
Fix StructuredDeserializeWithTransfer()
Browse files Browse the repository at this point in the history
97d644c was more breaking than planned as, e.g.,

postMessage(null, "*", [new ArrayBuffer(2)])
postMessage(null, "*", [new MessageChannel().port1])

still need to detach (and visibly transfer in case of MessagePort) the values given in the third argument.

See whatwg#793 (comment) for additional context.
  • Loading branch information
annevk authored and Alice Boxhall committed Jan 7, 2019
1 parent 2bef2b5 commit 3a4e8d9
Showing 1 changed file with 64 additions and 68 deletions.
132 changes: 64 additions & 68 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -8532,51 +8532,7 @@ o.myself = o;</pre>

<li><p>Let <var>value</var> be an uninitialized value.</p></li>

<li>
<p>If <var>serialized</var> contains a [[TransferConsumed]] field, then:</p>

<ol>
<li><p>Assert: <var>serialized</var>.[[TransferConsumed]] is false. (It must be impossible to
get in a situation where <span>StructuredDeserialize</span> is being called multiple times on
the same serialization, if that serialization contains transfer data holders.)</p></li>

<li><p>Set <var>serialized</var>.[[TransferConsumed]] to true.</p></li>

<li>
<p>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 is
<var>serialized</var>.[[ArrayBufferData]], and whose [[ArrayBufferByteLength]] internal slot
value is <var>serialized</var>.[[ArrayBufferByteLength]].</p>

<p class="note">In cases where the original memory occupied by [[ArrayBufferData]] is
accessible during the deserialization, this step is unlikely to throw an exception, as no new
memory needs to be allocated: the memory occupied by [[ArrayBufferData]] is instead just
getting transferred into the new ArrayBuffer. This could be true, for example, when both the
source and target Realms are in the same process.</p>
</li>

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

<ol>
<li><p>Let <var>interfaceName</var> be <var>serialized</var>.[[Type]].</p></li>

<li><p>If the interface identified by <var>interfaceName</var> is not exposed in
<var>targetRealm</var>, then throw a <span>"<code>DataCloneError</code>"</span>
<code>DOMException</code>.</p></li>

<li><p>Set <var>value</var> to a new instance of the interface identified by
<var>interfaceName</var>, created in <var>targetRealm</var>.</p></li>

<li><p>Perform the appropriate <span>transfer-receiving steps</span> for the interface
identified by <var>interfaceName</var> given <var>serialized</var> and
<var>value</var>.</p></li>
</ol>
</li>
</ol>
</li>

<li><p>Otherwise, if <var>serialized</var>.[[Type]] is "primitive", then set <var>value</var> to
<li><p>If <var>serialized</var>.[[Type]] is "primitive", then set <var>value</var> to
<var>serialized</var>.[[Value]].</p>

<li><p>Otherwise, if <var>serialized</var>.[[Type]] is "Boolean", then set <var>value</var> to a new Boolean object in
Expand Down Expand Up @@ -8843,10 +8799,13 @@ o.myself = o;</pre>
<var>transferable</var>.<span>[[Detached]]</span> is true, then throw a
<span>"<code>DataCloneError</code>"</span> <code>DOMException</code>.</p></li>

<li><p>Let <var>placeholder</var> be a user-agent-defined placeholder object.</p></li>
<li>
<p><span data-x="map set">Set</span> <var>memory</var>[<var>transferable</var>] to {
[[Type]]: an uninitialized value }.</p>

<li><p><span data-x="map set">Set</span> <var>memory</var>[<var>transferable</var>] to
<var>placeholder</var>.</p></li>
<p class="note"><var>transferable</var> is not transferred yet as that operation has side
effects and <span>StructuredSerializeInternal</span> can throw.</p>
</li>
</ol>
</li>

Expand All @@ -8861,17 +8820,19 @@ o.myself = o;</pre>
<var>transferList</var>:</p>

<ol>
<li><p>Let <var>placeholder</var> be <var>memory</var>[<var>transferable</var>].</p></li>

<li><p>Let <var>dataHolder</var> be an uninitialized value.</p></li>
<li><p>Let <var>dataHolder</var> be <var>memory</var>[<var>transferable</var>].</p></li>

<li>
<p>If <var>transferable</var> has an [[ArrayBufferData]] internal slot, then:</p>

<ol>
<li><p>Set <var>dataHolder</var> to { [[TransferConsumed]]: false, [[Type]]: "ArrayBuffer",
[[ArrayBufferData]]: <var>transferable</var>.[[ArrayBufferData]], [[ArrayBufferByteLength]]:
<var>transferable</var>.[[ArrayBufferByteLength]] }.</p></li>
<li><p>Set <var>dataHolder</var>.[[Type]] to "ArrayBuffer".</p></li>

<li><p>Set <var>dataHolder</var>.[[ArrayBufferData]] to
<var>transferable</var>.[[ArrayBufferData]].</p></li>

<li><p>Set <var>dataHolder</var>.[[ArrayBufferByteLength]] to
<var>transferable</var>.[[ArrayBufferByteLength]].</p></li>

<li><p>Perform ! <span>DetachArrayBuffer</span>(<var>transferable</var>).</p></li>
</ol>
Expand All @@ -8887,8 +8848,7 @@ o.myself = o;</pre>
<li><p>Let <var>interfaceName</var> be the identifier of the <span>primary interface</span>
of <var>transferable</var>.</p></li>

<li><p>Set <var>dataHolder</var> to { [[TransferConsumed]]: false, [[Type]]:
<var>interfaceName</var> }.</p></li>
<li><p>Set <var>dataHolder</var>.[[Type]] to <var>interfaceName</var>.</p></li>

<li><p>Perform the appropriate <span>transfer steps</span> for the interface identified by
<var>interfaceName</var>, given <var>transferable</var> and <var>dataHolder</var>.</p></li>
Expand All @@ -8897,9 +8857,6 @@ o.myself = o;</pre>
</ol>
</li>

<li><p>Within <var>serialized</var>, replace all instances of <var>placeholder</var> with
<var>dataHolder</var>.</p></li>

<li><p><span data-x="list append">Append</span> <var>dataHolder</var> to
<var>transferDataHolders</var>.</p></li>
</ol>
Expand All @@ -8918,15 +8875,13 @@ o.myself = o;</pre>
<li>
<p>Let <var>memory</var> be an empty <span data-x="ordered map">map</span>.</p>

<p class="note">In addition to how it is used normally by <span>StructuredDeserialize</span>, in
this algorithm <var>memory</var> is also used to help us determine the list of transferred
values.</p>
<p class="note">Analogous to <span>StructuredSerializeWithTransfer</span>, in addition to how it
is used normally by <span>StructuredDeserialize</span>, in this algorithm <var>memory</var> is
also used to ensure that <span>StructuredDeserialize</span> ignores items in
<var>serializeWithTransferResult</var>.[[TransferDataHolders]], and let us do our own handling
instead.</p>
</li>

<li><p>Let <var>deserialized</var> be ?
<span>StructuredDeserialize</span>(<var>serializeWithTransferResult</var>.[[Serialized]],
<var>targetRealm</var>, <var>memory</var>).</p></li>

<li><p>Let <var>transferredValues</var> be a new empty <span
data-x="js-List">List</span>.</p></li>

Expand All @@ -8935,11 +8890,52 @@ o.myself = o;</pre>
<var>serializeWithTransferResult</var>.[[TransferDataHolders]]:</p>

<ol>
<li><p><span data-x="list append">Append</span>
<var>memory</var>[<var>transferDataHolder</var>] to <var>transferredValues</var>.</p></li>
<li><p>Let <var>value</var> be an uninitialized value.</p></li>

<li>
<p>If <var>transferDataHolder</var>.[[Type]] is "ArrayBuffer", then set <var>value</var> to a
new ArrayBuffer object in <var>targetRealm</var> whose [[ArrayBufferData]] internal slot value
is <var>transferDataHolder</var>.[[ArrayBufferData]], and whose [[ArrayBufferByteLength]]
internal slot value is <var>transferDataHolder</var>.[[ArrayBufferByteLength]].</p>

<p class="note">In cases where the original memory occupied by [[ArrayBufferData]] is
accessible during the deserialization, this step is unlikely to throw an exception, as no new
memory needs to be allocated: the memory occupied by [[ArrayBufferData]] is instead just
getting transferred into the new ArrayBuffer. This could be true, for example, when both the
source and target Realms are in the same process.</p>
</li>

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

<ol>
<li><p>Let <var>interfaceName</var> be <var>transferDataHolder</var>.[[Type]].</p></li>

<li><p>If the interface identified by <var>interfaceName</var> is not exposed in
<var>targetRealm</var>, then throw a <span>"<code>DataCloneError</code>"</span>
<code>DOMException</code>.</p></li>

<li><p>Set <var>value</var> to a new instance of the interface identified by
<var>interfaceName</var>, created in <var>targetRealm</var>.</p></li>

<li><p>Perform the appropriate <span>transfer-receiving steps</span> for the interface
identified by <var>interfaceName</var> given <var>transferDataHolder</var> and
<var>value</var>.</p></li>
</ol>
</li>

<li><p><span data-x="map set">Set</span> <var>memory</var>[<var>transferDataHolder</var>] to
<var>value</var>.</p></li>

<li><p><span data-x="list append">Append</span> <var>value</var> to
<var>transferredValues</var>.</p></li>
</ol>
</li>

<li><p>Let <var>deserialized</var> be ?
<span>StructuredDeserialize</span>(<var>serializeWithTransferResult</var>.[[Serialized]],
<var>targetRealm</var>, <var>memory</var>).</p></li>

<li><p>Return { [[Deserialized]]: <var>deserialized</var>, [[TransferredValues]]:
<var>transferredValues</var> }.</p></li>
</ol>
Expand Down

0 comments on commit 3a4e8d9

Please sign in to comment.