| <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 | |
| Editor: Ryan Hunt, w3cid 112030, Mozilla Foundation | |
| 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/web-api/", | |
| "title": "WebAssembly Web API Specification", | |
| "publisher": "W3C WebAssembly Community Group", | |
| "status": "Draft" | |
| } | |
| } | |
| </pre> | |
| <pre class="anchors"> | |
| urlPrefix: https://tc39.es/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-string-object | |
| text: String | |
| url: sec-returnifabrupt-shorthands | |
| text: ! | |
| text: ? | |
| url: sec-ecmascript-language-types-bigint-type | |
| text: is a BigInt | |
| text: is not a BigInt | |
| url: sec-ecmascript-language-types-boolean-type | |
| text: is a Boolean | |
| text: is not a Boolean | |
| url: sec-ecmascript-language-types-number-type | |
| text: is a Number | |
| text: is not a Number | |
| url: sec-ecmascript-language-types-string-type | |
| text: is a String | |
| text: is not a String | |
| url: sec-ecmascript-language-types-symbol-type | |
| text: is a Symbol | |
| text: is not a Symbol | |
| url: sec-object-type | |
| text: is an Object | |
| text: is not an Object | |
| text: current Realm; url: current-realm | |
| text: CreateBuiltinFunction; url: sec-createbuiltinfunction | |
| text: the Number value; url: sec-ecmascript-language-types-number-type | |
| text: is a Number; url: sec-ecmascript-language-types-number-type | |
| text: is a BigInt; url: sec-ecmascript-language-types-bigint-type | |
| text: Built-in Function Objects; url: sec-built-in-function-objects | |
| text: NativeError Object Structure; url: sec-nativeerror-object-structure | |
| text: CreateArrayFromList; url: sec-createarrayfromlist | |
| text: GetMethod; url: sec-getmethod | |
| text: IterableToList; url: sec-iterabletolist | |
| text: ToBigInt64; url: #sec-tobigint64 | |
| text: BigInt; url: #sec-ecmascript-language-types-bigint-type | |
| text: MakeBasicObject; url: #sec-makebasicobject | |
| text: ℝ; url: #ℝ | |
| text: 𝔽; url: #𝔽 | |
| text: ℤ; url: #ℤ | |
| text: mathematical value; url: #mathematical-value | |
| text: SameValue; url: sec-samevalue | |
| text: IsStrictlyEqual; url: sec-isstrictlyequal | |
| text: IsLessThan; url: sec-islessthan | |
| text: String.fromCharCode; url: sec-string.fromcharcode | |
| text: String.fromCodePoint; url: sec-string.fromcodepoint | |
| text: String.prototype.charCodeAt; url: sec-string.prototype.charcodeat | |
| text: String.prototype.codePointAt; url: sec-string.prototype.codepointat | |
| text: String.prototype.concat; url: sec-string.prototype.concat | |
| text: String.prototype.substring; url: sec-string.prototype.substring | |
| 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: appendix/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 | |
| urlPrefix: valid/matching.html; for: matches | |
| text: valtype; url: #match-valtype | |
| text: reftype; url: #match-reftype | |
| 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.i31 | |
| text: ref.array | |
| text: ref.struct | |
| text: ref.func | |
| text: ref.host | |
| text: ref.extern | |
| text: ref.exn | |
| 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: ref_type; url: appendix/embedding.html#embed-ref-type | |
| text: val_default; url: appendix/embedding.html#embed-val-default | |
| text: match_valtype; url: appendix/embedding.html#embed-match-valtype | |
| text: match_externtype; url: appendix/embedding.html#embed-match-externtype | |
| text: error; url: appendix/embedding.html#embed-error | |
| text: exception; url: appendix/embedding.html#embed-error | |
| text: store; url: exec/runtime.html#syntax-store | |
| text: address type; url: syntax/types.html#syntax-addrtype | |
| 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: tag address; url: exec/runtime.html#syntax-tagaddr | |
| text: tag type; url: syntax/types.html#syntax-tagtype | |
| text: struct address; url: exec/runtime.html#syntax-structaddr | |
| text: array address; url: exec/runtime.html#syntax-arrayaddr | |
| text: exception address; url: exec/runtime.html#syntax-exnaddr | |
| text: host address; url: exec/runtime.html#syntax-hostaddr | |
| text: extern address; url: exec/runtime.html#syntax-externaddr | |
| text: page size; url: exec/runtime.html#page-size | |
| text: tag_alloc; url: appendix/embedding.html#embed-tag-alloc | |
| text: tag_type; url: appendix/embedding.html#embed-tag-type | |
| text: exn_alloc; url: appendix/embedding.html#embed-exn-alloc | |
| text: exn_tag; url: appendix/embedding.html#embed-exn-tag | |
| text: exn_read; url: appendix/embedding.html#embed-exn-read | |
| url: syntax/values.html#syntax-int | |
| text: u32 | |
| text: u64 | |
| 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: exnref | |
| text: externref | |
| text: ref | |
| url: syntax/types.html#heap-types; for: heap-type | |
| text: extern | |
| text: func | |
| text: i31 | |
| text: any | |
| 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 | |
| url: exec/runtime.html#syntax-externval | |
| text: external value | |
| for: external value | |
| text: func | |
| text: table | |
| text: mem | |
| text: global | |
| text: tag | |
| 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; for: external-type | |
| text: external type | |
| text: func | |
| text: table | |
| text: mem | |
| text: global | |
| for: externtype | |
| text: tag | |
| text: global type; url: syntax/types.html#syntax-globaltype | |
| url: syntax/types.html#syntax-mut | |
| text: mut | |
| url: syntax/types.html#syntax-comptype; for: comp-type | |
| text: func | |
| text: defined type; url: valid/conventions.html#syntax-deftype | |
| text: expansion; url: valid/conventions.html#aux-expand-deftype | |
| text: address; url: exec/runtime.html#addresses | |
| text: signed_31; url: exec/numerics.html#aux-signed | |
| text: signed_32; url: exec/numerics.html#aux-signed | |
| text: memory.grow; url: exec/instructions.html#exec-memory-grow | |
| text: throw_ref; url: exec/instructions.html#exec-throw-ref | |
| 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 | |
| text: exception; for: tagtype/attribute; url: syntax/types.html#syntax-tagtype | |
| urlPrefix: https://webidl.spec.whatwg.org/; spec: WebIDL | |
| type: dfn | |
| text: create a namespace object; url: create-a-namespace-object | |
| text: [EnforceRange]; url: #EnforceRange | |
| text: unsigned long; url: #idl-unsigned-long | |
| text: js-unsigned-long; url: #js-unsigned-long | |
| text: converted to a JavaScript value; url: #dfn-convert-idl-to-javascript-value | |
| urlPrefix: https://webassembly.github.io/js-types/js-api/; spec: WebAssembly JS API (JS Type Reflection) | |
| type: abstract-op; text: FromValueType; url: abstract-opdef-fromvaluetype | |
| 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>Exported GC Object cache</dfn>, mapping [=struct address=]es and [=array address=]es to [=Exported GC Object=] objects. | |
| * The <dfn>Global object cache</dfn>, mapping [=global address=]es to {{Global}} objects. | |
| * The <dfn>Tag object cache</dfn>, mapping [=tag address=]es to {{Tag}} objects. | |
| * The <dfn>Exception object cache</dfn>, mapping [=exception address=]es to {{Exception}} objects. | |
| * The <dfn>Host value cache</dfn>, mapping [=host address=]es to values. | |
| <h2 id="webassembly-namespace">The WebAssembly Namespace</h2> | |
| <pre class="idl"> | |
| dictionary WebAssemblyInstantiatedSource { | |
| required Module module; | |
| required Instance instance; | |
| }; | |
| dictionary WebAssemblyCompileOptions { | |
| USVString? importedStringConstants = null; | |
| sequence<USVString> builtins = []; | |
| }; | |
| [Exposed=*] | |
| namespace WebAssembly { | |
| boolean validate([AllowResizable] AllowSharedBufferSource bytes, optional WebAssemblyCompileOptions options = {}); | |
| Promise<Module> compile([AllowResizable] AllowSharedBufferSource bytes, optional WebAssemblyCompileOptions options = {}); | |
| Promise<WebAssemblyInstantiatedSource> instantiate( | |
| [AllowResizable] AllowSharedBufferSource bytes, optional object importObject, optional WebAssemblyCompileOptions options = {}); | |
| Promise<Instance> instantiate( | |
| Module moduleObject, optional object importObject); | |
| readonly attribute Tag JSTag; | |
| }; | |
| </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> | |
| To <dfn>validate builtins and imported string for a WebAssembly module</dfn> from module |module|, enabled builtins |builtinSetNames|, and |importedStringModule|, perform the following steps: | |
| 1. If [=validate builtin set names|validating builtin set names=] for |builtinSetNames| is false, return false. | |
| 1. [=list/iterate|For each=] |import| of [=module_imports=](|module|), | |
| 1. If |importedStringModule| is not null and |import|[0] equals |importedStringModule|, | |
| 1. Let |importExternType| be |import|[2]. | |
| 1. Let |stringExternType| be [=external-type/global=] [=ref=] [=heap-type/extern=]. | |
| 1. If [=match_externtype=](|stringExternType|, |importExternType|) is false, return false | |
| 1. Else, | |
| 1. If [=validate an import for builtins|validating an import for builtins=] with |import| and |builtinSetNames| is false, return false. | |
| 1. Return true. | |
| </div> | |
| <div algorithm> | |
| The <dfn method for="WebAssembly">validate(|bytes|, |options|)</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. Let |builtinSetNames| be |options|["builtins"]. | |
| 1. Let |importedStringModule| be |options|["importedStringConstants"]. | |
| 1. If [=validate builtins and imported string for a WebAssembly module|validating builtins and imported strings=] for |module| with |builtinSetNames| and |importedStringModule| returns false, 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]]. | |
| * \[[BuiltinSets]] : an ordered set of names of <a href="#builtins">builtin sets</a> | |
| * \[[ImportedStringModule]] : an optional module specifier string where any string constant can be imported from. | |
| <div algorithm> | |
| To <dfn>construct a WebAssembly module object</dfn> from a module |module|, source bytes |bytes|, enabled builtins |builtinSetNames|, and |importedStringModule|, perform the following steps: | |
| 1. Let |moduleObject| be a [=/new=] {{Module}}. | |
| 1. Set |moduleObject|.\[[Module]] to |module|. | |
| 1. Set |moduleObject|.\[[Bytes]] to |bytes|. | |
| 1. Set |moduleObject|.\[[BuiltinSets]] to |builtinSetNames|. | |
| 1. Set |moduleObject|.\[[ImportedStringModule]] to |importedStringModule|. | |
| 1. Return |moduleObject|. | |
| </div> | |
| <div algorithm> | |
| To <dfn>asynchronously compile a WebAssembly module</dfn> from source bytes |bytes| and {{WebAssemblyCompileOptions}} |options| 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=] on |taskSource|, if provided, to perform the following steps: | |
| 1. If |module| is [=error=], [=reject=] |promise| with a {{CompileError}} exception and return. | |
| 1. Let |builtinSetNames| be |options|["builtins"]. | |
| 1. Let |importedStringModule| be |options|["importedStringConstants"]. | |
| 1. If [=validate builtins and imported string for a WebAssembly module|validating builtins and imported strings=] for |module| with |builtinSetNames| and |importedStringModule| is false, [=reject=] |promise| with a {{CompileError}} exception. | |
| 1. Otherwise, | |
| 1. [=Construct a WebAssembly module object=] from |module|, |bytes|, |builtinSetNames|, |importedStringModule|, and let |moduleObject| be the result. | |
| 1. [=Resolve=] |promise| with |moduleObject|. | |
| 1. Return |promise|. | |
| </div> | |
| <div algorithm> | |
| The <dfn method for="WebAssembly">compile(|bytes|, |options|)</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| using |options| and return the result. | |
| </div> | |
| <div algorithm> | |
| To <dfn>instantiate imported strings</dfn> with module |module| and |importedStringModule|, perform the following steps: | |
| 1. Assert: |importedStringModule| is not null. | |
| 1. Let |exportsObject| be [$OrdinaryObjectCreate$](null). | |
| 1. [=list/iterate|For each=] (|moduleName|, |componentName|, |externtype|) of [=module_imports=](|module|), | |
| 1. If |moduleName| does not equal |importedStringModule|, then [=iteration/continue=]. | |
| 1. Let |stringConstant| be |componentName|. | |
| 1. Let |status| be [=!=] [$CreateDataProperty$](|exportsObject|, |stringConstant|, |stringConstant|). | |
| 1. Assert: |status| is true. | |
| 1. Return |exportsObject|. | |
| </div> | |
| <div algorithm="read-the-imports"> | |
| To <dfn>read the imports</dfn> from a WebAssembly module |module| from imports object |importObject|, enabled builtins |builtinSetNames|, and |importedStringModule|, perform the following steps: | |
| 1. If [=module_imports=](|module|) [=list/is empty|is not empty=], and |importObject| is missing, throw a {{TypeError}} exception. | |
| 1. Let |builtinOrStringImports| be the ordered map «[ ]». | |
| 1. [=list/iterate|For each=] |builtinSetName| of |builtinSetNames|, | |
| 1. Let |builtinSetQualifiedName| be |builtinSetName| prefixed with "wasm:" | |
| 1. Assert: |builtinOrStringImports| does not contain |builtinSetQualifiedName| | |
| 1. If |builtinSetName| does not refer to a builtin set, then [=iteration/continue=]. | |
| 1. Let |exportsObject| be the result of [=instantiate a builtin set=] with |builtinSetName| | |
| 1. [=map/set|Set=] |builtinOrStringImports|[|builtinSetQualifiedName|] to |exportsObject| | |
| 1. If |importedStringModule| is not null, | |
| 1. Let |exportsObject| be the result of [=instantiate imported strings=] with |module| and |importedStringModule| | |
| 1. [=map/set|Set=] |builtinOrStringImports|[|importedStringModule|] to |exportsObject| | |
| 1. Let |imports| be « ». | |
| 1. [=list/iterate|For each=] (|moduleName|, |componentName|, |externtype|) of [=module_imports=](|module|), | |
| 1. If |builtinOrStringImports|[|moduleName|] [=map/exists=], | |
| 1. Let |o| be |builtinOrStringImports|[|moduleName|]. | |
| 1. If |o| [=is not an Object=] or if [=?=] [$HasProperty$](|o|, |componentName|) is false, | |
| 1. Set |o| to [=?=] [$Get$](|importObject|, |moduleName|). | |
| 1. Else, | |
| 1. Let |o| be [=?=] [$Get$](|importObject|, |moduleName|). | |
| 1. If |o| [=is not an Object=], throw a {{TypeError}} exception. | |
| 1. Let |v| be [=?=] [$Get$](|o|, |componentName|). | |
| 1. If |externtype| is of the form [=external-type/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 [=external-type/global=] <var ignore>mut</var> |valtype|, | |
| 1. If |v| [=implements=] {{Global}}, | |
| 1. Let |globaladdr| be |v|.\[[Global]]. | |
| 1. Otherwise, | |
| 1. If |valtype| is [=i64=] and |v| [=is not a BigInt=], | |
| 1. Throw a {{LinkError}} exception. | |
| 1. If |valtype| is one of [=i32=], [=f32=] or [=f64=] and |v| [=is not a Number=], | |
| 1. Throw a {{LinkError}} exception. | |
| 1. If |valtype| is [=v128=], | |
| 1. Throw a {{LinkError}} exception. | |
| 1. Let |value| be [=ToWebAssemblyValue=](|v|, |valtype|). If this operation throws a {{TypeError}}, catch it, and throw a {{LinkError}} exception. | |
| 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. | |
| 1. Let (|store|, |globaladdr|) be [=global_alloc=](|store|, |valtype|, |value|). | |
| 1. Set the [=surrounding agent=]'s [=associated store=] to |store|. | |
| 1. Let |externglobal| be [=external value/global=] |globaladdr|. | |
| 1. [=list/Append=] |externglobal| to |imports|. | |
| 1. If |externtype| is of the form [=external-type/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 [=external-type/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. If |externtype| is of the form [=external-type/tag=] <var ignore>functype</var>, | |
| 1. If |v| does not [=implement=] {{Tag}}, throw a {{LinkError}} exception. | |
| 1. Let |tagaddr| be |v|.\[[Address]]. | |
| 1. Let |externtag| be the [=external value=] [=external value/tag=] |tagaddr|. | |
| 1. [=list/Append=] |externtag| 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 [=external-type/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 [=external-type/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 [=external-type/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 [=external-type/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. If |externtype| is of the form [=external-type/tag=] <var ignore>functype</var>, | |
| 1. Assert: |externval| is of the form [=external value/tag=] |tagaddr|. | |
| 1. Let [=external value/tag=] |tagaddr| be |externval|. | |
| 1. Let |tag| be [=create a Tag object|a new Tag object=] created from |tagaddr|. | |
| 1. Let |value| be |tag|. | |
| 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 (|store|, |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. Set the [=surrounding agent=]'s [=associated store=] to |store|. | |
| 1. Return |result|. | |
| </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. Let |builtinSetNames| be |moduleObject|.\[[BuiltinSets]]. | |
| 1. Let |importedStringModule| be |moduleObject|.\[[ImportedStringModule]]. | |
| 1. [=Read the imports=] of |module| with imports |importObject|, |builtinSetNames| and |importedStringModule|, 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|, |options|)</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| using |options| 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>. | |
| <div algorithm> | |
| The getter of the <dfn attribute for="WebAssembly">JSTag</dfn> attribute of the {{WebAssembly}} Namespace, when invoked, performs the following steps: | |
| 1. Let |JSTagAddr| be the result of [=get the JavaScript exception tag|getting the JavaScript exception tag=]. | |
| 1. Let |JSTagObject| be the result of [=create a Tag object|creating a Tag object=] from |JSTagAddr|. | |
| 1. Return |JSTagObject|. | |
| </div> | |
| <h3 id="modules">Modules</h3> | |
| <pre class="idl"> | |
| enum ImportExportKind { | |
| "function", | |
| "table", | |
| "memory", | |
| "global", | |
| "tag" | |
| }; | |
| enum AddressType { | |
| "i32", | |
| "i64", | |
| }; | |
| typedef any AddressValue; | |
| 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([AllowResizable] AllowSharedBufferSource bytes, optional WebAssemblyCompileOptions options = {}); | |
| 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 [=external-type/func=] <var ignore>functype</var> | |
| * "table" if |type| is of the form [=external-type/table=] <var ignore>tabletype</var> | |
| * "memory" if |type| is of the form [=external-type/mem=] <var ignore>memtype</var> | |
| * "global" if |type| is of the form [=external-type/global=] <var ignore>globaltype</var> | |
| * "tag" if |type| is of the form [=external-type/tag=] <var ignore>tag</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 |builtinSetNames| be |moduleObject|.\[[BuiltinSets]]. | |
| 1. Let |importedStringModule| be |moduleObject|.\[[ImportedStringModule]]. | |
| 1. Let |imports| be « ». | |
| 1. [=list/iterate|For each=] (|moduleName|, |name|, |type|) of [=module_imports=](|module|), | |
| 1. If [=find a builtin=] for (|moduleName|, |name|, |type|) and |builtinSetNames| is not null, then [=iteration/continue=]. | |
| 1. If |importedStringModule| is not null and |moduleName| equals |importedStringModule|, then [=iteration/continue=]. | |
| 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|, |options|)</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. Let |builtinSetNames| be |options|["builtins"]. | |
| 1. Let |importedStringModule| be |options|["importedStringConstants"]. | |
| 1. If [=validate builtins and imported string for a WebAssembly module|validating builtins and imported strings=] for |module| with |builtinSetNames| and |importedStringModule| returns false, throw a {{CompileError}} exception. | |
| 1. Set **this**.\[[Module]] to |module|. | |
| 1. Set **this**.\[[Bytes]] to |stableBytes|. | |
| 1. Set **this**.\[[BuiltinSets]] to |builtinSetNames|. | |
| 1. Set **this**.\[[ImportedStringModule]] to |importedStringModule|. | |
| 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(|moduleObject|, |importObject|)</dfn> constructor, when invoked, runs the following steps: | |
| 1. Let |builtinSetNames| be |moduleObject|.\[[BuiltinSets]]. | |
| 1. Let |importedStringModule| be |moduleObject|.\[[ImportedStringModule]]. | |
| 1. Let |module| be |moduleObject|.\[[Module]]. | |
| 1. [=Read the imports=] of |module| with imports |importObject|, |builtinSetNames|, and |importedStringModule|, 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 AddressValue initial; | |
| AddressValue maximum; | |
| AddressType address; | |
| }; | |
| [LegacyNamespace=WebAssembly, Exposed=*] | |
| interface Memory { | |
| constructor(MemoryDescriptor descriptor); | |
| AddressValue grow(AddressValue 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. 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]] to |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. If |descriptor|["address"] [=map/exists=], let |addrtype| be [=ToValueType=](|descriptor|["address"]); otherwise, let |addrtype| be [=i32=]. | |
| 1. Let |initial| be [=?=] [=AddressValueToU64=](|descriptor|["initial"], |addrtype|). | |
| 1. If |descriptor|["maximum"] [=map/exists=], let |maximum| be [=?=] [=AddressValueToU64=](|descriptor|["maximum"], |addrtype|); otherwise, let |maximum| be empty. | |
| 1. Let |memtype| be the [=memory type=] |addrtype| [|initial| .. |maximum|] page. | |
| 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 [=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. Let |store| be the [=surrounding agent=]'s [=associated store=]. | |
| 1. Let (|addrtype|, <var ignore>limits</var>) be [=mem_type=](|store|, |memaddr|). | |
| 1. Let |delta64| be [=?=] [=AddressValueToU64=](|delta|, |addrtype|). | |
| 1. Let |ret| be the result of [=grow the memory buffer|growing the memory buffer=] associated with |memaddr| by |delta64|. | |
| 1. Return [=U64ToAddressValue=](|ret|, |addrtype|). | |
| </div> | |
| Immediately after a WebAssembly [=memory.grow=] |x| instruction executes, perform the following steps: | |
| <div algorithm="memory.grow"> | |
| 1. If the top of the stack is not [=i32.const=] (−1) and the top of the stack is not [=i64.const=] (−1), | |
| 1. Let |frame| be the [=current frame=]. | |
| 1. Assert: due to validation, |frame|.[=frame/module=].[=moduleinst/memaddrs=][|x|] exists. | |
| 1. Let |memaddr| be the [=memory address=] |frame|.[=frame/module=].[=moduleinst/memaddrs=][|x|]. | |
| 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 |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| does not have a max, | |
| 1. [=Throw=] a {{TypeError}} exception. | |
| 1. Let |buffer| be **this**.\[[BufferObject]]. | |
| 1. If [=IsFixedLengthArrayBuffer=](|buffer|) is false, return |buffer|. | |
| 1. Assert: |memtype| has a max. | |
| 1. Let |maxsize| be the max value in |memtype| * 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 AddressValue initial; | |
| AddressValue maximum; | |
| AddressType address; | |
| }; | |
| [LegacyNamespace=WebAssembly, Exposed=*] | |
| interface Table { | |
| constructor(TableDescriptor descriptor, optional any value); | |
| AddressValue grow(AddressValue delta, optional any value); | |
| any get(AddressValue index); | |
| undefined set(AddressValue index, optional any value); | |
| readonly attribute AddressValue 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. If |descriptor|["address"] [=map/exists=], let |addrtype| be [=ToValueType=](|descriptor|["address"]); otherwise, let |addrtype| be [=i32=]. | |
| 1. Let |initial| be [=?=] [=AddressValueToU64=](|descriptor|["initial"], |addrtype|). | |
| 1. If |descriptor|["maximum"] [=map/exists=], let |maximum| be [=?=] [=AddressValueToU64=](|descriptor|["maximum"], |addrtype|); otherwise, let |maximum| be empty. | |
| 1. Let |type| be the [=table type=] |addrtype| [|initial| .. |maximum|] |elementtype|. | |
| 1. If |type| is not [=valid tabletype|valid=], throw a {{RangeError}} exception. | |
| 1. If |value| is missing, | |
| 1. Let |ref| be [=DefaultValue=](|elementtype|). | |
| 1. Assert: |ref| is not [=error=]. | |
| 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 (|addrtype|, <var ignore>limits</var>, |elementtype|) be [=table_type=](|store|, |tableaddr|). | |
| 1. Let |delta64| be [=?=] [=AddressValueToU64=](|delta|, |addrtype|). | |
| 1. If |value| is missing, | |
| 1. Let |ref| be [=DefaultValue=](|elementtype|). | |
| 1. If |ref| is [=error=], throw a {{TypeError}} exception. | |
| 1. Otherwise, | |
| 1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementtype|). | |
| 1. Let |result| be [=table_grow=](|store|, |tableaddr|, |delta64|, |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 [=U64ToAddressValue=](|initialSize|, |addrtype|). | |
| </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. Let (|addrtype|, <var ignore>limits</var>, <var ignore>elementtype</var>) be [=table_type=](|store|, |tableaddr|). | |
| 1. Let |length64| be [=table_size=](|store|, |tableaddr|). | |
| 1. Return [=U64ToAddressValue=](|length64|, |addrtype|). | |
| </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 (|addrtype|, <var ignore>limits</var>, |elementtype|) be [=table_type=](|store|, |tableaddr|). | |
| 1. If |elementtype| [=matches/reftype|matches=] [=exnref=], | |
| 1. Throw a {{TypeError}} exception. | |
| 1. Let |index64| be [=?=] [=AddressValueToU64=](|index|, |addrtype|). | |
| 1. Let |result| be [=table_read=](|store|, |tableaddr|, |index64|). | |
| 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 |store| be the [=surrounding agent=]'s [=associated store=]. | |
| 1. Let (|addrtype|, <var ignore>limits</var>, |elementtype|) be [=table_type=](|store|, |tableaddr|). | |
| 1. If |elementtype| [=matches/reftype|matches=] [=exnref=], | |
| 1. Throw a {{TypeError}} exception. | |
| 1. Let |index64| be [=?=] [=AddressValueToU64=](|index|, |addrtype|). | |
| 1. If |value| is missing, | |
| 1. Let |ref| be [=DefaultValue=](|elementtype|). | |
| 1. If |ref| is [=error=], throw a {{TypeError}} exception. | |
| 1. Otherwise, | |
| 1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementtype|). | |
| 1. Let |store| be [=table_write=](|store|, |tableaddr|, |index64|, |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 [=externref=], return [=!=] [=ToWebAssemblyValue=](undefined, |valuetype|). | |
| 1. Return [=val_default=](|valuetype|). | |
| </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| [=matches/valtype|matches=] [=v128=] or [=exnref=], | |
| 1. Throw a {{TypeError}} exception. | |
| 1. If |v| is missing, | |
| 1. Let |value| be [=DefaultValue=](|valuetype|). | |
| 1. Assert: |value| is not [=error=]. | |
| 1. Otherwise, | |
| 1. Let |value| be [=?=] [=ToWebAssemblyValue=](|v|, |valuetype|). | |
| 1. If |mutable| is true, let |globaltype| be [=mut=] |valuetype|; otherwise, let |globaltype| be |valuetype|. | |
| 1. Let |store| be the [=surrounding 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 [=surrounding 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 [=surrounding 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> |valuetype| where |valuetype| [=matches/valtype|matches=] [=v128=] or [=exnref=], throw a {{TypeError}}. | |
| 1. Let |value| be [=global_read=](|store|, |globaladdr|). | |
| 1. Return [=ToJSValue=](|value|). | |
| </div> | |
| <div algorithm="Global value getter"> | |
| The getter of the <dfn attribute for="Global">value</dfn> attribute of {{Global}}, when invoked, performs the following steps: | |
| 1. Return [=GetGlobalValue=](**this**). | |
| </div> | |
| <div algorithm="Global value setter"> | |
| The setter of the value attribute of {{Global}}, when invoked, performs the following steps: | |
| 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. | |
| 1. Let |globaladdr| be **this**.\[[Global]]. | |
| 1. Let |mut| |valuetype| be [=global_type=](|store|, |globaladdr|). | |
| 1. If |valuetype| [=matches/valtype|matches=] [=v128=] or [=exnref=], throw a {{TypeError}}. | |
| 1. If |mut| is empty, 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 [=surrounding 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|.funcs. | |
| 1. Let |index| be the index of |moduleinst|.funcs 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 [=comp-type/func=] |paramTypes| → <var ignore>resultTypes</var> be the [=expansion=] of |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 [=comp-type/func=] |parameters| → |results| be the [=expansion=] of |functype|. | |
| 1. If any type in |parameters| or |results| [=matches/valtype|matches=] [=v128=] or [=exnref=], 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. If |ret| is of the form [=/exception=] |exnaddr|, then | |
| 1. Let |tagaddr| be [=exn_tag=](|store|, |exnaddr|). | |
| 1. Let |payload| be [=exn_read=](|store|, |exnaddr|). | |
| 1. Let |jsTagAddr| be the result of [=get the JavaScript exception tag|getting the JavaScript exception tag=]. | |
| 1. If |tagaddr| is equal to |jsTagAddr|, | |
| 1. Throw [=ToJSValue=](|payload|[0]). | |
| 1. Otherwise, | |
| 1. Let |exception| be [=create an Exception object|a new Exception=] created from |exnaddr|. | |
| 1. Throw |exception|. | |
| 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 [=comp-type/func=] |parameters| → |results| be the [=expansion=] of |functype|. | |
| 1. If any type in |parameters| or |results| [=matches/valtype|matches=] [=v128=] or [=exnref=], 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. Let |store| be the [=surrounding agent=]'s [=associated store=]. | |
| 1. If |result|.\[[Type]] is <emu-const>throw</emu-const>, then: | |
| 1. Let |v| be |result|.\[[Value]]. | |
| 1. If |v| [=implements=] {{Exception}}, | |
| 1. Let |address| be |v|.\[[Address]]. | |
| 1. Otherwise, | |
| 1. Let |type| be the result of [=get the JavaScript exception tag|getting the JavaScript exception tag=]. | |
| 1. Let |payload| be [=!=] [=ToWebAssemblyValue=](|v|, [=externref=]). | |
| 1. Let (|store|, |address|) be [=exn_alloc=](|store|, |type|, « |payload| »). | |
| 1. Set the [=surrounding agent=]'s [=associated store=] to |store|. | |
| 1. Execute the WebAssembly instructions ([=ref.exn=] |address|) ([=throw_ref=]). | |
| 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. Assert: |w| is not of the form [=ref.exn=] <var ignore>exnaddr</var>. | |
| 1. If |w| is of the form [=i64.const=] |u64|, | |
| 1. Let |i64| be [=signed_64=](|u64|). | |
| 1. Return [=ℤ=](|i64| interpreted as a [=mathematical value=]). | |
| 1. If |w| is of the form [=i32.const=] |u32|, | |
| 1. Let |i32| be [=signed_32=](|u32|). | |
| 1. Return [=𝔽=](|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=], return null. | |
| 1. If |w| is of the form [=ref.i31=] |u31|, | |
| 1. Let |i31| be [=signed_31=](|u31|). | |
| 1. Return [=𝔽=](|i31| interpreted as a [=mathematical value=]). | |
| 1. If |w| is of the form [=ref.struct=] |structaddr|, return the result of creating [=a new Exported GC Object=] from |structaddr| and "struct". | |
| 1. If |w| is of the form [=ref.array=] |arrayaddr|, return the result of creating [=a new Exported GC Object=] from |arrayaddr| and "array". | |
| 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.host=] |hostaddr|, return the result of [=retrieving a host value=] from |hostaddr|. | |
| 1. If |w| is of the form [=ref.extern=] |ref|, return [=ToJSValue=](|ref|). | |
| Note: Number values which are equal to NaN may have various observable NaN payloads; see [$NumericToRawBytes$] for details. | |
| </div> | |
| <div algorithm> | |
| For <dfn>retrieving a host value</dfn> from an [=host address=] |hostaddr|, perform the following steps: | |
| 1. Let |map| be the [=surrounding agent=]'s associated [=host value cache=]. | |
| 1. Assert: |map|[|hostaddr|] [=map/exists=]. | |
| 1. Return |map|[|hostaddr|]. | |
| </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. Assert: |type| does not [=matches/valtype|match=] [=exnref=]. | |
| 1. If |type| is [=i64=], | |
| 1. Let |i64| be [=?=] [$ToBigInt64$](|v|). | |
| 1. Let |u64| be the unsigned integer such that |i64| is [=signed_64=](|u64|). | |
| 1. Return [=i64.const=] |u64|. | |
| 1. If |type| is [=i32=], | |
| 1. Let |i32| be [=?=] [$ToInt32$](|v|). | |
| 1. Let |u32| be the unsigned integer such that |i32| is [=signed_32=](|u32|). | |
| 1. Return [=i32.const=] |u32|. | |
| 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-2019 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 of the form [=ref=] |null| <var ignore>heaptype</var>, | |
| 1. If |v| is null, | |
| 1. Let |r| be [=ref.null=]. | |
| 1. Else if [=match_valtype=](|type|, [=ref=] |null| [=heap-type/extern=]) is true, | |
| 1. Let |ref| be [=!=] [=ToWebAssemblyValue=](|v|, [=ref=] [=heap-type/any=]). | |
| 1. Let |r| be [=ref.extern=] |ref|. | |
| 1. Else if |v| is an [=Exported Function=] and [=match_valtype=](|type|, [=ref=] |null| [=heap-type/func=]) is true, | |
| 1. Let |funcaddr| be the value of |v|'s \[[FunctionAddress]] internal slot. | |
| 1. Let |r| be [=ref.func=] |funcaddr|. | |
| 1. Else if |v| [=is a Number=] and |v| is equal to [=?=] [$ToInt32$](|v|) and [=ℝ=](|v|) < 2<sup>30</sup> and [=ℝ=](|v|) ⩾ -2<sup>30</sup>, | |
| 1. Let |i31| be [=?=] [$ToInt32$](|v|). | |
| 1. Let |u31| be the unsigned integer such that |i31| is [=signed_31=](|u31|). | |
| 1. Let |r| be [=ref.i31=] |u31|. | |
| 1. Else if |v| is an [=Exported GC Object=], | |
| 1. Let |objectaddr| be the value of |v|'s \[[ObjectAddress]] internal slot. | |
| 1. Let |objectkind| be the value of |v|'s \[[ObjectKind]] internal slot. | |
| 1. If |objectkind| is "array", | |
| 1. Let |r| be [=ref.array=] |objectaddr|. | |
| 1. Else if |objectkind| is "struct", | |
| 1. Let |r| be [=ref.struct=] |objectaddr|. | |
| 1. Else, | |
| 1. Let |map| be the [=surrounding agent=]'s associated [=host value cache=]. | |
| 1. If a [=host address=] |hostaddr| exists such that |map|[|hostaddr|] is the same as |v|, | |
| 1. Return [=ref.host=] |hostaddr|. | |
| 1. Let |hostaddr| be the smallest [=host address=] such that |map|[|hostaddr|] [=map/exists=] is false. | |
| 1. [=map/Set=] |map|[|hostaddr|] to |v|. | |
| 1. Let |r| be [=ref.host=] |hostaddr|. | |
| 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. | |
| 1. Let |actualtype| be [=ref_type=](|store|, |r|). | |
| 1. If [=match_valtype=](|actualtype|, |type|) is false, | |
| 1. Throw a {{TypeError}}. | |
| 1. Return |r|. | |
| 1. Assert: This step is not reached. | |
| </div> | |
| <div algorithm> | |
| The algorithm <dfn>AddressValueToU64</dfn>(|v|, |addrtype|) converts an IDL value to a WebAssembly [=u64=] for use in embedding operations. It is designed to act like [=[EnforceRange]=] [=unsigned long=] for {{AddressType}} "i32", and to extend these semantics to {{AddressType}} "i64", by performing the following steps: | |
| 1. Let |jsValue| be |v|, [=converted to a JavaScript value=]. | |
| Note: The IDL `any` type is a discriminated union, not a transparent wrapper around a JavaScript value. | |
| 1. If |addrtype| is [=i32=], | |
| 1. Let |n| be [=?=] [$ConvertToInt$](|jsValue|, 32, "unsigned"), where the destination type is associated with [=[EnforceRange]=]. | |
| Note: This is equivalent to the [=js-unsigned-long|JS conversion rules=] for [=[EnforceRange]=] [=unsigned long=]. | |
| 1. Return [=ℝ=](|n|) as a WebAssembly [=u64=]. | |
| 1. If |addrtype| is [=i64=], | |
| 1. Let |n| be [=?=] [$ToBigInt$](|jsValue|). | |
| 1. Let |r| be [=ℝ=](|n|). | |
| 1. If |r| < 0 or |r| > 2<sup>64</sup> − 1, [=throw=] a {{TypeError}}. | |
| Note: This operation is designed to emulate [=[EnforceRange]=]. | |
| 1. Return |r| as a WebAssembly [=u64=]. | |
| 1. Assert: This step is not reached. | |
| </div> | |
| <div algorithm> | |
| The algorithm <dfn>U64ToAddressValue</dfn>(|v|, |addrtype|) converts a [=u64=] value from a WebAssembly embedding operation to the correct variant of {{AddressValue}} for an {{AddressType}}, by performing the following steps: | |
| 1. If |addrtype| is [=i32=], return [=𝔽=](|v| interpreted as a [=mathematical value=]). | |
| 1. Else if |addrtype| is [=i64=], return [=ℤ=](|v| interpreted as a [=mathematical value=]). | |
| 1. Assert: This step is not reached. | |
| </div> | |
| <h3 id="tags">Tags</h3> | |
| <h4 id="tag-types">Tag types</h4> | |
| <pre class="idl"> | |
| dictionary TagType { | |
| required sequence<ValueType> parameters; | |
| }; | |
| [LegacyNamespace=WebAssembly, Exposed=*] | |
| interface Tag { | |
| constructor(TagType type); | |
| }; | |
| </pre> | |
| A {{Tag}} value represents an exception tag. | |
| <div algorithm> | |
| To <dfn>initialize a Tag object</dfn> |tag| from a [=tag address=] |tagAddress|, perform the following steps: | |
| 1. Let |map| be the [=surrounding agent=]'s associated [=Tag object cache=]. | |
| 1. Assert: |map|[|tagAddress|] doesn't [=map/exist=]. | |
| 1. Set |tag|.\[[Address]] to |tagAddress|. | |
| 1. [=map/Set=] |map|[|tagAddress|] to |tag|. | |
| </div> | |
| <div algorithm> | |
| To <dfn>create a Tag object</dfn> from a [=tag address=] |tagAddress|, perform the following steps: | |
| 1. Let |map| be the [=surrounding agent=]'s associated [=Tag object cache=]. | |
| 1. If |map|[|tagAddress|] [=map/exists=], | |
| 1. Return |map|[|tagAddress|]. | |
| 1. Let |tag| be a [=/new=] {{Tag}}. | |
| 1. [=initialize a Tag object|Initialize=] |tag| from |tagAddress|. | |
| 1. Return |tag|. | |
| </div> | |
| <div algorithm> | |
| The <dfn constructor for="Tag" lt="Tag(type)">new Tag(|type|)</dfn> constructor steps are: | |
| 1. Let |parameters| be |type|["parameters"]. | |
| 1. Let |wasmParameters| be «». | |
| 1. [=list/iterate|For each=] |paramType| of |parameters|, | |
| 1. [=list/Append=] [=ToValueType=](|paramType|) to |wasmParameters|. | |
| 1. Let |tagtype| be the [=defined type=] such that [=comp-type/func=] |wasmParameters| → « » is the [=expansion=] of |tagtype|. | |
| 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. | |
| 1. Let (|store|, |tagAddress|) be [=tag_alloc=](|store|, |tagtype|). | |
| 1. Set the [=surrounding agent=]'s [=associated store=] to |store|. | |
| 1. [=initialize a Tag object|Initialize=] **this** from |tagAddress|. | |
| </div> | |
| <h3 id="gc-exotic-objects">Garbage Collected Objects</h3> | |
| A WebAssembly struct or array is made available in JavaScript as an <dfn>Exported GC Object</dfn>. | |
| An [=Exported GC Object=] is an exotic object that wraps a garbage collected WebAssembly reference value. | |
| Most JavaScript operations on an [=Exported GC Object=] will throw an exception or return undefined. | |
| Note: These operations may be refined in the future to allow richer interactions in JavaScript with WebAssembly structs and arrays. | |
| An [=Exported GC Object=] contains an \[[ObjectAddress]] internal slot, which holds a [=object address=] relative to the [=surrounding agent=]'s [=associated store=], | |
| and an \[[ObjectKind]] internal slot, which holds the string value "struct" or "array". | |
| The internal methods of an [=Exported GC Object=] use the following implementations. | |
| <div algorithm> | |
| The <dfn>\[[GetPrototypeOf]] internal method of an Exported GC Object</dfn> <var ignore>O</var> takes no arguments and returns null. It performs the following steps when called: | |
| 1. Return null. | |
| </div> | |
| <div algorithm> | |
| The <dfn>\[[SetPrototypeOf]] internal method of an Exported GC Object</dfn> <var ignore>O</var> takes argument <var ignore>V</var> (an Object or null) and returns a boolean. It performs the following steps when called: | |
| 1. Return false. | |
| </div> | |
| <div algorithm> | |
| The <dfn>\[[IsExtensible]] internal method of an Exported GC Object</dfn> <var ignore>O</var> takes no arguments and returns a boolean. It performs the following steps when called: | |
| 1. Return false. | |
| </div> | |
| <div algorithm> | |
| The <dfn>\[[PreventExtensions]] internal method of an Exported GC Object</dfn> <var ignore>O</var> takes no arguments and returns a boolean. It performs the following steps when called: | |
| 1. Return false. | |
| </div> | |
| <div algorithm> | |
| The <dfn>\[[GetOwnProperty]] internal method of an Exported GC Object</dfn> <var ignore>O</var> takes argument <var ignore>P</var> (a property key) and returns undefined. It performs the following steps when called: | |
| 1. Return undefined. | |
| </div> | |
| <div algorithm> | |
| The <dfn>\[[DefineOwnProperty]] internal method of an Exported GC Object</dfn> <var ignore>O</var> takes arguments <var ignore>P</var> (a property key) and <var ignore>Desc</var> (a property descriptor) and returns a boolean. It performs the following steps when called: | |
| 1. Return false. | |
| </div> | |
| <div algorithm> | |
| The <dfn>\[[HasProperty]] internal method of an Exported GC Object</dfn> <var ignore>O</var> takes argument <var ignore>P</var> (a property key) and returns a boolean. It performs the following steps when called: | |
| 1. Return false. | |
| </div> | |
| <div algorithm> | |
| The <dfn>\[[Get]] internal method of an Exported GC Object</dfn> <var ignore>O</var> takes arguments <var ignore>P</var> (a property key) and <var ignore>Receiver</var> (an ECMAScript language value) and returns undefined. It performs the following steps when called: | |
| 1. Return undefined. | |
| </div> | |
| <div algorithm> | |
| The <dfn>\[[Set]] internal method of an Exported GC Object</dfn> <var ignore>O</var> takes arguments <var ignore>P</var> (a property key), <var ignore>V</var> (an ECMAScript language value), and <var ignore>Receiver</var> (an ECMAScript language value) and throws an exception. It performs the following steps when called: | |
| 1. Throw a {{TypeError}}. | |
| </div> | |
| <div algorithm> | |
| The <dfn>\[[Delete]] internal method of an Exported GC Object</dfn> <var ignore>O</var> takes argument <var ignore>P</var> (a property key) and throws an exception. It performs the following steps when called: | |
| 1. Throw a {{TypeError}}. | |
| </div> | |
| <div algorithm> | |
| The <dfn>\[[OwnPropertyKeys]] internal method of an Exported GC Object</dfn> <var ignore>O</var> takes no arguments and returns a list. It performs the following steps when called: | |
| 1. Return « ». | |
| </div> | |
| <div algorithm> | |
| To create <dfn>a new Exported GC Object</dfn> from a WebAssembly [=object address=] |objectaddr| and a string |objectkind|, perform the following steps: | |
| 1. Assert: |objectkind| is either "array" or "struct". | |
| 1. Let |map| be the [=surrounding agent=]'s associated [=exported GC object cache=]. | |
| 1. If |map|[|objectaddr|] [=map/exists=], | |
| 1. Return |map|[|objectaddr|]. | |
| 1. Let |object| be [=MakeBasicObject=](« \[[ObjectAddress]], \[[ObjectKind]] »). | |
| 1. Set |object|.\[[ObjectAddress]] to |objectaddr|. | |
| 1. Set |object|.\[[ObjectKind]] to |objectkind|. | |
| 1. Set |object|.\[[GetPrototypeOf]] as specified in [=[[GetPrototypeOf]] internal method of an Exported GC Object=]. | |
| 1. Set |object|.\[[SetPrototypeOf]] as specified in [=[[SetPrototypeOf]] internal method of an Exported GC Object=]. | |
| 1. Set |object|.\[[IsExtensible]] as specified in [=[[IsExtensible]] internal method of an Exported GC Object=]. | |
| 1. Set |object|.\[[PreventExtensions]] as specified in [=[[PreventExtensions]] internal method of an Exported GC Object=]. | |
| 1. Set |object|.\[[GetOwnProperty]] as specified in [=[[GetOwnProperty]] internal method of an Exported GC Object=]. | |
| 1. Set |object|.\[[DefineOwnProperty]] as specified in [=[[DefineOwnProperty]] internal method of an Exported GC Object=]. | |
| 1. Set |object|.\[[HasProperty]] as specified in [=[[HasProperty]] internal method of an Exported GC Object=]. | |
| 1. Set |object|.\[[Get]] as specified in [=[[Get]] internal method of an Exported GC Object=]. | |
| 1. Set |object|.\[[Set]] as specified in [=[[Set]] internal method of an Exported GC Object=]. | |
| 1. Set |object|.\[[Delete]] as specified in [=[[Delete]] internal method of an Exported GC Object=]. | |
| 1. Set |object|.\[[OwnPropertyKeys]] as specified in [=[[OwnPropertyKeys]] internal method of an Exported GC Object=]. | |
| 1. [=map/Set=] |map|[|objectaddr|] to |object|. | |
| 1. Return |object|. | |
| </div> | |
| <h3 id="exceptions">Exceptions</h3> | |
| <pre class="idl"> | |
| dictionary ExceptionOptions { | |
| boolean traceStack = false; | |
| }; | |
| [LegacyNamespace=WebAssembly, Exposed=*] | |
| interface Exception { | |
| constructor(Tag exceptionTag, sequence<any> payload, optional ExceptionOptions options = {}); | |
| any getArg(Tag exceptionTag, [EnforceRange] unsigned long index); | |
| boolean is(Tag exceptionTag); | |
| readonly attribute (DOMString or undefined) stack; | |
| }; | |
| </pre> | |
| An {{Exception}} value represents an exception. | |
| <div algorithm> | |
| To <dfn>initialize an Exception object</dfn> |exn| from an [=Exception address=] |exnAddress|, perform the following steps: | |
| 1. Let |map| be the [=surrounding agent=]'s associated [=Exception object cache=]. | |
| 1. Assert: |map|[|exnAddress|] doesn't [=map/exist=]. | |
| 1. Set |exn|.\[[Address]] to |exnAddress|. | |
| 1. [=map/Set=] |map|[|exnAddress|] to |exn|. | |
| 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. | |
| 1. Let |tagaddr| be [=exn_tag=](|store|, |exnAddress|). | |
| 1. Let |payload| be [=exn_read=](|store|, |exnAddress|). | |
| 1. Set |exn|.\[[Type]] to |tagaddr|. | |
| 1. Set |exn|.\[[Payload]] to |payload|. | |
| 1. Set |exn|.\[[Stack]] to undefined. | |
| </div> | |
| <div algorithm> | |
| To <dfn>create an Exception object</dfn> from a [=exception address=] |exnAddress|, perform the following steps: | |
| 1. Let |map| be the [=surrounding agent=]'s associated [=Exception object cache=]. | |
| 1. If |map|[|exnAddress|] [=map/exists=], | |
| 1. Return |map|[|exnAddress|]. | |
| 1. Let |exn| be a [=/new=] {{Exception}}. | |
| 1. [=initialize an Exception object|Initialize=] |exn| from |exnAddress|. | |
| 1. Return |exn|. | |
| </div> | |
| <div algorithm> | |
| The <dfn constructor for=Exception | |
| lt="Exception(exceptionTag, payload, options)">new Exception(|exceptionTag|, |payload|, |options|)</dfn> | |
| constructor steps are: | |
| 1. Let |JSTagAddr| be the result of [=get the JavaScript exception tag|getting the JavaScript exception tag=]. | |
| 1. If |exceptionTag|.\[[Address]] is equal to |JSTagAddr|, | |
| 1. Throw a {{TypeError}}. | |
| 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. | |
| 1. Let [=comp-type/func=] |types| → « » be the [=expansion=] of [=tag_type=](|store|, |exceptionTag|.\[[Address]]). | |
| 1. If |types|'s [=list/size=] is not |payload|'s [=list/size=], | |
| 1. Throw a {{TypeError}}. | |
| 1. Let |wasmPayload| be « ». | |
| 1. [=list/iterate|For each=] |value| and |resultType| of |payload| and |types|, paired linearly, | |
| 1. If |resultType| [=matches/valtype|matches=] [=v128=] or [=exnref=], | |
| 1. Throw a {{TypeError}}. | |
| 1. [=list/Append=] [=?=] [=ToWebAssemblyValue=](|value|, |resultType|) to |wasmPayload|. | |
| 1. Let (|store|, |exceptionAddr|) be [=exn_alloc=](|store|, |exceptionTag|.\[[Address]], |wasmPayload|). | |
| 1. Set the [=surrounding agent=]'s [=associated store=] to |store|. | |
| 1. [=initialize an Exception object|Initialize=] **this** from |exceptionAddr|. | |
| 1. If |options|["traceStack"] is true, | |
| 1. Set **this**.\[[Stack]] to either a {{DOMString}} representation of the current call stack or undefined. | |
| </div> | |
| <div algorithm> | |
| The <dfn method for="Exception">getArg(|exceptionTag|, |index|)</dfn> method steps are: | |
| 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. | |
| 1. If **this**.\[[Type]] is not equal to |exceptionTag|.\[[Address]], | |
| 1. Throw a {{TypeError}}. | |
| 1. Let |tagaddr| be [=exn_tag=](|store|, **this**.\[[Address]]). | |
| 1. Let |payload| be [=exn_read=](|store|, **this**.\[[Address]]). | |
| 1. Assert: |tagaddr| is equal to **this**.\[[Type]]. | |
| 1. If |index| ≥ |payload|'s [=list/size=], | |
| 1. Throw a {{RangeError}}. | |
| 1. Let [=comp-type/func=] |types| → « » be the [=expansion=] of [=tag_type=](|store|, |tagaddr|). | |
| 1. If |types|[|index|] [=matches/valtype|matches=] [=v128=] or [=exnref=], | |
| 1. Throw a {{TypeError}}. | |
| 1. Return [=ToJSValue=](|payload|[|index|]). | |
| </div> | |
| <div algorithm> | |
| The <dfn method for="Exception">is(|exceptionTag|)</dfn> method steps are: | |
| 1. If **this**.\[[Type]] is not equal to |exceptionTag|.\[[Address]], | |
| 1. Return false. | |
| 1. Return true. | |
| </div> | |
| <div algorithm> | |
| The <dfn attribute for="Exception">stack</dfn> getter steps are: | |
| 1. Return **this**.\[[Stack]]. | |
| </div> | |
| <h4 id="js-exceptions">JavaScript exceptions</h4> | |
| The <dfn>JavaScript exception tag</dfn> is a [=tag address=] associated with | |
| the surrounding agent. It is allocated in the agent's [=associated store=] on | |
| first use and cached. It always has the [=tag type=] « [=externref=] » → « ». | |
| <div algorithm> | |
| To <dfn>get the JavaScript exception tag</dfn>, perform the following steps: | |
| 1. If the [=surrounding agent=]'s associated [=JavaScript exception tag=] has been initialized, | |
| 1. return the [=surrounding agent=]'s associated [=JavaScript exception tag=] | |
| 1. Let |tagtype| be the [=defined type=] such that [=comp-type/func=] « [=externref=] » → « » is the [=expansion=] of |tagtype|. | |
| 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. | |
| 1. Let (|store|, |tagAddress|) be [=tag_alloc=](|store|, |tagtype|). | |
| 1. Set the [=surrounding agent=]'s [=associated store=] to |store|. | |
| 1. Set the [=surrounding agent=]'s associated [=JavaScript exception tag=] to |tagAddress|. | |
| 1. return |tagAddress|. | |
| </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="builtins">Builtins</h2> | |
| The JS-API defines sets of builtin functions which can be imported through {{WebAssemblyCompileOptions|options}} when compiling a module. WebAssembly builtin functions mirror existing JavaScript builtins, but adapt them to be useable directly as WebAssembly functions with minimal overhead. | |
| All builtin functions are grouped into sets. Every builtin set has a <dfn for="builtin-set">|name|</dfn> that is used in {{WebAssemblyCompileOptions}}, and a <dfn for="builtin-set">|qualified name|</dfn> with a `wasm:` prefix that [=read the imports|is used during import lookup=]. | |
| <div algorithm> | |
| To <dfn>get the builtins for a builtin set</dfn> with |builtinSetName|, perform the following steps: | |
| 1. Return a list of (|name|, |funcType|, |steps|) for the set with name |builtinSetName| defined within this section. | |
| </div> | |
| <div algorithm> | |
| To <dfn>find a builtin</dfn> with |import| and enabled builtins |builtinSetNames|, perform the following steps: | |
| 1. Assert: [=validate builtin set names=] |builtinSetNames| is true. | |
| 1. Let |importModuleName| be |import|[0]. | |
| 1. Let |importName| be |import|[1]. | |
| 1. [=list/iterate|For each=] |builtinSetName| of |builtinSetNames|, | |
| 1. If |builtinSetName| does not refer to a builtin set, then [=iteration/continue=]. | |
| 1. Let |builtinSetQualifiedName| be |builtinSetName| prefixed with "wasm:". | |
| 1. If |importModuleName| equals |builtinSetQualifiedName|, | |
| 1. Let |builtins| be the result of [=get the builtins for a builtin set=] |builtinSetName|. | |
| 1. [=list/iterate|For each=] |builtin| of |builtins|, | |
| 1. Let |builtinName| be |builtin|[0]. | |
| 1. If |importName| equals |builtinName|, return (|builtinSetName|, |builtin|). | |
| 1. Return null. | |
| </div> | |
| <div algorithm> | |
| To <dfn>validate builtin set names</dfn> with |builtinSetNames|, perform the following steps: | |
| 1. If |builtinSetNames| contains any duplicates, return false. | |
| 1. Return true. | |
| </div> | |
| <div algorithm> | |
| To <dfn>create a builtin function</dfn> from type |funcType| and execution steps |steps|, perform the following steps: | |
| 1. Let |hostfunc| be a [=host function=] which executes |steps| when called. | |
| 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> | |
| To <dfn>instantiate a builtin set</dfn> with name |builtinSetName|, perform the following steps: | |
| 1. Let |builtins| be the result of [=get the builtins for a builtin set=] |builtinSetName|. | |
| 1. Let |exportsObject| be [$OrdinaryObjectCreate$](null). | |
| 1. [=list/iterate|For each=] (|name|, |funcType|, |steps|) of |builtins|, | |
| 1. Let |funcaddr| be the result of [=create a builtin function=] with |funcType| and |steps|. | |
| 1. Let |func| be the result of creating [=a new Exported Function=] from |funcaddr|. | |
| 1. Let |value| be |func|. | |
| 1. Let |status| be [=!=] [$CreateDataProperty$](|exportsObject|, |name|, |value|). | |
| 1. Assert: |status| is true. | |
| 1. Return |exportsObject|. | |
| </div> | |
| <div algorithm> | |
| To <dfn>validate an import for builtins</dfn> with |import|, enabled builtins |builtinSetNames|, perform the following steps: | |
| 1. Assert: [=validate builtin set names=] |builtinSetNames| is true. | |
| 1. Let |maybeBuiltin| be the result of [=find a builtin|finding a builtin=] for |import| and |builtinSetNames|. | |
| 1. If |maybeBuiltin| is null, return true. | |
| 1. Let |importExternType| be |import|[2]. | |
| 1. Let |builtinFuncType| be |maybeBuiltin|[1][1]. | |
| 1. Let |builtinExternType| be `func |builtinFuncType|`. | |
| 1. Return [=match_externtype=](|builtinExternType|, |importExternType|). | |
| </div> | |
| <h3 id="builtins-js-string">String Builtins</h3> | |
| String builtins adapt the interface of the [=String=] builtin object. The [=builtin-set/name=] for this set is `js-string`, and the [=builtin-set/qualified name=] is `wasm:js-string`. | |
| Note: The algorithms in this section refer to JS builtins defined on [=String=]. These refer to the actual builtin and do not perform a dynamic lookup on the [=String=] object. | |
| <h4 id="builtins-js-string-abstract-ops">Abstract operations</h4> | |
| <div algorithm> | |
| The <dfn abstract-op lt="UnwrapString">UnwrapString(|v|)</dfn> abstract operation, when invoked, performs the following steps: | |
| 1. If |v| [=is not a String=], | |
| 1. Throw a {{RuntimeError}} exception as if a [=trap=] was executed. | |
| 1. Return |v| | |
| </div> | |
| <div algorithm> | |
| The <dfn abstract-op lt="FromCharCode">FromCharCode(|v|)</dfn> abstract operation, when invoked, performs the following steps: | |
| 1. Assert: |v| is of type [=i32=]. | |
| 1. Return [=!=] [$Call$]([=String.fromCharCode=], undefined, « [=ToJSValue=](|v|) »). | |
| </div> | |
| <div algorithm> | |
| The <dfn abstract-op lt="CharCodeAt">CharCodeAt(|string|, |index|)</dfn> abstract operation, when invoked, performs the following steps: | |
| 1. Assert: |index| is of type [=i32=]. | |
| 1. Return [=!=] [$Call$]([=String.prototype.charCodeAt=], |string|, « [=ToJSValue=](|index|) »). | |
| </div> | |
| <h4 id="js-string-cast">cast</h4> | |
| The |funcType| of this builtin is `(rec (type (func (param externref) (result (ref extern))))).0`. | |
| <div algorithm="js-string-cast"> | |
| When this builtin is invoked with parameter |v|, the following steps must be run: | |
| 1. Return [=?=] [$UnwrapString$](|v|) | |
| </div> | |
| <h4 id="js-string-test">test</h4> | |
| The |funcType| of this builtin is `(rec (type (func (param externref) (result i32)))).0`. | |
| <div algorithm="js-string-test"> | |
| When this builtin is invoked with parameter |v|, the following steps must be run: | |
| 1. If |v| [=is not a String=], | |
| 1. Return 0. | |
| 1. Return 1. | |
| </div> | |
| <h4 id="js-string-fromCharCodeArray">fromCharCodeArray</h4> | |
| Let |arrayType| be `(rec (type (array (mut i16)))).0`. | |
| The |funcType| of this builtin is `(rec (type (func (param (ref null arrayType) i32 i32) (result (ref extern))))).0`. | |
| <div algorithm="js-string-fromCharCodeArray"> | |
| When this builtin is invoked with parameters |array|, |start|, and |end|, the following steps must be run: | |
| 1. If |array| is null, | |
| 1. Throw a {{RuntimeError}} exception as if a [=trap=] was executed. | |
| 1. Let |length| be the number of elements in |array|. | |
| 1. If |start| > |end| or |end| > |length|, | |
| 1. Throw a {{RuntimeError}} exception as if a [=trap=] was executed. | |
| 1. Let |result| be the empty string. | |
| 1. Let |i| be |start|. | |
| 1. While |i| < |end|: | |
| 1. Let |charCode| be the value of the element stored at index |i| in |array|. | |
| 1. Let |charCodeString| be [$FromCharCode$](|charCode|). | |
| 1. Let |result| be the concatenation of |result| and |charCodeString|. | |
| 1. Set |i| to |i| + 1. | |
| 1. Return |result|. | |
| </div> | |
| <h4 id="js-string-intoCharCodeArray">intoCharCodeArray</h4> | |
| Let |arrayType| be `(rec (type (array (mut i16)))).0`. | |
| The |funcType| of this builtin is `(rec (type (func (param externref (ref null arrayType) i32) (result i32)))).0`. | |
| <div algorithm="js-string-intoCharCodeArray"> | |
| When this builtin is invoked with parameters |string|, |array|, and |start|, the following steps must be run: | |
| 1. If |array| is null, | |
| 1. Throw a {{RuntimeError}} exception as if a [=trap=] was executed. | |
| 1. Let |string| be [=?=] [$UnwrapString$](|string|). | |
| 1. Let |stringLength| be the [=string/length=] of |string|. | |
| 1. Let |arrayLength| be the number of elements in |array|. | |
| 1. If |start| + |stringLength| > |arrayLength|, | |
| 1. Throw a {{RuntimeError}} exception as if a [=trap=] was executed. | |
| 1. Let |i| be 0. | |
| 1. While |i| < |stringLength|: | |
| 1. Let |charCode| be [$CharCodeAt$](|string|, |i|). | |
| 1. Set the element at index |start| + |i| in |array| to [=ToWebAssemblyValue=](|charCode|, [=i32=]). | |
| 1. Set |i| to |i| + 1. | |
| 1. Return |stringLength|. | |
| </div> | |
| <h4 id="js-string-fromCharCode">fromCharCode</h4> | |
| The |funcType| of this builtin is `(rec (type (func (param i32) (result (ref extern))))).0`. | |
| <div algorithm="js-string-fromCharCode"> | |
| When this builtin is invoked with parameter |v|, the following steps must be run: | |
| 1. Return [$FromCharCode$](|v|). | |
| </div> | |
| <h4 id="js-string-fromCodePoint">fromCodePoint</h4> | |
| The |funcType| of this builtin is `(rec (type (func (param i32) (result externref)))).0`. | |
| <div algorithm="js-string-fromCodePoint"> | |
| When this builtin is invoked with parameter |v|, the following steps must be run: | |
| 1. If |v| > 0x10ffff, | |
| 1. Throw a {{RuntimeError}} exception as if a [=trap=] was executed. | |
| 1. Return [=!=] [$Call$]([=String.fromCodePoint=], undefined, « [=ToJSValue=](|v|) »). | |
| </div> | |
| <h4 id="js-string-charCodeAt">charCodeAt</h4> | |
| The type of this function is `(rec (type (func (param externref i32) (result i32)))).0`. | |
| <div algorithm="js-string-charCodeAt"> | |
| When this builtin is invoked with parameters |string| and |index|, the following steps must be run: | |
| 1. Let |string| be [=?=] [$UnwrapString$](|string|). | |
| 1. Let |length| be the [=string/length=] of |string|. | |
| 1. If |index| >= |length|, | |
| 1. Throw a {{RuntimeError}} exception as if a [=trap=] was executed. | |
| 1. Return [$CharCodeAt$](|string|, |index|). | |
| </div> | |
| <h4 id="js-string-codePointAt">codePointAt</h4> | |
| The type of this function is `(rec (type (func (param externref i32) (result i32)))).0`. | |
| <div algorithm="js-string-codePointAt"> | |
| When this builtin is invoked with parameters |string| and |index|, the following steps must be run: | |
| 1. Let |string| be [=?=] [$UnwrapString$](|string|). | |
| 1. Let |length| be the [=string/length=] of |string|. | |
| 1. If |index| >= |length|, | |
| 1. Throw a {{RuntimeError}} exception as if a [=trap=] was executed. | |
| 1. Return [=!=] [$Call$]([=String.prototype.codePointAt=], |string|, « [=ToJSValue=](|index|) »). | |
| </div> | |
| <h4 id="js-string-length">length</h4> | |
| The |funcType| of this builtin is `(rec (type (func (param externref) (result i32)))).0`. | |
| <div algorithm="js-string-length"> | |
| When this builtin is invoked with parameter |v|, the following steps must be run: | |
| 1. Let |string| be [=?=] [$UnwrapString$](|v|). | |
| 1. Return the [=string/length=] of |string|. | |
| </div> | |
| <h4 id="js-string-concat">concat</h4> | |
| The |funcType| of this builtin is `(rec (type (func (param externref externref) (result (ref extern))))).0`. | |
| <div algorithm="js-string-concat"> | |
| When this builtin is invoked with parameters |first| and |second|, the following steps must be run: | |
| 1. Let |first| be [=?=] [$UnwrapString$](|first|). | |
| 1. Let |second| be [=?=] [$UnwrapString$](|second|). | |
| 1. Return [=!=] [$Call$]([=String.prototype.concat=], |first|, « |second| »). | |
| </div> | |
| <h4 id="js-string-substring">substring</h4> | |
| The |funcType| of this builtin is `(rec (type (func (param externref i32 i32) (result (ref extern))))).0`. | |
| <div algorithm="js-string-substring"> | |
| When this builtin is invoked with parameters |string|, |start|, and |end|, the following steps must be run: | |
| 1. Let |string| be [=?=] [$UnwrapString$](|string|). | |
| 1. Let |length| be the [=string/length=] of |string|. | |
| 1. If |start| > |end| or |start| > |length|, | |
| 1. Return the empty string. | |
| 1. Return [=!=] [$Call$]([=String.prototype.substring=], |string|, « [=ToJSValue=](|start|), [=ToJSValue=](|end|) »). | |
| </div> | |
| <h4 id="js-string-equals">equals</h4> | |
| The |funcType| of this builtin is `(rec (type (func (param externref externref) (result i32)))).0`. | |
| Note: Explicitly allow null strings to be compared for equality as that is meaningful. | |
| <div algorithm="js-string-equals"> | |
| When this builtin is invoked with parameters |first| and |second|, the following steps must be run: | |
| 1. If |first| is not null and |first| [=is not a String=], | |
| 1. Throw a {{RuntimeError}} exception as if a [=trap=] was executed. | |
| 1. If |second| is not null and |second| [=is not a String=], | |
| 1. Throw a {{RuntimeError}} exception as if a [=trap=] was executed. | |
| 1. If [=IsStrictlyEqual=](|first|, |second|) is true, | |
| 1. Return 1. | |
| 1. Return 0. | |
| </div> | |
| <h4 id="js-string-compare">compare</h4> | |
| The |funcType| of this builtin is `(rec (type (func (param externref externref) (result i32)))).0`. | |
| <div algorithm="js-string-compare"> | |
| When this builtin is invoked with parameters |first| and |second|, the following steps must be run: | |
| 1. Let |first| be [=?=] [$UnwrapString$](|first|). | |
| 1. Let |second| be [=?=] [$UnwrapString$](|second|). | |
| 1. If [=IsStrictlyEqual=](|first|, |second|) is true, | |
| 1. Return 0. | |
| 1. If [=!=] [=IsLessThan=](|first|, |second|, true) is true, | |
| 1. Return -1. | |
| 1. Return 1. | |
| </div> | |
| <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 recursion groups defined in the types sections is 1,000,000.</li> | |
| <li>The maximum number of types defined in a recursion group is 1,000,000.</li> | |
| <li>The maximum depth of a defined subtype hierarchy is 63 (where a type defined with no supertype has depth 0). | |
| <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 1,000,000.</li> | |
| <li>The maximum number of exports declared in a module is 1,000,000.</li> | |
| <li>The maximum number of globals defined in a module is 1,000,000.</li> | |
| <li>The maximum number of tags 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 defined and imported memories, is 100.</li> | |
| <li>The maximum `min` or `max` field of a 32-bit memory is 65,536 pages (4 GiB).</li> | |
| <li>The maximum `min` or `max` field of a 64-bit memory is 2^37-1 pages (2^53 - 2^16 bytes).</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> | |
| <li>The maximum number of fields in a struct is 10,000.</li> | |
| <li>The maximum number of operands to `array.new_fixed` is 10,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 size of a 32-bit memory is 65,536 pages (4 GiB).</li> | |
| <li>The maximum size of a 64-bit memory is 262,144 pages (16 GiB).</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 to and from JavaScript functions 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. | |
| <h4 id="changes-multitable" class="no-toc heading settled">Multiple Tables</h4> | |
| Multiple tables can be exported and imported to and from JavaScript. | |
| <h3 id="release-30">Release 3.0</h3> | |
| <h4 id="changes-multimemory" class="no-toc heading settled">Multiple Memories</h4> | |
| Multiple memories can be exported and imported to and from JavaScript. | |
| <h4 id="changes-js-sb" class="no-toc heading settled">JS String Builtins</h4> | |
| Added a builtins option when compiling a module, and a collection of builtin functions for manipulating JS Strings. |