Skip to content
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

Require support for AsyncContext #9408

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
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
123 changes: 98 additions & 25 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -3080,6 +3080,16 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<ul class="brief">
<li>The <dfn data-x-href="https://tc39.es/proposal-resizablearraybuffer/#sec-isarraybufferviewoutofbounds">IsArrayBufferViewOutOfBounds</dfn> abstract operation</li>
</ul>

<p>User agents that support JavaScript must also implement the <cite>AsyncContext</cite>
proposal. The following terms are defined there, and used in this specification:
<ref>JSASYNCCONTEXT</ref></p>

<ul class="brief">
<li>The <dfn data-x="js-AsyncContextSnapshot" data-x-href="https://tc39.es/proposal-async-context/#sec-asynccontext-snapshot">AsyncContextSnapshot</dfn> abstract operation</li>
<li>The <dfn data-x="js-AsyncContextSwap" data-x-href="https://tc39.es/proposal-async-context/#sec-asynccontext-swap">AsyncContextSwap</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.es/proposal-async-context/#sec-asynccontext-mapping-record-specification-type">Async Context Mapping Record</dfn> specification type</li>
</ul>
</dd>

<dt>WebAssembly</dt>
Expand Down Expand Up @@ -105767,19 +105777,28 @@ dictionary <dfn dictionary>ErrorEventInit</dfn> : <span>EventInit</span> {
<var>global</var> to run the following substep:</p>

<ol>
<li><p>For each promise <var>p</var> in <var>list</var>:</p>
<li><p>For each tuple <var>element</var> in <var>list</var>:</p>

<ol>
<li><p>Let <var>p</var> be <var>element</var>[0].

<li><p>If <var>p</var>'s [[PromiseIsHandled]] internal slot is true, continue to the next
iteration of the loop.</p></li>

<li><p>Let <var>previousContextMapping</var> be <span
data-x="js-AsyncContextSwap">AsyncContextSwap</span>(<var>element</var>[1]).</p></li>

<li><p>Let <var>notHandled</var> be the result of <span data-x="concept-event-fire">firing an
event</span> named <code data-x="event-unhandledrejection">unhandledrejection</code> at
<var>global</var>, using <code>PromiseRejectionEvent</code>, with the <code
data-x="dom-Event-cancelable">cancelable</code> attribute initialized to true, the <code
data-x="dom-PromiseRejectionEvent-promise">promise</code> attribute initialized to
<var>p</var>, and the <code data-x="dom-PromiseRejectionEvent-reason">reason</code> attribute
initialized to the value of <var>p</var>'s [[PromiseResult]] internal slot.</p></li>
initialized to the value of <var>p</var>'s [[PromiseResult]] internal slot, with
useCallerAsyncContextFlag set.</p></li>

<li><p>Perform <span data-x="js-AsyncContextSwap">AsyncContextSwap</span>(<var
>previousContextMapping</var>).</p></li>

<li><p>If <var>notHandled</var> is false, then the promise rejection is <i
data-x="concept-promise-rejection-handled">handled</i>. Otherwise, the promise rejection is
Expand Down Expand Up @@ -106706,8 +106725,11 @@ dictionary <dfn dictionary>PromiseRejectionEventInit</dfn> : <span>EventInit</sp
<p>If <var>operation</var> is "<code data-x="">reject</code>", then:</p>

<ol>
<li><p><span data-x="list append">Append</span> <var>promise</var> to <var>settings
object</var>'s <span>about-to-be-notified rejected promises list</span>.</p></li>
<li><p>Let <var>snapshot</var> be <span
data-x="js-AsyncContextSnapshot">AsyncContextSnapshot</span>().</p></li>

<li><p><span data-x="list append">Append</span> (<var>promise</var>, <var>snapshot</var>) to
<var>settings object</var>'s <span>about-to-be-notified rejected promises list</span>.</p></li>
</ol>
</li>

Expand All @@ -106716,8 +106738,9 @@ dictionary <dfn dictionary>PromiseRejectionEventInit</dfn> : <span>EventInit</sp

<ol>
<li><p>If <var>settings object</var>'s <span>about-to-be-notified rejected promises
list</span> <span data-x="list contains">contains</span> <var>promise</var>, then <span
data-x="list remove">remove</span> <var>promise</var> from that list and return.</p></li>
list</span> <span data-x="list contains">contains</span> an element <var>element</var> for
which <var>element</var>[0] is <var>promise</var>, then <span
data-x="list remove">remove</span> <var>element</var> from that list and return.</p></li>

<li><p>If <var>settings object</var>'s <span>outstanding rejected promises weak set</span>
does not <span data-x="list contains">contain</span> <var>promise</var>, then return.</p></li>
Expand All @@ -106734,7 +106757,8 @@ dictionary <dfn dictionary>PromiseRejectionEventInit</dfn> : <span>EventInit</sp
<code>PromiseRejectionEvent</code>, with the <code
data-x="dom-PromiseRejectionEvent-promise">promise</code> attribute initialized to
<var>promise</var>, and the <code data-x="dom-PromiseRejectionEvent-reason">reason</code>
attribute initialized to <var>promise</var>.[[PromiseResult]].</p></li>
attribute initialized to <var>promise</var>.[[PromiseResult]], and useCallerAsyncContextFlag
set.</p></li>
</ol>
</li>
</ol>
Expand Down Expand Up @@ -106783,9 +106807,16 @@ dictionary <dfn dictionary>PromiseRejectionEventInit</dfn> : <span>EventInit</sp
<p class="note">This affects the <span>active script</span> while the callback runs.</p>
</li>

<li><p>Let <var>previousContextMapping</var> be <span
data-x="js-AsyncContextSwap">AsyncContextSwap</span>(<var
>callback</var>.[[AsyncContextSnapshot]]).</p></li>

<li><p>Let <var>result</var> be <span>Call</span>(<var>callback</var>.[[Callback]], <var>V</var>,
<var>argumentsList</var>).</p></li>

<li><p>Perform <span
data-x="js-AsyncContextSwap">AsyncContextSwap</span>(<var>previousContextMapping</var>).</p></li>

<li><p>If <var>script execution context</var> is not null, then <span data-x="stack
pop">pop</span> <var>script execution context</var> from the <span>JavaScript execution context
stack</span>.</p></li>
Expand Down Expand Up @@ -107019,7 +107050,11 @@ dictionary <dfn dictionary>PromiseRejectionEventInit</dfn> : <span>EventInit</sp
</div>
</li>

<li><p>Let <var>snapshot</var> be <span
data-x="js-AsyncContextSnapshot">AsyncContextSnapshot</span>().</p></li>

<li><p>Return the <span>JobCallback Record</span> { [[Callback]]: <var>callable</var>,
[[AsyncContextSnapshot]]: <var>snapshot</var>,
[[HostDefined]]: { [[IncumbentSettings]]: <var>incumbent settings</var>, [[ActiveScriptContext]]:
<var>script execution context</var> } }.</p></li>
</ol>
Expand Down Expand Up @@ -108884,7 +108919,8 @@ import "https://example.com/foo/../module2.mjs";</code></pre>
steps.</p></li>

<li><p>Set <var>eventHandler</var>'s <span data-x="event handler value">value</span> to the
<span>internal raw uncompiled handler</span> <var>value</var>/<var>location</var>.</p></li>
<span>internal raw uncompiled handler</span> (<var>value</var>, <var>location</var>,
<span data-x="js-AsyncContextSnapshot">AsyncContextSnapshot</span>()).</p></li>

<li><p><span>Activate an event handler</span> given <var>eventTarget</var> and
<var>localName</var>.</p></li>
Expand Down Expand Up @@ -109227,6 +109263,8 @@ typedef <span>OnBeforeUnloadEventHandlerNonNull</span>? <dfn typedef>OnBeforeUnl

<li>A location where the script body originated, in case an error needs to be reported

<li>A <span>list</span> of <span data-x="Async Context Mapping Record">Async Context Mapping
Records</span>
</ul>

<p>When the user agent is to <dfn data-x="getting the current value of the event handler">get the
Expand All @@ -109241,9 +109279,11 @@ typedef <span>OnBeforeUnloadEventHandlerNonNull</span>? <dfn typedef>OnBeforeUnl

<li><p>Let <var>eventHandler</var> be <var>handlerMap</var>[<var>name</var>].</p></li>

<li><p>Let <var>value</var> be <var>eventHandler</var>'s
<span data-x="event handler value">value</span>.</p></li>

<li>
<p>If <var>eventHandler</var>'s <span data-x="event handler value">value</span> is an
<span>internal raw uncompiled handler</span>, then:</p>
<p>If <var>value</var> is an <span>internal raw uncompiled handler</span>, then:</p>

<ol>
<li><p>If <var>eventTarget</var> is an element, then let <var>element</var> be
Expand All @@ -109255,11 +109295,9 @@ typedef <span>OnBeforeUnloadEventHandlerNonNull</span>? <dfn typedef>OnBeforeUnl
<li><p>If <span data-x="concept-n-noscript">scripting is disabled</span> for
<var>document</var>, then return null.</p></li>

<li><p>Let <var>body</var> be the uncompiled script body in <var>eventHandler</var>'s <span
data-x="event handler value">value</span>.</p></li>
<li><p>Let <var>body</var> be <var>value</var>[0].</p></li>

<li><p>Let <var>location</var> be the location where the script body originated, as
given by <var>eventHandler</var>'s <span data-x="event handler value">value</span>.</p></li>
<li><p>Let <var>location</var> be <var>value</var>[1].</p></li>

<li><p>If <var>element</var> is not null and <var>element</var> has a
<span>form owner</span>, let <var>form owner</var> be that <span>form owner</span>.
Expand Down Expand Up @@ -109414,10 +109452,13 @@ typedef <span>OnBeforeUnloadEventHandlerNonNull</span>? <dfn typedef>OnBeforeUnl
</div>
</li>

<li><p>Let <var>context</var> be the tuple (<var>settings object</var>,
<var>value</var>[2]).</p></li>

<li><p>Set <var>eventHandler</var>'s <span data-x="event handler value">value</span> to the
result of creating a Web IDL <code>EventHandler</code> callback function object whose object
reference is <var>function</var> and whose <span>callback context</span> is <var>settings
object</var>.</p></li>
reference is <var>function</var> and whose <span>callback context</span> is
<var>context</var>.</p></li>
</ol>
</li>

Expand Down Expand Up @@ -110668,6 +110709,9 @@ partial interface <span id="ShadowRoot-partial">ShadowRoot</span> {
object; otherwise let <var>thisArg</var> be the <code>WindowProxy</code> that corresponds to
<var>global</var>.</p></li>

<li><p>Let <var>snapshot</var> be <span
data-x="js-AsyncContextSnapshot">AsyncContextSnapshot</span>().</p></li>

<li><p>If <var>previousId</var> was given, let <var>id</var> be <var>previousId</var>;
otherwise, let <var>id</var> be an <span>implementation-defined</span> integer that is greater
than zero and does not already <span data-x="map exists">exist</span> in <var>global</var>'s
Expand Down Expand Up @@ -110704,6 +110748,10 @@ partial interface <span id="ShadowRoot-partial">ShadowRoot</span> {
<li><p>If <var>id</var> does not <span data-x="map exists">exist</span> in <var>global</var>'s
<span>map of active timers</span>, then abort these steps.</p></li>

<li><p>Let <var>previousContextMapping</var> be <span
data-x="js-AsyncContextSwap">AsyncContextSwap</span>(<var
>callback</var>.[[AsyncContextSnapshot]]).</p></li>

<li><p>If <var>handler</var> is a <code data-x="idl-Function">Function</code>, then <span
data-x="es-invoking-callback-functions">invoke</span> <var>handler</var> given
<var>arguments</var> with the <span data-x="dfn-callback-this-value">callback this
Expand All @@ -110718,8 +110766,8 @@ partial interface <span id="ShadowRoot-partial">ShadowRoot</span> {

<li><p>Perform <span
data-x="the-hostensurecancompilestrings-implementation">HostEnsureCanCompileStrings</span>(<var>realm</var>).
If this throws an exception, catch it, <span>report the exception</span>, and abort these
steps.</p></li>
If this throws an exception, catch it, <span>report the exception</span>, and jump to the
step labeled <i>return</i>.</p></li>

<li><p>Let <var>settings object</var> be <var>global</var>'s <span>relevant settings
object</span>.</p></li>
Expand Down Expand Up @@ -110773,7 +110821,7 @@ partial interface <span id="ShadowRoot-partial">ShadowRoot</span> {

<li>
<p>If <var>id</var> does not <span data-x="map exists">exist</span> in <var>global</var>'s
<span>map of active timers</span>, then abort these steps.</p>
<span>map of active timers</span>, then jump to the step labeled <i>return</i>.</p>

<p class="note">It might have been removed via the author code in <var>handler</var> calling
<code data-x="dom-clearTimeout">clearTimeout()</code> or <code
Expand All @@ -110786,6 +110834,9 @@ partial interface <span id="ShadowRoot-partial">ShadowRoot</span> {

<li><p>Otherwise, <span data-x="map remove">remove</span> <var>global</var>'s <span>map of
active timers</span>[<var>id</var>].</p></li>

<li><p><i>Return</i>: Perform <span
data-x="js-AsyncContextSwap">AsyncContextSwap</span>(<var>previousContextMapping</var>).</p></li>
</ol>
</li>

Expand Down Expand Up @@ -114275,6 +114326,9 @@ function receiver(e) {
<span>StructuredSerializeWithTransfer</span>(<var>message</var>, <var>transfer</var>). Rethrow
any exceptions.</p></li>

<li><p>Let <var>snapshot</var> be <span
data-x="js-AsyncContextSnapshot">AsyncContextSnapshot</span>().</p></li>

<li>
<p><span>Queue a global task</span> on the <dfn>posted message task source</dfn> given
<var>targetWindow</var> to run the following steps:</p>
Expand All @@ -114285,6 +114339,9 @@ function receiver(e) {
<code>Document</code></span>'s <span data-x="concept-document-origin">origin</span> is not
<span>same origin</span> with <var>targetOrigin</var>, then return.</p></li>

<li><p>Let <var>previousContextMapping</var> be <span
data-x="js-AsyncContextSwap">AsyncContextSwap</span>(<var>snapshot</var>).</p></li>

<li><p>Let <var>origin</var> be the <span data-x="serialization of an
origin">serialization</span> of <var>incumbentSettings</var>'s <span
data-x="concept-settings-object-origin">origin</span>.</p></li>
Expand All @@ -114303,7 +114360,7 @@ function receiver(e) {
<var>targetWindow</var>, using <code>MessageEvent</code>, with the <code
data-x="dom-MessageEvent-origin">origin</code> attribute initialized to <var>origin</var> and
the <code data-x="dom-MessageEvent-source">source</code> attribute initialized to
<var>source</var>, and then return.</p>
<var>source</var>, and then jump to the step below labeled <i>return</i>.</p>
</li>

<li><p>Let <var>messageClone</var> be <var>deserializeRecord</var>.[[Deserialized]].</p></li>
Expand All @@ -114318,8 +114375,11 @@ function receiver(e) {
attribute initialized to <var>origin</var>, the <code
data-x="dom-MessageEvent-source">source</code> attribute initialized to <var>source</var>, 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 <var>newPorts</var>.</p></li>
<var>messageClone</var>, the <code data-x="dom-MessageEvent-ports">ports</code> attribute
initialized to <var>newPorts</var>, and <var>useCallerAsyncContextFlag</var> flag set.</p></li>

<li><p><i>Return</i>: Perform <span data-x="js-AsyncContextSwap"
>AsyncContextSwap</span>(<var>previousContextMapping</var>).</p></li>
</ol>
</li>
</ol>
Expand Down Expand Up @@ -114775,6 +114835,9 @@ dictionary <dfn dictionary>StructuredSerializeOptions</dfn> {
algorithm runs scripts). We don't throw an exception for 'doomed' being true, because this can't
necessarily be detected right now every time -->

<li><p>Let <var>snapshot</var> be <span
data-x="js-AsyncContextSnapshot">AsyncContextSnapshot</span>().</p></li>

<li>
<p>Add a <span data-x="concept-task">task</span> that runs the following steps to the <span>port
message queue</span> of <var>targetPort</var>:</p>
Expand All @@ -114791,14 +114854,18 @@ dictionary <dfn dictionary>StructuredSerializeOptions</dfn> {
<li><p>Let <var>targetRealm</var> be <var>finalTargetPort</var>'s <span
data-x="concept-relevant-realm">relevant realm</span>.</p></li>

<li><p>Let <var>previousContextMapping</var> be <span
data-x="js-AsyncContextSwap">AsyncContextSwap</span>(<var>snapshot</var>).</p></li>

<li>
<p>Let <var>deserializeRecord</var> be
<span>StructuredDeserializeWithTransfer</span>(<var>serializeWithTransferResult</var>,
<var>targetRealm</var>).</p>

<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>finalTargetPort</var>, using <code>MessageEvent</code>, and then jump to the step below
labeled <i>return</i>.</p>
</li>

<li><p>Let <var>messageClone</var> be <var>deserializeRecord</var>.[[Deserialized]].</p></li>
Expand All @@ -114810,9 +114877,12 @@ dictionary <dfn dictionary>StructuredSerializeOptions</dfn> {
<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
<code>MessageEvent</code>, with the <code data-x="dom-MessageEvent-data">data</code> attribute
initialized to <var>messageClone</var> and the <code
initialized to <var>messageClone</var>, the <code
data-x="dom-MessageEvent-ports">ports</code> attribute initialized to
<var>newPorts</var>.</p></li>
<var>newPorts</var>, and <var>useCallerAsyncContextFlag</var> flag set.</p></li>

<li><p><i>Return</i>: Perform <span data-x="js-AsyncContextSwap"
>AsyncContextSwap</span>(<var>previousContextMapping</var>).</p></li>
</ol>
</li>
</ol>
Expand Down Expand Up @@ -140070,6 +140140,9 @@ INSERT INTERFACES HERE
<dt id="refsJPEG">[JPEG]</dt>
<dd><cite><a href="https://www.w3.org/Graphics/JPEG/jfif3.pdf">JPEG File Interchange Format</a></cite>, E. Hamilton.</dd>

<dt id="refsJSASYNCCONTEXT">[JSASYNCCONTEXT]</dt>
<dd><cite><a href="https://tc39.es/proposal-async-context/">AsyncContext</a></cite>. Ecma International.</dd>

<dt id="refsJSERRORSTACKS">[JSERRORSTACKS]</dt>
<dd>(Non-normative) <cite><a href="https://tc39.es/proposal-error-stacks/">Error Stacks</a></cite>. Ecma International.</dd>

Expand Down