forked from w3c/css-houdini-drafts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOverview.bs
588 lines (424 loc) · 23.9 KB
/
Overview.bs
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
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
<pre class='metadata'>
Title: Worklets Level 1
Status: ED
Group: houdini
ED: https://drafts.css-houdini.org/worklets/
TR: http://www.w3.org/TR/2016/WD-worklets-1-20160607/
Previous Version: http://www.w3.org/TR/2016/WD-worklets-1-20160607/
Shortname: worklets
Level: 1
Abstract: This specification defines an API for running scripts in stages of the rendering pipeline independent of the main javascript execution environment.
Editor: Ian Kilpatrick, ikilpatrick@chromium.org
</pre>
<style>
/* Put nice boxes around each algorithm. */
[data-algorithm]:not(.heading) {
padding: .5em;
border: thin solid #ddd; border-radius: .5em;
margin: .5em calc(-0.5em - 1px);
}
[data-algorithm]:not(.heading) > :first-child {
margin-top: 0;
}
[data-algorithm]:not(.heading) > :last-child {
margin-bottom: 0;
}
</style>
<pre class=link-defaults>
spec:fetch; type:dfn; for:/; text:fetch
spec:html; type:dfn; for:/; text:browsing context
spec:html; type:dfn; for:environment settings object;
text: global object
text: https state
text: referrer policy
spec:html; type:dfn; for:environment; text:id
spec:webidl; type:dfn; for:interface; text:inherit
</pre>
<pre class="anchors">
urlPrefix: http://heycam.github.io/webidl/; type: dfn;
urlPrefix: #es-;
text: invoking callback functions
urlPrefix: https://html.spec.whatwg.org/multipage/workers.html; type: dfn;
urlPrefix: #dom-workerglobalscope-;
text: self
urlPrefix: https://html.spec.whatwg.org/multipage/webappapis.html; type: dfn;
text: document environment
text: event loop processing model
text: microtask queue
text: task queues
urlPrefix: http://www.ecma-international.org/ecma-262/6.0/#sec-; type: dfn;
text: Construct
text: InitializeHostDefinedRealm
text: Invoke
text: strict mode code
</pre>
Introduction {#intro}
=====================
Motivations {#motivations}
--------------------------
<em>This section is not normative.</em>
Allowing extension points defined in the <a>document environment</a> is difficult, as rendering
engines would need to abandon previously held assumptions for what could happen in the middle of a
phase.
For example, during the layout phase the rendering engine assumes that no DOM will be modified.
Additionally defining extension points in the <a>document environment</a> would restrict rendering
engines to performing work in the same thread as the <a>document environment</a>. (Unless rendering
engines added complex, high-overhead infrastructure to allow thread-safe APIs in addition to thread
joining guarantees).
The worklet is designed to allow such extension points in rendering engines, while keeping
guarantees which rendering engines rely currently on.
Worklets are similar to <a>web workers</a> however they:
- Are thread-agnostic. That is, they are not defined to run on a particular thread. Rendering
engines may run them wherever they choose.
- Are able to have multiple duplicate instances of the global scope created for the purpose of
parallelism.
- Are not event API based. Instead classes are registered on the global scope, whose methods are to
be invoked by the user agent.
- Have a reduced API surface on the global scope.
- Have a lifetime for the global scope which is defined by subsequent specifications or user
agents. They aren't tied to the lifetime of the document.
As worklets have a relatively high overhead, they should be used sparingly. Due to this worklets are
expected to be shared between separate scripts. This is similar to the <a>document environment</a>.
Code Idempotency {#code-idempotency}
------------------------------------
Some specifications which use worklets ([[css-paint-api-1]]), allow user agents to parallelize work
over multiple threads, or to move work between threads as required.
In these specifications user agents might invoke methods on a class in a different order to other
user agents.
As a result of this, to prevent this compatibility risk between user agents, authors who register
classes on the global scope using these APIs, should make their code idempotent. That is, a method
or set of methods on a class should produce the same output given a particular input.
The following techniques are used in order to encourage authors to write code in an idempotent way:
- No reference to the global object, e.g. <a>self</a> on a {{DedicatedWorkerGlobalScope}}.
- Code is loaded as a <a>module script</a> which resulting in the code being executed in <a>strict
mode code</a> without a shared this. This prevents two different module scripts sharing
state be referencing shared objects on the global scope.
- These specifications must require user agents to always have at least two {{WorkletGlobalScope}}s
per {{Worklet}} and randomly assign a method or set of methods on a class to a particular
global scope. These specifications can provide an opt-out under memory constraints.
- User agents can create and destroy {{WorkletGlobalScope}}s at any time for these specifications.
Infrastructure {#infrastructure}
================================
The Global Scope {#the-global-scope}
------------------------------------
The {{WorkletGlobalScope}} object provides a <dfn>worklet global scope</dfn> which represents the
global execution context of a {{Worklet}}.
<pre class='idl'>
[Exposed=Worklet]
interface WorkletGlobalScope {
};
</pre>
Each {{WorkletGlobalScope}} has an associated <a>environment settings object</a>.
Each {{WorkletGlobalScope}} has an associated <dfn for=WorkletGlobalScope>module map</dfn>. It is a
<a>module map</a>, initially empty.
Each {{WorkletGlobalScope}} has a <dfn>worklet global scope execution environment</dfn>. This
execution environment may be parallel (i.e. it may be on a separate thread, process, or other
equivalent construct), or it may live on the same thread or process as the {{Worklet}} object it
belongs to. Which thread or process it lives on is decided by the user agent.
Note:
The {{WorkletGlobalScope}} has a limited global scope when compared to a
{{DedicatedWorkerGlobalScope}}. It is expected that other specifications will extend
{{WorkletGlobalScope}} with <code class='lang-javascript'>registerAClass</code> methods which
will allow authors to register classes for the user agent create and invoke methods on.
When asked to <a>report an exception</a>, do nothing instead, or optionally report the exception to
a developer console.
Issue(whatwg/html#2611): HTML's <a>report an exception</a> needs updating to work with
non-EventTarget global objects.
### The event loop ### {#the-event-loop}
Each {{WorkletGlobalScope}} object has a distinct <a>event loop</a>. This <a>event loop</a> has no
associated <a>browsing context</a>. The <a>event loop</a> is created by the <a>create a
WorkletGlobalScope</a> algorithm.
The <a>event loop</a> is run on the <a>worklet global scope execution environment</a> defined above.
It is expected that only tasks associated {{Worklet/addModule()}}, the user agent invoking author
defined callbacks, and <a>microtasks</a> will use this <a>event loop</a>.
Note:
Even through the <a>event loop processing model</a> specifies that it loops continually,
practically implementations aren't expected to do this. The <a>microtask queue</a> is emptied
while <a>invoking callback functions</a> provided by the author.
### Creating a WorkletGlobalScope ### {#creating-a-workletglobalscope}
<div algorithm>
When a user agent is to <dfn>create a WorkletGlobalScope</dfn>, given |workletGlobalScopeType|,
|moduleResponsesMap|, and |outsideSettings|, it <em>must</em> run the following steps:
1. Create the <a>worklet global scope execution environment</a> and run the rest of these steps
in that context.
2. Call the JavaScript <a>InitializeHostDefinedRealm</a> abstract operation with the following
customizations:
- For the global object, create a new |workletGlobalScopeType| object. Let
|workletGlobalScope| be the created object.
- Let |realmExecutionContext| be the created JavaScript execution context.
3. Let |insideSettings| be the result of <a>set up a worklet environment settings object</a>
given |realmExecutionContext|, and |outsideSettings|.
4. Associate the |insideSettings| with |workletGlobalScope|.
5. For each |entry| in the given |moduleResponsesMap| (in insertion order), run the following
substeps:
1. Let |moduleURLRecord| be |entry|'s key.
2. Let |script| be the result of <a>fetch a worklet script</a> given |moduleURLRecord|,
|moduleResponsesMap|, |outsideSettings|, and |insideSettings| when
it asynchronously completes.
3. <a>Run a module script</a> given |script|.
Note: <a>Fetch a worklet script</a> won't actually perform a network request as it will hit
the worklet's <a>module responses map</a>. It also won't have a parsing error as at this
point it should have successfully been parsed by another worklet global scope. I.e.
|script| should never be null here.
6. Run the <a>responsible event loop</a> specified by |insideSettings|.
</div>
### Script settings for worklets ### {#script-settings-for-worklets}
<div algorithm>
When a user agent is to <dfn>set up a worklet environment settings object</dfn>, given a
|executionContext|, and |outsideSettings|, it must run the following steps:
1. Let |inheritedResponsibleBrowsingContext| be |outsideSettings|'s <a>responsible browsing
context</a>.
2. Let |inheritedAPIBaseURL| be |outsideSettings|'s <a>API base URL</a>.
3. Let |origin| be a unique <a>opaque origin</a>.
4. Let |inheritedHTTPSState| be |outsideSettings|'s <a>HTTPS state</a>.
5. Let |inheritedReferrerPolicy| be |outsideSettings|'s <a>referrer policy</a>.
6. Let |workletEventLoop| be a newly created <a>event loop</a>.
7. Let |realm| be the value of |executionContext|'s Realm component.
8. Let |workletGlobalScope| be |realm|'s <a>global object</a>.
9. Let |settingsObject| be a new <a>environment settings object</a> whose algorithms are defined
as follows:
: The <a>realm execution context</a>
:: Return |executionContext|.
: The <a>module map</a>.
:: Return |workletGlobalScope|'s <a for=WorkletGlobalScope>module map</a>.
: The <a>responsible browsing context</a>
:: Return |inheritedResponsibleBrowsingContext|.
: The <a>responsible event loop</a>
:: Return |workletEventLoop|.
: The <a>responsible document</a>
:: Not applicable (the <a>responsible event loop</a> is not a <a>browsing context</a>
<a>event loop</a>).
: The <a>API URL character encoding</a>
:: Return <a>UTF-8</a>.
: The <a>API base URL</a>
:: Return |inheritedAPIBaseURL|.
: The <a for="environment settings object">origin</a>
:: Return |origin|.
: The <a>HTTPS state</a>
:: Return |inheritedHTTPSState|.
: The <a>referrer policy</a>
:: Return |inheritedReferrerPolicy|.
10. Set |settingsObject|'s <a>id</a> to a new unique opaque string, |settingsObject|'s
<a>creation URL</a> to |inheritedAPIBaseURL|, |settingsObject|'s <a>target browsing
context</a> to null, and |settingsObject|'s <a>active service worker</a> to null.
11. Set |realm|'s \[[HostDefined]] field to |settingsObject|.
12. Return |settingsObject|.
</div>
Issue: Merge this with https://html.spec.whatwg.org/multipage/workers.html#set-up-a-worker-environment-settings-object
Worklet {#worklet-section}
--------------------------
The {{Worklet}} object provides the capability to add module scripts into its associated
{{WorkletGlobalScope}}s. The user agent can then create classes registered on the
{{WorkletGlobalScope}}s and invoke their methods.
<pre class='idl'>
interface Worklet {
[NewObject] Promise<void> addModule(USVString moduleURL, optional WorkletOptions options);
};
dictionary WorkletOptions {
RequestCredentials credentials = "omit";
};
</pre>
A {{Worklet}} has a <dfn export>worklet global scope type</dfn>. This is used for creating new
{{WorkletGlobalScope}} and the type must <a>inherit</a> from {{WorkletGlobalScope}}.
Note: As an example the <a>worklet global scope type</a> might be a {{PaintWorkletGlobalScope}}.
A {{Worklet}} has a list of the <dfn export>worklet's WorkletGlobalScopes</dfn>. Initially this list
is empty; it is populated when the user agent chooses to create its {{WorkletGlobalScope}}.
A {{Worklet}} has a <dfn>module responses map</dfn>. This is a ordered map of module URLs to values
that are a <a>fetch</a> responses. The map's entries are ordered based on their insertion order.
Access to this map should be thread-safe.
The <a>module responses map</a> exists to ensure that {{WorkletGlobalScope}}s created at different
times contain the same set of script source text and have the same behaviour. The creation of
additional {{WorkletGlobalScope}}s should be transparent to the author.
<div class='note'>
Practically user agents aren't expected to implement the following algorithm using a
thread-safe map. Instead when {{Worklet/addModule()}} is called user agents can fetch the module
graph on the main thread, and send the fetched sources (the data contained in the <a>module
responses map</a>) to each thread which has a {{WorkletGlobalScope}}.
If the user agent wishes to create a new {{WorkletGlobalScope}} it can simply sent the list of
all fetched sources from the main thread to the thread which owns the {{WorkletGlobalScope}}.
</div>
A <dfn>pending tasks struct</dfn> is a <a>struct</a> consisting of:
- A <dfn for="pending tasks struct">counter</dfn>.
This is used by the algorithms below.
<div algorithm>
When the <dfn method for=Worklet>addModule(|moduleURL|, |options|)</dfn> method is called on a
{{Worklet}} object, the user agent <em>must</em> run the following steps:
1. Let |promise| be <a>a new promise</a>.
2. Let |worklet| be this {{Worklet}}.
3. Let |outsideSettings| be the <a>relevant settings object</a> of <b>this</b>.
4. Let |moduleURLRecord| be the result of <a>parsing</a> the |moduleURL| argument relative to
|outsideSettings|.
5. If |moduleURLRecord| is failure, then reject promise with a "{{SyntaxError}}"
{{DOMException}} and return |promise|.
6. Return |promise|, and then continue running this algorithm <a>in parallel</a>.
7. Let |credentialOptions| be the {{WorkletOptions/credentials}} member of |options|.
8. Let |moduleResponsesMap| be |worklet|'s <a>module responses map</a>.
9. Let |workletGlobalScopeType| be |worklet|'s <a>worklet global scope type</a>.
10. If the <a>worklet's WorkletGlobalScopes</a> is empty, run the following steps:
1. <a>Create a WorkletGlobalScope</a> given |workletGlobalScopeType|, |moduleResponsesMap|,
and |outsideSettings|.
2. Add the {{WorkletGlobalScope}} to <a>worklet's WorkletGlobalScopes</a>.
Depending on the type of worklet the user agent may create additional
{{WorkletGlobalScope}}s at this time.
Note: Specifically the [[css-paint-api-1]] allows for multiple global scopes, while the
[[webaudio]] API does not.
Wait for this step to complete before continuing.
11. Let |pendingTaskStruct| be a new <a>pending tasks struct</a> with <a
for="pending tasks struct">counter</a> initialized to the length of <a>worklet's
WorkletGlobalScopes</a>.
12. For each |workletGlobalScope| in the <a>worklet's WorkletGlobalScopes</a>, <a>queue a
task</a> on the |workletGlobalScope| to <a>fetch and invoke a worklet script</a> given
|workletGlobalScope|, |moduleURLRecord|, |moduleResponsesMap|, |credentialOptions|,
|outsideSettings|, |pendingTaskStruct|, and |promise|.
Note: The rejecting and resolving of the |promise| occurs within the <a>fetch and invoke a
worklet script</a> algorithm.
</div>
<div algorithm>
When the user agent is to <dfn>fetch and invoke a worklet script</dfn> given |workletGlobalScope|,
|moduleURLRecord|, |moduleResponsesMap|, |credentialOptions|, |outsideSettings|,
|pendingTaskStruct|, and |promise|, the user agent <em>must</em> run the following steps:
Note: This algorithm is to be run within the <a>worklet global scope execution environment</a>.
1. Let |insideSettings| be the |workletGlobalScope|'s associated <a>environment settings
object</a>.
2. Let |script| by the result of <a>fetch a worklet script</a> given |moduleURLRecord|,
|moduleResponsesMap|, |credentialOptions|, |outsideSettings|, and |insideSettings| when it
asynchronously completes.
3. If |script| is null, then <a>queue a task</a> on |outsideSettings|'s <a>responsible event
loop</a> to run these steps:
1. If |pendingTaskStruct|'s <a for="pending tasks struct">counter</a> is not <b>-1</b>, then
run these steps:
1. Set |pendingTaskStruct|'s <a for="pending tasks struct">counter</a> to <b>-1</b>.
2. Reject |promise| with an "{{AbortError}}" {{DOMException}}.
4. <a>Run a module script</a> given |script|.
5. <a>Queue a task</a> on |outsideSettings|'s <a>responsible event loop</a> to run these steps:
1. If |pendingTaskStruct|'s <a for="pending tasks struct">counter</a> is not <b>-1</b>, then
run these steps:
1. Decrement |pendingTaskStruct|'s <a for="pending tasks struct">counter</a> by
<b>1</b>.
2. If |pendingTaskStruct|'s <a for="pending tasks struct">counter</a> is <b>0</b>, then
resolve |promise|.
</div>
<div algorithm>
When the user agent is to <dfn>fetch a worklet script</dfn> given |moduleURLRecord|,
|moduleResponsesMap|, |credentialOptions|, |outsideSettings|, and |insideSettings|, the user agent
<em>must</em> run the following steps:
Note: This algorithm is to be run within the <a>worklet global scope execution environment</a>.
1. <a>Fetch a module worker script graph</a> given |moduleURLRecord|, |outsideSettings|, "script",
|credentialOptions|, and |insideSettings|.
To <a>perform the fetch</a> given |request|, perform the following steps:
1. Let |cache| be the |moduleResponsesMap|.
2. Let |url| be |request|'s <a for=request>url</a>.
3. If |cache| contains an entry with key |url| whose value is "fetching", wait until that
entry's value changes, then proceed to the next step.
4. If |cache| contains an entry with key |url|, asynchronously complete this algorithm with
that entry's value, and abort these steps.
5. Create an entry in |cache| with key |url| and value "fetching".
6. <a>Fetch</a> |request|.
7. Let |response| be the result of <a>fetch</a> when it asynchronously completes.
8. Set the value of the entry in |cache| whose key is |url| to |response|, and
asynchronously complete this algorithm with |response|.
2. Return the result of <a>fetch a module worker script graph</a> when it asynchronously completes.
Note: Specifically, if a script fails to parse or fails to load over the network, it will reject the
promise. If the script throws an error while first evaluating the promise it will resolve as a
classes may have been registered correctly.
<div class=example>
When an author adds code into a {{Worklet}} the code may run against multiple
{{WorkletGlobalScope}}s, for example:
<pre class='lang-javascript'>
// script.js
console.log('Hello from a WorkletGlobalScope!');
</pre>
<pre class='lang-javascript'>
// main.js
await CSS.paintWorklet.addModule('script.js');
</pre>
Behind the scenes the user agent may load the <code class='lang-javascript'>script.js</code>
into 4 global scopes, in which case the debugging tools for the user agent would print:
<pre class='lang-javascript'>
[paintWorklet#1] Hello from a WorkletGlobalScope!
[paintWorklet#4] Hello from a WorkletGlobalScope!
[paintWorklet#2] Hello from a WorkletGlobalScope!
[paintWorklet#3] Hello from a WorkletGlobalScope!
</pre>
If the user agent decided to kill and restart a {{WorkletGlobalScope}} number 3 in this example,
it would print <code class='lang-javascript'>[paintWorklet#3] Hello from a
WorkletGlobalScope!</code> again in the debugging tools when this occurs.
</div>
</div>
Issue(w3c/css-houdini-drafts#47): Need ability to load code into a {{WorkletGlobalScope}}
declaratively.
Lifetime of the Worklet {#lifetime-of-the-worklet}
--------------------------------------------------
The lifetime of a {{Worklet}} is tied to the object it belongs to, for example the {{Window}}.
The lifetime of a {{WorkletGlobalScope}} should be defined by subsequent specifications which
inherit from {{WorkletGlobalScope}}.
Subsequent specifications <em>may</em> define that a {{WorkletGlobalScope}} can be terminated at any
time particularly if there are no pending operations, or detects abnormal operation such as infinite
loops and callbacks exceeding imposed time limits.
Security Considerations {#security-considerations}
==================================================
Issue(w3c/css-houdini-drafts#92): Need to decide if to allow worklets for unsecure context, etc.
Examples {#examples}
====================
<em>This section is not normative.</em>
For these examples we'll use a fake worklet on window.
<div class=example>
<pre class='idl'>
partial interface Window {
[SameObject] readonly attribute Worklet fakeWorklet1;
[SameObject] readonly attribute Worklet fakeWorklet2;
};
</pre>
<pre class='idl'>
callback Function = any (any... arguments);
[Global=(Worklet,FakeWorklet),Exposed=FakeWorklet]
interface FakeWorkletGlobalScope : WorkletGlobalScope {
void registerAnArbitaryClass(DOMString type, Function classConstructor);
};
</pre>
Each {{FakeWorkletGlobalScope}} has a map of the <dfn>registered class constructors map</dfn>.
When the <dfn method for=FakeWorkletGlobalScope>
registerAnArbitaryClass(|type|, |classConstructor|)</dfn> method is called, the user agent will add
the |classConstructor| of |type| to the map of <a>registered class constructors map</a>.
</div>
Loading scripts into a worklet. {#example-single}
-------------------------------------------------
<pre class='lang-javascript'>
window.fakeWorklet1.addModule('script1.js');
window.fakeWorklet1.addModule('script2.js');
// Assuming no other calls to fakeWorklet1 valid script loading orderings are:
// 1. 'script1.js', 'script2.js'
// 2. 'script2.js', 'script1.js'
</pre>
Loading scripts into multiple worklets. {#example-multiple}
-----------------------------------------------------------
<pre class='lang-javascript'>
Promise.all([
window.fakeWorklet1.addModule('script1.js'),
window.fakeWorklet2.addModule('script2.js')
]).then(function() {
// Both scripts now have loaded code, can do a task which relies on this.
});
</pre>
Create a registered class and invoke a method. {#example-class}
---------------------------------------------------------------
<pre class='lang-javascript'>
// Inside FakeWorkletGlobalScope
registerAnArbitaryClass('key', class FooClass {
process(arg) {
return !arg;
}
});
</pre>
As an example, if the user agent wants to invoke "process" on a new class instance, the user agent
could follow the following steps:
1. Let |workletGlobalScope| be a {{FakeWorkletGlobalScope}} from the list of <a>worklet's
WorkletGlobalScopes</a> from the fake {{Worklet}}.
The user agent <em>may</em> also <a>create a WorkletGlobalScope</a> given the fake
{{Worklet}} and use that.
2. Let |classCtor| be the result of performing a lookup in <a>registered class constructors
map</a> with "key" as the key.
3. Let |classInstance| be the result of <a>Construct</a>(|classCtor|).
4. Let |result| be the result of <a>Invoke</a>(O=|classInstance|, P="process",
Arguments=["true"]).
5. Return |result|.