Skip to content

Commit 07db2cb

Browse files
committed
Keep track of the context in which an exception was thrown
This is needed for `error` events in the web integration (equivalent to Node.js's `process.on("uncaughtException")`). This might be used by web specs like this: > 1. Let `previousContext` be AsyncContextSwap(`someContext`). > 2. Invoke `someCallback`. If this throws an exception `err`, then: > 1. Let `throwContext` be the surrounding agent's > [[ThrowAsyncContextMapping]]. > 2. If `throwContext` is EMPTY, set `throwContext` to > AsyncContextSnapshot(). > 3. Report the exception `err` with `throwContext`.
1 parent 1fd6726 commit 07db2cb

File tree

1 file changed

+81
-9
lines changed

1 file changed

+81
-9
lines changed

spec.html

+81-9
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,17 @@ <h1>Agents</h1>
126126
<ins>A map from the AsyncContext.Variable instances to the saved ECMAScript language value. Every Record in the List contains a unique [[AsyncContextKey]]. The map is initially empty.</ins>
127127
</td>
128128
</tr>
129+
<tr>
130+
<td>
131+
<ins>[[ThrowAsyncContextMapping]]</ins>
132+
</td>
133+
<td>
134+
<ins>~unused~ or a List of Async Context Mapping Records</ins>
135+
</td>
136+
<td>
137+
<ins>The value of [[AsyncContextMapping]] at the time of the last time an exception was thrown, if any. Used by hosts to provide Async Context Mapping information when reporting uncaught exceptions.</ins>
138+
</td>
139+
</tr>
129140
</table>
130141
</emu-table>
131142
</emu-clause>
@@ -148,7 +159,7 @@ <h1>
148159
1. <del>Perform ? HostCallJobCallback(_callback_, *undefined*, « _cell_.[[HeldValue]] »).</del>
149160
1. <ins>Let _previousContextMapping_ be AsyncContextSwap(_finalizationRegistry_.[[FinalizationRegistryAsyncContextSnapshot]]).</ins>
150161
1. <ins>Let _result_ be Completion(HostCallJobCallback(_callback_, *undefined*, « _cell_.[[HeldValue]] »)).</ins>
151-
1. <ins>AsyncContextSwap(_previousContextMapping_).</ins>
162+
1. <ins>AsyncContextSwap(_previousContextMapping_, _result_).</ins>
152163
1. <ins>Perform ? _result_.</ins>
153164
1. Return ~unused~.
154165
</emu-alg>
@@ -203,6 +214,62 @@ <h1>
203214
</emu-clause>
204215
</emu-clause>
205216

217+
<emu-clause id="sec-ecmascript-language-statements-and-declarations">
218+
<h1>ECMAScript Language: Statements and Declarations</h1>
219+
220+
<emu-clause id="sec-try-statement">
221+
<h1>The `try` Statement</h1>
222+
223+
<emu-clause id="sec-try-statement-runtime-semantics-evaluation" type="sdo">
224+
<h1>Runtime Semantics: Evaluation</h1>
225+
<emu-grammar>TryStatement : `try` Block Catch</emu-grammar>
226+
<emu-alg>
227+
1. Let _B_ be Completion(Evaluation of |Block|).
228+
1. <del>If _B_ is a throw completion, let _C_ be Completion(CatchClauseEvaluation of |Catch| with argument _B_.[[Value]]).</del>
229+
1. <del>Else, let _C_ be _B_.</del>
230+
1. <ins>If _B_ is a throw completion, then</ins>
231+
1. <ins>Let _agentRecord_ be the surrounding agent's Agent Record.</ins>
232+
1. <ins>Set _agentRecord_.[[ThrowAsyncContextMapping]] to ~empty~.</ins>
233+
1. <ins>Let _C_ be Completion(CatchClauseEvaluation of |Catch| with argument _B_.[[Value]]).</ins>
234+
1. <ins>Else,</ins>
235+
1. <ins>Let _C_ be _B_.</ins>
236+
1. Return ? UpdateEmpty(_C_, *undefined*).
237+
</emu-alg>
238+
<emu-grammar>TryStatement : `try` Block Finally</emu-grammar>
239+
<emu-alg>
240+
1. <ins>Let _agentRecord_ be the surrounding agent's AgentRecord.</ins>
241+
1. Let _B_ be Completion(Evaluation of |Block|).
242+
1. <ins>Let _throwAsyncContextMapping_ be _agentRecord_.[[ThrowAsyncContextMapping]].</ins>
243+
1. Let _F_ be Completion(Evaluation of |Finally|).
244+
1. <del>If _F_ is a normal completion, set _F_ to _B_.</del>
245+
1. <ins>If _F_ is a normal completion, then</ins>
246+
1. <ins>Set _agentRecord_.[[ThrowAsyncContextMapping]] to _throwAsyncContextMapping_.</ins>
247+
1. <ins>Set _F_ to _B_.</ins>
248+
1. Return ? UpdateEmpty(_F_, *undefined*).
249+
</emu-alg>
250+
<emu-grammar>TryStatement : `try` Block Catch Finally</emu-grammar>
251+
<emu-alg>
252+
1. <ins>Let _agentRecord_ be the surrounding agent's Agent Record.</ins>
253+
1. Let _B_ be Completion(Evaluation of |Block|).
254+
1. <del>If _B_ is a throw completion, let _C_ be Completion(CatchClauseEvaluation of |Catch| with argument _B_.[[Value]]).</del>
255+
1. <del>Else, let _C_ be _B_.</del>
256+
1. <ins>If _B_ is a throw completion, then</ins>
257+
1. <ins>Set _agentRecord_.[[ThrowAsyncContextMapping]] to ~empty~.</ins>
258+
1. <ins>Let _C_ be Completion(CatchClauseEvaluation of |Catch| with argument _B_.[[Value]]).</ins>
259+
1. <ins>Else,</ins>
260+
1. <ins>Let _C_ be _B_.</ins>
261+
1. <ins>Let _throwAsyncContextMapping_ be _agentRecord_.[[ThrowAsyncContextMapping]].</ins>
262+
1. Let _F_ be Completion(Evaluation of |Finally|).
263+
1. <del>If _F_ is a normal completion, set _F_ to _C_.</del>
264+
1. <ins>If _F_ is a normal completion, then</ins>
265+
1. <ins>Set _agentRecord_.[[ThrowAsyncContextMapping]] to _throwAsyncContextMapping_.</ins>
266+
1. <ins>Set _F_ to _C_.</ins>
267+
1. Return ? UpdateEmpty(_F_, *undefined*).
268+
</emu-alg>
269+
</emu-clause>
270+
</emu-clause>
271+
</emu-clause>
272+
206273
<emu-clause id="sec-ecmascript-language-functions-and-classes">
207274
<h1>ECMAScript Language: Functions and Classes</h1>
208275

@@ -397,7 +464,7 @@ <h1>
397464
1. Else,
398465
1. <del>Return ? Call(_promiseCapability_.[[Resolve]], *undefined*, « _handlerResult_.[[Value]] »).</del>
399466
1. <ins>Let _resolvingFunctionResult_ be Completion(Call(_promiseCapability_.[[Resolve]], *undefined*, « _handlerResult_.[[Value]] »)).</ins>
400-
1. <ins>AsyncContextSwap(_previousContextMapping_).</ins>
467+
1. <ins>AsyncContextSwap(_previousContextMapping_, _resolvingFunctionResult_).</ins>
401468
1. <ins>Return _resolvingFunctionResult_.</ins>
402469
1. Let _handlerRealm_ be *null*.
403470
1. If _reaction_.[[Handler]] is not ~empty~, then
@@ -428,7 +495,7 @@ <h1>
428495
1. If _thenCallResult_ is an abrupt completion, then
429496
1. <del>Return ? Call(_resolvingFunctions_.[[Reject]], *undefined*, « _thenCallResult_.[[Value]] »).</del>
430497
1. <ins>Let _rejectResult_ be Completion(Call(_resolvingFunctions_.[[Reject]], *undefined*, « _thenCallResult_.[[Value]] »)).</ins>
431-
1. <ins>AsyncContextSwap(_previousContextMapping_).</ins>
498+
1. <ins>AsyncContextSwap(_previousContextMapping_, _rejectResult_).</ins>
432499
1. <ins>Return _rejectResult_.</ins>
433500
1. <ins>AsyncContextSwap(_previousContextMapping_).</ins>
434501
1. Return ? _thenCallResult_.
@@ -679,7 +746,7 @@ <h1>
679746
1. Assert: When we return here, _genContext_ has already been removed from the execution context stack and _methodContext_ is the currently running execution context.
680747
1. <ins>If _previousContextMapping_ is not ~empty~, then</ins>
681748
1. <ins>Assert: The result of AsyncContextSnapshot() is _generator_.[[GeneratorAsyncContextMapping]].</ins>
682-
1. <ins>AsyncContextSwap(_previousContextMapping_).</ins>
749+
1. <ins>AsyncContextSwap(_previousContextMapping_, _result_).</ins>
683750
1. Return ? _result_.
684751
</emu-alg>
685752
</emu-clause>
@@ -718,7 +785,7 @@ <h1>
718785
1. Assert: When we return here, _genContext_ has already been removed from the execution context stack and _methodContext_ is the currently running execution context.
719786
1. <ins>If _previousContextMapping_ is not ~empty~, then</ins>
720787
1. <ins>Assert: The result of AsyncContextSnapshot() is _generator_.[[GeneratorAsyncContextMapping]].</ins>
721-
1. <ins>AsyncContextSwap(_previousContextMapping_).</ins>
788+
1. <ins>AsyncContextSwap(_previousContextMapping_, _result_).</ins>
722789
1. Return ? _result_.
723790
</emu-alg>
724791
</emu-clause>
@@ -954,7 +1021,8 @@ <h1>
9541021
<emu-clause id="sec-asynccontextswap" type="abstract operation">
9551022
<h1>
9561023
AsyncContextSwap (
957-
_snapshotMapping_: a List of Async Context Mapping Records
1024+
_snapshotMapping_: a List of Async Context Mapping Records,
1025+
optional _completion_: a Completion Record,
9581026
): a List of Async Context Mapping Records
9591027
</h1>
9601028
<dl class="header">
@@ -964,6 +1032,10 @@ <h1>
9641032
<emu-alg>
9651033
1. Let _agentRecord_ be the surrounding agent's Agent Record.
9661034
1. Let _asyncContextMapping_ be _agentRecord_.[[AsyncContextMapping]].
1035+
1. If _completion_ is present and it is an abrupt completion, then
1036+
1. If _agentRecord_.[[ThrowAsyncContextMapping]] is ~empty~, set it to _asyncContextMapping_.
1037+
1. Else,
1038+
1. Set _agentRecord_.[[ThrowAsyncContextMapping]] to ~empty~.
9671039
1. Set _agentRecord_.[[AsyncContextMapping]] to _snapshotMapping_.
9681040
1. Return _asyncContextMapping_.
9691041
</emu-alg>
@@ -1048,7 +1120,7 @@ <h1>AsyncContext.Snapshot.wrap ( _fn_ )</h1>
10481120
1. Let _thisArgument_ be the *this* value.
10491121
1. Let _previousContextMapping_ be AsyncContextSwap(_snapshot_).
10501122
1. Let _result_ be Completion(Call(_fn_, _thisArgument_, _args_)).
1051-
1. AsyncContextSwap(_previousContextMapping_).
1123+
1. AsyncContextSwap(_previousContextMapping_, _result_).
10521124
1. Return _result_.
10531125
1. Let _wrapped_ be CreateBuiltinFunction(_closure_).
10541126
1. Perform ? CopyNameAndLength(_wrapped_, _fn_, *"wrapped"*).
@@ -1084,7 +1156,7 @@ <h1>AsyncContext.Snapshot.prototype.run ( _func_, ..._args_ )</h1>
10841156
1. Perform ? RequireInternalSlot(_asyncSnapshot_, [[AsyncSnapshotMapping]]).
10851157
1. Let _previousContextMapping_ be AsyncContextSwap(_asyncSnapshot_.[[AsyncSnapshotMapping]]).
10861158
1. Let _result_ be Completion(Call(_func_, *undefined*, _args_)).
1087-
1. AsyncContextSwap(_previousContextMapping_).
1159+
1. AsyncContextSwap(_previousContextMapping_, _result_).
10881160
1. Return _result_.
10891161
</emu-alg>
10901162
</emu-clause>
@@ -1212,7 +1284,7 @@ <h1>AsyncContext.Variable.prototype.run ( _value_, _func_, ..._args_ )</h1>
12121284
1. Append _p_ to _asyncContextMapping_.
12131285
1. AsyncContextSwap(_asyncContextMapping_).
12141286
1. Let _result_ be Completion(Call(_func_, *undefined*, _args_)).
1215-
1. AsyncContextSwap(_previousContextMapping_).
1287+
1. AsyncContextSwap(_previousContextMapping_, _result_).
12161288
1. Return _result_.
12171289
</emu-alg>
12181290
</emu-clause>

0 commit comments

Comments
 (0)