| <pre class='metadata'> |
| Title: WebAssembly JavaScript Interface |
| Shortname: wasm-js-api |
| Group: wasm |
| Status: ED |
| Issue Tracking: GitHub https://github.com/WebAssembly/spec/issues |
| Level: 2 |
| TR: https://www.w3.org/TR/wasm-js-api-2/ |
| ED: https://webassembly.github.io/spec/js-api/ |
| Implementation Report: https://webassembly.org/features/ |
| Editor: Ms2ger, w3cid 46309, 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 |
| Date: now |
| </pre> |
| |
| <pre class='biblio'> |
| { |
| "WEBASSEMBLY": { |
| "href": "https://webassembly.github.io/spec/core/", |
| "title": "WebAssembly Core Specification", |
| "publisher": "W3C WebAssembly Community Group", |
| "status": "Draft" |
| }, |
| "WASMWEB": { |
| "href": "https://webassembly.github.io/spec/js-api/", |
| "title": "WebAssembly Web API 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 |
| url: sec-returnifabrupt-shorthands |
| text: ! |
| text: ? |
| text: Type; url: sec-ecmascript-data-types-and-values |
| text: current Realm; url: current-realm |
| text: Built-in Function Objects; url: sec-built-in-function-objects |
| text: NativeError Object Structure; url: sec-nativeerror-object-structure |
| text: ๐ฝ; url: #๐ฝ |
| text: โค; url: #โค |
| text: SameValue; url: sec-samevalue |
| text: Array; url: sec-array-exotic-objects |
| text: BigInt; url: sec-ecmascript-language-types-bigint-type |
| urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: dfn |
| text: embedding interface; url: appending/embedding.html |
| text: scope; url: intro/introduction.html#scope |
| url: valid/modules.html#valid-module |
| text: valid |
| text: WebAssembly module validation |
| text: valid limits; url: valid/types.html#valid-limits |
| text: valid memtype; url: valid/types.html#valid-memtype |
| text: valid tabletype; url: valid/types.html#valid-tabletype |
| 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: i64.const |
| text: i32.const |
| text: f32.const |
| text: f64.const |
| text: v128.const |
| text: ref.null |
| text: ref.func |
| text: ref.extern |
| 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: limits; url: syntax/types.html#syntax-limits |
| 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 type; url: syntax/types.html#syntax-memtype |
| text: memory address; url: exec/runtime.html#syntax-memaddr |
| text: global address; url: exec/runtime.html#syntax-globaladdr |
| text: extern address; url: exec/runtime.html#syntax-externaddr |
| text: page size; url: exec/runtime.html#page-size |
| url: syntax/types.html#syntax-numtype |
| text: i32 |
| text: i64 |
| text: f32 |
| text: f64 |
| url: syntax/types.html#vector-types |
| text: v128 |
| url: syntax/types.html#syntax-reftype |
| text: reftype |
| text: funcref |
| text: externref |
| url: syntax/values.html#syntax-float |
| text: +โ |
| text: โโ |
| text: nan |
| text: canon |
| text: signif |
| 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: imports; url: syntax/modules.html#syntax-module |
| text: import; url: syntax/modules.html#syntax-import |
| url: syntax/types.html#external-types |
| text: external type |
| text: func |
| text: table |
| text: mem |
| text: global |
| 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: module; for: frame; url: exec/runtime.html#syntax-frame |
| text: memaddrs; for: moduleinst; url: exec/runtime.html#syntax-moduleinst |
| text: signed_64; url: exec/numerics.html#aux-signed |
| text: sequence; url: syntax/conventions.html#grammar-notation |
| urlPrefix: https://heycam.github.io/webidl/; spec: WebIDL |
| type: dfn |
| text: create a namespace object; url: create-a-namespace-object |
| urlPrefix: https://tc39.es/proposal-resizablearraybuffer/; spec: ResizableArrayBuffer proposal |
| type: dfn |
| text: handled; url: sec-hostresizearraybuffer |
| text: IsFixedLengthArrayBuffer; url: sec-isfixedarraybuffer |
| text: HostResizeArrayBuffer; url: sec-hostresizearraybuffer |
| </pre> |
| |
| <pre class='link-defaults'> |
| spec:infra; type:dfn; text:list |
| spec:ecma-262; type:exception; for:ECMAScript; text:Error |
| 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:ecmascript; type:dfn; text:agent |
| spec:webidl; type:dfn; text:resolve |
| </pre> |
| |
| <style> |
| emu-const { |
| font-family: serif; |
| } |
| </style> |
| |
| <h2 id="intro">Introduction</h2> |
| |
| By design, the [=scope=] of the WebAssembly core specification [[WEBASSEMBLY]] does not include a description of how WebAssembly programs interact with their surrounding execution environment. |
| Instead it defines an abstract [=embedding interface=] between WebAssembly and its environment, (called the *embedder*). |
| It is only through this interface that an embedder interacts with the semantics of WebAssembly, and the embedder implements the connection between its host environment and the embedding API. |
| This document describes the embedding of WebAssembly into JavaScript [[ECMASCRIPT]] environments, including how WebAssembly modules can be constructed and instantiated, how imported and exported functions are called, how data is exchanged, and how errors are handled. |
| When the JavaScript environment is itself embedded in a Web browser, the Web API spec [[WASMWEB]] describes additional behavior relevant to the Web environment. |
| |
| |
| <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="notation">Notation</h2> |
| |
| This specification depends on the Infra Standard. [[INFRA]] |
| |
| The WebAssembly [=sequence=] type is equivalent to the [=list=] type defined there; values of one |
| are treated as values of the other transparently. |
| |
| <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 [=store_init=](). |
| |
| 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. However, this property does not hold for shared objects. |
| |
| 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. |
| * The <dfn>Extern value cache</dfn>, mapping [=extern address=]es to values. |
| |
| <h2 id="webassembly-namespace">The WebAssembly Namespace</h2> |
| |
| <pre class="idl"> |
| dictionary WebAssemblyInstantiatedSource { |
| required Module module; |
| required Instance instance; |
| }; |
| |
| [Exposed=*] |
| namespace WebAssembly { |
| boolean validate(BufferSource bytes); |
| Promise<Module> compile(BufferSource bytes); |
| |
| Promise<WebAssemblyInstantiatedSource> instantiate( |
| BufferSource bytes, optional object importObject); |
| |
| Promise<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> |
| |
| 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 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|.[=imports=] [=list/is empty|is not empty=], and |importObject| is undefined, throw a {{TypeError}} exception. |
| 1. Let |imports| be ยซ ยป. |
| 1. [=list/iterate|For each=] (|moduleName|, |componentName|, |externtype|) of [=module_imports=](|module|), |
| 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 [=func=] |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. |
| 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|func=] |funcaddr|. |
| 1. [=list/Append=] |externfunc| to |imports|. |
| 1. If |externtype| is of the form [=global=] <var ignore>mut</var> |valtype|, |
| 1. If [=Type=](|v|) is Number or BigInt, |
| 1. If |valtype| is [=i64=] and [=Type=](|v|) is Number, |
| 1. Throw a {{LinkError}} exception. |
| 1. If |valtype| is not [=i64=] and [=Type=](|v|) is BigInt, |
| 1. Throw a {{LinkError}} exception. |
| 1. If |valtype| is [=v128=], |
| 1. 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. Otherwise, if |v| [=implements=] {{Global}}, |
| 1. Let |globaladdr| be |v|.\[[Global]]. |
| 1. Otherwise, |
| 1. Throw a {{LinkError}} exception. |
| 1. Let |externglobal| be [=external value|global=] |globaladdr|. |
| 1. [=list/Append=] |externglobal| to |imports|. |
| 1. If |externtype| is of the form [=mem=] <var ignore>memtype</var>, |
| 1. If |v| does not [=implement=] {{Memory}}, throw a {{LinkError}} exception. |
| 1. Let |externmem| be the [=external value=] [=external value|mem=] |v|.\[[Memory]]. |
| 1. [=list/Append=] |externmem| to |imports|. |
| 1. If |externtype| is of the form [=table=] <var ignore>tabletype</var>, |
| 1. If |v| does not [=implement=] {{Table}}, throw a {{LinkError}} exception. |
| 1. Let |tableaddr| be |v|.\[[Table]]. |
| 1. Let |externtable| be the [=external value=] [=external value|table=] |tableaddr|. |
| 1. [=list/Append=] |externtable| to |imports|. |
| 1. Return |imports|. |
| |
| Note: This algorithm only verifies the right kind of JavaScript values are passed. |
| The verification of WebAssembly type requirements is deferred to the |
| "[=instantiate the core of a WebAssembly module=]" algorithm. |
| </div> |
| |
| <div algorithm> |
| To <dfn>create an exports object</dfn> from a WebAssembly module |module| and instance |instance|, perform the following steps: |
| 1. Let |exportsObject| be [=!=] [$OrdinaryObjectCreate$](null). |
| 1. [=list/iterate|For each=] (|name|, |externtype|) of [=module_exports=](|module|), |
| 1. Let |externval| be [=instance_export=](|instance|, |name|). |
| 1. Assert: |externval| is not [=error=]. |
| 1. If |externtype| is of the form [=func=] <var ignore>functype</var>, |
| 1. Assert: |externval| is of the form [=external value|func=] |funcaddr|. |
| 1. Let [=external value|func=] |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 [=global=] <var ignore>mut</var> <var ignore>globaltype</var>, |
| 1. Assert: |externval| is of the form [=external value|global=] |globaladdr|. |
| 1. Let [=external value|global=] |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 [=mem=] <var ignore>memtype</var>, |
| 1. Assert: |externval| is of the form [=external value|mem=] |memaddr|. |
| 1. Let [=external value|mem=] |memaddr| be |externval|. |
| 1. Let |memory| be [=create a memory object|a new Memory object=] created from |memaddr|. |
| 1. Let |value| be |memory|. |
| 1. If |externtype| is of the form [=table=] <var ignore>tabletype</var>, |
| 1. Assert: |externval| is of the form [=external value|table=] |tableaddr|. |
| 1. Let [=external value|table=] |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 |exportsObject|. |
| </div> |
| |
| <div algorithm> |
| To <dfn>initialize an instance object</dfn> |instanceObject| from a WebAssembly module |module| and instance |instance|, perform the following steps: |
| |
| 1. [=Create an exports object=] from |module| and |instance| and let |exportsObject| be the result. |
| 1. Set |instanceObject|.\[[Instance]] to |instance|. |
| 1. Set |instanceObject|.\[[Exports]] 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. Run the following steps [=in parallel=]: |
| 1. [=Queue a task=] to perform the following steps: |
| Note: Implementation-specific work may be performed here. |
| 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. Let |instanceObject| be a [=/new=] {{Instance}}. |
| 1. [=initialize an instance object|Initialize=] |instanceObject| from |module| and |instance|. |
| 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> |
| 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. [=React=] to |promiseOfModule|: |
| * If |promiseOfModule| was fulfilled with value |module|: |
| 1. [=asynchronously instantiate a WebAssembly module|Instantiate the WebAssembly module=] |module| importing |importObject|, and let |innerPromise| be the result. |
| 1. [=React=] to |innerPromise|: |
| * If |innerPromise| was fulfilled with value |instance|. |
| 1. Let |result| be the {{WebAssemblyInstantiatedSource}} value ยซ[ "{{WebAssemblyInstantiatedSource/module}}" โ |module|, "{{WebAssemblyInstantiatedSource/instance}}" โ |instance| ]ยป. |
| 1. [=Resolve=] |promise| with |result|. |
| * If |innerPromise| was rejected with reason |reason|: |
| 1. [=Reject=] |promise| with |reason|. |
| * If |promiseOfModule| was rejected with reason |reason|: |
| 1. [=Reject=] |promise| with |reason|. |
| 1. Return |promise|. |
| </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, Exposed=*] |
| interface Module { |
| constructor(BufferSource bytes); |
| static sequence<ModuleExportDescriptor> exports(Module moduleObject); |
| static sequence<ModuleImportDescriptor> imports(Module moduleObject); |
| static sequence<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 [=func=] <var ignore>functype</var> |
| * "table" if |type| is of the form [=table=] <var ignore>tabletype</var> |
| * "memory" if |type| is of the form [=mem=] <var ignore>memtype</var> |
| * "global" if |type| is of the form [=global=] <var ignore>globaltype</var> |
| </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 ยซ ยป. |
| 1. [=list/iterate|For each=] (|name|, |type|) of [=module_exports=](|module|), |
| 1. Let |kind| be the [=string value of the extern type=] |type|. |
| 1. Let |obj| be ยซ[ "{{ModuleExportDescriptor/name}}" โ |name|, "{{ModuleExportDescriptor/kind}}" โ |kind| ]ยป. |
| 1. [=list/Append=] |obj| to |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 ยซ ยป. |
| 1. [=list/iterate|For each=] (|moduleName|, |name|, |type|) of [=module_imports=](|module|), |
| 1. Let |kind| be the [=string value of the extern type=] |type|. |
| 1. Let |obj| be ยซ[ "{{ModuleImportDescriptor/module}}" โ |moduleName|, "{{ModuleImportDescriptor/name}}" โ |name|, "{{ModuleImportDescriptor/kind}}" โ |kind| ]ยป. |
| 1. [=list/Append=] |obj| to |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 ยซ ยป. |
| 1. [=list/iterate|For each=] [=custom section=] |customSection| of |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. [=list/Append=] a new {{ArrayBuffer}} containing a copy of the bytes in |bytes| for the range matched by this [=customsec=] production to |customSections|. |
| 1. Return |customSections|. |
| </div> |
| |
| <div algorithm> |
| The <dfn constructor for="Module">Module(|bytes|)</dfn> constructor, 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 the WebAssembly module=] |stableBytes| and store the result as |module|. |
| 1. If |module| is [=error=], throw a {{CompileError}} exception. |
| 1. Set **this**.\[[Module]] to |module|. |
| 1. Set **this**.\[[Bytes]] to |stableBytes|. |
| |
| Note: Some implementations enforce a size limitation on |bytes|. Use of this API is discouraged, in favor of asynchronous APIs. |
| </div> |
| |
| <h3 id="instances">Instances</h3> |
| |
| <pre class="idl"> |
| [LegacyNamespace=WebAssembly, Exposed=*] |
| interface Instance { |
| constructor(Module module, optional object importObject); |
| readonly attribute object exports; |
| }; |
| </pre> |
| |
| <div algorithm> |
| The <dfn constructor for="Instance">Instance(|module|, |importObject|)</dfn> constructor, when invoked, runs the following steps: |
| 1. Let |module| be |module|.\[[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. [=initialize an instance object|Initialize=] **this** from |module| and |instance|. |
| |
| Note: The use of this synchronous API is discouraged, as some implementations sometimes do long-running compilation work when instantiating. |
| </div> |
| |
| <div algorithm> |
| The getter of the <dfn attribute for="Instance">exports</dfn> attribute of {{Instance}} returns **this**.\[[Exports]]. |
| </div> |
| |
| <h3 id="memories">Memories</h3> |
| |
| <pre class="idl"> |
| dictionary MemoryDescriptor { |
| required [EnforceRange] unsigned long initial; |
| [EnforceRange] unsigned long maximum; |
| }; |
| |
| [LegacyNamespace=WebAssembly, Exposed=*] |
| interface Memory { |
| constructor(MemoryDescriptor descriptor); |
| unsigned long grow([EnforceRange] unsigned long delta); |
| ArrayBuffer toFixedLengthBuffer(); |
| ArrayBuffer toResizableBuffer(); |
| readonly attribute ArrayBuffer buffer; |
| }; |
| </pre> |
| |
| 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 algorithm> |
| To <dfn>create a fixed length 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}} with the internal slots \[[ArrayBufferData]], \[[ArrayBufferByteLength]], and \[[ArrayBufferDetachKey]]. |
| 1. Set |buffer|.\[[ArrayBufferData]] to |block|. |
| 1. Set |buffer|.\[[ArrayBufferByteLength]] to the length of |block|. |
| 1. Set |buffer|.\[[ArrayBufferDetachKey]] to "WebAssembly.Memory". |
| 1. Return |buffer|. |
| </div> |
| |
| <div algorithm> |
| To <dfn>create a resizable memory buffer</dfn> from a [=memory address=] |memaddr| and a |maxsize|, perform the following steps: |
| |
| 1. Let |block| be a [=Data Block=] which is [=identified with=] the underlying memory of |memaddr|. |
| 1. Let |length| be the length of |block|. |
| 1. If |maxsize| > (65536 × 65536), |
| 1. Throw a {{RangeError}} exception. |
| 1. Let |buffer| be a new {{ArrayBuffer}} with the internal slots \[[ArrayBufferData]], \[[ArrayBufferByteLength]], \[[ArrayBufferMaxByteLength]], and \[[ArrayBufferDetachKey]]. |
| 1. Set |buffer|.\[[ArrayBufferData]] to |block|. |
| 1. Set |buffer|.\[[ArrayBufferByteLength]] to |length|. |
| 1. Set |buffer|.\[[ArrayBufferMaxByteLength]] is |maxsize|. |
| 1. Set |buffer|.\[[ArrayBufferDetachKey]] to "WebAssembly.Memory". |
| 1. Return |buffer|. |
| </div> |
| |
| <div algorithm> |
| To <dfn>initialize a memory object</dfn> |memory| from a [=memory address=] |memaddr|, perform the following steps: |
| 1. Let |map| be the [=surrounding agent=]'s associated [=Memory object cache=]. |
| 1. Assert: |map|[|memaddr|] doesn't [=map/exist=]. |
| 1. Let |buffer| be the result of [=create a fixed length memory buffer|creating a fixed length memory buffer=] from |memaddr|. |
| 1. Set |memory|.\[[Memory]] to |memaddr|. |
| 1. Set |memory|.\[[BufferObject]] to |buffer|. |
| 1. [=map/Set=] |map|[|memaddr|] to |memory|. |
| </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 |memory| be a [=/new=] {{Memory}}. |
| 1. [=initialize a memory object|Initialize=] |memory| from |memaddr|. |
| 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"] [=map/exists=], let |maximum| be |descriptor|["maximum"]; otherwise, let |maximum| be empty. |
| 1. Let |memtype| be the [=memory type=] { <b>[=limits|min=]</b> |initial|, <b>[=limits|max=]</b> |maximum| }. |
| 1. If |memtype| is not [=valid memtype|valid=], throw a {{RangeError}} exception. |
| 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. [=initialize a memory object|Initialize=] **this** from |memaddr|. |
| </div> |
| |
| <div algorithm> |
| To <dfn>refresh 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. Let |buffer| be |memory|.\[[BufferObject]]. |
| 1. If [=IsFixedLengthArrayBuffer=](|buffer|) is true, |
| 1. Perform [=!=] [$DetachArrayBuffer$](|buffer|, "WebAssembly.Memory"). |
| 1. Let |buffer| be the result of [=create a fixed length memory buffer|creating a fixed length memory buffer=] from |memaddr|. |
| 1. Set |memory|.\[[BufferObject]] to |buffer|. |
| 1. Otherwise, |
| 1. Let |block| be a [=Data Block=] which is [=identified with=] the underlying memory of |memaddr|. |
| 1. Set |buffer|.\[[ArrayBufferData]] to |block|. |
| 1. Set |buffer|.\[[ArrayBufferByteLength]] to the length of |block|. |
| </div> |
| |
| <div algorithm> |
| To <dfn>grow the memory buffer</dfn> associated with a [=memory address=] |memaddr| by |delta|, perform the following steps: |
| |
| 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. |
| 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. [=Refresh the memory buffer=] of |memaddr|. |
| 1. Return |ret|. |
| </div> |
| |
| <div algorithm=dom-Memory-grow> |
| The <dfn method for="Memory">grow(|delta|)</dfn> method, when invoked, performs the following steps: |
| 1. Let |memaddr| be **this**.\[[Memory]]. |
| 1. Return the result of [=grow the memory buffer|growing the memory buffer=] associated with |memaddr| by |delta|. |
| </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 [=i32.const=] (โ1), |
| 1. Let |frame| be the [=current frame=]. |
| 1. Assert: due to validation, |frame|.[=frame/module=].[=moduleinst/memaddrs=][0] exists. |
| 1. Let |memaddr| be the memory address |frame|.[=frame/module=].[=moduleinst/memaddrs=][0]. |
| 1. [=Refresh the memory buffer=] of |memaddr|. |
| </div> |
| |
| <div algorithm=dom-Memory-toFixedLengthBuffer> |
| The <dfn method for="Memory">toFixedLengthBuffer()</dfn> method, when invoked, performs the following steps: |
| 1. Let |buffer| be **this**.\[[BufferObject]]. |
| 1. If [=IsFixedLengthArrayBuffer=](|buffer|) is true, return |buffer|. |
| 1. Let |memaddr| be **this**.\[[Memory]]. |
| 1. Let |fixedBuffer| be the result of [=create a fixed length memory buffer|creating a fixed length memory buffer=] from |memaddr|. |
| 1. Perform [=!=] [$DetachArrayBuffer$](|buffer|, "WebAssembly.Memory"). |
| 1. Set **this**.\[[BufferObject]] to |fixedBuffer|. |
| 1. Return |fixedBuffer|. |
| </div> |
| |
| <div algorithm=dom-Memory-toResizableBuffer> |
| The <dfn method for="Memory">toResizableBuffer()</dfn> method, when invoked, performs the following steps: |
| 1. Let |buffer| be **this**.\[[BufferObject]]. |
| 1. If [=IsFixedLengthArrayBuffer=](|buffer|) is false, return |buffer|. |
| 1. Let |memaddr| be **this**.\[[Memory]]. |
| 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. |
| 1. Let |memtype| be [=mem_type=](|store|, |memaddr|). |
| 1. If |memtype| has a max, |
| 1. Let |maxsize| be the max value in |memtype|. |
| 1. Otherwise, |
| 1. Let |maxsize| be 65536 × 65536. |
| 1. Let |resizableBuffer| be the result of [=create a resizable memory buffer|creating a resizable memory buffer=] from |memaddr| and |maxsize|. |
| 1. Perform [=!=] [$DetachArrayBuffer$](|buffer|, "WebAssembly.Memory"). |
| 1. Set **this**.\[[BufferObject]] to |resizableBuffer|. |
| 1. Return |resizableBuffer|. |
| </div> |
| |
| {{ArrayBuffer}} objects returned by a {{Memory}} object must have a size that is a multiple of a WebAssembly [=page size=] (the constant 65536). For this reason [=HostResizeArrayBuffer=] is redefined as follows. |
| |
| <div algorithm> |
| |
| The <dfn id=HostResizeArrayBuffer export>abstract operation [=HostResizeArrayBuffer=]</dfn> takes arguments |buffer| (an {{ArrayBuffer}}) and |newLength|. It performs the following steps when called. |
| |
| 1. If |buffer|.\[[ArrayBufferDetachKey]] is "WebAssembly.Memory", |
| 1. Let |map| be the [=surrounding agent=]'s associated [=Memory object cache=]. |
| 1. Assert: |buffer| is the \[[BufferObject]] of exactly one value in |map|. |
| 1. [=map/iterate|For each=] |memaddr| → |mem| in |map|, |
| 1. If [=SameValue=](|mem|.\[[BufferObject]], |buffer|) is true, |
| 1. Assert: |buffer|.\[[ArrayBufferByteLength]] modulo 65536 is 0. |
| 1. Let |lengthDelta| be |newLength| - |buffer|.\[[ArrayBufferByteLength]]. |
| 1. If |lengthDelta| < 0 or |lengthDelta| modulo 65536 is not 0, |
| 1. Throw a {{RangeError}} exception. |
| 1. Let |delta| be |lengthDelta| ÷ 65536. |
| 1. [=Grow the memory buffer=] associated with |memaddr| by |delta|. |
| 1. Return <emu-const>handled</emu-const>. |
| 1. Otherwise, return <emu-const>unhandled</emu-const>. |
| </div> |
| |
| <div algorithm> |
| The getter of the <dfn attribute for="Memory">buffer</dfn> attribute of {{Memory}} returns **this**.\[[BufferObject]]. |
| </div> |
| |
| <h3 id="tables">Tables</h3> |
| |
| <pre class="idl"> |
| enum TableKind { |
| "externref", |
| "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, Exposed=*] |
| interface Table { |
| constructor(TableDescriptor descriptor, optional any value); |
| unsigned long grow([EnforceRange] unsigned long delta, optional any value); |
| any get([EnforceRange] unsigned long index); |
| undefined set([EnforceRange] unsigned long index, optional any value); |
| readonly attribute unsigned long length; |
| }; |
| </pre> |
| |
| A {{Table}} object represents a single [=table instance=] which can be simultaneously referenced by |
| multiple {{Instance}} objects. |
| Each {{Table}} object has a \[[Table]] internal slot, which is a [=table address=]. |
| |
| <div algorithm> |
| To <dfn>initialize a table object</dfn> |table| from a [=table address=] |tableaddr|, perform the following steps: |
| 1. Let |map| be the [=surrounding agent=]'s associated [=Table object cache=]. |
| 1. Assert: |map|[|tableaddr|] doesn't [=map/exist=]. |
| 1. Set |table|.\[[Table]] to |tableaddr|. |
| 1. [=map/Set=] |map|[|tableaddr|] to |table|. |
| </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 |table| be a [=/new=] {{Table}}. |
| 1. [=initialize a table object|Initialize=] |table| from |tableaddr|. |
| 1. Return |table|. |
| </div> |
| |
| <div algorithm> |
| The <dfn constructor for="Table">Table(|descriptor|, |value|)</dfn> constructor, when invoked, performs the following steps: |
| 1. Let |elementType| be [=ToValueType=](|descriptor|["element"]). |
| 1. If |elementType| is not a [=reftype=], |
| 1. [=Throw=] a {{TypeError}} exception. |
| 1. Let |initial| be |descriptor|["initial"]. |
| 1. If |descriptor|["maximum"] [=map/exists=], let |maximum| be |descriptor|["maximum"]; otherwise, let |maximum| be empty. |
| 1. Let |type| be the [=table type=] { <b>[=limits|min=]</b> |initial|, <b>[=limits|max=]</b> |maximum| } |elementType|. |
| 1. If |type| is not [=valid tabletype|valid=], throw a {{RangeError}} exception. |
| |
| Note: Because tables may have up to 2<sup>32</sup> - 1 elements in validation, the checks for [=limits|min=] โค 2<sup>32</sup> - 1 and [=limits|max=] โค 2<sup>32</sup> - 1 in [=valid limits|limits validation=] cannot fail. |
| 1. If |value| is missing, |
| 1. Let |ref| be [=DefaultValue=](|elementType|). |
| 1. Otherwise, |
| 1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementType|). |
| 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. |
| 1. Let (|store|, |tableaddr|) be [=table_alloc=](|store|, |type|, |ref|). If allocation fails, throw a {{RangeError}} exception. |
| 1. Set the [=surrounding agent=]'s [=associated store=] to |store|. |
| 1. [=initialize a table object|Initialize=] **this** from |tableaddr|. |
| </div> |
| |
| <div algorithm=dom-Table-grow> |
| The <dfn method for="Table">grow(|delta|, |value|)</dfn> method, when invoked, performs the following steps: |
| 1. Let |tableaddr| be **this**.\[[Table]]. |
| 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. |
| 1. Let |initialSize| be [=table_size=](|store|, |tableaddr|). |
| 1. Let (<var ignore>limits</var>, |elementType|) be [=table_type=](|tableaddr|). |
| 1. If |value| is missing, |
| 1. Let |ref| be [=DefaultValue=](|elementType|). |
| 1. Otherwise, |
| 1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementType|). |
| 1. Let |result| be [=table_grow=](|store|, |tableaddr|, |delta|, |ref|). |
| 1. If |result| is [=error=], throw a {{RangeError}} exception. |
| |
| Note: The above exception can happen due to either insufficient memory or an invalid size parameter. |
| |
| 1. Set the [=surrounding agent=]'s [=associated store=] to |result|. |
| 1. Return |initialSize|. |
| </div> |
| |
| <div algorithm> |
| The getter of the <dfn attribute for="Table">length</dfn> attribute of {{Table}}, when invoked, performs the following steps: |
| 1. Let |tableaddr| be **this**.\[[Table]]. |
| 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. |
| 1. Return [=table_size=](|store|, |tableaddr|). |
| </div> |
| |
| <div algorithm> |
| The <dfn method for="Table">get(|index|)</dfn> method, when invoked, performs the following steps: |
| 1. Let |tableaddr| be **this**.\[[Table]]. |
| 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. |
| 1. Let |result| be [=table_read=](|store|, |tableaddr|, |index|). |
| 1. If |result| is [=error=], throw a {{RangeError}} exception. |
| 1. Return [=ToJSValue=](|result|). |
| </div> |
| |
| <div algorithm> |
| The <dfn method for="Table">set(|index|, |value|)</dfn> method, when invoked, performs the following steps: |
| 1. Let |tableaddr| be **this**.\[[Table]]. |
| 1. Let (<var ignore>limits</var>, |elementType|) be [=table_type=](|tableaddr|). |
| 1. If |value| is missing, |
| 1. Let |ref| be [=DefaultValue=](|elementType|). |
| 1. Otherwise, |
| 1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementType|). |
| 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. |
| 1. Let |store| be [=table_write=](|store|, |tableaddr|, |index|, |ref|). |
| 1. If |store| is [=error=], throw a {{RangeError}} exception. |
| 1. Set the [=surrounding agent=]'s [=associated store=] to |store|. |
| </div> |
| |
| <h3 id="globals">Globals</h3> |
| |
| <pre class="idl"> |
| enum ValueType { |
| "i32", |
| "i64", |
| "f32", |
| "f64", |
| "v128", |
| "externref", |
| "anyfunc", |
| }; |
| </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, Exposed=*] |
| interface Global { |
| constructor(GlobalDescriptor descriptor, optional any v); |
| any valueOf(); |
| attribute any value; |
| }; |
| </pre> |
| |
| 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 algorithm> |
| To <dfn>initialize a global object</dfn> |global| from a [=global address=] |globaladdr|, perform the following steps: |
| 1. Let |map| be the [=surrounding agent=]'s associated [=Global object cache=]. |
| 1. Assert: |map|[|globaladdr|] doesn't [=map/exist=]. |
| 1. Set |global|.\[[Global]] to |globaladdr|. |
| 1. [=map/Set=] |map|[|globaladdr|] to |global|. |
| </div> |
| |
| <div algorithm> |
| To <dfn>create a global object</dfn> from a [=global address=] |globaladdr|, perform the following steps: |
| 1. Let |map| be the [=surrounding agent=]'s associated [=Global object cache=]. |
| 1. If |map|[|globaladdr|] [=map/exists=], |
| 1. Return |map|[|globaladdr|]. |
| 1. Let |global| be a [=/new=] {{Global}}. |
| 1. [=initialize a global object|Initialize=] |global| from |globaladdr|. |
| 1. Return |global|. |
| </div> |
| |
| <div algorithm> |
| The algorithm <dfn>ToValueType</dfn>(|s|) performs the following steps: |
| 1. If |s| equals "i32", return [=i32=]. |
| 1. If |s| equals "i64", return [=i64=]. |
| 1. If |s| equals "f32", return [=f32=]. |
| 1. If |s| equals "f64", return [=f64=]. |
| 1. If |s| equals "v128", return [=v128=]. |
| 1. If |s| equals "anyfunc", return [=funcref=]. |
| 1. If |s| equals "externref", return [=externref=]. |
| 1. Assert: This step is not reached. |
| </div> |
| |
| <div algorithm> |
| The algorithm <dfn>DefaultValue</dfn>(|valuetype|) performs the following steps: |
| 1. If |valuetype| equals [=i32=], return [=i32.const=] 0. |
| 1. If |valuetype| equals [=i64=], return [=i64.const=] 0. |
| 1. If |valuetype| equals [=f32=], return [=f32.const=] 0. |
| 1. If |valuetype| equals [=f64=], return [=f64.const=] 0. |
| 1. If |valuetype| equals [=funcref=], return [=ref.null=] [=funcref=]. |
| 1. If |valuetype| equals [=externref=], return [=ToWebAssemblyValue=](undefined, |valuetype|). |
| 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 |valuetype| is [=v128=], |
| 1. Throw a {{TypeError}} exception. |
| 1. If |v| is missing, |
| 1. Let |value| be [=DefaultValue=](|valuetype|). |
| 1. Otherwise, |
| 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. [=initialize a global object|Initialize=] **this** from |globaladdr|. |
| </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> [=v128=], 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. Return [=GetGlobalValue=](**this**). |
| |
| The setter of the value attribute of {{Global}}, when invoked, performs the following steps: |
| 1. Let |store| be the current agent's [=associated store=]. |
| 1. Let |globaladdr| be **this**.\[[Global]]. |
| 1. Let |mut| |valuetype| be [=global_type=](|store|, |globaladdr|). |
| 1. If |valuetype| is [=v128=], throw a {{TypeError}}. |
| 1. If |mut| is [=const=], throw a {{TypeError}}. |
| 1. Let |value| be [=ToWebAssemblyValue=](**the given value**, |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. Return [=GetGlobalValue=](**this**). |
| </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|.funcs[|funcaddr|]. |
| 1. If |funcinst| is of the form {type <var ignore>functype</var>, hostcode |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|.module. |
| 1. Assert: |funcaddr| is contained in |moduleinst|.funcaddrs. |
| 1. Let |index| be the index of |moduleinst|.funcaddrs 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 |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 |paramTypes|'s [=list/size=]. |
| 1. Let |name| be the [=name of the WebAssembly function=] |funcaddr|. |
| 1. Let |function| be [=!=] [$CreateBuiltinFunction$](|steps|, |arity|, |name|, ยซ \[[FunctionAddress]] ยป, |realm|). |
| 1. Set |function|.\[[FunctionAddress]] to |funcaddr|. |
| 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| contain [=v128=], throw a {{TypeError}}. |
| |
| Note: the above error is thrown each time the \[[Call]] method is invoked. |
| 1. Let |args| be ยซ ยป. |
| 1. Let |i| be 0. |
| 1. [=list/iterate|For each=] |t| of |parameters|, |
| 1. If |argValues|'s [=list/size=] > |i|, let |arg| be |argValues|[|i|]. |
| 1. Otherwise, let |arg| be undefined. |
| 1. [=list/Append=] [=ToWebAssemblyValue=](|arg|, |t|) to |args|. |
| 1. Set |i| to |i| + 1. |
| 1. Let (|store|, |ret|) be the result of [=func_invoke=](|store|, |funcaddr|, |args|). |
| 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. Let |outArity| be the [=list/size=] of |ret|. |
| 1. If |outArity| is 0, return undefined. |
| 1. Otherwise, if |outArity| is 1, return [=ToJSValue=](|ret|[0]). |
| 1. Otherwise, |
| 1. Let |values| be ยซ ยป. |
| 1. [=list/iterate|For each=] |r| of |ret|, |
| 1. [=list/Append=] [=ToJSValue=](|r|) to |values|. |
| 1. Return [$CreateArrayFromList$](|values|). |
| </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|, type |functype|, and [=list=] of [=WebAssembly values=] |arguments|, perform the following steps: |
| |
| 1. Let [|parameters|] โ [|results|] be |functype|. |
| 1. If |parameters| or |results| contain [=v128=], throw a {{TypeError}}. |
| 1. Let |jsArguments| be ยซ ยป. |
| 1. [=list/iterate|For each=] |arg| of |arguments|, |
| 1. [=list/Append=] [=!=] [=ToJSValue=](|arg|) to |jsArguments|. |
| 1. Let |ret| be [=?=] [$Call$](|func|, undefined, |jsArguments|). |
| 1. Let |resultsSize| be |results|'s [=list/size=]. |
| 1. If |resultsSize| is 0, return ยซ ยป. |
| 1. Otherwise, if |resultsSize| is 1, return ยซ [=?=] [=ToWebAssemblyValue=](|ret|, |results|[0]) ยป. |
| 1. Otherwise, |
| 1. Let |method| be [=?=] [$GetMethod$](|ret|, {{%Symbol.iterator%}}). |
| 1. If |method| is undefined, [=throw=] a {{TypeError}}. |
| 1. Let |values| be [=?=] [$IteratorToList$]([=?=] [$GetIteratorFromMethod$](|ret|, |method|)). |
| 1. Let |wasmValues| be a new, empty [=list=]. |
| 1. If |values|'s [=list/size=] is not |resultsSize|, throw a {{TypeError}} exception. |
| 1. For each |value| and |resultType| in |values| and |results|, paired linearly, |
| 1. [=list/Append=] [=ToWebAssemblyValue=](|value|, |resultType|) to |wasmValues|. |
| 1. Return |wasmValues|. |
| </div> |
| |
| <div algorithm> |
| To <dfn>create a host function</dfn> from the JavaScript object |func| and type |functype|, perform the following steps: |
| |
| 1. Assert: [$IsCallable$](|func|). |
| 1. Let |stored settings| be the <a spec=HTML>incumbent settings object</a>. |
| 1. Let |hostfunc| be a [=host function=] which performs the following steps when called with arguments |arguments|: |
| 1. Let |realm| be |func|'s [=associated Realm=]. |
| 1. Let |relevant settings| be |realm|'s [=realm/settings object=]. |
| 1. [=Prepare to run script=] with |relevant settings|. |
| 1. [=Prepare to run a callback=] with |stored settings|. |
| 1. Let |result| be the result of [=run a host function|running a host function=] from |func|, |functype|, and |arguments|. |
| 1. [=Clean up after running a callback=] with |stored settings|. |
| 1. [=Clean up after running script=] with |relevant settings|. |
| 1. Assert: |result|.\[[Type]] is <emu-const>throw</emu-const> or <emu-const>normal</emu-const>. |
| 1. If |result|.\[[Type]] is <emu-const>throw</emu-const>, 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 by performing the following steps: |
| |
| 1. Assert: |w| is not of the form [=v128.const=] <var ignore>v128</var>. |
| 1. If |w| is of the form [=i64.const=] |i64|, |
| 1. Let |v| be [=signed_64=](|i64|). |
| 1. Return [=โค=](|v| interpreted as a mathematical value). |
| 1. If |w| is of the form [=i32.const=] |i32|, return [=๐ฝ=]([=signed_32=](|i32| interpreted as a mathematical value)). |
| 1. If |w| is of the form [=f32.const=] |f32|, |
| 1. If |f32| is [=+โ=] or [=โโ=], return **+โ**<sub>๐ฝ</sub> or **-โ**<sub>๐ฝ</sub>, respectively. |
| 1. If |f32| is [=nan=], return **NaN**. |
| 1. Return [=๐ฝ=](|f32| interpreted as a mathematical value). |
| 1. If |w| is of the form [=f64.const=] |f64|, |
| 1. If |f64| is [=+โ=] or [=โโ=], return **+โ**<sub>๐ฝ</sub> or **-โ**<sub>๐ฝ</sub>, respectively. |
| 1. If |f64| is [=nan=], return **NaN**. |
| 1. Return [=๐ฝ=](|f64| interpreted as a mathematical value). |
| 1. If |w| is of the form [=ref.null=] <var ignore>t</var>, return null. |
| 1. If |w| is of the form [=ref.func=] |funcaddr|, return the result of creating [=a new Exported Function=] from |funcaddr|. |
| 1. If |w| is of the form [=ref.extern=] |externaddr|, return the result of [=retrieving an extern value=] from |externaddr|. |
| |
| Note: Number values which are equal to NaN may have various observable NaN payloads; see [$NumericToRawBytes$] for details. |
| </div> |
| |
| <div algorithm> |
| |
| For <dfn>retrieving an extern value</dfn> from an [=extern address=] |externaddr|, perform the following steps: |
| |
| 1. Let |map| be the [=surrounding agent=]'s associated [=extern value cache=]. |
| 1. Assert: |map|[|externaddr|] [=map/exists=]. |
| 1. Return |map|[|externaddr|]. |
| |
| </div> |
| |
| <div algorithm> |
| The algorithm <dfn>ToWebAssemblyValue</dfn>(|v|, |type|) coerces a JavaScript value to a [=WebAssembly value=] by performing the following steps: |
| |
| 1. Assert: |type| is not [=v128=]. |
| 1. If |type| is [=i64=], |
| 1. Let |i64| be [=?=] [$ToBigInt64$](|v|). |
| 1. Return [=i64.const=] |i64|. |
| 1. If |type| is [=i32=], |
| 1. Let |i32| be [=?=] [$ToInt32$](|v|). |
| 1. Return [=i32.const=] |i32|. |
| 1. If |type| is [=f32=], |
| 1. Let |number| be [=?=] [$ToNumber$](|v|). |
| 1. If |number| is **NaN**, |
| 1. Let |n| be an implementation-defined integer such that [=canon=]<sub>32</sub> โค |n| < 2<sup>[=signif=](32)</sup>. |
| 1. Let |f32| be [=nan=](n). |
| 1. Otherwise, |
| 1. Let |f32| be |number| rounded to the nearest representable value using IEEE 754-2008 round to nearest, ties to even mode. [[IEEE-754]] |
| 1. Return [=f32.const=] |f32|. |
| 1. If |type| is [=f64=], |
| 1. Let |number| be [=?=] [$ToNumber$](|v|). |
| 1. If |number| is **NaN**, |
| 1. Let |n| be an implementation-defined integer such that [=canon=]<sub>64</sub> โค |n| < 2<sup>[=signif=](64)</sup>. |
| 1. Let |f64| be [=nan=](n). |
| 1. Otherwise, |
| 1. Let |f64| be |number|. |
| 1. Return [=f64.const=] |f64|. |
| 1. If |type| is [=funcref=], |
| 1. If |v| is null, |
| 1. Return [=ref.null=] [=funcref=]. |
| 1. If |v| is an [=Exported Function=], |
| 1. Let |funcaddr| be the value of |v|'s \[[FunctionAddress]] internal slot. |
| 1. Return [=ref.func=] |funcaddr|. |
| 1. Throw a {{TypeError}}. |
| 1. If |type| is [=externref=], |
| 1. If |v| is null, |
| 1. Return [=ref.null=] [=externref=]. |
| 1. Let |map| be the [=surrounding agent=]'s associated [=extern value cache=]. |
| 1. If a [=extern address=] |externaddr| exists such that |map|[|externaddr|] is the same as |v|, |
| 1. Return [=ref.extern=] |externaddr|. |
| 1. Let [=extern address=] |externaddr| be the smallest address such that |map|[|externaddr|] [=map/exists=] is false. |
| 1. [=map/Set=] |map|[|externaddr|] to |v|. |
| 1. Return [=ref.extern=] |externaddr|. |
| 1. Assert: This step is not reached. |
| |
| </div> |
| |
| <h3 id="error-objects">Error Objects</h3> |
| |
| WebAssembly defines the following Error classes: <dfn exception>CompileError</dfn>, <dfn exception>LinkError</dfn>, and <dfn exception>RuntimeError</dfn>. |
| |
| <div algorithm="create the WebAssembly namespace object"> |
| When the [=namespace object=] for the {{WebAssembly}} namespace is [=create a namespace object|created=], the following steps must be run: |
| |
| 1. Let |namespaceObject| be the [=namespace object=]. |
| 1. [=list/iterate|For each=] |error| of ยซ "CompileError", "LinkError", "RuntimeError" ยป, |
| 1. Let |constructor| be a new object, implementing the [=NativeError Object Structure=], with <var ignore>NativeError</var> set to |error|. |
| 1. [=!=] [$DefineMethodProperty$](|namespaceObject|, |error|, |constructor|, false). |
| |
| </div> |
| |
| Note: This defines {{CompileError}}, {{LinkError}}, and {{RuntimeError}} classes on the {{WebAssembly}} namespace, which are produced by the APIs defined in this specification. |
| They expose the same interface as native JavaScript errors like {{TypeError}} and {{RangeError}}. |
| |
| Note: It is not currently possible to define this behavior using Web IDL. |
| |
| |
| <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 one of the following 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 1,073,741,824 bytes (1 GiB).</li> |
| <li>The maximum number of types defined in the types section is 1,000,000.</li> |
| <li>The maximum number of functions defined in a module is 1,000,000.</li> |
| <li>The maximum number of imports declared in a module is 100,000.</li> |
| <li>The maximum number of exports declared in a module is 100,000.</li> |
| <li>The maximum number of globals defined in a module is 1,000,000.</li> |
| <li>The maximum number of data segments defined in a module is 100,000.</li> |
| |
| <li>The maximum number of tables, including declared or imported tables, is 100,000.</li> |
| <li>The maximum size of a table is 10,000,000.</li> |
| <li>The maximum number of table entries in any table initialization is 10,000,000.</li> |
| <li>The maximum number of memories, including declared or imported memories, is 1.</li> |
| |
| <li>The maximum number of parameters to any function or block is 1,000.</li> |
| <li>The maximum number of return values for any function or block is 1,000.</li> |
| <li>The maximum size of a function body, including locals declarations, is 7,654,321 bytes.</li> |
| <li>The maximum number of locals declared in a function, including implicitly declared as parameters, is 50,000.</li> |
| </ul> |
| |
| An implementation must throw a {{RuntimeError}} if one of the following limits is exceeded during runtime: |
| In practice, an implementation may run out of resources for valid modules below these limits. |
| |
| <ul> |
| <li>The maximum size of a table is 10,000,000.</li> |
| <li>The maximum number of pages of a memory is 65,536.</li> |
| </ul> |
| |
| <h2 id="security-considerations">Security and Privacy Considerations</h2> |
| |
| <p><em>This section is non-normative.</em></p> |
| |
| This document defines a host environment for WebAssembly. It enables a WebAssembly instance to [=import=] JavaScript objects and functions from an [=read the imports|import object=], but otherwise provides no access to the embedding environment. Thus a WebAssembly instance is bound to the same constraints as JavaScript. |
| |
| <h2 id="change-history">Change History</h2> |
| |
| <p><em>This section is non-normative.</em></p> |
| |
| <p>Since the original release 1.0 of the WebAssembly specification, a number of proposals for extensions have been integrated. |
| The following sections provide an overview of what has changed.</p> |
| |
| <h3 id="release-20">Release 2.0</h3> |
| |
| <h4 id="changes-multivalue" class="no-toc heading settled">Multiple Values</h4> |
| Multiple values can be returned from WebAssembly functions into JavaScript as an [=Array=] object. |
| |
| <h4 id="changes-bigint" class="no-toc heading settled">BigInt Integration</h4> |
| WebAssembly [=i64=] values can be passed to and from JavaScript (via imported or exported globals, table get or set operations, function return values or arguments) as [=BigInt=] objects. |
| |
| <h4 id="changes-reftypes" class="no-toc heading settled">Reference types</h4> |
| JavaScript values can be passed to and from WebAssembly (via imported or exported globals, table set or get operations, and function arguments or return values) as [=externref=] values. |
| Multiple tables can be exported and imported to and from JavaScript. |