Skip to content

Commit

Permalink
Editorial: clarify worker event retargeting
Browse files Browse the repository at this point in the history
Previously, the standard used the ill-defined phrase "All messages received by that port must immediately be retargeted at the Worker object." This was not a sufficiently clear processing model. Instead, introduce the "message event target" concept to fire the events on the appropriate EventTarget.

This also adds linkable definitions for "inside port" and "outside port", and references them appropriately.
  • Loading branch information
nicolo-ribaudo authored Nov 21, 2024
1 parent e60b5e6 commit 531d153
Showing 1 changed file with 77 additions and 71 deletions.
148 changes: 77 additions & 71 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -112761,7 +112761,7 @@ import "https://example.com/foo/../module2.mjs";</code></pre>
</ol>

<p class="note">Certain <span>event handler IDL attributes</span> have additional requirements, in
particular the <code data-x="handler-MessagePort-onmessage">onmessage</code> attribute of
particular the <code data-x="handler-MessageEventTarget-onmessage">onmessage</code> attribute of
<code>MessagePort</code> objects.</p>

</div>
Expand Down Expand Up @@ -118994,13 +118994,13 @@ function handleMessage(event) {
<p>The key difference is that when using <code
data-x="dom-EventTarget-addEventListener">addEventListener()</code>, the <code
data-x="dom-MessagePort-start">start()</code> method must also be invoked. When using <code
data-x="handler-MessagePort-onmessage">onmessage</code>, the call to <code
data-x="handler-MessageEventTarget-onmessage">onmessage</code>, the call to <code
data-x="dom-MessagePort-start">start()</code> is implied.</p>

<p>The <code data-x="dom-MessagePort-start">start()</code> method, whether called explicitly or
implicitly (by setting <code data-x="handler-MessagePort-onmessage">onmessage</code>), starts the
flow of messages: messages posted on message ports are initially paused, so that they don't get
dropped on the floor before the script has had a chance to set up its handlers.</p>
implicitly (by setting <code data-x="handler-MessageEventTarget-onmessage">onmessage</code>),
starts the flow of messages: messages posted on message ports are initially paused, so that they
don't get dropped on the floor before the script has had a chance to set up its handlers.</p>

</div>

Expand Down Expand Up @@ -119142,7 +119142,29 @@ interface <dfn interface>MessageChannel</dfn> {

</div>

<h4 w-nodev><span id="the-messageeventtarget-abstract-interface"></span>The
<code>MessageEventTarget</code> mixin</h4>
<h4 w-dev>Properties present on <code>MessagePort</code>, <code>Worker</code>, and
<code>DedicatedWorkerGlobalScope</code></h4>

<pre><code class="idl">interface mixin <dfn interface>MessageEventTarget</dfn> {
attribute <span>EventHandler</span> <span data-x="handler-MessageEventTarget-onmessage">onmessage</span>;
attribute <span>EventHandler</span> <span data-x="handler-MessageEventTarget-onmessageerror">onmessageerror</span>;
};</code></pre>

<p>The following are the <span>event handlers</span> (and their corresponding <span data-x="event
handler event type">event handler event types</span>) <span w-nodev>that must be</span> supported,
as <span>event handler IDL attributes</span>, by <span w-nodev>objects implementing the
<code>MessageEventTarget</code> interface</span><span w-dev><code>MessagePort</code>,
<code>Worker</code>, and <code>DedicatedWorkerGlobalScope</code> objects</span>:</p>

<table>
<thead>
<tr><th><span data-x="event handlers">Event handler</span> <th><span>Event handler event type</span>
<tbody>
<tr><td><span id="handler-messageport-onmessage"></span><span id="handler-worker-onmessage"></span><span id="handler-dedicatedworkerglobalscope-onmessage"></span><dfn attribute for="MessageEventTarget"><code data-x="handler-MessageEventTarget-onmessage">onmessage</code></dfn> <td> <code data-x="event-message">message</code>
<tr><td><span id="handler-messageport-onmessageerror"></span><span id="handler-worker-onmessageerror"></span><span id="handler-dedicatedworkerglobalscope-onmessageerror"></span><dfn attribute for="MessageEventTarget"><code data-x="handler-MessageEventTarget-onmessageerror">onmessageerror</code></dfn> <td> <code data-x="event-messageerror">messageerror</code>
</table>

<h4>Message ports</h4>

Expand All @@ -119157,11 +119179,11 @@ interface <dfn interface>MessagePort</dfn> : <span>EventTarget</span> {
undefined <span data-x="dom-MessagePort-close">close</span>();

// event handlers
attribute <span>EventHandler</span> <span data-x="handler-MessagePort-onmessage">onmessage</span>;
attribute <span>EventHandler</span> <span data-x="handler-MessagePort-onmessageerror">onmessageerror</span>;
attribute <span>EventHandler</span> <span data-x="handler-MessagePort-onclose">onclose</span>;
};

<span>MessagePort</span> includes <span>MessageEventTarget</span>;

dictionary <dfn dictionary>StructuredSerializeOptions</dfn> {
sequence&lt;<span data-x="idl-object">object</span>&gt; <dfn dict-member for="StructuredSerializeOptions" data-x="dom-StructuredSerializeOptions-transfer">transfer</dfn> = [];
};</code></pre>
Expand All @@ -119187,6 +119209,11 @@ dictionary <dfn dictionary>StructuredSerializeOptions</dfn> {

<div w-nodev>

<p>Each <code>MessagePort</code> object has a <dfn>message event target</dfn> (a
<code>MessageEventTarget</code>), to which the <code data-x="event-message">message</code> and <code
data-x="event-messageerror">messageerror</code> events are dispatched. Unless otherwise
specified, it defaults to the <code>MessagePort</code> object itself.</p>

<p>Each <code>MessagePort</code> object can be entangled with another (a symmetric relationship).
Each <code>MessagePort</code> object also has a <span>task source</span> called the <dfn>port
message queue</dfn>, initially empty. A <span>port message queue</span> can be enabled or
Expand Down Expand Up @@ -119377,6 +119404,9 @@ dictionary <dfn dictionary>StructuredSerializeOptions</dfn> {
itself was transferred and thus all its tasks moved along with it.</p>
</li>

<li><p>Let <var>messageEventTarget</var> be <var>finalTargetPort</var>'s <span>message event
target</span>.</p></li>

<li><p>Let <var>targetRealm</var> be <var>finalTargetPort</var>'s <span
data-x="concept-relevant-realm">relevant realm</span>.</p></li>

Expand All @@ -119387,7 +119417,7 @@ dictionary <dfn dictionary>StructuredSerializeOptions</dfn> {

<p>If this throws an exception, catch it, <span data-x="concept-event-fire">fire an
event</span> named <code data-x="event-messageerror">messageerror</code> at
<var>finalTargetPort</var>, using <code>MessageEvent</code>, and then return.
<var>messageEventTarget</var>, using <code>MessageEvent</code>, and then return.
</li>

<li><p>Let <var>messageClone</var> be <var>deserializeRecord</var>.[[Deserialized]].</p></li>
Expand All @@ -119397,7 +119427,7 @@ dictionary <dfn dictionary>StructuredSerializeOptions</dfn> {
maintaining their relative order.</p></li>

<li><p><span data-x="concept-event-fire">Fire an event</span> named <code
data-x="event-message">message</code> at <var>finalTargetPort</var>, using
data-x="event-message">message</code> at <var>messageEventTarget</var>, using
<code>MessageEvent</code>, with the <code data-x="dom-MessageEvent-data">data</code> attribute
initialized to <var>messageClone</var> and the <code
data-x="dom-MessageEvent-ports">ports</code> attribute initialized to
Expand Down Expand Up @@ -119462,15 +119492,13 @@ dictionary <dfn dictionary>StructuredSerializeOptions</dfn> {
<thead>
<tr><th><span data-x="event handlers">Event handler</span> <th><span>Event handler event type</span>
<tbody>
<tr><td><dfn attribute for="MessagePort"><code data-x="handler-MessagePort-onmessage">onmessage</code></dfn> <td> <code data-x="event-message">message</code>
<tr><td><dfn attribute for="MessagePort"><code data-x="handler-MessagePort-onmessageerror">onmessageerror</code></dfn> <td> <code data-x="event-messageerror">messageerror</code>
<tr><td><dfn attribute for="MessagePort"><code data-x="handler-MessagePort-onclose">onclose</code></dfn> <td> <code data-x="event-close">close</code>
</table>

<p>The first time a <code>MessagePort</code> object's <code
data-x="handler-MessagePort-onmessage">onmessage</code> IDL attribute is set, the port's <span>port
message queue</span> must be enabled, as if the <code data-x="dom-MessagePort-start">start()</code>
method had been called.</p>
data-x="handler-MessageEventTarget-onmessage">onmessage</code> IDL attribute is set, the port's
<span>port message queue</span> must be enabled, as if the <code
data-x="dom-MessagePort-start">start()</code> method had been called.</p>

</div>

Expand Down Expand Up @@ -119797,8 +119825,8 @@ function showLogout() {

<p>The <code data-x="dom-Worker">Worker()</code> constructor call creates a worker and returns a
<code>Worker</code> object representing that worker, which is used to communicate with the worker.
That object's <code data-x="handler-Worker-onmessage">onmessage</code> event handler allows the
code to receive messages from the worker.</p>
That object's <code data-x="handler-MessageEventTarget-onmessage">onmessage</code> event handler
allows the code to receive messages from the worker.</p>

<p>The worker itself is as follows:</p>

Expand Down Expand Up @@ -120065,8 +120093,8 @@ function showLogout() {
other ports.</p>

<p>To receive messages from a dedicated worker, use the <code
data-x="handler-worker-onmessage">onmessage</code> <span data-x="event handler IDL attributes">event
handler IDL attribute</span> on the <code>Worker</code> object:</p>
data-x="handler-MessageEventTarget-onmessage">onmessage</code> <span data-x="event handler IDL
attributes">event handler IDL attribute</span> on the <code>Worker</code> object:</p>

<pre><code class="js">worker.onmessage = function (event) { ... };</code></pre>

Expand All @@ -120091,7 +120119,7 @@ function showLogout() {
}, [buffer]);</code></pre>

<p>To receive a message inside the worker, the <code
data-x="handler-DedicatedWorkerGlobalScope-onmessage">onmessage</code> <span data-x="event handler
data-x="handler-MessageEventTarget-onmessage">onmessage</code> <span data-x="event handler
IDL attributes">event handler IDL attribute</span> is used.</p>

<pre><code class="js">onmessage = function (event) { ... };</code></pre>
Expand Down Expand Up @@ -120295,18 +120323,14 @@ interface <dfn interface>DedicatedWorkerGlobalScope</dfn> : <span>WorkerGlobalSc
undefined <span data-x="dom-DedicatedWorkerGlobalScope-postMessage-options">postMessage</span>(any message, optional <span>StructuredSerializeOptions</span> options = {});

undefined <span data-x="dom-DedicatedWorkerGlobalScope-close">close</span>();
};

attribute <span>EventHandler</span> <span data-x="handler-DedicatedWorkerGlobalScope-onmessage">onmessage</span>;
attribute <span>EventHandler</span> <span data-x="handler-DedicatedWorkerGlobalScope-onmessageerror">onmessageerror</span>;
};</code></pre>

<p><code>DedicatedWorkerGlobalScope</code> objects act as if they had an implicit
<code>MessagePort</code> associated with them. This port is part of a channel that is set up when
the worker is created, but it is not exposed.<span w-nodev> This object must never be garbage
collected before the <code>DedicatedWorkerGlobalScope</code> object.</span></p>
<span>DedicatedWorkerGlobalScope</span> includes <span>MessageEventTarget</span>;</code></pre>

<p w-nodev>All messages received by that port must immediately be retargeted at the
<code>DedicatedWorkerGlobalScope</code> object.</p>
<p><code>DedicatedWorkerGlobalScope</code> objects have an associated <dfn>inside port</dfn> (a
<code>MessagePort</code>). This port is part of a channel that is set up when the worker is
created, but it is not exposed.<span w-nodev> This object must never be garbage collected before
the <code>DedicatedWorkerGlobalScope</code> object.</span></p>

<dl class="domintro">
<dt><code data-x=""><var>dedicatedWorkerGlobal</var>.<span subdfn data-x="dom-DedicatedWorkerGlobalScope-name">name</span></code></dt>
Expand Down Expand Up @@ -120363,21 +120387,6 @@ interface <dfn interface>DedicatedWorkerGlobalScope</dfn> : <span>WorkerGlobalSc

</div>

<p>The following are the <span>event handlers</span> (and their corresponding <span data-x="event
handler event type">event handler event types</span>) <span w-nodev>that must be</span> supported,
as <span>event handler IDL attributes</span>, by objects implementing the
<code>DedicatedWorkerGlobalScope</code> interface:</p>

<table>
<thead>
<tr><th><span data-x="event handlers">Event handler</span> <th><span>Event handler event type</span>
<tbody>
<tr><td><dfn attribute for="DedicatedWorkerGlobalScope"><code data-x="handler-DedicatedWorkerGlobalScope-onmessage">onmessage</code></dfn> <td> <code data-x="event-message">message</code>
<tr><td><dfn attribute for="DedicatedWorkerGlobalScope"><code data-x="handler-DedicatedWorkerGlobalScope-onmessageerror">onmessageerror</code></dfn> <td> <code data-x="event-messageerror">messageerror</code>
</table>



<h5>Shared workers and the <code subdfn>SharedWorkerGlobalScope</code> interface</h5>

<pre><code class="idl">[Global=(Worker,SharedWorker),Exposed=SharedWorker]
Expand Down Expand Up @@ -120733,7 +120742,17 @@ interface <dfn interface>SharedWorkerGlobalScope</dfn> : <span>WorkerGlobalScope
<var>inside settings</var>'s <span data-x="environment settings object's
realm">realm</span>.</p></li>

<li><p>Associate <var>inside port</var> with <var>worker global scope</var>.</p></li>
<li>
<p>If <var>shared</var> is false, then:</p>

<ol>
<li><p>Set <var>inside port</var>'s <span>message event target</span> to <var>worker global
scope</var>.</p></li>

<li><p>Set <var>worker global scope</var>'s <span>inside port</span> to <var>inside
port</var>.</p></li>
</ol>
</li>

<li><p><span>Entangle</span> <var>outside port</var> and <var>inside port</var>.</p></li>

Expand Down Expand Up @@ -120987,8 +121006,6 @@ interface <dfn interface>Worker</dfn> : <span>EventTarget</span> {

undefined <span data-x="dom-Worker-postMessage">postMessage</span>(any message, sequence&lt;<span data-x="idl-object">object</span>&gt; transfer);
undefined <span data-x="dom-Worker-postMessage-options">postMessage</span>(any message, optional <span>StructuredSerializeOptions</span> options = {});
attribute <span>EventHandler</span> <span data-x="handler-Worker-onmessage">onmessage</span>;
attribute <span>EventHandler</span> <span data-x="handler-Worker-onmessageerror">onmessageerror</span>;
};

dictionary <dfn dictionary>WorkerOptions</dfn> {
Expand All @@ -120999,7 +121016,8 @@ dictionary <dfn dictionary>WorkerOptions</dfn> {

enum <dfn enum>WorkerType</dfn> { "classic", "module" };

<span>Worker</span> includes <span>AbstractWorker</span>;</code></pre>
<span>Worker</span> includes <span>AbstractWorker</span>;
<span>Worker</span> includes <span>MessageEventTarget</span>;</code></pre>

<dl class="domintro">
<dt><code data-x=""><var>worker</var> = new <span subdfn data-x="dom-Worker">Worker</span>(<var>scriptURL</var> [, <var>options</var> ])</code></dt>
Expand All @@ -121024,17 +121042,15 @@ enum <dfn enum>WorkerType</dfn> { "classic", "module" };

<div w-nodev>

<p>Each <code>Worker</code> object has an associated <dfn for="Worker">outside port</dfn> (a
<code>MessagePort</code>). This port is part of a channel that is set up when the worker is
created, but it is not exposed. This object must never be garbage collected before the
<code>Worker</code> object.</p>

<p>The <dfn method for="Worker"><code data-x="dom-Worker-terminate">terminate()</code></dfn>
method, when invoked, must cause the <span>terminate a worker</span> algorithm to be run on the
worker with which the object is associated.</p>

<p><code>Worker</code> objects act as if they had an implicit <code>MessagePort</code> associated
with them. This port is part of a channel that is set up when the worker is created, but it is not
exposed. This object must never be garbage collected before the <code>Worker</code> object.</p>

<p>All messages received by that port must immediately be retargeted at the <code>Worker</code>
object.</p>

<p>The <dfn method for="Worker"><code
data-x="dom-Worker-postMessage">postMessage(<var>message</var>, <var>transfer</var>)</code></dfn>
and <dfn method for="Worker"><code
Expand All @@ -121043,8 +121059,8 @@ enum <dfn enum>WorkerType</dfn> { "classic", "module" };
they immediately invoked the respective <code
data-x="dom-MessagePort-postMessage">postMessage(<var>message</var>, <var>transfer</var>)</code>
and <code data-x="dom-MessagePort-postMessage-options">postMessage(<var>message</var>,
<var>options</var>)</code> on the port, with the same arguments, and returned the same return
value.</p>
<var>options</var>)</code> on <span>this</span>'s <span>outside port</span>, with the same
arguments, and returned the same return value.</p>

</div>

Expand All @@ -121057,19 +121073,6 @@ enum <dfn enum>WorkerType</dfn> { "classic", "module" };

</div>

<p>The following are the <span>event handlers</span> (and their corresponding <span data-x="event
handler event type">event handler event types</span>) <span w-nodev>that must be</span> supported,
as <span>event handler IDL attributes</span>, by objects implementing the <code>Worker</code>
interface:</p>

<table>
<thead>
<tr><th><span data-x="event handlers">Event handler</span> <th><span>Event handler event type</span>
<tbody>
<tr><td><dfn attribute for="Worker"><code data-x="handler-Worker-onmessage">onmessage</code></dfn> <td> <code data-x="event-message">message</code>
<tr><td><dfn attribute for="Worker"><code data-x="handler-Worker-onmessageerror">onmessageerror</code></dfn> <td> <code data-x="event-messageerror">messageerror</code>
</table>

<div w-nodev>

<hr>
Expand Down Expand Up @@ -121105,7 +121108,10 @@ enum <dfn enum>WorkerType</dfn> { "classic", "module" };
<li><p>Let <var>outside port</var> be a <span>new</span> <code>MessagePort</code> in <var>outside
settings</var>'s <span data-x="environment settings object's realm">realm</span>.</p></li>

<li><p>Associate the <var>outside port</var> with <var>worker</var>.</p></li>
<li><p>Set <var>outside port</var>'s <span>message event target</span> to
<var>worker</var>.</p></li>

<li><p>Set <var>worker</var>'s <span>outside port</span> to <var>outside port</var>.</p></li>

<li>
<p>Run this step <span>in parallel</span>:</p>
Expand Down

0 comments on commit 531d153

Please sign in to comment.