Short URL: http://html5.org/r/6273
| SVN | Bug | Comment | Time (UTC) |
|---|---|---|---|
| 6273 | 12947 | 2011-06-23 23:48 |
Index: source
===================================================================
--- source (revision 6272)
+++ source (revision 6273)
@@ -8616,25 +8616,68 @@
</div>
+
+ <h4>Transferable objects</h4>
+
+ <p>Some objects support being copied and closed in one operation.
+ This is called <i>transferring</i> the object, and is used in
+ particular to transfer ownership of unsharable or expensive
+ resources across worker boundaries.</p>
+
+ <pre class="idl">[NoInterfaceObject]
+interface <dfn>Transferable</dfn> { };</pre>
+
<div class="impl">
+ <p>To <dfn>transfer a <code>Transferable</code> object</dfn> to a
+ new owner, the user agent must run the steps defined for the type of
+ object in question. The steps will return a new object of the same
+ type, and will permanently neuter the original object. (This is an
+ irreversible and non-idempotent operation; once an object has been
+ transferred, it cannot be transferred, or indeed used, again.)</p>
+
+ </div>
+
+ <p>The following <code>Transferable</code> types exist:</p>
+
+ <ul class="brief">
+ <li><code>MessagePort</code>
+ <!--<li><code>ArrayBuffer</code>-->
+ </ul>
+
+
+ <div class="impl"><!-- should move down two sections XXX -->
+
<h4>Safe passing of structured data</h4>
<p>When a user agent is required to obtain a <dfn>structured
- clone</dfn> of a value, it must run the following algorithm, which
- either returns a separate value, or throws an exception.</p>
+ clone</dfn> of a value, optionally with a <i>transfer map</i>, it
+ must run the following algorithm, which either returns a separate
+ value, or throws an exception. If a <i>transfer map</i> is provided,
+ it consists of a association list of pairs of
+ <code>Transferable</code> objects; in each pair, one is the
+ <em>old</em> object and one is the <em>new</em> object.</p>
<ol>
<li><p>Let <var title="">input</var> be the value being
cloned.</p></li>
+ <li><p>Let <var title="">transfer map</var> be the <i>transfer
+ map</i> passed to the algorithm, if any, or the empty list
+ otherwise.</p></li>
+
<li><p>Let <var title="">memory</var> be an association list of
pairs of objects, initially empty. This is used to handle duplicate
references. In each pair of objects, one is called the
<em>source</em> object and the other the <em>destination</em>
object.</p></li>
+ <li><p>For each pair of objects in <var title="">transfer
+ map</var>, add a mapping from the old object (the source object) to
+ the new object (the destination object) to <var
+ title="">memory</var>.</p></li>
+
<li><p>Let <var title="">output</var> be the value resulting from
calling the <span>internal structured cloning algorithm</span> with
<var title="">input</var> as the "<var title="">input</var>"
@@ -8720,6 +8763,16 @@
<dd><p>Let <var title="">output</var> be a newly constructed <code>FileList</code> object containing a list of newly constructed <code>File</code> objects corresponding to the same underlying data as those in <var title="">input</var>, maintaining their relative order.</p></dd>
+<!--(when we add this, make sure to throw DATA_CLONE_ERR if these objects are already closed)
+ <dt>If <var title="">input</var> is an <code>ArrayBuffer</code> object</dt>
+
+ <dd><p>...</p></dd>
+
+ <dt>If <var title="">input</var> is an <code>ArrayBufferView</code> object</dt>
+
+ <dd><p>...</p></dd>
+-->
+
<dt>If <var title="">input</var> is an Array object</dt>
<dd><p>Let <var title="">output</var> be a newly constructed empty <code>Array</code> object.</p></dd>
@@ -10346,7 +10399,7 @@
and return true from the method.<!--SYNCLOAD Otherwise, continue running these
steps without yet returning.--></p></li>
- <li><p>Let <var title="">result</var> be an <code>Document</code>
+ <li><p>Let <var title="">result</var> be a <code>Document</code>
object.</p></li>
<li><p>Let <var title="">success</var> be false.</p></li>
@@ -70066,7 +70119,7 @@
any <span title="dom-showModalDialog">showModalDialog</span>(in DOMString url, in optional any argument<!--, in optional DOMString features-->);
<!--END w3c-html--><!--POSTMSG--> // <span>cross-document messaging</span>
- void <span title="dom-window-postMessage">postMessage</span>(in any message, in DOMString targetOrigin, in optional sequence<<span>MessagePort</span>> ports);
+ void <span title="dom-window-postMessage">postMessage</span>(in any message, in DOMString targetOrigin, in optional sequence<<span>Transferable</span>> transfer);
<!--START w3c-html--><!--POSTMSG-->
// <span>event handler IDL attributes</span>
attribute <span>Function</span>? <span title="handler-onabort">onabort</span>;
@@ -87839,7 +87892,7 @@
<pre class="idl">[Supplemental, NoInterfaceObject]
interface <dfn>DedicatedWorkerGlobalScope</dfn> : <span>WorkerGlobalScope</span> {
- void <span title="dom-DedicatedWorkerGlobalScope-postMessage">postMessage</span>(in any message, in optional sequence<<span>MessagePort</span>> ports);<!--
+ void <span title="dom-DedicatedWorkerGlobalScope-postMessage">postMessage</span>(in any message, in optional sequence<<span>Transferable</span>> transfer);<!--
<span>MessagePort</span> <span title="dom-DedicatedWorkerGlobalScope-startConversation">startConversation</span>(in any message);-->
attribute <span>Function</span>? <span title="handler-DedicatedWorkerGlobalScope-onmessage">onmessage</span>;
};</pre>
@@ -88488,7 +88541,7 @@
interface <dfn>Worker</dfn> : <span>AbstractWorker</span> {
void <span title="dom-Worker-terminate">terminate</span>();
- void <span title="dom-Worker-postMessage">postMessage</span>(in any message, in optional sequence<<span>MessagePort</span>> ports);<!--
+ void <span title="dom-Worker-postMessage">postMessage</span>(in any message, in optional sequence<<span>Transferable</span>> transfer);<!--
<span>MessagePort</span> <span title="dom-Worker-startConversation">startConversation</span>(in any message);-->
attribute <span>Function</span>? <span title="handler-Worker-onmessage">onmessage</span>;
};</pre>
@@ -91156,12 +91209,13 @@
<dl class="domintro">
- <dt><var title="">window</var> . <code title="dom-window-postMessage">postMessage</code>(<var title="">message</var>, <var title="">targetOrigin</var> [, <var title="">ports</var> ])</dt>
+ <dt><var title="">window</var> . <code title="dom-window-postMessage">postMessage</code>(<var title="">message</var>, <var title="">targetOrigin</var> [, <var title="">transfer</var> ])</dt>
<dd>
- <p>Posts a message, optionally with an array of ports, to the
- given window.</p>
+ <p>Posts a message to the given window. Objects listed in <var
+ title="">transfer</var> are transferred, not just cloned, meaning
+ that they are no longer usable on the sending side.</p>
<p>If the origin of the target window doesn't match the given
origin, the message is discarded, to avoid information leakage. To
@@ -91171,8 +91225,9 @@
state the origin, set the target origin to "<code
title="">/</code>".</p>
- <p>Throws an <code>INVALID_STATE_ERR</code> if the <var
- title="">ports</var> array contains duplicate ports.</p>
+ <p>Throws a <code>DATA_CLONE_ERR</code> if <var
+ title="">transfer</var> array contains duplicate objects or if
+ <var title="">message</var> could not be cloned.</p>
</dd>
@@ -91195,11 +91250,11 @@
<p>When a script invokes the <dfn
title="dom-window-postMessage"><code>postMessage(<var
title="">message</var>, <var title="">targetOrigin</var>, <var
- title="">ports</var>)</code></dfn> method (with two or three
+ title="">transfer</var>)</code></dfn> method (with two or three
arguments) on a <code>Window</code> object, the user agent must
- follow these steps:
+ follow these steps:</p>
- <ol>
+ <ol> <!-- a lot of this is similar or identical to port.postMessage -->
<li>
@@ -91213,40 +91268,52 @@
<li>
- <p>Let <var title="">message clone</var> be the result of
- obtaining a <span>structured clone</span> of the <var
- title="">message</var> argument. If this throws an exception, then
- throw that exception and abort these steps.</p>
+ <p>Let <var title="">new ports</var> be an empty array.</p>
</li>
<li>
- <p>If the <var title="">ports</var> argument is present but any
- <code>MessagePort</code> object is listed in <var
- title="">ports</var> more than once, or any of the
- <code>MessagePort</code> objects listed in <var
- title="">ports</var> have already been cloned once before, then
- throw an <code>INVALID_STATE_ERR</code> exception and abort these
- steps.</p>
+ <p>Let <var title="">transfer map</var> be an empty association
+ list of pairs of <code>Transferable</code> objects.</p>
</li>
<li>
- <p>Let <var title="">new ports</var> be an empty array.</p>
+ <p>If the method was invoked with a third argument <var
+ title="">transfer</var>, run these substeps:</p>
- <p>If the <var title="">ports</var> argument is present, then for
- each port in <var title="">ports</var> in turn, obtain a new port
- by <span title="clone a port">cloning</span> the port with the
- <code>Window</code> object on which the method was invoked as the
- owner of the clone, and append the clone to the <var title="">new
- ports</var> array.</p>
+ <ol>
- <p class="note">If the original <var title="">ports</var> argument
- was omitted or empty, then the <var title="">new ports</var> array
- will be empty.</p>
+ <li>
+ <p>If any object is listed in <var title="">transfer</var> more
+ than once, or any of the <code>Transferable</code> objects
+ listed in <var title="">transfer</var> have already been <span
+ title="transfer a Transferable object">transfered</span> once
+ before, then throw a <code>DATA_CLONE_ERR</code> exception and
+ abort these steps.</p>
+
+ </li>
+
+ <li>
+
+ <p>If the <var title="">transfer</var> argument is present, then
+ for each object in <var title="">transfer</var> in turn, obtain
+ a new object by <span title="transfer a Transferable
+ object">transferring</span> the object to the
+ <code>Window</code> object on which the method was invoked, and
+ add a mapping from the old object to the new transferred object
+ to <var title="">transfer map</var>. If the objects are
+ <code>MessagePort</code> objects, also append the new
+ transferred object to the <var title="">new ports</var>
+ array.</p>
+
+ </li>
+
+ </ol>
+
</li>
<li>
@@ -91258,6 +91325,16 @@
<li>
+ <p>Let <var title="">message clone</var> be the result of
+ obtaining a <span>structured clone</span> of the <var
+ title="">message</var> argument, with <var title="">transfer
+ map</var> as the <i>transfer map</i>. If this throws an exception,
+ then throw that exception and abort these steps.</p>
+
+ </li>
+
+ <li>
+
<p>Return from the <code
title="dom-window-postMessage">postMessage()</code> method, but
asynchronously continue running these steps.</p>
@@ -91456,7 +91533,7 @@
<pre class="idl">interface <dfn>MessagePort</dfn> {
<!-- v2-onclose readonly attribute boolean <span title="dom-MessagePort-active">active</span>;
---> void <span title="dom-MessagePort-postMessage">postMessage</span>(in any message, in optional sequence<<span>MessagePort</span>> ports);<!--
+--> void <span title="dom-MessagePort-postMessage">postMessage</span>(in any message, in optional sequence<<span>Transferable</span>> transfer);<!--
<span>MessagePort</span> <span title="dom-MessagePort-startConversation">startConversation</span>(in any message);-->
void <span title="dom-MessagePort-start">start</span>();
void <span title="dom-MessagePort-close">close</span>();
@@ -91464,7 +91541,8 @@
// event handlers
attribute <span>Function</span>? <span title="handler-MessagePort-onmessage">onmessage</span>;
};
-<span>MessagePort</span> implements <span>EventTarget</span>;</pre>
+<span>MessagePort</span> implements <span>EventTarget</span>;
+<span>MessagePort</span> implements <span>Transferable</span>;</pre>
<dl class="domintro">
<!-- v2-onclose
@@ -91476,16 +91554,18 @@
</dd>
-->
- <dt><var title="">port</var> . <code title="dom-MessagePort-poseMessage">postMessage</code>(<var title="">message</var> [, <var title="">ports</var>] )</dt>
+ <dt><var title="">port</var> . <code title="dom-MessagePort-postMessage">postMessage</code>(<var title="">message</var> [, <var title="">transfer</var>] )</dt>
<dd>
- <p>Posts a message through the channel, optionally with the given
- ports.</p>
+ <p>Posts a message through the channel. Objects listed in <var
+ title="">transfer</var> are transferred, not just cloned, meaning
+ that they are no longer usable on the sending side.</p>
- <p>Throws an <code>INVALID_STATE_ERR</code> if the <var
- title="">ports</var> array contains either duplicate ports, or the
- source or target port.</p>
+ <p>Throws a <code>DATA_CLONE_ERR</code> if <var
+ title="">transfer</var> array contains duplicate objects or the
+ source or target ports, or if <var title="">message</var> could
+ not be cloned.</p>
</dd>
@@ -91524,8 +91604,6 @@
instantiate a new <code>MessagePort</code> object, and let its owner
be <var title="">owner</var>.</p>
- <hr>
-
<p>When the user agent is to <dfn>entangle</dfn> two
<code>MessagePort</code> objects, it must run the following
steps:</p>
@@ -91551,8 +91629,6 @@
</ol>
- <hr>
-
<p>When the user agent is to <dfn>clone a port</dfn> <var
title="">original port</var>, with the clone being owned by <var
title="">owner</var>, it must run the following steps, which return
@@ -91595,6 +91671,13 @@
</ol>
+ <p id="transferMessagePort">To <span title="transfer a Transferable
+ object">transfer</span> a <code>MessagePort</code> object <var
+ title="">old</var> to a new owner <var title="">owner</var>, a user
+ agent must <span title="clone a port">clone</span> the <var
+ title="">old</var> object with the cloned being owned by <var
+ title="">owner</var>, and must return the resulting object.</p>
+
<hr>
<!-- v2-onclose
<p>The <dfn title="dom-MessagePort-active"><code>active</code></dfn>
@@ -91608,74 +91691,113 @@
method, when called on a port <var title="">source port</var>, must
cause the user agent to run the following steps:</p>
- <ol>
+ <ol> <!-- a lot of this is similar or identical to window.postMessage -->
<li><p>Let <var title="">target port</var> be the port with which
<var title="">source port</var> is entangled, if any.</p></li>
- <li><p>If the method was called with a second argument <var
- title="">ports</var>, then, if any <code>MessagePort</code> object
- is listed in <var title="">ports</var> more than once, if any of the
- <code>MessagePort</code> objects listed in <var title="">ports</var>
- have already been cloned once before, or if any of the entries
- in <var title="">ports</var> are either the <var title="">source
- port</var> or the <var title="">target port</var> (if any), then
- throw an <code>INVALID_STATE_ERR</code> exception.</p></li>
+ <li><p>Let <var title="">new owner</var> be the owner of <var
+ title="">target port</var>, if there is a <var title="">target
+ port</var>, or else some arbitrary owner. (This <var title="">new
+ owner</var> is used when transfering objects below. If there is no
+ <var title="">target port</var>, the <code>Transferable</code>
+ objects given in the second argument, if any, are still <span
+ title="transfer a Transferable object">transfered</span>, but since
+ they are then discarded, it doesn't matter where they are
+ transfered to.)</p></li>
- <li><p>Create an event that uses the <code>MessageEvent</code>
- interface, with the name <code
- title="event-message">message</code>, which does not bubble, is not
- cancelable, and has no default action.</p></li>
+ <li>
- <li><p>Let <var title="">message</var> be the method's first
- argument.</p></li>
+ <p>Let <var title="">new ports</var> be an empty array.</p>
- <li><p>Let <var title="">message clone</var> be the result of
- obtaining a <span>structured clone</span> of <var
- title="">message</var>. If this throws an exception, then throw
- that exception and abort these steps.</p></li>
+ </li>
- <li><p>Let the <code title="dom-MessageEvent-data">data</code>
- attribute of the event have the value of <var title="">message
- clone</var>.</p></li>
+ <li>
- <li><p>If the method was called with a second argument <var
- title="">ports</var>, then run the following substeps:</p>
+ <p>Let <var title="">transfer map</var> be an empty association
+ list of pairs of <code>Transferable</code> objects.</p>
+ </li>
+
+ <li>
+
+ <p>If the method was invoked with a second argument <var
+ title="">transfer</var>, run these substeps:</p>
+
<ol>
<li>
- <p>Let <var title="">new ports</var> be an empty array.</p>
+ <p>If any object is listed in <var title="">transfer</var> more
+ than once, or any of the <code>Transferable</code> objects
+ listed in <var title="">transfer</var> have already been <span
+ title="transfer a Transferable object">transfered</span> once
+ before, then throw a <code>DATA_CLONE_ERR</code> exception and
+ abort these steps.</p>
- <p>For each port in <var title="">ports</var> in turn,
- obtain a new port by <span title="clone a port">cloning</span>
- the port with the owner of the <var title="">target port</var>
- as the owner of the clone, and append the clone to the <var
- title="">new ports</var> array.</p>
+ </li>
- <p class="note">If the original <var title="">ports</var>
- array was empty, then the <var title="">new ports</var> array will
- also be empty.</p>
+ <li>
+ <p>If any of the objects in <var title="">transfer</var> are
+ either the <var title="">source port</var> or the <var
+ title="">target port</var> (if any), then throw a
+ <code>DATA_CLONE_ERR</code> exception and abort these
+ steps.</p></li>
+
</li>
<li>
- <p>Make <var title="">new ports</var> into a <span
- title="dfn-read-only-array">read only</span> array.</p>
+ <p>If the <var title="">transfer</var> argument is present, then
+ for each object in <var title="">transfer</var> in turn, obtain
+ a new object by <span title="transfer a Transferable
+ object">transferring</span> the object to <var title="">new
+ owner</var>, and add a mapping from the old object to the new
+ transferred object to <var title="">transfer map</var>. If the
+ objects are <code>MessagePort</code> objects, also append the
+ new transferred object to the <var title="">new ports</var>
+ array.</p>
</li>
- <li><p>Let the <code
- title="dom-MessageEvent-ports">ports</code>
- attribute of the event be the <var title="">new ports</var>
- array.</p></li>
-
</ol>
</li>
+ <li>
+
+ <p>Make <var title="">new ports</var> into a <span
+ title="dfn-read-only-array">read only</span> array.</p>
+
+ </li>
+
+ <li><p>Let <var title="">message</var> be the method's first
+ argument.</p></li>
+
+ <li>
+
+ <p>Let <var title="">message clone</var> be the result of
+ obtaining a <span>structured clone</span> of the <var
+ title="">message</var> argument, with <var title="">transfer
+ map</var> as the <i>transfer map</i>. If this throws an exception,
+ then throw that exception and abort these steps.</p>
+
+ </li>
+
+ <li><p>Create an event that uses the <code>MessageEvent</code>
+ interface, with the name <code
+ title="event-message">message</code>, which does not bubble, is not
+ cancelable, and has no default action.</p></li>
+
+ <li><p>Let the <code title="dom-MessageEvent-data">data</code>
+ attribute of the event have the value of <var title="">message
+ clone</var>.</p></li>
+
+ <li><p>Let the <code title="dom-MessageEvent-ports">ports</code>
+ attribute of the event be the <var title="">new ports</var>
+ array.</p></li>
+
<li><p>If there is no <var title="">target port</var> (i.e. if <var
title="">source port</var> is not entangled), then abort these
steps.</p></li> <!-- we don't raise an exception if there is no