blob: 55bfa36c5819ff5d5094904a748f2b2157345ed3 [file] [log] [blame]
<pre class='metadata'>
Title: WebAssembly JavaScript Interface
Shortname: wasm-js-api
Group: wasm
Status: ED
Level: 1
TR: https://www.w3.org/TR/wasm-js-api-1/
ED: https://webassembly.github.io/spec/js-api/
Editor: Daniel Ehrenberg (Igalia)
Repository: WebAssembly/spec
Markup Shorthands: css no, markdown yes
Abstract: This document provides an explicit JavaScript API for interacting with WebAssembly.
Prepare For TR: true
</pre>
<pre class='biblio'>
{
"WEBASSEMBLY": {
"href": "https://webassembly.github.io/spec/core/",
"title": "WebAssembly Core Specification",
"publisher": "W3C WebAssembly Community Group",
"status": "Draft"
}
}
</pre>
<pre class="anchors">
urlPrefix: https://tc39.github.io/ecma262/; spec: ECMASCRIPT
type: interface; for: ECMAScript
text: ArrayBuffer; url: sec-arraybuffer-objects
type: exception; for: ECMAScript
text: Error; url: sec-error-objects
text: NativeError; url: sec-nativeerror-constructors
text: TypeError; url: sec-native-error-types-used-in-this-standard-typeerror
text: RangeError; url: sec-native-error-types-used-in-this-standard-rangeerror
type: dfn
text: agent cluster; url: sec-agent-clusters
text: agent; url: agent
text: data block; url: sec-data-blocks
text: Bound Function; url: sec-bound-function-exotic-objects
text: NumericLiteral; url: sec-literals-numeric-literals
text: surrounding agent; url: surrounding-agent
text: ToNumber; url: sec-tonumber
text: ToInt32; url: sec-toint32
text: ToString; url: sec-tostring
url: sec-ecmascript-data-types-and-values
text: Type
text: Type(x)
url: sec-iscallable
text: IsCallable
text: callable; for: ECMAScript
url: sec-well-known-intrinsic-objects
text: %ErrorPrototype%
text: %ObjectPrototype%; url: sec-properties-of-the-object-prototype-object
text: %FunctionPrototype%; url: sec-properties-of-the-function-prototype-object
text: %Promise%; url: sec-promise-constructor
text: Property Descriptor; url: sec-property-descriptor-specification-type
text: array index; url: sec-array-exotic-objects
text: OrdinaryGetOwnProperty; url: sec-ordinarygetownproperty
text: OrdinaryDefineOwnProperty; url: sec-ordinarydefineownproperty
text: OrdinaryPreventExtensions; url: sec-ordinarypreventextensions
text: OrdinarySet; url: sec-ordinaryset
text: equally close values; url: sec-ecmascript-language-types-number-type
text: internal slot; url: sec-object-internal-methods-and-internal-slots
text: JavaScript execution context stack; url: execution-context-stack
text: running JavaScript execution context; url: running-execution-context
text: GetIterator; url: sec-getiterator
text: IteratorStep; url: sec-iteratorstep
text: NormalCompletion; url: sec-normalcompletion
text: IteratorValue; url: sec-iteratorvalue
url: sec-well-known-symbols
text: @@iterator
text: @@toStringTag
text: CreateDataProperty; url: sec-createdataproperty
text: DetachArrayBuffer; url: sec-detacharraybuffer
text: SetIntegrityLevel; url: sec-setintegritylevel
text: Call; url: sec-call
text: Get; url: sec-get-o-p
text: DefinePropertyOrThrow; url: sec-definepropertyorthrow
text: current Realm; url: current-realm
text: ObjectCreate; url: sec-objectcreate
text: CreateBuiltinFunction; url: sec-createbuiltinfunction
text: SetFunctionName; url: sec-setfunctionname
text: SetFunctionLength; url: sec-setfunctionlength
text: the Number value; url: sec-ecmascript-language-types-number-type
text: NumberToRawBytes; url: sec-numbertorawbytes
text: Built-in Function Objects; url: sec-built-in-function-objects
urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: dfn
url: valid/modules.html#valid-module
text: valid
text: WebAssembly module validation
text: module grammar; url: binary/modules.html#binary-module
text: custom section; url: binary/modules.html#custom-section
text: customsec; url: binary/modules.html#binary-customsec
text: memory instance; url: exec/runtime.html#memory-instances
text: table instance; url: exec/runtime.html#table-instances
text: global instance; url: exec/runtime.html#global-instances
text: trap; url: exec/runtime.html#syntax-trap
url: exec/runtime.html#values
text: WebAssembly value
text: π—‚πŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—
text: 𝗂πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—
text: 𝖿πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—
text: π–ΏπŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—
text: function index; url: syntax/modules.html#syntax-funcidx
text: function instance; url: exec/runtime.html#function-instances
text: store_init; url: appendix/embedding.html#embed-store-init
text: module_decode; url: appendix/embedding.html#embed-module-decode
text: module_validate; url: appendix/embedding.html#embed-module-validate
text: module_instantiate; url: appendix/embedding.html#embed-module-instantiate
text: module_imports; url: appendix/embedding.html#embed-module-imports
text: module_exports; url: appendix/embedding.html#embed-module-exports
text: instance_export; url: appendix/embedding.html#embed-instance-export
text: func_alloc; url: appendix/embedding.html#embed-func-alloc
text: func_type; url: appendix/embedding.html#embed-func-type
text: func_invoke; url: appendix/embedding.html#embed-func-invoke
text: table_alloc; url: appendix/embedding.html#embed-table-alloc
text: table_type; url: appendix/embedding.html#embed-table-type
text: table_read; url: appendix/embedding.html#embed-table-read
text: table_write; url: appendix/embedding.html#embed-table-write
text: table_size; url: appendix/embedding.html#embed-table-size
text: table_grow; url: appendix/embedding.html#embed-table-grow
text: mem_alloc; url: appendix/embedding.html#embed-mem-alloc
text: mem_type; url: appendix/embedding.html#embed-mem-type
text: mem_read; url: appendix/embedding.html#embed-mem-read
text: mem_write; url: appendix/embedding.html#embed-mem-write
text: mem_size; url: appendix/embedding.html#embed-mem-size
text: mem_grow; url: appendix/embedding.html#embed-mem-grow
text: global_alloc; url: appendix/embedding.html#embed-global-alloc
text: global_type; url: appendix/embedding.html#embed-global-type
text: global_read; url: appendix/embedding.html#embed-global-read
text: global_write; url: appendix/embedding.html#embed-global-write
text: error; url: appendix/embedding.html#embed-error
text: store; url: exec/runtime.html#syntax-store
text: table type; url: syntax/types.html#syntax-tabletype
text: table address; url: exec/runtime.html#syntax-tableaddr
text: function address; url: exec/runtime.html#syntax-funcaddr
text: memory address; url: exec/runtime.html#syntax-memaddr
text: global address; url: exec/runtime.html#syntax-globaladdr
url: syntax/types.html#syntax-valtype
text: 𝗂πŸ₯𝟀
text: π—‚πŸ¨πŸ¦
text: 𝖿πŸ₯𝟀
text: π–ΏπŸ¨πŸ¦
text: function element; url: exec/runtime.html#syntax-funcelem
text: import component; url: syntax/modules.html#imports
text: external value; url: exec/runtime.html#syntax-externval
text: host function; url: exec/runtime.html#syntax-hostfunc
text: the instantiation algorithm; url: exec/modules.html#instantiation
text: module; url: syntax/modules.html#syntax-module
text: π—‚π—†π—‰π—ˆπ—‹π—π—Œ; url: syntax/modules.html#syntax-module
url: syntax/types.html#external-types
text: external type
text: π–Ώπ—Žπ—‡π–Ό
text: 𝗍𝖺𝖻𝗅𝖾
text: 𝗆𝖾𝗆
text: π—€π—…π—ˆπ–»π–Ίπ—…
text: global type; url: syntax/types.html#syntax-globaltype
url: syntax/types.html#syntax-mut
text: var
text: const
text: address; url: exec/runtime.html#addresses
text: signed_32; url: exec/numerics.html#aux-signed
text: memory.grow; url: exec/instructions.html#exec-memory-grow
text: current frame; url: exec/conventions.html#exec-notation-textual
text: π—†π—ˆπ–½π—Žπ—…π–Ύ; url: exec/runtime.html#syntax-frame
text: π—†π–Ύπ—†π–Ίπ–½π–½π—‹π—Œ; url: exec/runtime.html#syntax-moduleinst
text: sequence; url: syntax/conventions.html#grammar-notation
</pre>
<pre class='link-defaults'>
spec:infra; type:dfn; text:list
spec:ecma-262; type:exception; for:ECMAScript; text:Error
spec:infra; type:dfn; for:set; text:append
spec:ecmascript; type:exception; for:ECMAScript; text:TypeError
spec:ecmascript; type:exception; for:ECMAScript; text:RangeError
spec:ecmascript; type:interface; for:ECMAScript; text:ArrayBuffer
spec:promises-guide-1; type:dfn; text:resolve
</pre>
This API privides a way to access WebAssembly [[WEBASSEMBLY]] through a bridge to explicitly construct modules from JavaScript [[ECMASCRIPT]].
<h2 id="sample">Sample API Usage</h2>
<p><em>This section is non-normative.</em></p>
Given `demo.wat` (encoded to `demo.wasm`):
```lisp
(module
(import "js" "import1" (func $i1))
(import "js" "import2" (func $i2))
(func $main (call $i1))
(start $main)
(func (export "f") (call $i2))
)
```
and the following JavaScript, run in a browser:
```javascript
var importObj = {js: {
import1: () => console.log("hello,"),
import2: () => console.log("world!")
}};
fetch('demo.wasm').then(response =>
response.arrayBuffer()
).then(buffer =>
WebAssembly.instantiate(buffer, importObj)
).then(({module, instance}) =>
instance.exports.f()
);
```
<h2 id="webassembly-storage">Internal storage</h2>
<h3 id="store">Interaction of the WebAssembly Store with JavaScript</h3>
Note: WebAssembly semantics are defined in terms of an abstract [=store=], representing the state of the WebAssembly abstract machine. WebAssembly operations take a store and return an updated store.
Each [=agent=] has an <dfn>associated store</dfn>. When a new agent is created, its associated store is set to the result of [=init_store=]().
Note: In this specification, no WebAssembly-related objects, memory or addresses can be shared among agents in an [=agent cluster=]. In a future version of WebAssembly, this may change.
Elements of the WebAssembly store may be <dfn>identified with</dfn> JavaScript values. In particular, each WebAssembly [=memory instance=] with a corresponding {{Memory}} object is identified with a JavaScript [=Data Block=]; modifications to this Data Block are identified to updating the agent's store to a store which reflects those changes, and vice versa.
<h3 id="object-caches">WebAssembly JS Object Caches</h3>
Note: There are several WebAssembly objects that may have a corresponding JavaScript object. The correspondence is stored in a per-agent mapping from WebAssembly [=address=]es to JavaScript objects. This mapping is used to ensure that, for a given [=agent=], there exists at most one JavaScript object for a particular WebAssembly address.
Each [=agent=] is associated with the following [=ordered map=]s:
* The <dfn>Memory object cache</dfn>, mapping [=memory address=]es to {{Memory}} objects.
* The <dfn>Table object cache</dfn>, mapping [=table address=]es to {{Table}} objects.
* The <dfn>Exported Function cache</dfn>, mapping [=function address=]es to [=Exported Function=] objects.
* The <dfn>Global object cache</dfn>, mapping [=global address=]es to {{Global}} objects.
<h2 id="webassembly-namespace">The WebAssembly Namespace</h2>
<pre class="idl">
dictionary WebAssemblyInstantiatedSource {
required Module module;
required Instance instance;
};
[Exposed=(Window,Worker,Worklet)]
namespace WebAssembly {
boolean validate(BufferSource bytes);
Promise&lt;Module> compile(BufferSource bytes);
Promise&lt;WebAssemblyInstantiatedSource> instantiate(
BufferSource bytes, optional object importObject);
Promise&lt;Instance> instantiate(
Module moduleObject, optional object importObject);
};
</pre>
<!--
Should we include notes describing what the functions do, as the HTML spec does? It could look like this:
Note:
WebAssembly.validate(|bytes|) synchronously validates bytes of WebAssembly, returning true if the validation was successful.
WebAssembly.compile(|bytes|) asynchronously validates and complies bytes of WebAssembly into a Module.
WebAssembly.instantiate(|bytes|, |importObject|) asynchronously compiles and instantiates a WebAssembly module from bytes of source.
The WebAssembly.instantiate(|moduleObject|, |importObject|) asynchronously instantiates a compiled module.
-->
<div algorithm>
To <dfn>compile a WebAssembly module</dfn> from source bytes |bytes|, perform the following steps:
1. Let |module| be [=module_decode=](|bytes|). If |module| is [=error=], return [=error=].
1. If [=module_validate=](|module|) is [=error=], return [=error=].
1. Return |module|.
</div>
<div algorithm>
The <dfn method for="WebAssembly">validate(|bytes|)</dfn> method, when invoked, performs the following steps:
1. Let |stableBytes| be a [=get a copy of the buffer source|copy of the bytes held by the buffer=] |bytes|.
1. [=Compile a WebAssembly module|Compile=] |stableBytes| as a WebAssembly module and store the results as |module|.
1. If |module| is [=error=], return false.
1. Return true.
</div>
<div>
A {{Module}} object represents a single WebAssembly module. Each {{Module}} object has the following internal slots:
* \[[Module]] : a WebAssembly [=module=]
* \[[Bytes]] : the source bytes of \[[Module]].
</div>
<div algorithm>
To <dfn>construct a WebAssembly module object</dfn> from a module |module| and source bytes |bytes|, perform the following steps:
1. Let |moduleObject| be a new {{Module}} object.
1. Set |moduleObject|.\[[Module]] to |module|.
1. Set |moduleObject|.\[[Bytes]] to |bytes|.
1. Return |moduleObject|.
</div>
<div algorithm>
To <dfn>asynchronously compile a WebAssembly module</dfn> from source bytes |bytes|, using optional [=task source=] |taskSource|, perform the following steps:
1. Let |promise| be [=a new promise=].
1. Run the following steps [=in parallel=]:
1. [=compile a WebAssembly module|Compile the WebAssembly module=] |bytes| and store the result as |module|.
1. [=Queue a task=] to perform the following steps. If |taskSource| was provided, queue the task on that task source.
1. If |module| is [=error=], reject |promise| with a {{CompileError}} exception.
1. Otherwise,
1. [=Construct a WebAssembly module object=] from |module| and |bytes|, and let |moduleObject| be the result.
1. [=Resolve=] |promise| with |moduleObject|.
1. Return |promise|.
</div>
<div algorithm>
The <dfn method for="WebAssembly">compile(|bytes|)</dfn> method, when invoked, performs the following steps:
1. Let |stableBytes| be a [=get a copy of the buffer source|copy of the bytes held by the buffer=] |bytes|.
1. [=Asynchronously compile a WebAssembly module=] from |stableBytes| and return the result.
</div>
<div algorithm="read-the-imports">
To <dfn>read the imports</dfn> from a WebAssembly module |module| from imports object |importObject|, perform the following steps:
1. If |module|.[=π—‚π—†π—‰π—ˆπ—‹π—π—Œ=] is not an empty list, and |importObject| is undefined, throw a {{TypeError}} exception.
1. Let |imports| be an empty [=list=] of [=external value=]s.
1. For each (|moduleName|, |componentName|, |externtype|) in [=module_imports=](|module|), do
1. Let |o| be ? [=Get=](|importObject|, |moduleName|).
1. If [=Type=](|o|) is not [=Object=], throw a {{TypeError}} exception.
1. Let |v| be ? [=Get=](|o|, |componentName|)
1. If |externtype| is of the form [=π–Ώπ—Žπ—‡π–Ό=] |functype|,
1. If [=IsCallable=](|v|) is false, throw a {{LinkError}} exception.
1. If |v| has a \[[FunctionAddress]] internal slot, and therefore is an [=Exported Function=],
1. Let |funcaddr| be the value of |v|'s \[[FunctionAddress]] internal slot.
Note: The signature is checked by [=module_instantiate=] invoked below.
1. Otherwise,
1. [=Create a host function=] from |v| and |functype|, and let |funcaddr| be the result.
1. Let |index| be the number of external functions in |imports|. This value |index| is known as the <dfn>index of the host function</dfn> |funcaddr|.
1. Let |externfunc| be the [=external value=] [=external value|π–Ώπ—Žπ—‡π–Ό=] |funcaddr|.
1. [=Append=] |externfunc| to |imports|.
1. If |externtype| is of the form [=π—€π—…π—ˆπ–»π–Ίπ—…=] <var ignore>mut</var> |valtype|,
1. If [=Type=](|v|) is [=Number=],
1. If |valtype| is [=π—‚πŸ¨πŸ¦=], throw a {{LinkError}} exception.
1. Let |value| be [=ToWebAssemblyValue=](|v|, |valtype|)
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let (|store|, |globaladdr|) be [=global_alloc=](|store|, [=const=] |valtype|, |value|).
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
1. If |v| is a {{Global}} instance,
1. Let |globaladdr| be |v|.\[[Global]]
1. Otherwise,
1. Throw a {{LinkError}} exception.
1. Let |externglobal| be [=external value|π—€π—…π—ˆπ–»π–Ίπ—…=] |globaladdr|.
1. [=Append=] |externglobal| to |imports|.
1. If |externtype| is of the form [=𝗆𝖾𝗆=] <var ignore>memtype</var>,
1. If |v| is not a {{Memory}} object, throw a {{LinkError}} exception.
1. Note: [=module_instantiate=] invoked below will check the imported {{Memory}}'s size against the importing module's requirements.
1. Let |externmem| be the [=external value=] [=external value|𝗆𝖾𝗆=] |v|.\[[Memory]].
1. [=Append=] |externmem| to |imports|.
1. Otherwise, |externtype| is of the form [=𝗍𝖺𝖻𝗅𝖾=] <var ignore>tabletype</var>,
1. If |v| is not a {{Table}} instance, throw a {{LinkError}} exception.
1. Note: The table's length, etc. is checked by [=module_instantiate=] invoked below.
1. Let |tableaddr| be |v|.\[[Table]]
1. Let |externtable| be the [=external value=] [=external value|𝗍𝖺𝖻𝗅𝖾=] |tableaddr|.
1. [=Append=] |externtable| to |imports|.
1. Return |imports|.
</div>
<div algorithm>
To <dfn>create an instance object</dfn> from a WebAssembly module |module| and instance |instance|, perform the following steps:
1. Let |exportsObject| be ! [=ObjectCreate=](null).
1. For each pair (|name|, |externtype|) in [=module_exports=](|module|),
1. Let |externval| be [=instance_export=](|instance|, |name|).
1. Assert: |externval| is not [=error=].
1. If |externtype| is of the form [=π–Ώπ—Žπ—‡π–Ό=] <var ignore>functype</var>,
1. Assert: |externval| is of the form [=external value|π–Ώπ—Žπ—‡π–Ό=] |funcaddr|.
1. Let [=external value|π–Ώπ—Žπ—‡π–Ό=] |funcaddr| be |externval|.
1. Let |func| be the result of creating [=a new Exported Function=] from |funcaddr|.
1. Let |value| be |func|.
1. If |externtype| is of the form [=π—€π—…π—ˆπ–»π–Ίπ—…=] <var ignore>globaltype</var>,
1. Assert: |externval| is of the form [=external value|π—€π—…π—ˆπ–»π–Ίπ—…=] |globaladdr|.
1. Let [=external value|π—€π—…π—ˆπ–»π–Ίπ—…=] |globaladdr| be |externval|.
1. Let |global| be [=create a global object|a new Global object=] created from |globaladdr|.
1. Let |value| be |global|.
1. If |externtype| is of the form [=𝗆𝖾𝗆=] <var ignore>memtype</var>,
1. Assert: |externval| is of the form [=external value|𝗆𝖾𝗆=] |memaddr|.
1. Let [=external value|𝗆𝖾𝗆=] |memaddr| be |externval|.
1. Let |memory| be [=create a memory object|a new Memory object=] created from |memaddr|.
1. Let |value| be |memory|.
1. Otherwise, |externtype| is of the form [=𝗍𝖺𝖻𝗅𝖾=] <var ignore>tabletype</var>,
1. Assert: |externval| is of the form [=external value|𝗍𝖺𝖻𝗅𝖾=] |tableaddr|.
1. Let [=external value|𝗍𝖺𝖻𝗅𝖾=] |tableaddr| be |externval|.
1. Let |table| be [=create a Table object|a new Table object=] created from |tableaddr|.
1. Let |value| be |table|.
1. Let |status| be ! [=CreateDataProperty=](|exportsObject|, |name|, |value|).
1. Assert: |status| is true.
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. Perform ! [=SetIntegrityLevel=](|exportsObject|, `"frozen"`).
1. Return a new {{Instance}} object whose internal \[[Instance]] slot is set to |instance| and the \[[Exports]] slot to |exportsObject|.
</div>
<div algorithm>
To <dfn>instantiate the core of a WebAssembly module</dfn> from a module |module| and imports |imports|, perform the following steps:
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let |result| be [=module_instantiate=](|store|, |module|, |imports|).
1. If |result| is [=error=], throw an appropriate exception type:
* A {{LinkError}} exception for most cases which occur during linking.
* 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.
* Another error type if appropriate, for example an out-of-memory exception, as documented in <a href="#errors">the WebAssembly error mapping</a>.
1. Let (|store|, |instance|) be |result|.
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
1. Return |instance|.
</div>
<div algorithm>
To <dfn>asynchronously instantiate a WebAssembly module</dfn> from a {{Module}} |moduleObject| and imports |importObject|, perform the following steps:
1. Let |promise| be [=a new promise=].
1. Let |module| be |moduleObject|.\[[Module]].
1. [=Read the imports=] of |module| with imports |importObject|, and let |imports| be the result.
If this operation throws an exception, catch it, [=reject=] |promise| with the exception, and return |promise|.
1. [=Queue a task=] to perform the following steps:
1. [=Instantiate the core of a WebAssembly module=] |module| with |imports|, and let |instance| be the result.
If this throws an exception, catch it, [=reject=] |promise| with the exception, and terminate these substeps.
1. [=Create an instance object=] from |module| and |instance|, and let the result be |instanceObject|.
If this throws an exception, catch it, [=reject=] |promise| with the exception, and terminate these substeps.
1. [=Resolve=] |promise| with |instanceObject|.
1. Return |promise|.
</div>
<div algorithm="instantiate">
To <dfn>instantiate a WebAssembly module</dfn> from a {{Module}} |moduleObject| and imports |importObject|, perform the following steps:
1. Let |module| be |moduleObject|.\[[Module]].
1. [=Read the imports=] of |module| with imports |importObject|, and let |imports| be the result.
1. [=Instantiate the core of a WebAssembly module=] |module| with |imports|, and let |instance| be the result.
1. [=Create an instance object=] from |module| and |instance|, and let the result be |instanceObject|.
1. Return |instanceObject|.
</div>
<div algorithm>
To <dfn>instantiate a promise of a module</dfn> |promiseOfModule| with imports |importObject|, perform the following steps:
1. Let |promise| be [=a new promise=]
1. [=Upon fulfillment=] of |promiseOfModule| with value |module|:
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.
1. Let |result| be a {{WebAssemblyInstantiatedSource}} dictionary with {{WebAssemblyInstantiatedSource/module}} set to |module| and {{WebAssemblyInstantiatedSource/instance}} set to |instance|.
1. [=Resolve=] |promise| with |result|.
1. [=Upon rejection=] of |promiseOfModule| with reason |reason|:
1. [=Reject=] |promise| with |reason|.
1. Return |promise|.
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.
</div>
<div algorithm>
The <dfn method for="WebAssembly">instantiate(|bytes|, |importObject|)</dfn> method, when invoked, performs the following steps:
1. Let |stableBytes| be a [=get a copy of the buffer source|copy of the bytes held by the buffer=] |bytes|.
1. [=Asynchronously compile a WebAssembly module=] from |stableBytes| and let |promiseOfModule| be the result.
1. [=Instantiate a promise of a module|Instantiate=] |promiseOfModule| with imports |importObject| and return the result.
</div>
<div algorithm>
The <dfn method for="WebAssembly">instantiate(|moduleObject|, |importObject|)</dfn> method, when invoked, performs the following steps:
1. [=asynchronously instantiate a WebAssembly module|Asynchronously instantiate the WebAssembly module=] |moduleObject| importing |importObject|, and return the result.
</div>
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>.
<h3 id="modules">Modules</h3>
<pre class="idl">
enum ImportExportKind {
"function",
"table",
"memory",
"global"
};
dictionary ModuleExportDescriptor {
required USVString name;
required ImportExportKind kind;
// Note: Other fields such as signature may be added in the future.
};
dictionary ModuleImportDescriptor {
required USVString module;
required USVString name;
required ImportExportKind kind;
};
[LegacyNamespace=WebAssembly, Constructor(BufferSource bytes), Exposed=(Window,Worker,Worklet)]
interface Module {
static sequence&lt;ModuleExportDescriptor> exports(Module moduleObject);
static sequence&lt;ModuleImportDescriptor> imports(Module moduleObject);
static sequence&lt;ArrayBuffer> customSections(Module moduleObject, DOMString sectionName);
};
</pre>
<div algorithm>
The <dfn>string value of the extern type</dfn> |type| is
* "function" if |type| is of the form [=π–Ώπ—Žπ—‡π–Ό=] functype
* "table" if |type| is of the form [=𝗍𝖺𝖻𝗅𝖾=] tabletype
* "memory" if |type| is of the form [=𝗆𝖾𝗆=] memtype
* "global" if |type| is of the form [=π—€π—…π—ˆπ–»π–Ίπ—…=] globaltype
</div>
<div algorithm>
The <dfn method for="Module">exports(|moduleObject|)</dfn> method, when invoked, performs the following steps:
1. Let |module| be |moduleObject|.\[[Module]].
1. Let |exports| be an empty [=list=].
1. For each (|name|, |type|) in [=module_exports=](|module|)
1. Let |kind| be the [=string value of the extern type=] |type|.
1. Let |obj| be a new {{ModuleExportDescriptor}} dictionary with {{ModuleExportDescriptor/name}} |name| and {{ModuleExportDescriptor/kind}} |kind|.
1. [=Append=] |obj| to the end of |exports|.
1. Return |exports|.
</div>
<div algorithm>
The <dfn method for="Module">imports(|moduleObject|)</dfn> method, when invoked, performs the following steps:
1. Let |module| be |moduleObject|.\[[Module]].
1. Let |imports| be an empty [=list=].
1. For each (|moduleName|, |name|, |type|) in [=module_imports=](|module|),
1. Let |kind| be the [=string value of the extern type=] |type|.
1. Let |obj| be a new {{ModuleImportDescriptor}} dictionary with {{ModuleImportDescriptor/module}} |moduleName|, {{ModuleImportDescriptor/name}} |name| and {{ModuleImportDescriptor/kind}} |kind|.
1. [=Append=] |obj| to the end of |imports|.
1. Return |imports|.
</div>
<div algorithm>
The <dfn method for="Module">customSections(|moduleObject|, |sectionName|)</dfn> method, when invoked, performs the following steps:
1. Let |bytes| be |moduleObject|.\[[Bytes]].
1. Let |customSections| be an empty [=list=] of {{ArrayBuffer}}s.
1. For each [=custom section=] |customSection| in |bytes|, interpreted according to the [=module grammar=],
1. Let |name| be the <code>name</code> of |customSection|, [=UTF-8 decode without BOM or fail|decoded as UTF-8=].
1. Assert: |name| is not failure (|moduleObject|.\[[Module]] is [=valid=]).
1. If |name| equals |sectionName| as string values,
1. [=Append=] a new {{ArrayBuffer}} containing a copy of the bytes in |bytes| for the range matched by this [=customsec=] production.
1. Return |customSections|.
</div>
<div algorithm>
The <dfn constructor for="Module">Module(|bytes|)</dfn> constructor, when invoked, performs the follwing steps:
1. Let |stableBytes| be a [=get a copy of the buffer source|copy of the bytes held by the buffer=] |bytes|.
1. [=Compile a WebAssembly module|Compile the WebAssembly module=] |stableBytes| and store the result as |module|.
1. If |module| is [=error=], throw a {{CompileError}} exception.
1. [=Construct a WebAssembly module object=] from |module| and |stableBytes|, and return the result.
</div>
<h3 id="instances">Instances</h3>
<pre class="idl">
[LegacyNamespace=WebAssembly, Constructor(Module module, optional object importObject), Exposed=(Window,Worker,Worklet)]
interface Instance {
readonly attribute object exports;
};
</pre>
<div algorithm>
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.
</div>
<div algorithm>
The getter of the <dfn attribute for="Instance">exports</dfn> attribute of {{Instance}} returns the receiver's \[[Exports]] internal slot.
</div>
<h3 id="memories">Memories</h3>
<pre class="idl">
dictionary MemoryDescriptor {
required [EnforceRange] unsigned long initial;
[EnforceRange] unsigned long maximum;
};
[LegacyNamespace=WebAssembly, Constructor(MemoryDescriptor descriptor), Exposed=(Window,Worker,Worklet)]
interface Memory {
unsigned long grow([EnforceRange] unsigned long delta);
readonly attribute ArrayBuffer buffer;
};
</pre>
<div>
A {{Memory}} object represents a single [=memory instance=]
which can be simultaneously referenced by multiple {{Instance}} objects. Each
{{Memory}} object has the following internal slots:
* \[[Memory]] : a [=memory address=]
* \[[BufferObject]] : an {{ArrayBuffer}} whose [=Data Block=] is [=identified with=] the above memory address
</div>
<div algorithm>
To <dfn>create a memory buffer</dfn> from a [=memory address=] |memaddr|, perform the following steps:
1. Let |block| be a [=Data Block=] which is [=identified with=] the underlying memory of |memaddr|.
1. Let |buffer| be a new {{ArrayBuffer}} whose \[[ArrayBufferData]] is |block| and \[[ArrayBufferByteLength]] is set to the length of |block|.
1. Set |buffer|.\[[ArrayBufferDetachKey]] to "WebAssembly.Memory".
1. Return |buffer|.
</div>
<div algorithm>
To <dfn>create a memory object</dfn> from a [=memory address=] |memaddr|, perform the following steps:
1. Let |map| be the [=surrounding agent=]'s associated [=Memory object cache=].
1. If |map|[|memaddr|] [=map/exists=],
1. Return |map|[|memaddr|].
1. Let |buffer| be a the result of [=create a memory buffer|creating a memory buffer=] from |memaddr|.
1. Let |memory| be a new {{Memory}} instance with \[[Memory]] set to |memaddr| and \[[BufferObject]] set to |buffer|.
1. [=map/Set=] |map|[|memaddr|] to |memory|.
1. Return |memory|.
</div>
<div algorithm>
The <dfn constructor for="Memory">Memory(|descriptor|)</dfn> constructor, when invoked, performs the following steps:
1. let |initial| be |descriptor|["initial"].
1. If |descriptor|["maximum"] is [=present=], let |maximum| be |descriptor|["maximum"]; otherwise, let |maximum| be empty.
1. If |maximum| is not empty and |maximum| &lt; |initial|, throw a {{RangeError}} exception.
1. Let |memtype| be { min |initial|, max |maximum| }
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let (|store|, |memaddr|) be [=mem_alloc=](|store|, |memtype|). If allocation fails, throw a {{RangeError}} exception.
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
1. [=Create a memory object=] from the memory address |memaddr| and return the result.
</div>
<div algorithm>
To <dfn>reset the Memory buffer</dfn> of |memaddr|, perform the following steps:
1. Let |map| be the [=surrounding agent=]'s associated [=Memory object cache=].
1. Assert: |map|[|memaddr|] [=map/exists=]
1. Let |memory| be |map|[|memaddr|].
1. Perform ! [=DetachArrayBuffer=](|memory|.\[[BufferObject]], "WebAssembly.Memory").
1. Let |buffer| be a the result of [=create a memory buffer|creating a memory buffer=] from |memaddr|.
1. Set |memory|.\[[BufferObject]] to |buffer|.
</div>
<div algorithm=dom-Memory-grow>
The <dfn method for="Memory">grow(|delta|)</dfn> method, when invoked, performs the following steps:
1. Let |memory| be the Memory instance.
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let |memaddr| be |memory|.\[[Memory]].
1. Let |ret| be the [=mem_size=](|store|, |memaddr|).
1. Let |store| be [=mem_grow=](|store|, |memaddr|, |delta|).
1. If |store| is [=error=], throw a {{RangeError}} exception.
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
1. [=Reset the memory buffer=] of |memaddr|.
1. Return |ret|.
</div>
Immediately after a WebAssembly [=memory.grow=] instruction executes, perform the following steps:
<div algorithm="memory.grow">
1. If the top of the stack is not [=𝗂πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—=] (βˆ’1), then:
1. Let |frame| be the [=current frame=].
1. Assert: due to validation, |frame|.[=π—†π—ˆπ–½π—Žπ—…π–Ύ=].[=π—†π–Ύπ—†π–Ίπ–½π–½π—‹π—Œ=][0] exists.
1. Let |memaddr| be the memory address |frame|.[=π—†π—ˆπ–½π—Žπ—…π–Ύ=].[=π—†π–Ύπ—†π–Ίπ–½π–½π—‹π—Œ=][0].
1. [=Reset the memory buffer=] of |memaddr|.
</div>
<div algorithm>
The getter of the <dfn attribute for="Memory">buffer</dfn> attribute of {{Memory}} returns the receiver's \[[BufferObject]] internal slot.
</div>
<h3 id="tables">Tables</h3>
<pre class="idl">
enum TableKind {
"anyfunc",
// Note: More values may be added in future iterations,
// e.g., typed function references, typed GC references
};
dictionary TableDescriptor {
required TableKind element;
required [EnforceRange] unsigned long initial;
[EnforceRange] unsigned long maximum;
};
[LegacyNamespace=WebAssembly, Constructor(TableDescriptor descriptor), Exposed=(Window,Worker,Worklet)]
interface Table {
unsigned long grow([EnforceRange] unsigned long delta);
Function? get([EnforceRange] unsigned long index);
void set([EnforceRange] unsigned long index, Function? value);
readonly attribute unsigned long length;
};
</pre>
<div>
A {{Table}} object represents a single [=table instance=]
which can be simultaneously referenced by multiple {{Instance}} objects. Each
{{Table}} object has the following internal slots:
* \[[Table]] : a [=table address=]
* \[[Values]] : a List whose elements are either null or [=Exported Function=]s.
</div>
<div algorithm>
To <dfn>create a table object</dfn> from a [=table address=] |tableaddr|, perform the following steps:
1. Let |map| be the [=surrounding agent=]'s associated [=Table object cache=].
1. If |map|[|tableaddr|] [=map/exists=],
1. Return |map|[|tableaddr|].
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let |values| be a list whose length is [=table_size=](|store|, |tableaddr|) where each element is null.
1. Let |table| be a new {{Table}} instance with \[[Table]] set to |tableaddr| and \[[Values]] set to |values|.
1. [=map/Set=] |map|[|tableaddr|] to |table|.
1. Return |table|.
</div>
<div algorithm>
The <dfn constructor for="Table">Table(|descriptor|)</dfn> constructor, when invoked, performs the following steps:
1. let |initial| be |descriptor|["initial"].
1. If |descriptor|["maximum"] is [=present=], let |maximum| be |descriptor|["maximum"]; otherwise, let |maximum| be empty.
1. If |maximum| is not empty and |maximum| &lt; |initial|, throw a {{RangeError}} exception.
1. Let |type| be the [=table type=] {[=table type|𝗆𝗂𝗇=] n, [=table type|𝗆𝖺𝗑=] |maximum|} [=table type|π–Ίπ—‡π—’π–Ώπ—Žπ—‡π–Ό=].
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let (|store|, |tableaddr|) be [=table_alloc=](|store|, |type|). <!-- TODO(littledan): Report allocation failure https://github.com/WebAssembly/spec/issues/584 -->
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
1. [=Create a table object=] from the table address |tableaddr| and return the result.
</div>
<div algorithm=dom-Table-grow>
The <dfn method for="Table">grow(|delta|)</dfn> method, when invoked, performs the following steps:
1. Let |tableaddr| be the Table instance's \[[Table]] internal slot.
1. Let |initialSize| be the length of the Table instance's \[[Values]] internal slot.
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let |result| be [=table_grow=](|store|, |tableaddr|, |delta|).
1. If |result| is [=error=], throw a {{RangeError}} exception.
Note: The above exception may happen due to either insufficient memory or an invalid size parameter.
1. Set the [=surrounding agent=]'s [=associated store=] to |result|.
1. [=Append=] null to the Table instance's \[[Values]] internal slot |delta| times.
1. Return |initialSize|.
</div>
<div algorithm>
The getter of the <dfn attribute for="Table">length</dfn> attribute of {{Table}} returns the length of the table's \[[Values]] internal slot.
</div>
<div algorithm>
The <dfn method for="Table">get(|index|)</dfn> method, when invoked, performs the following steps:
1. Let |values| be the Table instance's \[[Values]] internal slot.
1. Let |size| be the length of |values|.
1. If |index| &ge; |size|, throw a {{RangeError}} exception.
1. Return |values|[|index|].
</div>
<div algorithm>
The <dfn method for="Table">set(|index|, |value|)</dfn> method, when invoked, performs the following steps:
1. Let |tableaddr| be the Table instance's \[[Table]] internal slot.
1. Let |values| be the Table instance's \[[Values]] internal slot.
1. If |value| is null, let |funcaddr| be an empty [=function element=].
1. Otherwise,
1. If |value| does not have a \[[FunctionAddress]] internal slot, throw a {{TypeError}} exception.
1. Let |funcaddr| be |value|.\[[FunctionAddress]].
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let |store| be [=table_write=](|store|, |tableaddr|, |index|, |funcaddr|).
1. If |store| is [=error=], throw a {{RangeError}} exception.
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
1. Set |values|[|index|] to |value|.
1. Return undefined.
</div>
<h3 id="globals">Globals</h3>
<pre class="idl">
enum ValueType {
"i32",
"i64",
"f32",
"f64"
};
</pre>
Note: this type may be extended with additional cases in future versions of WebAssembly.
<pre class="idl">
dictionary GlobalDescriptor {
required ValueType value;
boolean mutable = false;
};
[LegacyNamespace=WebAssembly, Constructor(GlobalDescriptor descriptor, optional any v), Exposed=(Window,Worker,Worklet)]
interface Global {
any valueOf();
attribute any value;
};
</pre>
<div>
A {{Global}} object represents a single [=global instance=]
which can be simultaneously referenced by multiple {{Instance}} objects. Each
{{Global}} object has one internal slot:
* \[[Global]] : a [=global address=]
</div>
<div algorithm>
To <dfn>create a global object</dfn> from a [=global address=] |globaladdr|, perform the following steps:
1. Let |map| be the current [=agent=]'s associated [=Global object cache=].
1. If |map|[|globaladdr|] [=map/exists=],
1. Return |map|[|globaladdr|].
1. Let |global| be a new {{Global}} instance with \[[Global]] set to |globaladdr|.
1. [=map/Set=] |map|[|globaladdr|] to |global|.
1. Return |global|.
</div>
<div algorithm>
The algorithm <dfn>ToValueType</dfn>(|s|) performs the following steps:
1. If |s| equals "i32", return [=𝗂πŸ₯𝟀=].
1. If |s| equals "i64", return [=π—‚πŸ¨πŸ¦=].
1. If |s| equals "f32", return [=𝖿πŸ₯𝟀=].
1. If |s| equals "f64", return [=π–ΏπŸ¨πŸ¦=].
</div>
<div algorithm>
The algorithm <dfn>DefaultValue</dfn>(|valuetype|) performs the following steps:
1. If |valuetype| equals [=𝗂πŸ₯𝟀=], return [=𝗂πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—=] 0.
1. If |valuetype| equals [=π—‚πŸ¨πŸ¦=], return [=π—‚πŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—=] 0.
1. If |valuetype| equals [=𝖿πŸ₯𝟀=], return [=𝖿πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—=] 0.
1. If |valuetype| equals [=π–ΏπŸ¨πŸ¦=], return [=π–ΏπŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—=] 0.
1. Assert: This step is not reached.
</div>
<div algorithm>
The <dfn constructor for="Global">Global(|descriptor|, |v|)</dfn> constructor, when invoked, performs the following steps:
1. Let |mutable| be |descriptor|["mutable"].
1. Let |valuetype| be [=ToValueType=](|descriptor|["value"]).
1. If |v| is undefined,
1. let |value| be [=DefaultValue=](|valuetype|).
1. Otherwise,
1. If |valuetype| is [=π—‚πŸ¨πŸ¦=], throw a {{TypeError}} exception.
1. Let |value| be [=ToWebAssemblyValue=](|v|, |valuetype|).
1. If |mutable| is true, let |globaltype| be [=var=] |valuetype|; otherwise, let |globaltype| be [=const=] |valuetype|.
1. Let |store| be the current agent's [=associated store=].
1. Let (|store|, |globaladdr|) be [=global_alloc=](|store|, |globaltype|, |value|). <!-- TODO(littledan): Report allocation failure https://github.com/WebAssembly/spec/issues/584 -->
1. Set the current agent's [=associated store=] to |store|.
1. [=Create a global object=] from the global address |globaladdr| and return the result.
</div>
<div algorithm>
The algorithm <dfn>GetGlobalValue</dfn>({{Global}} |global|) performs the following steps:
1. Let |store| be the current agent's [=associated store=].
1. Let |globaladdr| be |global|.\[[Global]].
1. Let |globaltype| be [=global_type=](|store|, |globaladdr|).
1. If |globaltype| is of the form <var ignore>mut</var> [=π—‚πŸ¨πŸ¦=], throw a {{TypeError}}.
1. Let |value| be [=global_read=](|store|, |globaladdr|).
1. Return [=ToJSValue=](|value|).
</div>
<div algorithm>
The getter of the <dfn attribute for="Global">value</dfn> attribute of {{Global}}, when invoked, performs the following steps:
1. Let |global| be the {{Global}} instance.
1. Return [=GetGlobalValue=](|global|).
The setter of the value attribute of {{Global}}, when invoked with a value |v|, performs the following steps:
1. Let |global| be the {{Global}} instance.
1. Let |store| be the current agent's [=associated store=].
1. Let |globaladdr| be |global|.\[[Global]].
1. Let |globaltype| be [=global_type=](|store|, |globaladdr|), where |globaltype| is of the form |mut| |valuetype|.
1. If |mut| is [=const=], throw a {{TypeError}}.
1. If |valuetype| is [=π—‚πŸ¨πŸ¦=], throw a {{TypeError}}.
1. Let |value| be [=ToWebAssemblyValue=](|v|, |valuetype|).
1. Let |store| be [=global_write=](|store|, |globaladdr|, |value|).
1. If |store| is [=error=], throw a {{RangeError}} exception.
1. Set the current agent's [=associated store=] to |store|.
</div>
<div algorithm>
The <dfn method for="Global">valueOf()</dfn> method, when invoked, performs the following steps:
1. Let |global| be the {{Global}} instance.
1. Return [=GetGlobalValue=](|global|).
</div>
<h3 id="exported-function-exotic-objects">Exported Functions</h3>
A WebAssembly function is made available in JavaScript as an <dfn>Exported Function</dfn>.
Exported Functions are [=Built-in Function Objects=] which are not constructors, and which have a \[[FunctionAddress]] internal slot.
This slot holds a [=function address=] relative to the [=surrounding agent=]'s [=associated store=].
<div algorithm>
The <dfn>name of the WebAssembly function</dfn> |funcaddr| is found by performing the following steps:
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let |funcinst| be |store|.π–Ώπ—Žπ—‡π–Όπ—Œ[|funcaddr|].
1. If |funcinst| is of the form {𝗍𝗒𝗉𝖾 <var ignore>functype</var>, π—π—ˆπ—Œπ—π–Όπ—ˆπ–½π–Ύ |hostfunc|},
1. Assert: |hostfunc| is a JavaScript object and [=IsCallable=](|hostfunc|) is true.
1. Let |index| be the [=index of the host function=] |funcaddr|.
1. Otherwise,
1. Let |moduleinst| be |funcinst|.π—†π—ˆπ–½π—Žπ—…π–Ύ.
1. Assert: |funcaddr| is contained in |moduleinst|.π–Ώπ—Žπ—‡π–Όπ–Ίπ–½π–½π—‹π—Œ.
1. Let |index| be the index of |moduleinst|.π–Ώπ—Žπ—‡π–Όπ–Ίπ–½π–½π—‹π—Œ where |funcaddr| is found.
1. Return ! [=ToString=](|index|).
</div>
<div algorithm>
To create <dfn>a new Exported Function</dfn> from a WebAssembly [=function address=] |funcaddr|, perform the following steps:
1. Let |map| be the [=surrounding agent=]'s associated [=Exported Function cache=].
1. If |map|[|funcaddr|] [=map/exists=],
1. Return |map|[|funcaddr|].
1. Let |steps| be "[=call an Exported Function|call the Exported Function=] |funcaddr| with arguments."
1. Let |realm| be the [=current Realm=].
1. Let |function| be [=CreateBuiltinFunction=](|realm|, |steps|, [=%FunctionPrototype%=], &laquo; \[[FunctionAddress]] &raquo;).
1. Set |function|.\[[FunctionAddress]] to |funcaddr|.
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let |functype| be [=func_type=](|store|, |funcaddr|).
1. Let [|paramTypes|] β†’ [<var ignore>resultTypes</var>] be |functype|.
1. Let |arity| be the length of |paramTypes|.
1. Perform ! [=SetFunctionLength=](|function|, |arity|).
1. Let |name| be the [=name of the WebAssembly function=] |funcaddr|.
1. Perform ! [=SetFunctionName=](|function|, |name|).
1. [=map/Set=] |map|[|funcaddr|] to |function|.
1. Return |function|.
</div>
<div algorithm>
To <dfn>call an Exported Function</dfn> with [=function address=] |funcaddr| and a [=list=] of JavaScript arguments |argValues|, perform the following steps:
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let |functype| be [=func_type=](|store|, |funcaddr|).
1. Let [|parameters|] β†’ [|results|] be |functype|.
1. If |parameters| or |results| contains an [=π—‚πŸ¨πŸ¦=], throw a {{TypeError}}.
Note: the above error is thrown each time the \[[Call]] method is invoked.
5. Let |args| be an empty list of WebAssembly values.
1. Let |i| be 0.
1. For each type |t| of |parameters|,
1. If the length of |argValues| &gt; |i|, let |arg| be |argValues|[|i|].
1. Otherwise, let |arg| be undefined.
1. [=Append=] [=ToWebAssemblyValue=](|arg|, |t|) to |args|.
1. Set |i| to |i| + 1.
1. Let |argsSeq| be a WebAssembly [=sequence=] containing the elements of |args|.
1. Let (|store|, |ret|) be the result of [=func_invoke=](|store|, |funcaddr|, |argsSeq|).
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
1. If |ret| is [=error=], throw an exception. This exception should be a WebAssembly {{RuntimeError}} exception, unless otherwise indicated by <a href="#errors">the WebAssembly error mapping</a>.
1. If |ret| is empty, return undefined.
1. Otherwise, return [=ToJSValue=](|v|), where |v| is the singular element of |ret|.
</div>
Note: [=call an Exported Function|Calling an Exported Function=] executes in the \[[Realm]] of the callee Exported Function, as per the definition of [=built-in function objects=].
Note: Exported Functions do not have a \[[Construct]] method and thus it is not possible to call one with the `new` operator.
<div algorithm>
To <dfn>run a host function</dfn> from the JavaScript object |func| and type |functype|, perform the following steps:
1. Let [|parameters|] β†’ [|results|] be |functype|.
1. Assert: |results|'s [=list/size=] is at most one.
1. If either |parameters| or |results| contains [=π—‚πŸ¨πŸ¦=], throw a {{TypeError}}.
1. Let |arguments| be a [=list=] of the arguments of the invocation of this function.
1. Let |jsArguments| be an empty [=list=].
1. For each |arg| in |arguments|,
1. [=list/Append=] ! [=ToJSValue=](|arg|) to |jsArguments|.
1. Let |ret| be ? [=Call=](|func|, undefined, |jsArguments|).
1. If |results| is [=list/empty=], return undefined.
1. Otherwise, return ? [=ToWebAssemblyValue=](|ret|, |results|[0]).
</div>
<div algorithm>
To <dfn>create a host function</dfn> from the JavaScript object |func| and type |functype|, perform the following steps:
1. Let |hostfunc| be a [=host function=] which performs the following steps when called:
1. Let |result| be the result of [=run a host function|running a host function=] from |func| and |functype|.
1. Assert: |result|.\[[Type]] is throw or return.
1. If |result|.\[[Type]] is [=throw=], then trigger a WebAssembly trap, and propagate |result|.\[[Value]] to the enclosing JavaScript.
1. Otherwise, return |result|.\[[Value]].
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let (|store|, |funcaddr|) be [=func_alloc=](|store|, |functype|, |hostfunc|).
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
1. Return |funcaddr|
</div>
<div algorithm>
The algorithm <dfn>ToJSValue</dfn>(|w|) coerces a [=WebAssembly value=] to a JavaScript value performs the following steps:
1. Assert: |w| is not of the form [=π—‚πŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—=] <var ignore>i64</var>.
1. If |w| is of the form [=𝗂πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—=] |i32|, return [=the Number value=] for [=signed_32=](|i32|).
1. If |w| is of the form [=𝖿πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—=] |f32|, return [=the Number value=] for |f32|.
1. If |w| is of the form [=π–ΏπŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—=] |f64|, return [=the Number value=] for |f64|.
<!-- If the WebAssembly value is optional, then given `None`, return JavaScript value `undefined`. -->
Note: Number values which are equal to NaN may have various observable NaN payloads; see [=NumberToRawBytes=] for details.
</div>
<div algorithm>
The algorithm <dfn>ToWebAssemblyValue</dfn>(|v|, |type|) coerce a JavaScript value to a [=WebAssembly value=] performs the following steps:
1. Assert: |type| is not [=π—‚πŸ¨πŸ¦=].
1. If |type| is [=𝗂πŸ₯𝟀=],
1. Let |i32| be ? [=ToInt32=](|v|).
1. Return [=𝗂πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—=] |i32|.
1. If |type| is [=𝖿πŸ₯𝟀=],
1. Let |f32| be ? [=ToNumber=](|v|) rounded to the nearest representable value using IEEE 754-2008 round to nearest, ties to even mode.
1. Return [=𝖿πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—=] |f32|.
1. If |type| is [=π–ΏπŸ¨πŸ¦=],
1. Let |f64| be ? [=ToNumber=](|v|).
1. Return [=π–ΏπŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—=] |f64|.
</div>
<h3 id="error-objects">Error Objects</h3>
WebAssembly defines the following Error classes: {{CompileError}}, {{LinkError}}, and {{RuntimeError}}. WebAssembly errors have the following custom bindings:
- Unlike normal interface types, the interface prototype object for these exception classes must have as its \[[Prototype]] the intrinsic object [=%ErrorPrototype%=].
- The constructor and properties of WebAssembly errors is as specified for {{NativeError}}.
- If an implementation gives native Error objects special powers or nonstandard properties (such as a stack property), it should also expose those on these exception instances.
<pre class='idl'>
[LegacyNamespace=WebAssembly]
interface CompileError { };
[LegacyNamespace=WebAssembly]
interface LinkError { };
[LegacyNamespace=WebAssembly]
interface RuntimeError { };
</pre>
<h2 id="errors">Error Condition Mappings to JavaScript</h2>
Running WebAssembly programs encounter certain events which halt execution of the WebAssembly code.
WebAssembly code (currently)
has no way to catch these conditions and thus an exception will necessarily
propagate to the enclosing non-WebAssembly caller (whether it is a browser,
JavaScript or another runtime system) where it is handled like a normal JavaScript exception.
If WebAssembly calls JavaScript via import and the JavaScript throws an
exception, the exception is propagated through the WebAssembly activation to the
enclosing caller.
Because JavaScript exceptions can be handled, and JavaScript can continue to
call WebAssembly exports after a trap has been handled, traps do not, in
general, prevent future execution.
<h3 id="stack-overflow">Stack Overflow</h3>
Whenever a stack overflow occurs in
WebAssembly code, the same class of exception is thrown as for a stack overflow in
JavaScript. The particular exception here is implementation-defined in both cases.
Note: ECMAScript doesn't specify any sort of behavior on stack overflow; implementations have been observed to throw {{RangeError}}, InternalError or Error. Any is valid here.
<h3 id="out-of-memory">Out of Memory</h3>
Whenever validation, compilation or instantiation run out of memory, the
same class of exception is thrown as for out of memory conditions in JavaScript.
The particular exception here is implementation-defined in both cases.
Note: ECMAScript doesn't specify any sort of behavior on out-of-memory conditions; implementations have been observed to throw OOMError and to crash. Either is valid here.
<div class="issue">
A failed allocation of a large table or memory may either result in
- a {{RangeError}}, as specified in the {{Memory}} {{Memory/grow()}} and {{Table}} {{Table/grow()}} operations
- returning -1 as the [=memory.grow=] instruction
- UA-specific OOM behavior as described in this section.
In a future revision, we may reconsider more reliable and recoverable errors for allocations of large amounts of memory.
See [Issue 879](https://github.com/WebAssembly/spec/issues/879) for further discussion.
</div>
<h2 id="limits">Implementation-defined Limits</h2>
The WebAssembly core specification allows an implementation to define limits on the syntactic structure of the module.
While each embedding of WebAssembly may choose to define its own limits, for predictability the standard WebAssembly JavaScript Interface described in this document defines the following exact limits.
An implementation must reject a module that exceeds these limits with a {{CompileError}}.
In practice, an implementation may run out of resources for valid modules below these limits.
<ul>
<li>The maximum size of a module is 1073741824 bytes (1 GiB).</li>
<li>The maximum number of types defined in the types section is 1000000.</li>
<li>The maximum number of functions defined in a module is 1000000.</li>
<li>The maximum number of imports declared in a module is 100000.</li>
<li>The maximum number of exports declared in a module is 100000.</li>
<li>The maximum number of globals defined in a module is 1000000.</li>
<li>The maximum number of data segments defined in a module is 100000.</li>
<li>The maximum number of tables, including declared or imported tables, is 1.</li>
<li>The maximum size of a table is 10000000.</li>
<li>The maximum number of table entries in any table initialization is 10000000.</li>
<li>The maximum number of memories, including declared or imported memories, is 1.</li>
<li>The initial or maximum number of pages for any memory, declared or imported, is at most 32767.</li>
<li>The maximum number of parameters to any function is 1000.</li>
<li>The maximum number of return values for any function is 1.</li>
<li>The maximum size of a function body, including locals declarations, is 7654321 bytes.</li>
<li>The maximum number of locals declared in a function, including implicitly declared as parameters, is 50000.</li>
</ul>