@@ -40,7 +40,6 @@ urlPrefix: https://html.spec.whatwg.org/multipage/webappapis.html; type: dfn;
40
40
text: environment settings object
41
41
text: event loop
42
42
text: event loop processing model
43
- text: fetch a module script tree
44
43
text: global object
45
44
text: https state
46
45
text: incumbent settings object
@@ -58,8 +57,6 @@ urlPrefix: https://html.spec.whatwg.org/multipage/webappapis.html; type: dfn;
58
57
urlPrefix: https://html.spec.whatwg.org/multipage/infrastructure.html; type: dfn;
59
58
text: cors setting attribute
60
59
text: in parallel
61
- urlPrefix: #js-;
62
- text: syntaxerror;
63
60
url: resolve-a-url; text: resolve;
64
61
urlPrefix: https://www.w3.org/2001/tag/doc/promises-guide; type: dfn;
65
62
text: a new promise
@@ -147,7 +144,12 @@ interface WorkletGlobalScope {
147
144
};
148
145
</pre>
149
146
150
- A {{WorkletGlobalScope}} has an associated <a>environment settings object</a> .
147
+ Each {{WorkletGlobalScope}} has an associated <a>environment settings object</a> .
148
+
149
+ Each {{WorkletGlobalScope}} has a <dfn>worklet global scope execution environment</dfn> . This
150
+ execution environment may be parallel (i.e. it may be on a separate thread, process, or other
151
+ equivalent construct), or it may live on the same thread or process as the {{Worklet}} object it
152
+ belongs to. Which thread or process it lives on is decided by the user agent.
151
153
152
154
Note:
153
155
The {{WorkletGlobalScope}} has a limited global scope when compared to a
@@ -158,21 +160,26 @@ Note:
158
160
### The event loop ### {#the-event-loop}
159
161
160
162
Each {{WorkletGlobalScope}} object has a distinct <a>event loop</a> . This <a>event loop</a> has no
161
- associated <a>browsing context</a> , and only its <a>microtask queue</a> is used (all other <a>task
162
- queues</a> are not used). The <a>event loop</a> is created by the <a>create a
163
+ associated <a>browsing context</a> . The <a>event loop</a> is created by the <a>create a
163
164
WorkletGlobalScope</a> algorithm.
164
165
166
+ The <a>event loop</a> is run on the <a>worklet global scope execution environment</a> defined above.
167
+
168
+ It is expected that only tasks associated {{Worklet/import()}} , the user agent invoking author
169
+ defined callbacks, and <a>microtasks</a> will use this <a>event loop</a> .
170
+
165
171
Note:
166
172
Even through the <a>event loop processing model</a> specifies that it loops continually,
167
- practically implementations aren't expected to do this. The <a>microtask queue</a> is the only
168
- queue used and is emptied while <a>invoking callback functions</a> provided by the author.
173
+ practically implementations aren't expected to do this. The <a>microtask queue</a> is emptied
174
+ while <a>invoking callback functions</a> provided by the author.
169
175
170
176
### Creating a WorkletGlobalScope ### {#creating-a-workletglobalscope}
171
177
172
- When a user agent is to <dfn>create a WorkletGlobalScope</dfn> , for a given |worklet|, it
173
- <em> must</em> run the following steps:
178
+ When a user agent is to <dfn>create a WorkletGlobalScope</dfn> , given |workletGlobalScopeType|,
179
+ |moduleResponsesMap|, and |outsideSettings|, it <em> must</em> run the following steps:
174
180
175
- 1. Let |workletGlobalScopeType| be the |worklet|'s <a>worklet global scope type</a> .
181
+ 1. Create the <a>worklet global scope execution environment</a> and run the rest of these steps
182
+ in that context.
176
183
177
184
2. Call the JavaScript <a>InitializeHostDefinedRealm</a> abstract operation with the following
178
185
customizations:
@@ -184,25 +191,29 @@ When a user agent is to <dfn>create a WorkletGlobalScope</dfn>, for a given |wor
184
191
185
192
- Do not obtain any source texts for scripts or modules.
186
193
187
- 3. Let |settingsObject | be the result of <a>set up a worklet environment settings object</a>
194
+ 3. Let |insideSettings | be the result of <a>set up a worklet environment settings object</a>
188
195
with |realmExecutionContext|.
189
196
190
- 4. Associate the |settingsObject| with |workletGlobalScope|.
191
-
192
- 5. For each |entry| in the given |worklet|'s <a>module responses map</a> (in insertion order),
193
- run the following substeps:
197
+ 4. Associate the |insideSettings| with |workletGlobalScope|.
194
198
195
- 1. Let |resolvedModuleURL| be |entry|'s key.
199
+ 5. For each |entry| in the given |moduleResponsesMap| (in insertion order), run the following
200
+ substeps:
196
201
197
- 2. Let |script| be the result of <a>fetch a module script tree</a> given
198
- |resolvedModuleURL|, "anonymous" for the <a>CORS setting attribute</a> , and
199
- |settingsObject|.
202
+ 1. Let |moduleURLRecord| be |entry|'s key.
200
203
201
- Note: Worklets follow <a>web workers</a> here in not allowing "use-credentials" for
202
- fetching resources.
204
+ 2. Let |script| be the result of <a>fetch a worklet script</a> given |moduleURLRecord|,
205
+ |moduleResponsesMap|, |outsideSettings|, and |insideSettings| when
206
+ it asynchronously completes.
203
207
204
208
3. <a>Run a module script</a> given |script|.
205
209
210
+ Note: <a>Fetch a worklet script</a> won't actually perform a network request as it will hit
211
+ the worklet's <a>module responses map</a> . It also won't have a parsing error as at this
212
+ point it should have successfully been parsed by another worklet global scope. I.e.
213
+ |script| should never be <em> null</em> here.
214
+
215
+ 6. Run the <a>responsible event loop</a> specified by |insideSettings|.
216
+
206
217
### Script settings for worklets ### {#script-settings-for-worklets}
207
218
208
219
When a user agent is to <dfn>set up a worklet environment settings object</dfn> , given a
@@ -285,85 +296,137 @@ The <a>module responses map</a> exists to ensure that {{WorkletGlobalScope}}s cr
285
296
times contain the same set of script source text and have the same behaviour. The creation of
286
297
additional {{WorkletGlobalScope}} s should be transparent to the author.
287
298
288
- Note:
289
- Practically user- agents aren't expected to implement the following algorithm using a
290
- thread-safe map. Instead when {{Worklet/import}} is called user- agents can fetch the module
299
+ <div class='note'>
300
+ Practically user agents aren't expected to implement the following algorithm using a
301
+ thread-safe map. Instead when {{Worklet/import() }} is called user agents can fetch the module
291
302
graph on the main thread, and send the fetched sources (the data contained in the <a>module
292
303
responses map</a> ) to each thread which has a {{WorkletGlobalScope}} .
293
304
294
305
If the user agent wishes to create a new {{WorkletGlobalScope}} it can simply sent the list of
295
306
all fetched sources from the main thread to the thread which owns the {{WorkletGlobalScope}} .
307
+ </div>
308
+
309
+ A <dfn>pending tasks struct</dfn> is a <a>struct</a> consiting of:
310
+ - A <dfn for="pending tasks struct">counter</dfn> .
311
+ This is used by the algorithms below.
312
+
313
+ <hr>
296
314
297
315
When the <dfn method for=Worklet>import(|moduleURL|)</dfn> method is called on a {{Worklet}} object,
298
316
the user agent <em> must</em> run the following steps:
299
317
1. Let |promise| be <a>a new promise</a> .
300
318
301
- 2. Let |resolvedModuleURL| be the result of <a>parsing</a> the |moduleURL| argument relative to
319
+ 2. Let |worklet| be the current {{Worklet}} .
320
+
321
+ 3. Let |moduleURLRecord| be the result of <a>parsing</a> the |moduleURL| argument relative to
302
322
the <a>relevant settings object</a> of <b> this</b> .
303
323
304
- 3. If this fails, reject |promise| with a "<a>SyntaxError</a> " <a>DOMException</a> and abort
305
- these steps.
324
+ 4. If |moduleURLRecord| is failure, then reject promise with a "<a>SyntaxError</a> "
325
+ <a>DOMException</a> and return |promise|.
326
+
327
+ 5. Return |promise|, and then continue running this algorithm <a>in parallel</a> .
328
+
329
+ 6. Let |outsideSettings| be the <a>relevant settings object</a> of <b> this</b> .
330
+
331
+ 7. Let |moduleResponsesMap| be |worklet|'s <a>module responses map</a> .
332
+
333
+ 8. Let |workletGlobalScopeType| be |worklet|'s <a>worklet global scope type</a> .
334
+
335
+ 9. If the <a>worklet's WorkletGlobalScopes</a> is empty, run the following steps:
336
+
337
+ 1. <a>Create a WorkletGlobalScope</a> given |workletGlobalScopeType|, |moduleResponsesMap|,
338
+ and |outsideSettings|.
339
+
340
+ 2. Add the {{WorkletGlobalScope}} to <a>worklet's WorkletGlobalScopes</a> .
341
+
342
+ The user agent may also create additional {{WorkletGlobalScope}} s at this time.
343
+
344
+ Wait for this step to complete before continuing.
345
+
346
+ 10. Let |pendingTaskStruct| be a new <a>pending tasks struct</a> with <a
347
+ for="pending tasks struct"> counter</a> initialized to the length of <a>worklet's
348
+ WorkletGlobalScopes</a> .
349
+
350
+ 11. For each |workletGlobalScope| in the <a>worklet's WorkletGlobalScopes</a> , <a>queue a
351
+ task</a> on the |workletGlobalScope| to <a>fetch and invoke a worklet script</a> given
352
+ |workletGlobalScope|, |moduleURLRecord|, |moduleResponsesMap|, |outsideSettings|,
353
+ |pendingTaskStruct|, and |promise|.
354
+
355
+ Note: The rejecting and resolving of the |promise| occurs within the <a>fetch and invoke a
356
+ worklet script</a> algorithm.
357
+
358
+ <hr>
359
+
360
+ When the user agent is to <dfn>fetch and invoke a worklet script</dfn> given |workletGlobalScope|,
361
+ |moduleURLRecord|, |moduleResponsesMap|, |outsideSettings|, |pendingTaskStruct|, and |promise|, the
362
+ user agent <em> must</em> run the following steps:
363
+
364
+ Note: This algorithm is to be run within the <a>worklet global scope execution environment</a> .
365
+
366
+ 1. Let |insideSettings| be the |workletGlobalScope|'s associated <a>environment settings object</a> .
367
+
368
+ 2. Let |script| by the result of <a>fetch a worklet script</a> given |moduleURLRecord|,
369
+ |moduleResponsesMap|, |outsideSettings|, and |insideSettings| when it asynchronously completes.
370
+
371
+ 3. If |script| is <em> null</em> , then <a>queue a task</a> on |outsideSettings|'s <a>responsible
372
+ event loop</a> to run these steps:
373
+
374
+ 1. If |pendingTaskStruct|'s <a for="pending tasks struct">counter</a> is not <b> -1</b> , then
375
+ run these steps:
306
376
307
- 4. Ensure that there is at least one {{WorkletGlobalScope}} in the <a>worklet's
308
- WorkletGlobalScopes</a> . If not <a>create a WorkletGlobalScope</a> given the current
309
- {{Worklet}} .
377
+ 1. Set |pendingTaskStruct|'s <a for="pending tasks struct">counter</a> to <b> -1</b> .
310
378
311
- The user-agent may also create additional {{WorkletGlobalScope}} s at this time .
379
+ 2. Reject |promise| with an " <a>AbortError</a> " <a>DOMException</a> .
312
380
313
- 5. Let |outsideSettings| be the <a>relevant settings object </a> of <b> this </b> .
381
+ 4. <a>Run a module script </a> given |script| .
314
382
315
- 6. Run the following steps <a>in parallel </a> :
383
+ 5. <a>Queue a task</a> on |outsideSettings|'s <a>responsible event loop </a> to run these steps :
316
384
317
- 1. For each {{WorkletGlobalScope}} in the <a>worklet's WorkletGlobalScopes</a > , run these
318
- substeps :
385
+ 1. If |pendingTaskStruct|'s <a for="pending tasks struct">counter</a> is not <b> -1 </b > , then run
386
+ these steps :
319
387
320
- 1. Let |insideSettings| be the {{WorkletGlobalScope}} 's associated <a>environment
321
- settings object</a> .
388
+ 1. Decrement |pendingTaskStruct|'s <a for="pending tasks struct">counter</a> by <b> 1</b> .
322
389
323
- 2. <a>Fetch a module script tree</a> given |resolvedModuleURL|, "omit", the empty string
324
- (as no cryptographic nonce is present for worklets), "not parser-inserted",
325
- "script", |outsideSettings|, and |insideSettings|.
390
+ 1. If |pendingTaskStruct|'s <a for="pending tasks struct">counter</a> is <b> 0</b> , then
391
+ resolve |promise|.
326
392
327
- To <a>perform the request</a> given |request|, perform the following steps:
393
+ <hr>
328
394
329
- 1. Let |cache| be the current {{Worklet}} 's <a>module responses map</a> .
395
+ When the user agent is to <dfn>fetch a worklet script</dfn> given |moduleURLRecord|,
396
+ |moduleResponsesMap|, |outsideSettings|, and |insideSettings|, the user agent <em> must</em>
397
+ run the following steps:
330
398
331
- 2. Let |url| be |request|'s <a >url </a> .
399
+ Note: This algorithm is to be run within the <a>worklet global scope execution environment </a> .
332
400
333
- 3. If |cache| contains an entry with key |url| whose value is "fetching", wait
334
- (<a>in parallel</a> ) until that entry's value changes, then proceed to the
335
- next step.
401
+ 1. <a>Fetch a module worker script graph</a> given |moduleURLRecord|, |outsideSettings|, "script",
402
+ "omit", and |insideSettings|.
336
403
337
- 4. If |cache| contains an entry with key |url|, asynchronously complete this
338
- algorithm with that entry's value, and abort these steps.
404
+ To <a>perform the request</a> given |request|, perform the following steps:
339
405
340
- 5. Create an entry in |cache| with key |url| and value "fetching" .
406
+ 1. Let |cache| be the |moduleResponsesMap| .
341
407
342
- 6. <a>Fetch </a> |request| .
408
+ 2. Let |url| be |request|'s <a for=request>url </a> .
343
409
344
- 7. Let |response| be the result of <a>fetch</a> when it asynchronously
345
- completes .
410
+ 3. If |cache| contains an entry with key |url| whose value is "fetching", wait until that
411
+ entry's value changes, then proceed to the next step .
346
412
347
- 8. Set the value of the entry in |cache| whose key is |url| to |response|, and
348
- asynchronously complete this algorithm with |response| .
413
+ 4. If |cache| contains an entry with key |url|, asynchronously complete this algorithm with
414
+ that entry's value, and abort these steps .
349
415
350
- 3. Let |script| be the result of <a>fetch a module script tree</a> when it
351
- asynchronously completes.
416
+ 5. Create an entry in |cache| with key |url| and value "fetching".
352
417
353
- If |script| is <em> null</em> reject |promise| with a "<a>AbortError</a> "
354
- <a>DOMException</a> and abort all these steps.
418
+ 6. <a>Fetch</a> |request|.
355
419
356
- 4. <a>Run a module script </a> given |script| .
420
+ 7. Let |response| be the result of <a>fetch </a> when it asynchronously completes .
357
421
358
- 2. If <em> all</em> the steps above succeeded (in particular, if all of the scripts parsed
359
- and loaded into the global scopes), resolve |promise|.
360
- <br> Otherwise, reject |promise|.
422
+ 8. Set the value of the entry in |cache| whose key is |url| to |response|, and
423
+ asynchronously complete this algorithm with |response|.
361
424
362
- Note: Specifically, if a script fails to parse or fails to load over the network, it will
363
- reject the promise; if the script throws an error while first evaluating the promise
364
- should resolve as a classes may have been registered correctly.
425
+ 2. Return the result of <a>fetch a module worker script graph</a> when it asynchronously completes.
365
426
366
- 7. Return |promise|.
427
+ Note: Specifically, if a script fails to parse or fails to load over the network, it will reject the
428
+ promise. If the script throws an error while first evaluating the promise it will resolve as a
429
+ classes may have been registered correctly.
367
430
368
431
<div class=example>
369
432
When an author imports code into a {{Worklet}} the code may run against multiple
@@ -378,16 +441,16 @@ the user agent <em>must</em> run the following steps:
378
441
await CSS.paintWorklet.import('script.js' );
379
442
</pre>
380
443
381
- Behind the scenes the user- agent may load the <code class='lang-javascript'> script.js</code>
382
- into 4 global scopes, in which case the debugging tools for the user- agent would print:
444
+ Behind the scenes the user agent may load the <code class='lang-javascript'> script.js</code>
445
+ into 4 global scopes, in which case the debugging tools for the user agent would print:
383
446
<pre class='lang-javascript'>
384
447
[paintWorklet#1] Hello from a WorkletGlobalScope!
385
448
[paintWorklet#4] Hello from a WorkletGlobalScope!
386
449
[paintWorklet#2] Hello from a WorkletGlobalScope!
387
450
[paintWorklet#3] Hello from a WorkletGlobalScope!
388
451
</pre>
389
452
390
- If the user- agent decided to kill and restart a {{WorkletGlobalScope}} number 3 in this example,
453
+ If the user agent decided to kill and restart a {{WorkletGlobalScope}} number 3 in this example,
391
454
it would print <code class='lang-javascript'> [paintWorklet#3] Hello from a
392
455
WorkletGlobalScope!</code> again in the debugging tools when this occurs.
393
456
</div>
0 commit comments