You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[jsapi] Always queue a task during asynchronous instantiation
JSC will have to do asynchronous compilation work during some instantiations.
To be consistent, this PR always queues a task to complete instantiation,
except through the synchronous Instance(module) API, to ensure consistency
across platforms.
This patch also cleans up the specification in various surrounding ways:
- Factor out the algorithms for reading imports from the import obj, etc.
- Include notes about APIs whose use is discouraged/may be limited
Copy file name to clipboardExpand all lines: document/js-api/index.bs
+79-45Lines changed: 79 additions & 45 deletions
Original file line number
Diff line number
Diff line change
@@ -316,10 +316,8 @@ A {{Module}} object represents a single WebAssembly module. Each {{Module}} obje
316
316
1. [=Asynchronously compile a WebAssembly module=] from |stableBytes| and return the result.
317
317
</div>
318
318
319
-
<div algorithm="instantiate">
320
-
To <dfn>instantiate a WebAssembly module</dfn> from a {{Module}} |moduleObject| and imports |importObject|, and optional algorithm |steps| is given |importObject| as a parameter, perform the following steps:
321
-
1. Let |module| be |moduleObject|.\[[Module]].
322
-
1. If |module|.[=𝗂𝗆𝗉𝗈𝗋𝗍𝗌=] is not an empty list, and |importObject| is undefined, throw a {{TypeError}} exception.
319
+
<div algorithm>
320
+
To <dfn>read the imports</dfn> from a WebAssembly module |module| from imports object |importObject|, perform the following steps:
323
321
1. Let |imports| be an empty [=list=] of [=external value=]s.
324
322
1. For each (|moduleName|, |componentName|, |externtype|) in [=module_imports=](|module|), do
325
323
1. Let |o| be ? [=Get=](|importObject|, |moduleName|).
@@ -364,59 +362,94 @@ A {{Module}} object represents a single WebAssembly module. Each {{Module}} obje
364
362
2. Let |tableaddr| be |v|.\[[Table]]
365
363
1. Let |externtable| be the [=external value=][=external value|𝗍𝖺𝖻𝗅𝖾=] |tableaddr|.
366
364
1. [=Append=] |externtable| to |imports|.
367
-
1. If |steps| is provided, user agents may either perform the following steps, or may perform additional work [=in parallel=] and then [=queue a task=] to perform the following steps. If |steps| is not provided, perform the following steps:
365
+
1. Return |imports|.
366
+
</div>
367
+
368
+
<div algorithm>
369
+
To <dfn>create an instance object</dfn> from a WebAssembly module |module| and instance |instance|, perform the following steps:
370
+
1. If |module|.[=𝗂𝗆𝗉𝗈𝗋𝗍𝗌=] is not an empty list, and |importObject| is undefined, throw a {{TypeError}} exception.
371
+
1. Let |exportsObject| be ! [=ObjectCreate=](null).
372
+
1. For each pair (|name|, |externtype|) in [=module_exports=](|module|),
373
+
1. Let |externval| be [=get_export=](|instance|, |name|).
374
+
1. Assert: |externval| is not [=error=].
375
+
1. If |externtype| is of the form [=𝖿𝗎𝗇𝖼=] |functype|,
376
+
1. Assert: |externval| is of the form [=external value|𝖿𝗎𝗇𝖼=] |funcaddr|.
377
+
1. Let [=external value|𝖿𝗎𝗇𝖼=] |funcaddr| be |externval|.
378
+
1. Let |func| be the result of creating [=a new Exported Function=] from |funcaddr|.
379
+
1. Let |value| be |func|.
380
+
1. If |externtype| is of the form [=𝗀𝗅𝗈𝖻𝖺𝗅=]<var ignore>globaltype</var>,
381
+
1. Assert: |externval| is of the form [=external value|𝗀𝗅𝗈𝖻𝖺𝗅=] |globaladdr|.
382
+
1. Let [=external value|𝗀𝗅𝗈𝖻𝖺𝗅=] |globaladdr| be |externval|.
383
+
1. Let |global| be [=create a global object|a new Global object=] created from |globaladdr|.
384
+
1. Let |value| be |global|.
385
+
1. If |externtype| is of the form [=𝗆𝖾𝗆=] |memtype|,
386
+
1. Assert: |externval| is of the form [=external value|𝗆𝖾𝗆=] |memaddr|.
387
+
1. Let [=external value|𝗆𝖾𝗆=] |memaddr| be |externval|.
388
+
1. Let |memory| be [=create a memory object|a new Memory object=] created from |memaddr|.
389
+
1. Let |value| be |memory|.
390
+
1. Otherwise, |externtype| is of the form [=𝗍𝖺𝖻𝗅𝖾=] |tabletype|,
391
+
1. Assert: |externval| is of the form [=external value|𝗍𝖺𝖻𝗅𝖾=] |tableaddr|.
392
+
1. Let [=external value|𝗍𝖺𝖻𝗅𝖾=] |tableaddr| be |externval|.
393
+
1. Let |table| be [=create a Table object|a new Table object=] created from |tableaddr|.
394
+
1. Let |value| be |table|.
395
+
1. Let |status| be ! [=CreateDataProperty=](|exportsObject|, |name|, |value|).
396
+
1. Assert: |status| is true.
397
+
398
+
Note: the validity and uniqueness checks performed during [=WebAssembly module validation=] ensure that each property name is valid and no properties are defined twice.
1. Return a new {{Instance}} object whose internal \[[Instance]] slot is set to |instance| and the \[[Exports]] slot to |exportsObject|.
401
+
</div>
402
+
403
+
<div algorithm>
404
+
To <dfn>instantate the core of a WebAssembly module</dfn> from a module |module| and imports |imports|, perform the following steps:
405
+
406
+
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
368
407
1. Let (|store|, |instance|) be [=instantiate_module=](|store|, |module|, |imports|).
369
408
1. If |instance| is [=error=], throw an appropriate exception type:
370
409
* A {{LinkError}} exception for most cases which occur during linking.
371
410
* If the error came when running the start function, throw a {{RuntimeError}} for most errors which occur from WebAssembly, or the error object propagated from inner ECMAScript code.
372
411
* Another error type if appropriate, for example an out-of-memory exception, as documented in <a href="#errors">the WebAssembly error mapping</a>.
373
-
1. Let |exportsObject| be ! [=ObjectCreate=](null).
374
-
1. For each pair (|name|, |externtype|) in [=module_exports=](|module|),
375
-
1. Let |externval| be [=get_export=](|instance|, |name|).
376
-
1. Assert: |externval| is not [=error=].
377
-
1. If |externtype| is of the form [=𝖿𝗎𝗇𝖼=] |functype|,
378
-
1. Assert: |externval| is of the form [=external value|𝖿𝗎𝗇𝖼=] |funcaddr|.
379
-
1. Let [=external value|𝖿𝗎𝗇𝖼=] |funcaddr| be |externval|.
380
-
1. Let |func| be the result of creating [=a new Exported Function=] from |funcaddr|.
381
-
1. Let |value| be |func|.
382
-
1. If |externtype| is of the form [=𝗀𝗅𝗈𝖻𝖺𝗅=]<var ignore>globaltype</var>,
383
-
1. Assert: |externval| is of the form [=external value|𝗀𝗅𝗈𝖻𝖺𝗅=] |globaladdr|.
384
-
1. Let [=external value|𝗀𝗅𝗈𝖻𝖺𝗅=] |globaladdr| be |externval|.
385
-
1. Let |global| be [=create a global object|a new Global object=] created from |globaladdr|.
386
-
1. Let |value| be |global|.
387
-
1. If |externtype| is of the form [=𝗆𝖾𝗆=] |memtype|,
388
-
1. Assert: |externval| is of the form [=external value|𝗆𝖾𝗆=] |memaddr|.
389
-
1. Let [=external value|𝗆𝖾𝗆=] |memaddr| be |externval|.
390
-
1. Let |memory| be [=create a memory object|a new Memory object=] created from |memaddr|.
391
-
1. Let |value| be |memory|.
392
-
1. Otherwise, |externtype| is of the form [=𝗍𝖺𝖻𝗅𝖾=] |tabletype|,
393
-
1. Assert: |externval| is of the form [=external value|𝗍𝖺𝖻𝗅𝖾=] |tableaddr|.
394
-
1. Let [=external value|𝗍𝖺𝖻𝗅𝖾=] |tableaddr| be |externval|.
395
-
1. Let |table| be [=create a Table object|a new Table object=] created from |tableaddr|.
396
-
1. Let |value| be |table|.
397
-
1. Let |status| be ! [=CreateDataProperty=](|exportsObject|, |name|, |value|).
398
-
1. Assert: |status| is true.
399
-
400
-
Note: the validity and uniqueness checks performed during [=WebAssembly module validation=] ensure that each property name is valid and no properties are defined twice.
1. Let |instanceObject| be a new {{Instance}} object whose internal \[[Instance]] slot is set to |instance| and the \[[Exports]] slot to |exportsObject|.
403
-
1. If |steps| is provided, perform |steps| given |instanceObject|.
404
-
1. Otherwise, return |instanceObject|.
412
+
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
413
+
1. Return |instance|.
414
+
</div>
415
+
416
+
<div algorithm="instantiate">
417
+
To <dfn>asynchronously instantiate a WebAssembly module</dfn> from a {{Module}} |moduleObject| and imports |importObject|, perform the following steps:
418
+
1. Let |module| be |moduleObject|.\[[Module]].
419
+
1. Let |promise| be [=a new promise=].
420
+
1. [=Read the imports=] of |module| with imports |importObject|, and let |imports| be the result. If this operation throws an exception, catch it, [=reject=]
421
+
1. Run the following steps [=in parallel=]:
422
+
Note: Implementation-specific work may be performed here.
423
+
1. [=Queue a task=] to perform the following steps:
424
+
1. [=Instantiate the core of a WebAssembly module=] |module| with |imports|, and let |instance| be the result. If this operation throws an exception, catch it, [=reject=] |promise| with the exception, and return |promise|.
425
+
1. [=Create an instance object=] from |module| and |instance|, and let the result be |instanceObject|. If this operation throws an exception, catch it, [=reject=] |promise| with the exception, and return |promise|.
426
+
1. [=Resolve=] |promise| with |instance|.
427
+
1. Return |promise|.
428
+
</div>
429
+
430
+
<div algorithm="instantiate">
431
+
To <dfn>synchronously instantiate a WebAssembly module</dfn> from a {{Module}} |moduleObject| and imports |importObject|, perform the following steps:
432
+
1. Let |module| be |moduleObject|.\[[Module]].
433
+
1. [=Read the imports=] of |module| with imports |importObject|, and let |imports| be the result.
434
+
1. [=Instantiate the core of a WebAssembly module=] |module| with |imports|, and let |instance| be the result.
435
+
1. [=Create an instance object=] from |module| and |instance|, and let the result be |instanceObject|.
436
+
1. Return |instanceObject|.
405
437
</div>
406
438
407
439
<div algorithm>
408
440
To <dfn>instantiate a promise of a module</dfn> |promiseOfModule| with imports |importObject|, perform the following steps:
409
441
410
442
1. Let |promise| be [=a new promise=]
411
443
1. [=Upon fulfillment=] of |promiseOfModule| with value |module|:
412
-
1. [=instantiate a WebAssembly module|Instantiate the WebAssembly module=] |module| importing |importObject|, with the following steps given |instance|. If this throws an exception, catch it, [=reject=] |promise| with the exception, and abort these substeps.
444
+
1. [=asynchronously instantiate a WebAssembly module|Instantiate the WebAssembly module=] |module| importing |importObject|, and let |innerPromise| be the result.
445
+
1. [=Upon fulfillment=] of |innerPromise| with value |instance|.
413
446
1. Let |result| be a {{WebAssemblyInstantiatedSource}} dictionary with {{WebAssemblyInstantiatedSource/module}} set to |module| and {{WebAssemblyInstantiatedSource/instance}} set to |instance|.
414
447
1. [=Resolve=] |promise| with |result|.
448
+
1. [=Upon rejection=] of |innerPromise| with reason |reason|:
449
+
1. [=Reject=] |promise| with |reason|.
415
450
1. [=Upon rejection=] of |promiseOfModule| with reason |reason|:
416
451
1. [=Reject=] |promise| with |reason|.
417
452
1. Return |promise|.
418
-
419
-
Note: It would be valid to perform certain parts of the instantiation [=in parallel=], but several parts need to happen in the event loop, including JavaScript operations to access the |importObject| and execution of the start function.
420
453
</div>
421
454
422
455
<div algorithm>
@@ -428,10 +461,7 @@ A {{Module}} object represents a single WebAssembly module. Each {{Module}} obje
428
461
429
462
<div algorithm>
430
463
The <dfn method for="WebAssembly">instantiate(|moduleObject|, |importObject|)</dfn> method, when invoked, performs the following steps:
431
-
1. Let |promise| be [=a new promise=].
432
-
1. [=instantiate a WebAssembly module|Instantiate the WebAssembly module=] |moduleObject| importing |importObject|, with the following steps, given |instance|. If this throws an exception, catch it, and [=reject=] |promise| with the exception.
433
-
1. [=Resolve=] |promise| with |instance|.
434
-
1. Return |promise|
464
+
1. [=asynchronously instantiate a WebAssembly module|Asynchronously instantiate the WebAssembly module=] |moduleObject| importing |importObject|, and return the result.
435
465
</div>
436
466
437
467
Note: A follow-on streaming API is documented in the <a href="https://webassembly.github.io/spec/web-api/index.html">WebAssembly Web API</a>.
@@ -515,6 +545,8 @@ interface Module {
515
545
1. [=Compile a WebAssembly module|Compile the WebAssembly module=] |stableBytes| and store the result as |module|.
516
546
1. If |module| is [=error=], throw a {{CompileError}} exception.
517
547
1. [=Construct a WebAssembly module object=] from |module| and |stableBytes|, and return the result.
548
+
549
+
Note: Some implementations may enforce a size limitation on |bytes|. Use of this API is discouraged, in favor of asynchronous APIs.
518
550
</div>
519
551
520
552
<h3 id="instances">Instances</h3>
@@ -527,7 +559,9 @@ interface Instance {
527
559
</pre>
528
560
529
561
<div algorithm>
530
-
The <dfn constructor for="Instance">Instance(|module|, |importObject|)</dfn> constructor, when invoked, [=instantiate a WebAssembly module|instantiates the WebAssembly module=] |module| importing |importObject| and returns the result.
562
+
The <dfn constructor for="Instance">Instance(|module|, |importObject|)</dfn> constructor, when invoked, [=synchronously instantiate a WebAssembly module|synchronously instantiates the WebAssembly module=] |module| importing |importObject| and returns the result.
563
+
564
+
Note: The use of this synchronous API is discouraged, as some implementations sometimes do long-running compilation work when instantiating.
0 commit comments