Skip to content

Commit 4d99845

Browse files
committed
Normative: Permit work in parallel during instantiation
On JSC, some compilation work takes place the first time that a Module is instantiated. If the module is instantiated in an asynchronous way, the work happens off the main thread. This patch loosens the specification of WebAssembly module instantiation to permit this specific type of delay. Based on skimming the code (but not running tests), I believe that the new specification matches 3/4 of the implementations I examined. The one which might not fit is V8, which defers reading properties of the import object to a microtask queue item at the beginning of WebAssembly.instantiate(Module), unlike the others, which read it synchronously. The previous specification didn't match any implementations, as it specified to queue an HTML task at the beginning of the WebAssembly.instantiate(Module) method, which no implementation actually did to my knowledge. Punting to a queue there doesn't really serve any purpose and was simply an error in drafting the previous specification. Closes #741 See also webpack/webpack#6433
1 parent 44dfa15 commit 4d99845

File tree

1 file changed

+43
-42
lines changed

1 file changed

+43
-42
lines changed

document/js-api/index.bs

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ A {{Module}} object represents a single WebAssembly module. Each {{Module}} obje
317317
</div>
318318

319319
<div algorithm="instantiate">
320-
To <dfn>instantiate a WebAssembly module</dfn> from a {{Module}} |moduleObject| and imports |importObject|, perform the following steps:
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:
321321
1. Let |module| be |moduleObject|.\[[Module]].
322322
1. If |module|.[=𝗂𝗆𝗉𝗈𝗋𝗍𝗌=] is not an empty list, and |importObject| is undefined, throw a {{TypeError}} exception.
323323
1. Let |imports| be an empty [=list=] of [=external value=]s.
@@ -364,52 +364,54 @@ A {{Module}} object represents a single WebAssembly module. Each {{Module}} obje
364364
2. Let |tableaddr| be |v|.\[[Table]]
365365
1. Let |externtable| be the [=external value=] [=external value|𝗍𝖺𝖻𝗅𝖾=] |tableaddr|.
366366
1. [=Append=] |externtable| to |imports|.
367-
1. Let (|store|, |instance|) be [=instantiate_module=](|store|, |module|, |imports|).
368-
1. If |instance| is [=error=], throw an appropriate exception type:
369-
* A {{LinkError}} exception for most cases which occur during linking.
370-
* 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.
371-
* Another error type if appropriate, for example an out-of-memory exception, as documented in <a href="#errors">the WebAssembly error mapping</a>.
372-
1. Let |exportsObject| be ! [=ObjectCreate=](null).
373-
1. For each pair (|name|, |externtype|) in [=module_exports=](|module|),
374-
1. Let |externval| be [=get_export=](|instance|, |name|).
375-
1. Assert: |externval| is not [=error=].
376-
1. If |externtype| is of the form [=𝖿𝗎𝗇𝖼=] |functype|,
377-
1. Assert: |externval| is of the form [=external value|𝖿𝗎𝗇𝖼=] |funcaddr|.
378-
1. Let [=external value|𝖿𝗎𝗇𝖼=] |funcaddr| be |externval|.
379-
1. Let |func| be the result of creating [=a new Exported Function=] from |funcaddr|.
380-
1. Let |value| be |func|.
381-
1. If |externtype| is of the form [=𝗀𝗅𝗈𝖻𝖺𝗅=] <var ignore>globaltype</var>,
382-
1. Assert: |externval| is of the form [=external value|𝗀𝗅𝗈𝖻𝖺𝗅=] |globaladdr|.
383-
1. Let [=external value|𝗀𝗅𝗈𝖻𝖺𝗅=] |globaladdr| be |externval|.
384-
1. Let |global| be [=create a global object|a new Global object=] created from |globaladdr|.
385-
1. Let |value| be |global|.
386-
1. If |externtype| is of the form [=𝗆𝖾𝗆=] |memtype|,
387-
1. Assert: |externval| is of the form [=external value|𝗆𝖾𝗆=] |memaddr|.
388-
1. Let [=external value|𝗆𝖾𝗆=] |memaddr| be |externval|.
389-
1. Let |memory| be [=create a memory object|a new Memory object=] created from |memaddr|.
390-
1. Let |value| be |memory|.
391-
1. Otherwise, |externtype| is of the form [=𝗍𝖺𝖻𝗅𝖾=] |tabletype|,
392-
1. Assert: |externval| is of the form [=external value|𝗍𝖺𝖻𝗅𝖾=] |tableaddr|.
393-
1. Let [=external value|𝗍𝖺𝖻𝗅𝖾=] |tableaddr| be |externval|.
394-
1. Let |table| be [=create a Table object|a new Table object=] created from |tableaddr|.
395-
1. Let |value| be |table|.
396-
1. Let |status| be ! [=CreateDataProperty=](|exportsObject|, |name|, |value|).
397-
1. Assert: |status| is true.
398-
399-
Note: the validity and uniqueness checks performed during [=WebAssembly module validation=] ensure that each property name is valid and no properties are defined twice.
400-
1. Perform ! [=SetIntegrityLevel=](|exportsObject|, `"frozen"`).
401-
1. Let |instanceObject| be a new {{Instance}} object whose internal \[[Instance]] slot is set to |instance| and the \[[Exports]] slot to |exportsObject|.
402-
1. Return |instanceObject|.
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:
368+
1. Let (|store|, |instance|) be [=instantiate_module=](|store|, |module|, |imports|).
369+
1. If |instance| is [=error=], throw an appropriate exception type:
370+
* A {{LinkError}} exception for most cases which occur during linking.
371+
* 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+
* 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.
401+
1. Perform ! [=SetIntegrityLevel=](|exportsObject|, `"frozen"`).
402+
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|.
403405
</div>
404406

405407
<div algorithm>
406408
To <dfn>instantiate a promise of a module</dfn> |promiseOfModule| with imports |importObject|, perform the following steps:
407409

408410
1. Let |promise| be [=a new promise=]
409411
1. [=Upon fulfillment=] of |promiseOfModule| with value |module|:
410-
1. [=instantiate a WebAssembly module|Instantiate the WebAssembly module=] |module| importing |importObject|, and let |instance| be the result. If this throws an exception, catch it, [=reject=] |promise| with the exception, and abort these substeps.
411-
1. Let |result| be a {{WebAssemblyInstantiatedSource}} dictionary with {{WebAssemblyInstantiatedSource/module}} set to |module| and {{WebAssemblyInstantiatedSource/instance}} set to |instance|.
412-
1. [=Resolve=] |promise| with |result|.
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.
413+
1. Let |result| be a {{WebAssemblyInstantiatedSource}} dictionary with {{WebAssemblyInstantiatedSource/module}} set to |module| and {{WebAssemblyInstantiatedSource/instance}} set to |instance|.
414+
1. [=Resolve=] |promise| with |result|.
413415
1. [=Upon rejection=] of |promiseOfModule| with reason |reason|:
414416
1. [=Reject=] |promise| with |reason|.
415417
1. Return |promise|.
@@ -427,8 +429,7 @@ A {{Module}} object represents a single WebAssembly module. Each {{Module}} obje
427429
<div algorithm>
428430
The <dfn method for="WebAssembly">instantiate(|moduleObject|, |importObject|)</dfn> method, when invoked, performs the following steps:
429431
1. Let |promise| be [=a new promise=].
430-
1. [=Queue a task=] to perform the following steps:
431-
1. [=instantiate a WebAssembly module|Instantiate the WebAssembly module=] |moduleObject| importing |importObject|, and let |instance| be the result. If this throws an exception, catch it, and [=reject=] |promise| with the exception.
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.
432433
1. [=Resolve=] |promise| with |instance|.
433434
1. Return |promise|
434435
</div>

0 commit comments

Comments
 (0)