forked from tc39/proposal-async-context
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspec.html
487 lines (457 loc) · 22 KB
/
spec.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
<!doctype html>
<meta charset="utf8">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/styles/github.min.css">
<pre class="metadata">
title: AsyncContext
stage: 1
contributors: Chengzhong Wu, Justin Ridgewell
</pre>
<emu-clause id="sec-executable-code-and-execution-contexts">
<h1>Executable Code and Execution Contexts</h1>
<emu-clause id="sec-agents">
<h1>Agents</h1>
<p>This proposal adds a new field to the Agent Record as the following table:</p>
<emu-table id="table-agent-record" caption="Agent Record Fields">
<table>
<tr>
<th>Field Name</th>
<th>Value</th>
<th>Meaning</th>
</tr>
<tr>
<td>[[LittleEndian]]</td>
<td>a Boolean</td>
<td>The default value computed for the <em>isLittleEndian</em> parameter when it is needed by the algorithms GetValueFromBuffer and SetValueInBuffer. The choice is implementation-defined and should be the alternative that is most efficient for the implementation. Once the value has been observed it cannot change.</td>
</tr>
<tr>
<td>[[CanBlock]]</td>
<td>a Boolean</td>
<td>Determines whether the agent can block or not.</td>
</tr>
<tr>
<td>[[Signifier]]</td>
<td>an agent signifier</td>
<td>Uniquely identifies the agent within its agent cluster.</td>
</tr>
<tr>
<td>[[IsLockFree1]]</td>
<td>a Boolean</td>
<td>*true* if atomic operations on one-<emu-not-ref>byte values</emu-not-ref> are lock-free, *false* otherwise.</td>
</tr>
<tr>
<td>[[IsLockFree2]]</td>
<td>a Boolean</td>
<td>*true* if atomic operations on two-<emu-not-ref>byte values</emu-not-ref> are lock-free, *false* otherwise.</td>
</tr>
<tr>
<td>[[IsLockFree8]]</td>
<td>a Boolean</td>
<td>*true* if atomic operations on eight-<emu-not-ref>byte values</emu-not-ref> are lock-free, *false* otherwise.</td>
</tr>
<tr>
<td>[[CandidateExecution]]</td>
<td>a candidate execution Record</td>
<td>See the memory model.</td>
</tr>
<tr>
<td>[[KeptAlive]]</td>
<td>a List of Objects</td>
<td>Initially a new empty List, representing the list of objects to be kept alive until the end of the current Job</td>
</tr>
<tr>
<td>
<ins>[[AsyncContextMapping]]</ins>
</td>
<td>
<ins>a List of Records with fields [[AsyncContextKey]] (a Symbol) and [[AsyncContextValue]] (an ECMAScript language value)</ins>
</td>
<td>
<ins>A map from the AsyncContext's key symbol to the saved ECMAScript language value. Every Record in the List contains a unique [[AsyncContextKey]].</ins>
</td>
</tr>
</table>
</emu-table>
</emu-clause>
<emu-clause id="sec-jobs">
<h1>Jobs and Host Operations to Enqueue Jobs</h1>
<emu-clause id="sec-jobcallback-records">
<h1>JobCallback Records</h1>
<p>This proposal adds a new field to the JobCallback Record as the following table:</p>
<emu-table id="table-jobcallback-records" caption="JobCallback Record Fields">
<table>
<tr>
<th>
Field Name
</th>
<th>
Value
</th>
<th>
Meaning
</th>
</tr>
<tr>
<td>
[[Callback]]
</td>
<td>
a function object
</td>
<td>
The function to invoke when the Job is invoked.
</td>
</tr>
<tr>
<td>
<ins>[[AsyncContextSnapshot]]</ins>
</td>
<td>
<ins>a List of Records with fields [[AsyncContextKey]] (a Symbol) and [[AsyncContextValue]] (an ECMAScript language value)</ins>
</td>
<td>
<ins>A map from the AsyncContext's key symbol to the saved ECMAScript language value. Every Record in the List contains a unique [[AsyncContextKey]].</ins>
</td>
</tr>
<tr>
<td>
[[HostDefined]]
</td>
<td>
anything (default value is ~empty~)
</td>
<td>
Field reserved for use by hosts.
</td>
</tr>
</table>
</emu-table>
</emu-clause>
<emu-clause id="sec-hostmakejobcallback" type="host-defined abstract operation">
<h1>
HostMakeJobCallback (
_callback_: a function object,
): a JobCallback Record
</h1>
<dl class="header">
</dl>
<p>An implementation of HostMakeJobCallback must conform to the following requirements:</p>
<ul>
<li>It must return a JobCallback Record whose [[Callback]] field is _callback_,</li>
<li><ins>It must return a JobCallback Record whose [[AsyncContextSnapshot]] field is a List of Records with fields [[AsyncContextKey]] (a Symbol) and [[AsyncContextValue]] (an ECMAScript language value).</ins></li>
</ul>
<p>The default implementation of HostMakeJobCallback performs the following steps when called:</p>
<emu-alg>
1. <del>Return the JobCallback Record { [[Callback]]: _callback_, [[HostDefined]]: ~empty~ }.</del>
1. <ins>Let _snapshot_ be AsyncContextSnapshot().</ins>
1. <ins>Return the JobCallback Record { [[Callback]]: _callback_, [[AsyncContextSnapshot]]: _snapshot_, [[HostDefined]]: ~empty~ }.</ins>
</emu-alg>
<p>ECMAScript hosts that are not web browsers must use the default implementation of HostMakeJobCallback.</p>
<emu-note>
<p>HostMakeJobCallback snapshots the current AsyncContext global state. HostCallJobCallback restores the snapshot.</p>
</emu-note>
</emu-clause>
<emu-clause id="sec-hostcalljobcallback" type="host-defined abstract operation">
<h1>
HostCallJobCallback (
_jobCallback_: a JobCallback Record,
_V_: an ECMAScript language value,
_argumentsList_: a List of ECMAScript language values,
): either a normal completion containing an ECMAScript language value or a throw completion
</h1>
<dl class="header">
</dl>
<p>An implementation of HostCallJobCallback must conform to the following requirements:</p>
<ul>
<li><ins>It must perform AsyncContextSwap before and after the call,</ins></li>
<li>It must perform and return the result of Call(_jobCallback_.[[Callback]], _V_, _argumentsList_).</li>
</ul>
<p>The default implementation of HostCallJobCallback performs the following steps when called:</p>
<emu-alg>
1. Assert: IsCallable(_jobCallback_.[[Callback]]) is *true*.
1. <del>Return ? Call(_jobCallback_.[[Callback]], _V_, _argumentsList_).</del>
1. <ins>Let _previousContextMapping_ be AsyncContextSwap(_jobCallback_.[[AsyncContextSnapshot]]).</ins>
1. <ins>Let _result_ be Completion(Call(_jobCallback_.[[Callback]], _V_, _argumentsList_)).</ins>
1. <ins>AsyncContextSwap(_previousContextMapping_).</ins>
1. <ins>Return _result_.</ins>
</emu-alg>
<p>ECMAScript hosts that are not web browsers must use the default implementation of HostCallJobCallback.</p>
<emu-note>
<p>HostCallJobCallback restores the snapshot saved in HostMakeJobCallback when calling the _jobCallback_.[[Callback]].</p>
</emu-note>
</emu-clause>
</emu-clause>
</emu-clause>
<ins class="block">
<emu-clause id="sec-ordinary-and-exotic-objects-behaviours">
<h1>Ordinary and Exotic Objects Behaviours</h1>
<emu-clause id="sec-built-in-exotic-object-internal-methods-and-slots">
<h1>Built-in Exotic Object Internal Methods and Slots</h1>
<emu-clause id="sec-asynccontext-wrapped-function-exotic-objects">
<h1>AsyncContext Wrapped Function Exotic Objects</h1>
<emu-note>
<p>This is based on <emu-xref href="#sec-bound-function-exotic-objects"></emu-xref></p>
</emu-note>
<p>An AsyncContext wrapped function exotic object is an exotic object that wraps another function object. An AsyncContext wrapped function exotic object is callable (it has a [[Call]] internal method and may have a [[Construct]] internal method). Calling an AsyncContext wrapped function exotic object generally results in a call of its wrapped function.</p>
<p>An object is a <dfn id="asynccontext-wrapped-function-exotic-object" variants="async context wrapped function exotic objects">AsyncContext wrapped function exotic object</dfn> if its [[Call]] and (if applicable) [[Construct]] internal methods use the following implementations, and its other essential internal methods use the definitions found in Ordinary Object Internal Methods and Internal Slots. These methods are installed in AsyncContextWrappedFunctionCreate.</p>
<p>Async context wrapped function exotic objects do not have the internal slots of ECMAScript function objects listed in Internal Slots of ECMAScript Function Objects. Instead they have the internal slots listed in <emu-xref href="#table-internal-slots-of-asynccontext-wrapped-function-exotic-objects"></emu-xref>, in addition to [[Prototype]] and [[Extensible]].</p>
<emu-table id="table-internal-slots-of-asynccontext-wrapped-function-exotic-objects" caption="Internal Slots of AsyncContext Wrapped Function Exotic Objects">
<table>
<tr>
<th>
Internal Slot
</th>
<th>
Type
</th>
<th>
Description
</th>
</tr>
<tr>
<td>
[[WrappedTargetFunction]]
</td>
<td>
a callable Object
</td>
<td>
The wrapped function object.
</td>
</tr>
<tr>
<td>
[[AsyncContextSnapshot]]
</td>
<td>
a List of Records with fields [[AsyncContextKey]] (a Symbol) and [[AsyncContextValue]] (an ECMAScript language value)
</td>
<td>
A map from the AsyncContext's key symbol to the saved ECMAScript language value. Every Record in the List contains a unique [[AsyncContextKey]].
</td>
</tr>
</table>
</emu-table>
<emu-clause id="sec-asynccontext-wrapped-function-exotic-objects-call-thisargument-argumentslist" type="internal method">
<h1>
[[Call]] (
_thisArgument_: an ECMAScript language value,
_argumentsList_: a List of ECMAScript language values,
): either a normal completion containing an ECMAScript language value or a throw completion
</h1>
<dl class="header">
<dt>for</dt>
<dd>an AsyncContext wrapped function exotic object _F_</dd>
</dl>
<emu-alg>
1. Let _target_ be F.[[WrappedTargetFunction]].
1. Let _snapshot_ be F.[[AsyncContextSnapshot]].
1. Let _previousContextMapping_ be AsyncContextSwap(_snapshot_).
1. Let _result_ be Completion(Call(_target_, _thisArgument_, _argumentsList_)).
1. AsyncContextSwap(_previousContextMapping_).
1. Return _result_.
</emu-alg>
</emu-clause>
<emu-clause id="sec-asynccontext-wrapped-function-exotic-objects-construct-argumentslist-newtarget" type="internal method">
<h1>
[[Construct]] (
_argumentsList_: a List of ECMAScript language values,
_newTarget_: a constructor,
): either a normal completion containing an Object or a throw completion
</h1>
<dl class="header">
<dt>for</dt>
<dd>an AsyncContext wrapped function exotic object _F_</dd>
</dl>
<emu-alg>
1. Let _target_ be _F_.[[WrappedTargetFunction]].
1. Assert: IsConstructor(_target_) is *true*.
1. Let _snapshot_ be F.[[AsyncContextSnapshot]].
1. Let _previousContextMapping_ be AsyncContextSwap(_snapshot_).
1. If SameValue(_F_, _newTarget_) is *true*, set _newTarget_ to _target_.
1. Let _result_ be Completion(Construct(_target_, _argumentsList_, _newTarget_)).
1. AsyncContextSwap(_previousContextMapping_).
1. Return _result_.
</emu-alg>
</emu-clause>
<emu-clause id="sec-asynccontext-wrappedfunctioncreate" type="abstract operation">
<h1>
AsyncContextWrappedFunctionCreate (
_targetFunction_: a function object,
_snapshot_: a List of Records with fields [[AsyncContextKey]] (a Symbol) and [[AsyncContextValue]] (an ECMAScript language value),
): either a normal completion containing a function object or a throw completion
</h1>
<dl class="header">
<dt>description</dt>
<dd>It is used to specify the creation of new AsyncContext wrapped function exotic objects.</dd>
</dl>
<emu-alg>
1. Let _proto_ be ? <emu-meta effects="user-code">_targetFunction_.[[GetPrototypeOf]]</emu-meta>().
1. Let _internalSlotsList_ be the list-concatenation of « [[Prototype]], [[Extensible]] » and the internal slots listed in <emu-xref href="#table-internal-slots-of-asynccontext-wrapped-function-exotic-objects"></emu-xref>.
1. Let _obj_ be MakeBasicObject(_internalSlotsList_).
1. Set _obj_.[[Prototype]] to _proto_.
1. Set _obj_.[[Call]] as described in <emu-xref href="#sec-asynccontext-wrapped-function-exotic-objects-call-thisargument-argumentslist"></emu-xref>.
1. If IsConstructor(_targetFunction_) is *true*, then
1. Set _obj_.[[Construct]] as described in <emu-xref href="#sec-asynccontext-wrapped-function-exotic-objects-construct-argumentslist-newtarget"></emu-xref>.
1. Set _obj_.[[WrappedTargetFunction]] to _targetFunction_.
1. Set _obj_.[[AsyncContextSnapshot]] to _snapshot_.
1. Return _obj_.
</emu-alg>
</emu-clause>
</emu-clause>
</emu-clause>
</emu-clause>
</ins>
<ins class="block">
<emu-clause id="sec-control-abstraction-objects">
<h1>Control Abstraction Objects</h1>
<emu-clause id="sec-asynccontext-objects">
<h1>AsyncContext Objects</h1>
<emu-clause id="sec-asynccontext-abstract-operations">
<h1>AsyncContext Abstract Operations</h1>
<emu-clause id="sec-asynccontext-snapshot" type="abstract operation">
<h1>
AsyncContextSnapshot (
): a List of Records with fields [[AsyncContextKey]] (a Symbol) and [[AsyncContextValue]] (an ECMAScript language value)
</h1>
<dl class="header">
<dt>description</dt>
<dd>It is used to snapshot the surrounding agent's Agent Record's [[AsyncContextMapping]].</dd>
</dl>
<emu-alg>
1. Let _agentRecord_ be the surrounding agent's Agent Record.
1. Return _agentRecord_.[[AsyncContextMapping]].
</emu-alg>
</emu-clause>
<emu-clause id="sec-asynccontext-swap" type="abstract operation">
<h1>
AsyncContextSwap (
_snapshot_: a List of Records with fields [[AsyncContextKey]] (a Symbol) and [[AsyncContextValue]] (an ECMAScript language value)
): a List of Records with fields [[AsyncContextKey]] (a Symbol) and [[AsyncContextValue]] (an ECMAScript language value)
</h1>
<dl class="header">
<dt>description</dt>
<dd>It is used to swap the surrounding agent's Agent Record's [[AsyncContextMapping]] with the _snapshot_.</dd>
</dl>
<emu-alg>
1. Let _agentRecord_ be the surrounding agent's Agent Record.
1. Let _asyncContextMapping_ be _agentRecord_.[[AsyncContextMapping]].
1. Set _agentRecord_.[[AsyncContextMapping]] to _snapshot_.
1. Return _asyncContextMapping_.
</emu-alg>
</emu-clause>
</emu-clause>
<emu-clause id="sec-asynccontext-constructor">
<h1>The AsyncContext Constructor</h1>
<p>The AsyncContext constructor:</p>
<ul>
<li>is <dfn>%AsyncContext%</dfn>.</li>
<li>is the initial value of the *"AsyncContext"* property of the global object.</li>
<li>creates and initializes a new AsyncContext when called as a constructor.</li>
<li>is not intended to be called as a function and will throw an exception when called in that manner.</li>
<li>may be used as the value in an `extends` clause of a class definition. Subclass constructors that intend to inherit the specified AsyncContext behaviour must include a `super` call to the AsyncContext constructor to create and initialize the subclass instance with the internal state necessary to support the `AsyncContext` and `AsyncContext.prototype` built-in methods.</li>
</ul>
<emu-clause id="sec-asynccontext">
<h1>AsyncContext ( )</h1>
<p>This function performs the following steps when called:</p>
<emu-alg>
1. If NewTarget is *undefined*, throw a *TypeError* exception.
1. Let _asyncContext_ be ? OrdinaryCreateFromConstructor(NewTarget, *"%AsyncContext.prototype%"*, « [[AsyncContextKey]] »).
1. Set _asyncContext_.[[AsyncContextKey]] to a new Symbol.
1. Return _asyncContext_.
</emu-alg>
</emu-clause>
</emu-clause>
<emu-clause id="sec-properties-of-the-asynccontext-constructor">
<h1>Properties of the AsyncContext Constructor</h1>
<p>The AsyncContext constructor:</p>
<ul>
<li>has a [[Prototype]] internal slot whose value is %Function.prototype%.</li>
<li>has the following properties:</li>
</ul>
<emu-clause id="sec-asynccontext-wrap">
<h1>AsyncContext.wrap ( _func_ )</h1>
<p>This function returns a new function which opaquely captures the current value of all AsyncContexts and restores the captured value when being invoked.</p>
<emu-alg>
1. Let _snapshot_ be AsyncContextSnapshot().
1. Return ? AsyncContextWrappedFunctionCreate(_func_, _snapshot_).
</emu-alg>
</emu-clause>
</emu-clause>
<emu-clause id="sec-properties-of-the-asynccontext-prototype-object">
<h1>Properties of the AsyncContext Prototype Object</h1>
<p>The <dfn>AsyncContext prototype object</dfn>:</p>
<ul>
<li>is <dfn>%AsyncContext.prototype%</dfn>.</li>
<li>has a [[Prototype]] internal slot whose value is %Object.prototype%.</li>
<li>is an ordinary object.</li>
<li>does not have any of the other internal slots of AsyncContext instances.</li>
</ul>
<emu-clause id="sec-asynccontext.prototype.run">
<h1>AsyncContext.prototype.run ( _value_, _func_, ..._args_ )</h1>
<p>This method performs the following steps when called:</p>
<emu-alg>
1. Let _asyncContext_ be the *this* value.
1. Perform ? RequireInternalSlot(_asyncContext_, [[AsyncContextKey]]).
1. Let _asyncContextKey_ be _asyncContext_.[[AsyncContextKey]].
1. Let _previousContextMapping_ be AsyncContextSnapshot().
1. Let _asyncContextMapping_ be a new empty List.
1. For each Record { [[AsyncContextKey]], [[AsyncContextValue]] } _p_ of _previousContextMapping_, do
1. If SameValueZero(_p_.[[AsyncContextKey]], _asyncContextKey_) is *false*, then
1. Let _q_ be the Record { [[AsyncContextKey]]: _p_.[[AsyncContextKey]], [[AsyncContextValue]]: _p_.[[AsyncContextValue]] }.
1. Append _q_ to _asyncContextMapping_.
1. Assert: _asyncContextMapping_ does not contain a Record whose [[AsyncContextKey]] is _asyncContextKey_.
1. Let _p_ be the Record { [[AsyncContextKey]]: _asyncContextKey_, [[AsyncContextValue]]: _value_ }.
1. Append _p_ to _asyncContextMapping_.
1. AsyncContextSwap(_asyncContextMapping_).
1. Let _result_ be Completion(Call(_func_, *undefined*, _args_)).
1. AsyncContextSwap(_previousContextMapping_).
1. Return _result_.
</emu-alg>
</emu-clause>
<emu-clause id="sec-asynccontext.prototype.get">
<h1>AsyncContext.prototype.get ( )</h1>
<p>This method performs the following steps when called:</p>
<emu-alg>
1. Let _asyncContext_ be the *this* value.
1. Perform ? RequireInternalSlot(_asyncContext_, [[AsyncContextKey]]).
1. Let _agentRecord_ be the surrounding agent's Agent Record.
1. Let _asyncContextMapping_ be _agentRecord_.[[AsyncContextMapping]].
1. For each Record { [[AsyncContextKey]], [[AsyncContextValue]] } _p_ of _asyncContextMapping_, do
1. If SameValueZero(_p_.[[AsyncContextKey]], _asyncContext_.[[AsyncContextKey]]) is *true*, return _p_.[[AsyncContextValue]].
1. Return *undefined*.
</emu-alg>
</emu-clause>
</emu-clause>
<emu-clause id="sec-properties-of-asynccontext-instances">
<h1>Properties of AsyncContext Instances</h1>
<p>AsyncContext instances are ordinary objects that inherit properties from the AsyncContext prototype object (the intrinsic, %AsyncContext.prototype%). AsyncContext instances are initially created with the internal slots described in <emu-xref href="#table-internal-slots-of-asynccontext-instances"></emu-xref>.</p>
<emu-table id="table-internal-slots-of-asynccontext-instances" caption="Internal Slots of AsyncContext Instances">
<table>
<tr>
<th>
Internal Slot
</th>
<th>
Type
</th>
<th>
Description
</th>
</tr>
<tr>
<td>
[[AsyncContextKey]]
</td>
<td>
a Symbol
</td>
<td>
Represents the AsyncContext instance in the surrounding agent's Agent Record's [[AsyncContextMapping]].
</td>
</tr>
</table>
</emu-table>
</emu-clause>
</emu-clause>
</emu-clause>
</ins>