Skip to content

Commit

Permalink
Make StructuredClone throw if an object is not explicitly cloneable
Browse files Browse the repository at this point in the history
StructuredClone used to throw for “host objects” (now objects with a [[Clone]] internal method) and
objects whose [[Class]] was not “Object” (now objects which have an internal slot other than
[[Prototype]] or [[Extensible]]). This commit restores that behavior.

This also fixes the invocation of [[Clone]] by passing memory too.

This regressed in bfb960c.

This fixes #766.

This  affects Chrome. Edge and Firefox already do the right thing.
  • Loading branch information
annevk committed Mar 3, 2016
1 parent 0184feb commit 32e3822
Showing 1 changed file with 33 additions and 15 deletions.
48 changes: 33 additions & 15 deletions source
Expand Up @@ -7607,16 +7607,21 @@ interface <dfn>DOMStringMap</dfn> {
<span>cloneable objects</span> and not all aspects of objects that are <span>cloneable
objects</span> are necessarily preserved when cloned.</p>

<p>IDL-defined cloneable objects are <span>cloneable objects</span> defined through IDL that have
the following internal method:</p>
<p>IDL-defined objects have the following internal method:</p>

<p>[[<dfn>Clone</dfn>]] ( <var>targetRealm</var>, <var>memory</var> )</p>
<!-- For /deepClone/ support /memory/ would need to be changed as per StructuredClone or we would
need to add a [[DeepClone]] abstract operation. -->

<p>IDL-defined clonable objects must define the [[<span>Clone</span>]] internal method such that
it either throws or returns a clone of <b>this</b>, created in <var>targetRealm</var>. It is up to
IDL-defined cloneable objects to define what cloning means for them.</p>
<p>Unless specified otherwise, invoking the [[<span>Clone</span>]] internal method must throw a
<code>DataCloneError</code> exception. (By default, IDL-defined objects are not <span>cloneable
objects</span>.)</p>

<p>IDL-defined cloneable objects are <span>cloneable objects</span> defined through IDL whose
[[<span>Clone</span>]] internal method is specified to run a series of steps. The result of
running those steps must be a thrown exception or a clone of <b>this</b>, created in
<var>targetRealm</var>. It is up to IDL-defined cloneable objects to define what cloning means for
them.</p>

<p>Objects defined in the JavaScript specification are handled by the <span>StructuredClone</span>
abstract operation directly.</p>
Expand All @@ -7640,11 +7645,15 @@ interface <dfn>DOMStringMap</dfn> {
<!-- If we ever add /memory/ support here we need to update the language around replacing
references -->

<p class="note">Whereas all IDL-defined objects have a [[<span>Clone</span>]] internal method, not
all have a [[<span>Detached</span>]] internal slot and a [[<span>Transfer</span>]] internal
method.</p>

<p>IDL-defined transferable objects must define the [[<span>Transfer</span>]] internal method such
that it either throws or returns a clone of <b>this</b>, created in <var>targetRealm</var>, with
<b>this</b>'s underlying data shared with the return value, and <b>this</b>'s
[[<span>Detached</span>]] internal slot value set to true. It is up to IDL-defined transferable
objects to define what transfering means for them.</p>
that it either throws an exception or returns a clone of <b>this</b>, created in
<var>targetRealm</var>, with <b>this</b>'s underlying data shared with the return value, and
<b>this</b>'s [[<span>Detached</span>]] internal slot value set to true. It is up to IDL-defined
transferable objects to define what transfering means for them.</p>

<p>Objects defined in the JavaScript specification are handled by the
<span>StructuredCloneWithTransfer</span> abstract operation directly. (Technically, by
Expand Down Expand Up @@ -7853,17 +7862,26 @@ interface <dfn>DOMStringMap</dfn> {
</ol>
</li>

<li><p>Otherwise, if <var>input</var> has a [[<span>Clone</span>]] internal method, then let
<var>output</var> be ? <var>input</var>.[[<span>Clone</span>]](<var>targetRealm</var>,
<var>memory</var>).</p></li>

<li><p>Otherwise, if <span>IsCallable</span>(<var>input</var>) is true, then throw a
<code>DataCloneError</code> exception.</p></li>

<li><p>Otherwise, if <var>input</var> has an [[ErrorData]] internal slot, then throw a
<code>DataCloneError</code> exception.</p></li>
<li>
<p>Otherwise, if <var>input</var> has any internal slot other than [[Prototype]] or
[[Extensible]], then throw a <code>DataCloneError</code> exception.</p>

<li><p>Otherwise, if <var>input</var> has a [[<span>Clone</span>]] internal method, then let
<var>output</var> be ? <var>input</var>.[[<span>Clone</span>]](<var>targetRealm</var>).</p></li>
<p class="example">For instance, a [[PromiseState]] or [[WeakMapData]] internal slot.</p>
</li>

<li><p>Otherwise, if <var>input</var> is an exotic object, then throw a
<code>DataCloneError</code> exception.</p></li>
<li>
<p>Otherwise, if <var>input</var> is an exotic object, then throw a
<code>DataCloneError</code> exception.</p>

<p class="example">For instance, a proxy object.</p>
</li>

<li>
<p>Otherwise:</p>
Expand Down

0 comments on commit 32e3822

Please sign in to comment.