Skip to content

Clarify that "this" is not available while in parallel #11129

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 14, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 44 additions & 32 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -1637,23 +1637,25 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<li><p>Let <var>p</var> be a new promise created in <span>this</span>'s <span
data-x="concept-relevant-realm">relevant realm</span>.</p></li>

<li><p>Let <var>global</var> be <span>this</span>'s <span>relevant global
object</span>.</p></li>

<li>
<p>Run the following steps <span>in parallel</span>:</p>

<ol>
<li><p>If <var>nameList</var> <span data-x="list contains">contains</span> <var>name</var>,
then <span>queue a global task</span> on the <span>DOM manipulation task source</span> given
<span>this</span>'s <span>relevant global object</span> to reject <var>p</var> with a
<code>TypeError</code>, and abort these steps.</p></li>
<var>global</var> to reject <var>p</var> with a <code>TypeError</code>, and abort these
steps.</p></li>

<li><p>Do some potentially lengthy work.</p></li>

<li><p><span data-x="list append">Append</span> <var>name</var> to
<var>nameList</var>.</p></li>

<li><p><span>Queue a global task</span> on the <span>DOM manipulation task source</span>
given <span>this</span>'s <span>relevant global object</span> to resolve <var>p</var> with
undefined.</p></li>
<li><p><span>Queue a global task</span> on the <span>DOM manipulation task source</span> given
<var>global</var> to resolve <var>p</var> with undefined.</p></li>
</ol>
</li>

Expand All @@ -1671,23 +1673,25 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<li><p>Let <var>p</var> be a new promise created in <span>this</span>'s <span
data-x="concept-relevant-realm">relevant realm</span>.</p></li>

<li><p>Let <var>global</var> be <span>this</span>'s <span>relevant global
object</span>.</p></li>

<li>
<p><mark><span>Enqueue the following steps</span> to <var>nameListQueue</var>:</mark></p>

<ol>
<li><p>If <var>nameList</var> <span data-x="list contains">contains</span> <var>name</var>,
then <span>queue a global task</span> on the <span>DOM manipulation task source</span> given
<span>this</span>'s <span>relevant global object</span> to reject <var>p</var> with a
<code>TypeError</code>, and abort these steps.</p></li>
<var>global</var> to reject <var>p</var> with a <code>TypeError</code>, and abort these
steps.</p></li>

<li><p>Do some potentially lengthy work.</p></li>

<li><p><span data-x="list append">Append</span> <var>name</var> to
<var>nameList</var>.</p></li>

<li><p><span>Queue a global task</span> on the <span>DOM manipulation task source</span>
given <span>this</span>'s <span>relevant global object</span> to resolve <var>p</var> with
undefined.</p></li>
<li><p><span>Queue a global task</span> on the <span>DOM manipulation task source</span> given
<var>global</var> to resolve <var>p</var> with undefined.</p></li>
</ol>
</li>

Expand Down Expand Up @@ -72160,6 +72164,8 @@ interface <dfn interface>OffscreenCanvas</dfn> : <span>EventTarget</span> {

<li><p>Let <var>result</var> be a new promise object.</p></li>

<li><p>Let <var>global</var> be <span>this</span>'s <span>relevant global object</span>.</p></li>

<li>
<p>Run these steps <span>in parallel</span>:</p>

Expand All @@ -72171,14 +72177,14 @@ interface <dfn interface>OffscreenCanvas</dfn> : <span>EventTarget</span> {

<li>
<p><span>Queue a global task</span> on the <span>canvas blob serialization task source</span>
given <span>this</span>'s <span>relevant global object</span> to run these steps:</p>
given <var>global</var> to run these steps:</p>

<ol>
<li><p>If <var>file</var> is null, then reject <var>result</var> with an
<span>"<code>EncodingError</code>"</span> <code>DOMException</code>.</p></li>

<li><p>Otherwise, resolve <var>result</var> with a new <code>Blob</code> object, created in
<span>this</span>'s <span data-x="concept-relevant-realm">relevant realm</span>, representing
<var>global</var>'s <span data-x="concept-relevant-realm">relevant realm</span>, representing
<var>file</var>. <ref>FILEAPI</ref></p></li>
</ol>
</li>
Expand Down Expand Up @@ -114024,6 +114030,10 @@ import "https://example.com/foo/../module2.mjs";</code></pre>
Doing so would create data races observable to JavaScript code, since after all, your algorithm
steps are running <em><span>in parallel</span></em> to the JavaScript code.</p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the new sentence would probably be best as a new paragraph. The parenthetical and the sentence about data races seem a bit awkward after the new interruption.

Copy link
Member Author

@domfarolino domfarolino Mar 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. I guess one interesting thing is that this paragraph says we cannot use "global" objects while in parallel, while we clearly agree that we actually make an exception for globals, since that's the only way we can schedule things back on the main thread. In other words, we are assuming #6475 (comment) to be true—that most accesses to a global, especially when scheduling tasks, are atomic. That's the right assumption make IMO. I'm just trying to think if we should state this assumption/exception clearly in this paragraph too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's a case to be made for porting (some much shorter version of) w3c/ServiceWorker#1755 (comment) into the spec, to acknowledge the messy reality and carve out some clearer exceptions. But that's a more ambitious followup, I think.


<p>By extension, you cannot access Web IDL's <span>this</span> value from steps running <span>in
parallel</span>, even if those steps were activated by an algorithm that <em>does</em> have access
to the <span>this</span> value.</p>

<p>You can, however, manipulate specification-level data structures and values from
<cite>Infra</cite>, as those are realm-agnostic. They are never directly exposed to JavaScript without
a specific conversion taking place (often <span data-x="concept-idl-convert">via Web IDL</span>).
Expand Down Expand Up @@ -123951,48 +123961,50 @@ dictionary <dfn dictionary>WorkletOptions</dfn> {

<li><p>Let <var>promise</var> be a new promise.</p></li>

<li><p>Let <var>workletInstance</var> be <span>this</span>.</p></li>

<li>
<p>Run the following steps <span>in parallel</span>:</p>

<ol>
<li>
<p>If <span>this</span>'s <span data-x="concept-Worklet-global-scopes">global scopes</span>
<span data-x="list is empty">is empty</span>, then:</p>
<p>If <var>workletInstance</var>'s <span data-x="concept-Worklet-global-scopes">global
scopes</span> <span data-x="list is empty">is empty</span>, then:</p>

<ol>
<li><p><span>Create a worklet global scope</span> given <span>this</span>.</p></li>
<li><p><span>Create a worklet global scope</span> given <var>workletInstance</var>.</p></li>

<li><p>Optionally, <span data-x="create a worklet global scope">create</span> additional
global scope instances given <span>this</span>, depending on the specific worklet in question
and its specification.</p></li>
global scope instances given <var>workletInstance</var>, depending on the specific worklet in
question and its specification.</p></li>

<li><p>Wait for all steps of the <span data-x="create a worklet global scope">creation</span>
process(es) — including those taking place within the <span data-x="worklet agent">worklet
agents</span> — to complete, before moving on.</p></li>
</ol>
</li>

<li><p>Let <var>pendingTasks</var> be <span>this</span>'s <span
<li><p>Let <var>pendingTasks</var> be <var>workletInstance</var>'s <span
data-x="concept-Worklet-global-scopes">global scopes</span>'s <span data-x="list
size">size</span>.</p></li>

<li><p>Let <var>addedSuccessfully</var> be false.</p></li>

<li>
<p><span data-x="list iterate">For each</span> <var>workletGlobalScope</var> of
<span>this</span>'s <span data-x="concept-Worklet-global-scopes">global scopes</span>,
<span>queue a global task</span> on the <span>networking task source</span> given
<var>workletGlobalScope</var> to <span>fetch a worklet script graph</span> given
<var>moduleURLRecord</var>, <var>outsideSettings</var>, <span>this</span>'s <span>worklet
destination type</span>, <var>options</var>["<code
<var>workletInstance</var>'s <span data-x="concept-Worklet-global-scopes">global
scopes</span>, <span>queue a global task</span> on the <span>networking task source</span>
given <var>workletGlobalScope</var> to <span>fetch a worklet script graph</span> given
<var>moduleURLRecord</var>, <var>outsideSettings</var>, <var>workletInstance</var>'s
<span>worklet destination type</span>, <var>options</var>["<code
data-x="dom-WorkletOptions-credentials">credentials</code>"], <var>workletGlobalScope</var>'s
<span>relevant settings object</span>, <span>this</span>'s <span
<span>relevant settings object</span>, <var>workletInstance</var>'s <span
data-x="concept-Worklet-module-responses-map">module responses map</span>, and the following
steps given <var>script</var>:</p>

<p class="note">Only the first of these fetches will actually perform a network request; the
ones for other <code>WorkletGlobalScope</code>s will reuse <span
data-x="concept-response">responses</span> from <span>this</span>'s <span
data-x="concept-response">responses</span> from <var>workletInstance</var>'s <span
data-x="concept-Worklet-module-responses-map">module responses map</span>.</p>

<ol>
Expand All @@ -124002,7 +124014,7 @@ dictionary <dfn dictionary>WorkletOptions</dfn> {
<ol>
<li>
<p><span>Queue a global task</span> on the <span>networking task source</span> given
<span>this</span>'s <span>relevant global object</span> to perform the following
<var>workletInstance</var>'s <span>relevant global object</span> to perform the following
steps:</p>

<ol>
Expand Down Expand Up @@ -124030,7 +124042,7 @@ dictionary <dfn dictionary>WorkletOptions</dfn> {
<ol>
<li>
<p><span>Queue a global task</span> on the <span>networking task source</span> given
<span>this</span>'s <span>relevant global object</span> to perform the following
<var>workletInstance</var>'s <span>relevant global object</span> to perform the following
steps:</p>

<ol>
Expand All @@ -124056,8 +124068,8 @@ dictionary <dfn dictionary>WorkletOptions</dfn> {

<ol>
<li><p><span data-x="list append">Append</span> <var>moduleURLRecord</var> to
<span>this</span>'s <span data-x="concept-Worklet-added-modules-list">added modules
list</span>.</p></li>
<var>workletInstance</var>'s <span data-x="concept-Worklet-added-modules-list">added
modules list</span>.</p></li>

<li><p>Set <var>addedSuccessfully</var> to true.</p></li>
</ol>
Expand All @@ -124066,9 +124078,9 @@ dictionary <dfn dictionary>WorkletOptions</dfn> {
<li><p><span>Run a module script</span> given <var>script</var>.</p></li>

<li>
<p><span>Queue a global task</span> on the
<span>networking task source</span> given <span>this</span>'s <span>relevant global
object</span> to perform the following steps:</p>
<p><span>Queue a global task</span> on the <span>networking task source</span> given
<var>workletInstance</var>'s <span>relevant global object</span> to perform the following
steps:</p>

<ol>
<li>
Expand Down