diff --git a/document/js-api/index.bs b/document/js-api/index.bs index 88505d87c..b1005667c 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -81,18 +81,21 @@ urlPrefix: https://tc39.github.io/ecma262/; spec: ECMASCRIPT text: ObjectCreate; url: sec-objectcreate text: CreateBuiltinFunction; url: sec-createbuiltinfunction text: SetFunctionName; url: sec-setfunctionname + text: SetFunctionLength; url: sec-setfunctionlength text: the Number value; url: sec-ecmascript-language-types-number-type text: NumberToRawBytes; url: sec-numbertorawbytes text: Built-in Function Objects; url: sec-built-in-function-objects + text: Cyclic Module Record; url: cyclic-module-record urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: dfn url: valid/modules.html#valid-module text: valid text: WebAssembly module validation - text: binary format of a module; url: binary/modules.html + 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 @@ -132,6 +135,7 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df text: table address; url: exec/runtime.html#syntax-tableaddr text: function address; url: exec/runtime.html#syntax-funcaddr text: memory address; url: exec/runtime.html#syntax-memaddr + text: global address; url: exec/runtime.html#syntax-globaladdr url: syntax/types.html#syntax-valtype text: 𝗂πŸ₯𝟀 text: π—‚πŸ¨πŸ¦ @@ -153,12 +157,16 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df text: 𝗆𝖾𝗆 text: π—€π—…π—ˆπ–»π–Ίπ—… text: global type; url: syntax/types.html#syntax-globaltype + url: syntax/types.html#syntax-mut + text: var + text: const text: address; url: exec/runtime.html#addresses text: signed_32; url: exec/numerics.html#aux-signed - text: grow_memory; url: exec/instructions.html#exec-grow-memory + text: memory.grow; url: exec/instructions.html#exec-memory-grow text: current frame; url: exec/conventions.html#exec-notation-textual text: π—†π—ˆπ–½π—Žπ—…π–Ύ; url: exec/runtime.html#syntax-frame text: π—†π–Ύπ—†π–Ίπ–½π–½π—‹π—Œ; url: exec/runtime.html#syntax-moduleinst + text: sequence; url: syntax/conventions.html#grammar-notation @@ -464,7 +506,7 @@ interface Module {
- The exports(moduleObject) method, when invoked, performs the following steps: + The exports(|moduleObject|) method, when invoked, performs the following steps: 1. Let |module| be |moduleObject|.\[[Module]]. 1. Let |exports| be an empty [=list=]. 1. For each (|name|, |type|) in [=module_exports=](|module|) @@ -475,7 +517,7 @@ interface Module {
- The imports(moduleObject) method, when invoked, performs the following steps: + The imports(|moduleObject|) method, when invoked, performs the following steps: 1. Let |module| be |moduleObject|.\[[Module]]. 1. Let |imports| be an empty [=list=]. 1. For each (|moduleName|, |name|, |type|) in [=module_imports=](|module|), @@ -486,24 +528,26 @@ interface Module {
- The customSections(moduleObject, sectionName) method, when invoked, performs the following steps: + The customSections(|moduleObject|, |sectionName|) method, when invoked, performs the following steps: 1. Let |bytes| be |moduleObject|.\[[Bytes]]. 1. Let |customSections| be an empty [=list=] of {{ArrayBuffer}}s. - 1. For each [=custom section=] |customSection| in the binary format of |bytes|, - 1. Let |name| be the name of the custom section, [=UTF-8 decode without BOM or fail|decoded as UTF-8=]. + 1. For each [=custom section=] |customSection| in |bytes|, interpreted according to the [=module grammar=], + 1. Let |name| be the name 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 |secondName| as string values, - 1. [=Append=] a new {{ArrayBuffer}} containing a [=get a copy of the buffer source|copy of the bytes held by the buffer=] |bytes| for the range matched by this [=customsec=] production. + 1. If |name| equals |sectionName| as string values, + 1. [=Append=] a new {{ArrayBuffer}} containing a copy of the bytes in |bytes| for the range matched by this [=customsec=] production. 1. Return |customSections|.
- The Module(bytes) constructor, when invoked, performs the follwing steps: + The Module(|bytes|) constructor, when invoked, performs the follwing steps: 1. Let |stableBytes| be a [=get a copy of the buffer source|copy of the bytes held by the buffer=] |bytes|. 1. [=Compile a WebAssembly module|Compile the WebAssembly module=] |stableBytes| and store the result as |module|. 1. If |module| is [=error=], throw a {{CompileError}} exception. - 1. [=Construct a WebAssembly module object=] from |module| and |bytes|, and return the result. + 1. [=Construct a WebAssembly module object=] from |module| and |stableBytes|, and return the result. + +Note: Some implementations may enforce a size limitation on |bytes|. Use of this API is discouraged, in favor of asynchronous APIs.

Instances

@@ -516,7 +560,9 @@ interface Instance {
- The Instance(module, importObject) constructor, when invoked, [=instantiate a WebAssembly module|instantiates the WebAssembly module=] |module| importing |importObject| and returns the result. + The Instance(|module|, |importObject|) constructor, when invoked, [=synchronously instantiate a WebAssembly module|synchronously instantiates the WebAssembly module=] |module| importing |importObject| and returns the result. + +Note: The use of this synchronous API is discouraged, as some implementations sometimes do long-running compilation work when instantiating.
@@ -547,25 +593,32 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each * \[[BufferObject]] : an {{ArrayBuffer}} whose [=Data Block=] is [=identified with=] the above memory address
+
+ To create a memory buffer from a [=memory address=] |memaddr|, perform the following steps: + + 1. Let |block| be a [=Data Block=] which is [=identified with=] the underlying memory of |memaddr|. + 1. Let |buffer| be a new {{ArrayBuffer}} whose \[[ArrayBufferData]] is |block| and \[[ArrayBufferByteLength]] is set to the length of |block|. + 1. Set |buffer|.\[[ArrayBufferDetachKey]] to "WebAssembly.Memory". + 1. Return |buffer|. +
+
To create a memory object 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 |block| be a Data Block which is [=identified with=] the underlying memory of |memaddr| - 1. Let |buffer| be a new {{ArrayBuffer}} whose \[[ArrayBufferData]] is |block| and \[[ArrayBufferByteLength]] is set to the length of |block|. + 1. Let |buffer| be a the result of [=create a memory buffer|creating a memory buffer=] from |memaddr|. 1. Let |memory| be a new {{Memory}} instance with \[[Memory]] set to |memaddr| and \[[BufferObject]] set to |buffer|. 1. [=map/Set=] |map|[|memaddr|] to |memory|. 1. Return |memory|. - - Issue: Any attempts to [=DetachArrayBuffer|detach=] |buffer|, other than the detachment performed by {{Memory/grow(delta)}}, will throw a {{TypeError}} exception. Specifying this behavior requires changes to the ECMAScript specification.
- The Memory(descriptor) constructor, when invoked, performs the following steps: - 1. If |descriptor|["initial"] is [=present=], let |initial| be |descriptor|["initial"]; otherwise, let |initial| be 0. + The Memory(|descriptor|) constructor, when invoked, performs the following steps: + 1. let |initial| be |descriptor|["initial"]. 1. If |descriptor|["maximum"] is [=present=], let |maximum| be |descriptor|["maximum"]; otherwise, let |maximum| be empty. + 1. If |maximum| is not empty and |maximum| < |initial|, throw a {{RangeError}} exception. 1. Let |memtype| be { min |initial|, max |maximum| } 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. 1. Let (|store|, |memaddr|) be [=alloc_mem=](|store|, |memtype|). If allocation fails, throw a {{RangeError}} exception. @@ -579,14 +632,13 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each 1. Let |map| be the [=surrounding agent=]'s associated [=Memory object cache=]. 1. Assert: |map|[|memaddr|] [=map/exists=] 1. Let |memory| be |map|[|memaddr|]. - 1. Perform ! [=DetachArrayBuffer=](|memory|.\[[BufferObject]]). - 1. Let |block| be a [=Data Block=] which is [=identified with=] the underlying memory of |memaddr|. - 1. Let |buffer| be a new {{ArrayBuffer}} whose \[[ArrayBufferData]] is |block| and \[[ArrayBufferByteLength]] is set to the length of |block|. + 1. Perform ! [=DetachArrayBuffer=](|memory|.\[[BufferObject]], "WebAssembly.Memory"). + 1. Let |buffer| be a the result of [=create a memory buffer|creating a memory buffer=] from |memaddr|. 1. Set |memory|.\[[BufferObject]] to |buffer|.
-
- The grow(delta) method, when invoked, performs the following steps: +
+ The grow(|delta|) method, when invoked, performs the following steps: 1. Let |memory| be the Memory instance. 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. 1. Let |memaddr| be |memory|.\[[Memory]]. @@ -598,9 +650,9 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each 1. Return |ret|.
-Immediately after a WebAssembly [=grow_memory=] instruction executes, perform the following steps: +Immediately after a WebAssembly [=memory.grow=] instruction executes, perform the following steps: -
+
1. If the top of the stack is not [=𝗂πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—=] (βˆ’1), then: 1. Let |frame| be the [=current frame=]. 1. Assert: due to validation, |frame|.[=π—†π—ˆπ–½π—Žπ—…π–Ύ=].[=π—†π–Ύπ—†π–Ίπ–½π–½π—‹π—Œ=][0] exists. @@ -608,6 +660,10 @@ Immediately after a WebAssembly [=grow_memory=] instruction executes, perform th 1. [=Reset the memory buffer=] of |memaddr|.
+
+ The getter of the buffer attribute of {{Memory}} returns the receiver's \[[BufferObject]] internal slot. +
+

Tables

@@ -646,6 +702,7 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each
     1. Let |map| be the [=surrounding agent=]'s associated [=Table object cache=].
     1. If |map|[|tableaddr|] [=map/exists=],
         1. Return |map|[|tableaddr|].
+    1. Let |store| be the [=surrounding agent=]'s [=associated store=].
     1. Let |values| be a list whose length is [=size_table=](|store|, |tableaddr|) where each element is null.
     1. Let |table| be a new {{Table}} instance with \[[Table]] set to |tableaddr| and \[[Values]] set to |values|.
     1. [=map/Set=] |map|[|tableaddr|] to |table|.
@@ -653,29 +710,29 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each
 
- The Table(descriptor) constructor, when invoked, performs the following steps: - 1. If |descriptor|["initial"] is [=present=], let |n| be |descriptor|["initial"]; otherwise, let |n| be 0. - 1. If |descriptor|["maximum"] is [=present=], let |m| be |descriptor|["maximum"]; otherwise, let |m| be empty. - 1. If |m| is not empty and |m| < |n|, throw a {{RangeError}} exception. - 1. Let |type| be the [=table type=] {[=table type|𝗆𝗂𝗇=] n, [=table type|𝗆𝖺𝗑=] |m|} [=table type|π–Ίπ—‡π—’π–Ώπ—Žπ—‡π–Ό=]. + The Table(|descriptor|) constructor, when invoked, performs the following steps: + 1. let |initial| be |descriptor|["initial"]. + 1. If |descriptor|["maximum"] is [=present=], let |maximum| be |descriptor|["maximum"]; otherwise, let |maximum| be empty. + 1. If |maximum| is not empty and |maximum| < |initial|, throw a {{RangeError}} exception. + 1. Let |type| be the [=table type=] {[=table type|𝗆𝗂𝗇=] n, [=table type|𝗆𝖺𝗑=] |maximum|} [=table type|π–Ίπ—‡π—’π–Ώπ—Žπ—‡π–Ό=]. 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. 1. Let (|store|, |tableaddr|) be [=alloc_table=](|store|, |type|). 1. Set the [=surrounding agent=]'s [=associated store=] to |store|. 1. [=Create a table object=] from the table address |tableaddr| and return the result.
-
- The grow(d) method, when invoked, performs the following steps: +
+ The grow(|delta|) method, when invoked, performs the following steps: 1. Let |tableaddr| be the Table instance's \[[Table]] internal slot. 1. Let |initialSize| be the length of the Table instance's \[[Values]] internal slot. 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. - 1. Let |result| be [=grow_table=](|store|, |tableaddr|, |d|). + 1. Let |result| be [=grow_table=](|store|, |tableaddr|, |delta|). 1. If |result| is [=error=], throw a {{RangeError}} exception. Note: The above exception may happen due to either insufficient memory or an invalid size parameter. - 6. Set the [=surrounding agent=]'s [=associated store=] to |store|. - 1. [=Append=] null to the Table instance's \[[Values]] internal slot |d| times. + 1. Set the [=surrounding agent=]'s [=associated store=] to |result|. + 1. [=Append=] null to the Table instance's \[[Values]] internal slot |delta| times. 1. Return |initialSize|.
@@ -684,7 +741,7 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each
- The get(index) method, when invoked, performs the following steps: + The get(|index|) method, when invoked, performs the following steps: 1. Let |values| be the Table instance's \[[Values]] internal slot. 1. Let |size| be the length of |values|. 1. If |index| ≥ |size|, throw a {{RangeError}} exception. @@ -692,7 +749,7 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each
- The set(index, value) method, when invoked, performs the following steps: + The set(|index|, |value|) method, when invoked, performs the following steps: 1. Let |tableaddr| be the Table instance's \[[Table]] internal slot. 1. Let |values| be the Table instance's \[[Values]] internal slot. 1. If |value| is null, let |funcaddr| be an empty [=function element=]. @@ -707,6 +764,107 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each 1. Return undefined.
+

Globals

+ +
+dictionary GlobalDescriptor {
+  required USVString value;
+  boolean mutable = false;
+};
+
+[LegacyNamespace=WebAssembly, Constructor(GlobalDescriptor descriptor, optional any v), Exposed=(Window,Worker,Worklet)]
+interface Global {
+  any valueOf();
+  attribute any value;
+};
+
+ +
+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=] +
+ +
+ To create a global object from a [=global address=] |globaladdr|, perform the following steps: + 1. Let |map| be the current [=agent=]'s associated [=Global object cache=]. + 1. If |map|[|globaladdr|] [=map/exists=], + 1. Return |map|[|globaladdr|]. + 1. Let |global| be a new {{Global}} instance with \[[Global]] set to |globaladdr|. + 1. [=map/Set=] |map|[|globaladdr|] to |global|. + 1. Return |global|. +
+ +
+ The algorithm ToValueType(|s|) performs the following steps: + 1. If |s| equals "i32", return [=𝗂πŸ₯𝟀=]. + 1. If |s| equals "i64", return [=π—‚πŸ¨πŸ¦=]. + 1. If |s| equals "f32", return [=𝖿πŸ₯𝟀=]. + 1. If |s| equals "f64", return [=π–ΏπŸ¨πŸ¦=]. + 1. Otherwise, throw a {{TypeError}} exception. +
+ +
+ The algorithm DefaultValue(|valuetype|) performs the following steps: + 1. If |valuetype| equals [=𝗂πŸ₯𝟀=], return [=𝗂πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—=] 0. + 1. If |valuetype| equals [=π—‚πŸ¨πŸ¦=], return [=π—‚πŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—=] 0. + 1. If |valuetype| equals [=𝖿πŸ₯𝟀=], return [=𝖿πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—=] 0. + 1. If |valuetype| equals [=π–ΏπŸ¨πŸ¦=], return [=π–ΏπŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—=] 0. + 1. Assert: This step is not reached. +
+ +
+ The Global(|descriptor|, |v|) constructor, when invoked, performs the following steps: + 1. Let |mutable| be |descriptor|["mutable"]. + 1. Let |valuetype| be [=ToValueType=](|descriptor|["value"]). + 1. If |v| is undefined, + 1. let |value| be [=DefaultValue=](|valuetype|). + 1. Otherwise, + 1. If |valuetype| is [=π—‚πŸ¨πŸ¦=], throw a {{TypeError}} exception. + 1. Let |value| be [=ToWebAssemblyValue=](|v|, |valuetype|). + 1. If |mutable| is true, let |globaltype| be [=var=] |valuetype|; otherwise, let |globaltype| be [=const=] |valuetype|. + 1. Let |store| be the current agent's [=associated store=]. + 1. Let (|store|, |globaladdr|) be [=alloc_global=](|store|, |globaltype|, |value|). + 1. Set the current agent's [=associated store=] to |store|. + 1. [=Create a global object=] from the global address |globaladdr| and return the result. +
+ +
+ The algorithm GetGlobalValue({{Global}} |global|) performs the following steps: + 1. Let |store| be the current agent's [=associated store=]. + 1. Let |globaladdr| be |global|.\[[Global]]. + 1. Let |globaltype| be [=type_global=](|store|, |globaladdr|). + 1. If |globaltype| is of the form mut [=π—‚πŸ¨πŸ¦=], throw a {{TypeError}}. + 1. Let |value| be [=read_global=](|store|, |globaladdr|). + 1. Return [=ToJSValue=](|value|). +
+ +
+ The getter of the value attribute of {{Global}}, when invoked, performs the following steps: + 1. Let |global| be the {{Global}} instance. + 1. Return [=GetGlobalValue=](|global|). + + The setter of the value attribute of {{Global}}, when invoked with a value |v|, performs the following steps: + 1. Let |global| be the {{Global}} instance. + 1. Let |store| be the current agent's [=associated store=]. + 1. Let |globaladdr| be |global|.\[[Global]]. + 1. Let |globaltype| be [=type_global=](|store|, |globaladdr|), where |globaltype| is of the form |mut| |valuetype|. + 1. If |mut| is [=const=], throw a {{TypeError}}. + 1. If |valuetype| is [=π—‚πŸ¨πŸ¦=], throw a {{TypeError}}. + 1. Let |value| be [=ToWebAssemblyValue=](|v|, |valuetype|). + 1. Let |store| be [=write_global=](|store|, |globaladdr|, |value|). + 1. If |store| is [=error=], throw a {{RangeError}} exception. + 1. Set the current agent's [=associated store=] to |store|. +
+ +
+ The valueOf() method, when invoked, performs the following steps: + 1. Let |global| be the {{Global}} instance. + 1. Return [=GetGlobalValue=](|global|). +
+

Exported Functions

A WebAssembly function is made available in JavaScript as an Exported Function. @@ -718,7 +876,7 @@ This slot holds a [=function address=] relative to the [=surrounding agent=]'s [ 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. 1. Let |funcinst| be |store|.π–Ώπ—Žπ—‡π–Όπ—Œ[|funcaddr|]. - 1. If |funcinst| is of the form {𝗍𝗒𝗉𝖾 |functype|, π—π—ˆπ—Œπ—π–Όπ—ˆπ–½π–Ύ |hostfunc|}, + 1. If |funcinst| is of the form {𝗍𝗒𝗉𝖾 functype, π—π—ˆπ—Œπ—π–Όπ—ˆπ–½π–Ύ |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, @@ -736,13 +894,13 @@ This slot holds a [=function address=] relative to the [=surrounding agent=]'s [ 1. Return |map|[|funcaddr|]. 1. Let |steps| be "[=call an Exported Function|call the Exported Function=] |funcaddr| with arguments." 1. Let |realm| be the [=current Realm=]. - 1. Let |function| be [=CreateBuiltinFunction=](|realm|, |steps|, [=%FunctionPrototype%=], « \[[FunctionAddress]]). + 1. Let |function| be [=CreateBuiltinFunction=](|realm|, |steps|, [=%FunctionPrototype%=], « \[[FunctionAddress]] »). 1. Set |function|.\[[FunctionAddress]] to |funcaddr|. 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. 1. Let |functype| be [=type_func=](|store|, |funcaddr|). - 1. Let [|arguments|] β†’ [|results|] be |functype|. - 1. Let |arity| be the length of |arguments|. - 1. Perform ! [=DefinePropertyOrThrow=](|function|, `"length"`, PropertyDescriptor {\[[Value]]: |arity|, \[[Writable]]: false, \[[Enumerable]]: false, \[[Configurable]]: true}). + 1. Let [|paramTypes|] β†’ [resultTypes] be |functype|. + 1. Let |arity| be the length of |paramTypes|. + 1. Perform ! [=SetFunctionLength=](|function|, |arity|). 1. Let |name| be the [=name of the WebAssembly function=] |funcaddr|. 1. Perform ! [=SetFunctionName=](|function|, |name|). 1. [=map/Set=] |map|[|funcaddr|] to |function|. @@ -762,14 +920,15 @@ This slot holds a [=function address=] relative to the [=surrounding agent=]'s [ 5. Let |args| be an empty list of WebAssembly values. 1. Let |i| be 0. 1. For each type |t| of |parameters|, - 1. If the length of |argValues| > |i|, let |arg| be |argValues|[i]. + 1. If the length of |argValues| > |i|, let |arg| be |argValues|[|i|]. 1. Otherwise, let |arg| be undefined. 1. [=Append=] [=ToWebAssemblyValue=](|arg|, |t|) to |args|. 1. Set |i| to |i| + 1. - 1. Let (|store|, |ret|) be the result of [=invoke_func=](|store|, |funcaddr|, |args|). + 1. Let |argsSeq| be a WebAssembly [=sequence=] containing the elements of |args|. + 1. Let (|store|, |ret|) be the result of [=invoke_func=](|store|, |funcaddr|, |argsSeq|). 1. Set the [=surrounding agent=]'s [=associated store=] to |store|. 1. If |ret| is [=error=], throw an exception. This exception should be a WebAssembly {{RuntimeError}} exception, unless otherwise indicated by the WebAssembly error mapping. - 1. If |outArity| is 0, return undefined. + 1. If |ret| is empty, return undefined. 1. Otherwise, return [=ToJSValue=](|v|), where |v| is the singular element of |ret|.
@@ -778,18 +937,28 @@ Note: [=call an Exported Function|Calling an Exported Function=] executes in the Note: Exported Functions do not have a \[[Construct]] method and thus it is not possible to call one with the `new` operator.
- To create a host function from the JavaScript object |func|, perform the following steps: + To run a host function from the JavaScript object |func| and type |functype|, perform the following steps: + + 1. Let [|parameters|] β†’ [|results|] be |functype|. + 1. Assert: |results|'s [=list/size=] is at most one. + 1. If either |parameters| or |results| contains [=π—‚πŸ¨πŸ¦=], throw a {{TypeError}}. + 1. Let |arguments| be a [=list=] of the arguments of the invocation of this function. + 1. Let |jsArguments| be an empty [=list=]. + 1. For each |arg| in |arguments|, + 1. [=list/Append=] ! [=ToJSValue=](|arg|) to |jsArguments|. + 1. Let |ret| be ? [=Call=](|func|, undefined, |jsArguments|). + 1. If |results| is [=list/empty=], return undefined. + 1. Otherwise, return ? [=ToWebAssemblyValue=](|ret|, |results|[0]). +
+ +
+ To create a host function from the JavaScript object |func| and type |functype|, perform the following steps: 1. Let |hostfunc| be a [=host function=] which performs the following steps when called: - 1. If the signature contains an [=π—‚πŸ¨πŸ¦=] (as argument or result), the host function throws a {{TypeError}} when called. - 1. Let |arguments| be a [=list=] of the arguments of the invocation of this function. - 1. Let |jsArguments| be an empty [=list=]. - 1. For each |arg| in |arguments|, - 1. [=Append=] [=ToJSValue=](|arg|) to |jsArguments|. - 1. Let |ret| be ? [=Call=](|func|, undefined, |jsArguments|). If an exception is thrown, trigger a WebAssembly trap, and propagate the exception to the enclosing JavaScript. - 1. Let [|parameters|] β†’ [|results|] be |functype|. - 1. If |results| is empty, return undefined. - 1. Otherwise, return [=ToWebAssemblyValue=](|ret|, |results|[0]). + 1. Let |result| be the result of [=run a host function|running a host function=] from |func| and |functype|. + 1. Assert: |result|.\[[Type]] is throw or return. + 1. If |result|.\[[Type]] is [=throw=], then trigger a WebAssembly trap, and propagate |result|.\[[Value]] to the enclosing JavaScript. + 1. Otherwise, return |result|.\[[Value]]. 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. 1. Let (|store|, |funcaddr|) be [=alloc_func=](|store|, |functype|, |hostfunc|). 1. Set the [=surrounding agent=]'s [=associated store=] to |store|. @@ -799,21 +968,21 @@ Note: Exported Functions do not have a \[[Construct]] method and thus it is not
The algorithm ToJSValue(|w|) coerces a [=WebAssembly value=] to a JavaScript value performs the following steps: -Assert: |w| is not of the form [=π—‚πŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—=] |i64|. +1. Assert: |w| is not of the form [=π—‚πŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—=] i64. 1. If |w| is of the form [=𝗂πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—=] |i32|, return [=the Number value=] for [=signed_32=](|i32|). 1. If |w| is of the form [=𝖿πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—=] |f32|, return [=the Number value=] for |f32|. 1. If |w| is of the form [=π–ΏπŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—=] |f64|, return [=the Number value=] for |f64|. -Note: Implementations may optionally replace the NaN payload with any other NaN payload at this point in the f32 or f64 cases; such a change would not be observable through [=NumberToRawBytes=]. +Note: Number values which are equal to NaN may have various observable NaN payloads; see [=NumberToRawBytes=] for details.
The algorithm ToWebAssemblyValue(|v|, |type|) coerce a JavaScript value to a [=WebAssembly value=] performs the following steps: -Assert: |type| is not [=π—‚πŸ¨πŸ¦=]. +1. Assert: |type| is not [=π—‚πŸ¨πŸ¦=]. 1. If |type| is [=𝗂πŸ₯𝟀=], 1. Let |i32| be ? [=ToInt32=](|v|). 1. Return [=𝗂πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—=] |i32|. @@ -876,11 +1045,52 @@ 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. +
+ 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. +
+ +

Implementation-defined Limits

+ +The WebAssembly core specification allows an implementation to define limits on the syntactic structure of the module. +While each embedding of WebAssembly may choose to define its own limits, for predictability the standard WebAssembly JavaScript Interface described in this document defines the following exact limits. +An implementation must reject a module that exceeds these limits with a {{CompileError}}. +In practice, an implementation may run out of resources for valid modules below these limits. + + +

Integration with ECMAScript modules

WebAssembly modules can be used in a module graph with ECMAScript modules. -WebAssembly Module Records are a subclass of Circular Module Records which contain WebAssembly code. WebAssembly Module Records has one additional internal slot: +Because WebAssembly module instantiation is asynchronous, these semantics are built on the top-level await TC39 JavaScript proposal. + +WebAssembly Module Records are a subclass of [=Cyclic Module Record=] which contain WebAssembly code. WebAssembly Module Records has one additional internal slot: * \[[WebAssemblyModule]] : a WebAssembly {{Module}} object
@@ -894,6 +1104,7 @@ To parse a WebAssembly module given a an {{ArrayBuffer}} |body|, a Re 1. [=set/Append=] |moduleName| to |requestedModules|. 1. Return { \[[Realm]]: |realm|, \[[Environment]]: undefined, \[[Namespace]]: undefined, \[[Status]]: "uninstantiated", \[[EvaluationError]]: undefined, \[[HostDefined]]: |hostDefined|, \[[WebAssemblyModule]]: |module|, \[[RequestedModules]]: |requestedModules|, \[[DFSIndex]]: undefined, \[[DFSAncestorIndex]]: undefined }. +Note: From HTML, it's not observable when [=parse a WebAssembly module=] begins, so any work perfomed in compilation may be performed off-thread.
@@ -918,7 +1129,7 @@ WebAssembly Module Records have the following methods: 1. If the [=export name list=] of |record| contains |exportName|, return { \[[Module]]: |record|, \[[BindingName]]: |exportName| }. 1. Otherwise, return null. -

ModuleDeclarationEnvironmentSetup ( ) Concrete Method

+

InitializeEnvironment ( ) Concrete Method

1. Let |record| be this WebAssembly Module Record. 1. Let |env| be NewModuleEnvironment(null). 1. Set |record|.\[[Environment]] to |env|. @@ -926,7 +1137,7 @@ WebAssembly Module Records have the following methods: 1. For each |name| in the [=export name list=] of |record|, 1. Perform ! |envRec|.CreateImmutableBinding(|name|, true). -

ModuleExecution ( ) Concrete Method

+

ExecuteModule ( |promiseCapability| ) Concrete Method

1. Let |record| be this WebAssembly Module Record. 1. Let |module| be |record|.\[[WebAssemblyModule]]. 1. Let |imports| be a new, empty [=map=]. @@ -942,19 +1153,17 @@ WebAssembly Module Records have the following methods: 1. For each |importedName| β†’ |importedValue| of |imports|, 1. Perform ! CreateDataPropertyOrThrow(|moduleImportsObject|, |importedName|, |importedValuealue|). 1. Perform ! CreateDataPropertyOrThrow(|importsObject|, |key|, |moduleImportsObject|). -1. [=Instantiate a WebAssembly module=] |module| with imports |importsObject| and let |instance| be the result. -1. Let |envRec| be the EnvironmentRecord of |record|.\[[Environment]]. -1. For each |name| in the [=export name list=] of |record|, - 1. Perform ! |envRec|.InitializeBinding(|name|, ! Get(|instance|.\[[Exports]], |name|)). - -Note: Instantiating the WebAssembly module may yield to the task queue and is not guaranteed to be synchronous. - -

Modifications to HTML

- -The fetch a single module script algorithm, in Step 9, would switch off of the mimetype. If the response has a JavaScript mimetype, continue the algorithm. If it has a non-wasm mimetype, abort the algorithm. If it has an `application/wasm` mimetype, perform the following steps: - -1. Let |source| be |response|'s body as an {{ArrayBuffer}} -1. Create a module script, but with step 7 replacing ParseModule with the [=parse a WebAssembly Module=] algorithm. -1. Set |moduleMap|[|url|] to to |module| - -TODO: Write this up as a PR against the HTML spec. +1. [=Asynchronously instantiate a WebAssembly module=] |module| with imports |importsObject| and let |instancePromise| be the result. +1. [=Upon fulfillment=] of |instancePromise| with value |instance|: + 1. Let |envRec| be the EnvironmentRecord of |record|.\[[Environment]]. + 1. For each |name| in the [=export name list=] of |record|, + 1. Perform ! |envRec|.InitializeBinding(|name|, ! Get(|instance|.\[[Exports]], |name|)). + 1. Perform ! Call(|promiseCapability|.\[[Resolve]], undefined, undefined). +1. [=Upon rejection=] of |instancePromise| with reason |r|: + 1. Perform ! Call(|promiseCapability|.\[[Reject]], undefined, |r|). + 1. [=Reject=] |promiseCapability| with |r|. + Note: exported bindings are left uninitialized, i.e., in TDZ. + +Note: In the synchronous branch of the top-level await proposal, add the following additional algorithm step: "Set |module|.\[[EvaluationResult]] to |promiseCapability|.\[[Promise]]." to indicate that instantiating WebAssembly modules is always asynchronous. + +Note: See corresponding modifications to HTML in PR #4372.