generated from legendecas/tc39-proposal
/
spec.html
278 lines (223 loc) · 12.2 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
<pre class="metadata">
title: Zones
status: proposal
stage: 0
location: https://domenic.github.io/zones/
copyright: false
contributors: Domenic Denicola
</pre>
<script src="https://bterlson.github.io/ecmarkup/ecmarkup.js" defer></script>
<link rel="stylesheet" href="https://bterlson.github.io/ecmarkup/elements.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/styles/solarized_light.min.css">
<emu-clause id="sec-zone-objects">
<h1>Zone Objects</h1>
<p>A Zone is an object that represents a logical asynchronous context.</p>
<emu-clause id="sec-zone-abstract-operations">
<h1>Zone Abstract Operations</h1>
<p>None yet... Will probably want to refactor some out in order to make them more accessible to other specifications.</p>
</emu-clause>
<emu-clause id="sec-zone-constructor">
<h1>The Zone Constructor</h1>
<p>The Zone constructor is the <dfn>%Zone%</dfn> intrinsic object and the initial value of the `Zone` property of the global object. When called as a constructor it creates and initializes a new Zone object. `Zone` is not intended to be called as a function and will throw an exception when called in that manner.</p>
<p>The `Zone` constructor is designed to be subclassable. It may be used as the value in an `extends` clause of a class definition. Subclass constructors that intend to inherit the specified `Zone` behaviour must include a `super` call to the `Zone` constructor to create and initialize the subclass instance with the internal state necessary to support the `Zone` and `Zone.prototype` built-in methods.</p>
<emu-note>
<p>(Spec review note) I'm not sure if you can subclass classes that have internal slots on their constructors. Which is fine with me; just would need to revise the above. Might also want to make some things not go through `.constructor` in that case, and perhaps prohibit subclassing by checking NewTarget.</p>
</emu-note>
<emu-clause id="sec-zone">
<h1>Zone ( _options_ )</h1>
<p>When the `Zone` function is called with argument _options_, the following steps are taken:</p>
<emu-alg>
1. If NewTarget is *undefined*, throw a *TypeError* exception.
1. Let _functionRealm_ be ? GetFunctionRealm(the active function object).
1. Let _name_ be `"(unnamed zone)"`.
1. Let _parent_ be *null*.
1. If _options_ is *undefined*, set _options_ to ! ObjectCreate(%ObjectPrototype%).
1. Perform ? RequireObjectCoercible(_options_).
1. Let _nameOption_ be ? GetV(_options_, `"name"`).
1. If _nameOption_ is not *undefined*, set _name_ to ? ToString(_nameOption_).
1. Let _parentOption_ be ? GetV(_options_, `"parent"`).
1. If _parentOption_ is not *undefined*, set _parent_ to _parentOption_.
1. If _parent_ is not *null* and does not have a [[ParentZone]] internal slot, throw a *TypeError* exception.
1. Let _zone_ be ? OrdinaryCreateFromConstructor(NewTarget, `"%ZonePrototype"`, « [[ParentZone]], [[Realm]] »).
1. Set _zone_'s [[ParentZone]] internal slot to _parent_.
1. Set _zone_'s [[Realm]] internal slot to _currentRealm_.
1. Perform ! DefinePropertyOrThrow(_zone_, `"name"`, PropertyDescriptor {[[Value]]: _name_, [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: true }).
1. Return _zone_.
</emu-alg>
<emu-note>
<p>The `Zone` constructor is not typically used directly. Instead, `anotherZone.fork({ name })` is used to create a new zone that is the child of an existing one. A particular common pattern is `Zone.current.fork({ name })`.</p>
</emu-note>
<emu-note>
<p>(Spec review note) This is intended to mimic the signature `constructor({ name = "(unnamed zone)", parent = null } = {}) { ... }`.</p>
</emu-note>
</emu-clause>
</emu-clause>
<emu-clause id="sec-properties-of-the-zone-constructor">
<h1>Properties of the Zone Constructor</h1>
<p>The value of the [[Prototype]] internal slot of the `Zone` constructor is the intrinsic object %FunctionPrototype%.</p>
<p>The Zone constructor has the following properties:</p>
<emu-clause id="sec-zone.prototype">
<h1>Zone.prototype</h1>
<p>The initial value of `Zone.prototype` is the intrinsic object %ZonePrototype%.</p>
<p>This property has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *false* }.</p>
</emu-clause>
<emu-clause id="sec-get-zone.current">
<h1>get Zone.current</h1>
<p>`Zone.current` is an accessor property whose set accessor function is *undefined*. Its get accessor function performs the following steps:</p>
<emu-alg>
1. Let _C_ be the *this* value.
1. If IsCallable(_C_) is *false*, throw a *TypeError* exception.
1. Let _thisRealm_ be ? GetFunctionRealm(_C_).
1. Return _thisRealm_.[[CurrentZone]].
</emu-alg>
</emu-clause>
</emu-clause>
<emu-clause id="sec-properties-of-the-zone-prototype-object">
<h1>Properties of the Zone Prototype Object</h1>
<p>The Zone prototype object is the intrinsic object <dfn>%ZonePrototype%</dfn>. The value of the [[Prototype]] internal slot of the Zone prototype object is the intrinsic object %ObjectPrototype%. The Zone prototype object is an ordinary object. It does not have any of the internal slots of Zone instances.</p>
<emu-clause id="sec-get-zone.prototype.parent">
<h1>get Zone.prototype.parent</h1>
<p>`Zone.prototype.parent` is an accessor property whose set accessor function is *undefined*. Its get accessor function performs the following steps:</p>
<emu-alg>
1. Let _Z_ be the *this* value.
1. If Type(_Z_) is not Object, throw a *TypeError* exception.
1. If _Z_ does not have a [[ParentZone]] internal slot, throw a *TypeError* exception.
1. Return the value of _Z_'s [[ParentZone]] internal slot.
</emu-alg>
</emu-clause>
<emu-clause id="sec-zone.prototype.fork">
<h1>Zone.prototype.fork ( _options_ )</h1>
<p>When the `fork` method is called with argument _options_, the following steps are taken:</p>
<emu-alg>
1. Let _Z_ be the *this* value.
1. If Type(_Z_) is not Object, throw a *TypeError* exception.
1. If _Z_ does not have a [[ParentZone]] internal slot, throw a *TypeError* exception.
1. Let _name_ be *null*.
1. If _options_ is *undefined*, set _options_ to ! ObjectCreate(%ObjectPrototype%).
1. Perform ? RequireObjectCoercible(_options_).
1. Let _nameOption_ be ? GetV(_options_, `"name"`).
1. If _nameOption_ is *undefined*,
1. Let _parentName_ be ? ToString(? Get(_Z_, `"name"`)).
1. Set _name_ to the result of concatenating _parentName_ and the string `" child"`.
1. Otherwise, set _name_ to ? ToString(_nameOption_).
1. Let _constructorOptions_ be ! ObjectCreate(%ObjectPrototype%).
1. Peform ! CreateDataProperty(_constructorOptions_, `"parent"`, _Z_).
1. Perform ! CreateDataProperty(_options_, `"name"`, _name_).
1. Let _C_ be ? Get(_Z_, `"constructor"`).
1. Return ? Construct(_C_, « _options_ »)
</emu-alg>
<emu-note>
<p>(Spec review note) This is intended to mimic the function signature `fork({ name = ToString(this.name) + " child" } = {}) { ... }`.</p>
</emu-note>
</emu-clause>
<emu-clause id="sec-zone.prototype.run">
<h1>Zone.prototype.run ( _callback_ )</h1>
<p>When the `run` method is called with argument _callback_, the following steps are taken:</p>
<emu-alg>
1. Let _Z_ be the *this* value.
1. If Type(_Z_) is not Object, throw a *TypeError* exception.
1. If _Z_ does not have a [[ParentZone]] internal slot, throw a *TypeError* exception.
1. If IsCallable(_callback_) is *false*, throw a *TypeError* exception.
1. Let _thisRealm_ be the value of _Z_'s [[Realm]] internal slot.
1. Let _beforeZone_ be _thisRealm_.[[CurrentZone]].
1. Set _thisRealm_.[[CurrentZone]] to _Z_.
1. Let _status_ be Call(_callback_, *undefined*, « »).
1. Set _thisRealm_.[[CurrentZone]] to _beforeZone_.
1. Return _status_.
</emu-alg>
</emu-clause>
<emu-clause id="sec-zone.prototype.wrap">
<h1>Zone.prototype.wrap ( _callback_ )</h1>
<p>When the `wrap` method is called with argument _callback_, the following steps are taken:</p>
<emu-alg>
1. Let _Z_ be the *this* value.
1. If Type(_Z_) is not Object, throw a *TypeError* exception.
1. If _Z_ does not have a [[ParentZone]] internal slot, throw a *TypeError* exception.
1. TODO
</emu-alg>
</emu-clause>
</emu-clause>
<emu-clause id="sec-properties-of-zone-instances">
<h1>Properties of Zone Instances</h1>
<p>Zone instances are ordinary objects that inherit properties from the Zone prototype object (the intrinsic, %ZonePrototype%). Zone instances are initially created with the internal slots described in <emu-xref href="#table-zone-slots"></emu-xref>.</p>
<emu-table id="table-zone-slots" caption="Internal Slots of Zone Instances">
<table>
<thead>
<tr>
<th>Internal Slot</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>[[ParentZone]]</td>
<td>The zone in which this zone was created.</td>
</tr>
<tr>
<td>[[Realm]]</td>
<td>The realm of the `Zone` constructor that created this instance.</td>
</tr>
</tbody>
</table>
</emu-table>
<p>Each Zone instance has the following own property:</p>
<emu-clause id="sec-properties-of-zone-instances-name">
<h1>name</h1>
<p>The value of the `name` property is a string that indicates the name of the zone, supplied at construction time. It is used for debugging and tooling purposes and does not affect the zone's behavior.</p>
<p>This property has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *true* }.</p>
</emu-clause>
</emu-clause>
</emu-clause>
<emu-clause id="monkeypatch-realms">
<h1>Revisions to Realms</h1>
<p>The table for Realm Record fields gets a new entry:</p>
<ins>
<emu-table id="table-monkeypatch-realm-record-fields" caption="Realm Record Fields">
<table>
<thead>
<tr>
<th>Field Name</th>
<th>Value</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td><ins>[[CurrentZone]]</ins></td>
<td><ins>A `Zone` object</ins></td>
<td><ins>The current zone for this realm</ins></td>
</tr>
</tbody>
</table>
</emu-table>
<emu-clause id="monkeypatch-createrealm">
<h1>CreateRealm ( )</h1>
<p>The abstract operation CreateRealm with no arguments performs the following steps:</p>
<emu-alg>
1. Let _realmRec_ be a new Realm Record.
1. Perform CreateIntrinsics(_realmRec_).
1. Set _realmRec_.[[GlobalObject]] to *undefined*.
1. Set _realmRec_.[[GlobalEnv]] to *undefined*.
1. Set _realmRec_.[[TemplateMap]] to a new empty List.
1. <ins>Let _options_ be ! ObjectCreate(%ObjectPrototype%).</ins>
1. <ins>Perform ! CreateDataProperty(_options_, `"name"`, `"(root zone)"`).</ins>
1. <ins>Set _realmRec_.[[CurrentZone]] to ! Construct(%Zone%, « _options_ »).</ins>
1. Return _realmRec_.
</emu-alg>
</emu-clause>
</emu-clause>
<emu-clause id="monkeypatch-promises">
<h1>Revisions to Promise Objects</h1>
<emu-clause id="monkeypatch-promisereaction-records">
<h1>PromiseReaction Records</h1>
<p>TODO: add a field for the zone so we can store it.</p>
</emu-clause>
<emu-clause id="monkeypatch-perform-promise-then">
<h1>PerformPromiseThen</h1>
<p>TODO: basically wrap the callbacks, except by storing the zone in the PromiseReaction instead of by generating a new function object.</p>
</emu-clause>
<emu-clause id="monkeypatch-promisereactionjob">
<h1>PromiseReactionJob</h1>
<p>TODO: use stored field to set zone before running the handler (and of course restore the old zone afterward).</p>
</emu-clause>
</emu-clause>