HTML5 Tracker

Diff (omit for latest revision)
Filter

Short URL: http://html5.org/r/6273

SVNBugCommentTime (UTC)
627312947[Gecko] [Internet Explorer] [Opera] [Webkit] add infrastructure to postMessage() to support ArrayBuffer cloning2011-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&lt;<span>MessagePort</span>&gt; ports);
+  void <span title="dom-window-postMessage">postMessage</span>(in any message, in DOMString targetOrigin, in optional sequence&lt;<span>Transferable</span>&gt; 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&lt;<span>MessagePort</span>&gt; ports);<!--
+  void <span title="dom-DedicatedWorkerGlobalScope-postMessage">postMessage</span>(in any message, in optional sequence&lt;<span>Transferable</span>&gt; 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&lt;<span>MessagePort</span>&gt; ports);<!--
+  void <span title="dom-Worker-postMessage">postMessage</span>(in any message, in optional sequence&lt;<span>Transferable</span>&gt; 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&lt;<span>MessagePort</span>&gt; ports);<!--
+-->  void <span title="dom-MessagePort-postMessage">postMessage</span>(in any message, in optional sequence&lt;<span>Transferable</span>&gt; 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

|