Note: This document is no longer being updated. Please see the normative documentation.
In the MVP, the only way to access WebAssembly on the Web is through
an explicit JS API which is defined below.
(In the future 🦄, WebAssembly may also
be loaded and run directly from an HTML <script type='module'> tag—and
any other Web API that loads ES6 modules via URL—as part of
ES6 Module integration.)
WebAssembly JS API declaration file for TypeScript can be found here which enable autocompletion and make TypeScript compiler happy.
Whenever WebAssembly semantics specify a trap,
a WebAssembly.RuntimeError object is thrown. WebAssembly code (currently)
has no way to catch this exception and thus the exception will necessarily
propagate to the enclosing non-WebAssembly caller (either the browser or
JavaScript) 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.
Whenever a stack overflow is happening in WebAssembly code, the same exception is thrown as for a stack overflow in JavaScript.
Whenever validation, compilation or instantiation run out of memory, the same exception is thrown as for out of memory conditions in JavaScript.
The WebAssembly object is the initial value of the WebAssembly property of
the global object. Like the Math and JSON objects, the WebAssembly object
is a plain JS object (not a constructor or function) that acts like a namespace
and has the following properties:
The initial value of the @@toStringTag
property is the String value "WebAssembly".
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
The following intrinsic objects are added:
WebAssembly.Module: theWebAssembly.ModuleconstructorWebAssembly.Instance: theWebAssembly.InstanceconstructorWebAssembly.Memory: theWebAssembly.MemoryconstructorWebAssembly.Table: theWebAssembly.TableconstructorWebAssembly.CompileError: a NativeError which indicates an error during WebAssembly decoding or validationWebAssembly.LinkError: a NativeError which indicates an error during WebAssembly instantiating a module (other than traps from the start function)WebAssembly.RuntimeError: a NativeError which is thrown whenever WebAssembly specifies a trap.
The validate function has the signature:
Boolean validate(BufferSource bytes)
If the given bytes argument is not a
BufferSource,
then a TypeError is thrown.
Otherwise, this function performs validation as defined by the WebAssembly
specification and returns true if validation succeeded, false if validation failed.
The compile function has the signature:
Promise<WebAssembly.Module> compile(BufferSource bytes)
If the given bytes argument is not a
BufferSource,
the returned Promise is rejected
with a TypeError.
Otherwise, this function starts an asynchronous task to compile a WebAssembly.Module
as described in the WebAssembly.Module constructor.
On success, the Promise is fulfilled
with the resulting WebAssembly.Module object. On failure, the Promise is
rejected with a
WebAssembly.CompileError.
The asynchronous compilation is logically performed on a copy of the state of
the given BufferSource captured during the call to compile; subsequent mutations
of the BufferSource after compile return do not affect ongoing compilations.
The instantiate function is overloaded based on types of its arguments.
If neither of the following overloads match, then the returned Promise is
rejected
with a TypeError.
dictionary WebAssemblyInstantiatedSource {
required WebAssembly.Module module;
required WebAssembly.Instance instance;
};
Promise<WebAssemblyInstantiatedSource>
instantiate(BufferSource bytes [, importObject])
If the given bytes argument is not a
BufferSource,
the returned Promise is rejected
with a TypeError.
This function starts an asynchronous task that first compiles a WebAssembly.Module
from bytes as described in the WebAssembly.Module constructor
and then queue a task to instantiate the resulting Module with importObject as described in the
WebAssembly.Instance constructor. After the instantiation task runs
and before any subsequent steps are taken, other unspecified asynchronous tasks may be run.
On success, the Promise is fulfilled
with a plain JavaScript object pair {module, instance} containing the resulting
WebAssembly.Module and WebAssembly.Instance. The 2 properties module and instance of the returned pair are configurable, enumerable and writable.
On failure, the Promise is
rejected with a
WebAssembly.CompileError, WebAssembly.LinkError, or WebAssembly.RuntimeError, depending on the cause of failure.
The asynchronous compilation is logically performed on a copy of the state of
the given BufferSource captured during the call to instantiate; subsequent mutations
of the BufferSource after instantiate return do not affect ongoing compilations.
Promise<WebAssembly.Instance> instantiate(moduleObject [, importObject])
This description applies if the first argument is a WebAssembly.Module instance.
This function asynchronously queues a task that instantiates a WebAssembly.Instance
from moduleObject and importObject as described in the
WebAssembly.Instance constructor. After the instantiation task runs
and before any subsequent steps are taken, other unspecified asynchronous tasks may be run.
On success, the Promise is fulfilled
with the resulting WebAssembly.Instance object. On failure, the Promise is
rejected with a
WebAssembly.CompileError, WebAssembly.LinkError, or WebAssembly.RuntimeError, depending on the cause of failure.
A WebAssembly.Module object represents the stateless result of compiling a
WebAssembly binary-format module and contains one internal slot:
- [[Module]] : an
Ast.modulewhich is the spec definition of a module
The WebAssembly.Module constructor has the signature:
new Module(BufferSource bytes)
If the NewTarget is undefined, a TypeError
exception is thrown (i.e., this constructor cannot be called as a function without new).
If the given bytes argument is not a
BufferSource,
a TypeError
exception is thrown.
Otherwise, this function performs synchronous compilation of the BufferSource:
- The byte range delimited by the
BufferSourceis first logically decoded according to BinaryEncoding.md and then validated according to the rules in spec/valid.ml. - The spec
stringvalues insideAst.moduleare decoded as UTF8 as described in Web.md. - On success, a new
WebAssembly.Moduleobject is returned with [[Module]] set to the validatedAst.module. - On failure, a new
WebAssembly.CompileErroris thrown.
The initial value of the @@toStringTag
property is the String value "WebAssembly.Module".
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
The exports function has the signature:
Array exports(moduleObject)
If moduleObject is not a WebAssembly.Module, a TypeError
is thrown.
This function returns a new Array every time it is called. Each such Array is produced by mapping each
Ast.export
e of moduleObject.[[Module]].exports
to the Object { name: String(e.name), kind: e.ekind } where e.name is decoded as UTF8
and e.ekind is mapped to one of the String values "function", "table", "memory", "global".
Note: other fields like signature may be added in the future.
The returned Array is populated in the same order exports appear in the WebAssembly binary's exports table.
The imports function has the signature:
Array imports(moduleObject)
If moduleObject is not a WebAssembly.Module, a TypeError
is thrown.
This function returns a new Array every time it is called. Each such Array is produced by mapping each
Ast.import
i of moduleObject.[[Module]].imports
to the Object { module: String(i.module_name), name: String(i.item_name), kind: i.ikind } where
i.module_name and i.item_name are decoded as UTF8 and
i.ikind is mapped to one of the String values "function", "table", "memory", "global".
Note: other fields like signature may be added in the future.
The returned Array is populated in the same order imports appear in the WebAssembly binary's imports table.
The customSections function has the signature:
Array customSections(moduleObject, sectionName)
If moduleObject is not a WebAssembly.Module, a TypeError
is thrown.
Let sectionNameString be the result of ToString(sectionName).
This function returns a new Array every time it is called. Each such Array is produced by mapping each
custom section (i.e., section with
id 0) whose name field (decoded as UTF-8) is equal to
sectionNameString to an ArrayBuffer containing a copy of the section's
payload_data. (Note: payload_data does not include name or name_len.).
The Array is populated in the same order custom sections appear in the WebAssembly binary.
A WebAssembly.Module is a
cloneable object
which means it can be cloned between windows/workers and also
stored/retrieved into/from an IDBObjectStore.
The semantics of a structured clone is as-if the binary source, from which the
WebAssembly.Module was compiled, were cloned and recompiled into the target realm.
Engines should attempt to share/reuse internal compiled code when performing
a structured clone although, in corner cases like CPU upgrade or browser
update, this may not be possible and full recompilation may be necessary.
Given the above engine optimizations, structured cloning provides developers explicit control over both compiled-code caching and cross-window/worker code sharing.
A WebAssembly.Instance object represents the instantiation of a
WebAssembly.Module into a
realm and has one
internal slot:
- [[Instance]] : an
Instance.instancewhich is the WebAssembly spec definition of an instance - [[Exports]] : the exports object created during instantiation
The WebAssembly.Instance constructor has the signature:
new Instance(moduleObject [, importObject])
If the NewTarget is undefined, a TypeError
exception is thrown (i.e., this
constructor cannot be called as a function without new).
If moduleObject is not a WebAssembly.Module, a TypeError
is thrown.
Let module be the Ast.module
moduleObject.[[Module]].
If the importObject parameter is not undefined and Type(importObject) is
not Object, a TypeError
is thrown. If the list of
module.imports
is not empty and Type(importObject) is not Object, a TypeError
is thrown.
Note: Imported JavaScript functions are wrapped as host function values in the following algorithm. For the purpose of the algorithm, a new host function value is always generated fresh and considered distinct from any other previously created host function value, including those wrapping the same JavaScript function object. Consequently, two closure values are considered equal if and only if:
- Either they are both WebAssembly functions for the same instance and referring to the same function definition.
- Or they are the same host function value.
Let funcs, memories and tables be initially-empty lists of callable JavaScript objects, WebAssembly.Memory objects and WebAssembly.Table objects, respectively.
Let imports be an initially-empty list of external values.
For each import
i in module.imports:
- Let
obe the resultant value of performingGet(importObject,i.module_name). - If
Type(o)is not Object, throw aTypeError. - Let
vbe the value of performingGet(o,i.item_name) - If
iis a function import:- If
IsCallable(v)isfalse, throw aWebAssembly.LinkError. - If
vis an Exported Function Exotic Object:- (The signature of
v.[[Closure]]is checked against the import's declaredfunc_typebyEval.initbelow.) - Let
closurebev.[[Closure]].
- (The signature of
- Otherwise:
- Let
closurebe a new host function value of the given signature and the following behavior: - If the signature contains an
i64(as argument or result), the host function immediately throws aTypeErrorwhen called. - Otherwise, the host function calls
vwith anundefinedreceiver and WebAssembly arguments coerced to JavaScript arguments viaToJSValue. The result is returned by coercing viaToWebAssemblyValue.
- Let
- Append
vtofuncs. - Append
closuretoimports.
- If
- If
iis a global import:- Assert: the global is immutable by MVP validation constraint.
- If the
global_typeofiisi64orType(v)is not Number, throw aWebAssembly.LinkError. - Append
ToWebAssemblyValue(v)toimports.
- If
iis a memory import:- If
vis not aWebAssembly.Memoryobject, throw aWebAssembly.LinkError. - (The imported
Memory'slengthandmaximumproperties are checked against the import's declaredmemory_typebyEval.initbelow.) - Append
vtomemories. - Append
v.[[Memory]]toimports.
- If
- Otherwise (
iis a table import):- If
vis not aWebAssembly.Tableobject, throw aWebAssembly.LinkError. - (The imported
Table'slength,maximumandelementproperties are checked against the import's declaredtable_typebyEval.initbelow.) - Append
vtotables. - Append
v.[[Table]]toimports. - For each index
iofv.[[Table]]:- Let
ebe theithe element ofv.[[Table]].
- Let
- If
eis aclosurec:- Append the
ith element ofv.[[Values]]tofuncs.
- Append the
- If
Let instance be the result of creating a new
instance
by calling
Eval.init
given module and imports.
If this terminates with a Link error, throw a WebAssembly.LinkError; if it causes a trap, throw a WebAssembly.RuntimeError; all other exceptions are propagated to the caller.
Among other things, this function performs the following observable steps:
-
If, after evaluating the
offsetinitializer expression of every Data and Element Segment, any of the segments do not fit in their respective Memory or Table, throw aWebAssembly.LinkError. -
Apply all Data and Element segments to their respective Memory or Table in the order in which they appear in the module. Segments may overlap and, if they do, the final value is the last value written in order. Note: there should be no errors possible that would cause this operation to fail partway through. After this operation completes, elements of
instanceare visible and callable through imported tables, even ifstartfails. -
If a
startis present, it is evaluated. Any errors thrown bystartare propagated to the caller.
The following steps are performed before the start function executes:
- For each table 't' in
instance.tables:- If there is no element in
tableswhosetable.[[Table]]ist:- Let
tablebe a newWebAssembly.Tableobject with [[Table]] set totand [[Values]] set to a new list of the same length all whose entries arenull. - Append
tabletotables.
- Let
- Otherwise:
- Let
tablebe the element intableswhosetable.[[Table]]ist
- Let
- (Note: At most one
WebAssembly.Tableobject is created for any table, so the abovetableis unique, even if there are multiple occurrances in the list. Moreover, if the item was an import, the original object will be found.) - For each index
ioft:- Let
cbe theith element oft - If
cis aclosurec:- If there is an Exported Function Exotic Object in
funcswhose[[Closure]]equalsc:- Let
funcbe that function object.
- Let
- (Note: At most one wrapper is created for any closure, so
funcis uniquely determined. Moreover, if the item was an import that is already an Exported Function Exotic Object, then the original function object will be found. For imports that are regular JS functions, a new wrapper will be created.) - Otherwise:
- Let
funcbe an Exported Function Exotic Object created fromc. - Append
functofuncs.
- Let
- Set the
ith element oftable.[[Values]]tofunc.
- If there is an Exported Function Exotic Object in
- Let
- If there is no element in
(Note: The table and element function objects created by the above steps are only observable for tables that are either imported or exported.)
Let exports be a list of (string, JS value) pairs that is mapped from
each external value e in instance.exports as follows:
- If
eis a closurec:- If there is an Exported Function Exotic Object
funcinfuncswhosefunc.[[Closure]]equalsc, then returnfunc. - (Note: At most one wrapper is created for any closure, so
funcis unique, even if there are multiple occurrances in the list. Moreover, if the item was an import that is already an Exported Function Exotic Object, then the original function object will be found. For imports that are regular JS functions, a new wrapper will be created.) - Otherwise:
- Let
funcbe an Exported Function Exotic Object created fromc. - Append
functofuncs. - Return
func.
- Let
- If there is an Exported Function Exotic Object
- If
eis a globalv: - If
eis a memorym:- If there is an element
memoryinmemorieswhosememory.[[Memory]]ism, then returnmemory. - (Note: At most one
WebAssembly.Memoryobject is created for any memory, so the abovememoryis unique, even if there are multiple occurrances in the list. Moreover, if the item was an import, the original object will be found.) - Otherwise:
- Let
memorybe a newWebAssembly.Memoryobject created viaCreateMemoryObjectfromm. - Append
memorytomemories. - Return
memory.
- Let
- If there is an element
- Otherwise
emust be a tablet:- Assert: There is an element
tableintableswhosetable.[[Table]]ist. - Return that
table.
- Assert: There is an element
Let exportsObject be a new frozen
plain JS object with [[Prototype]] set to Null and with properties defined
by mapping each export in exports to an enumerable, non-writable,
non-configurable data property. Note: the validity and uniqueness checks
performed during module validation ensure
that each property name is valid and no properties are defined twice.
Let instanceObject be a new WebAssembly.Instance object setting
the internal [[Instance]] slot to instance and the [[Exports]] slot to
exportsObject.
Return instanceObject.
The initial value of the @@toStringTag
property is the String value "WebAssembly.Instance".
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
This is an accessor property whose [[Set]] is Undefined and whose [[Get]] accessor function performs the following steps:
Let T be the this value. If T is not a WebAssembly.Instance, a TypeError
is thrown.
Return T.[[Exports]].
A function with function index index
from an Instance inst is reflected to JS via a new kind of Exported
Function Exotic Object.
Like Bound Function Exotic Object,
Exported Functions do not have the normal function internal slots but instead have:
- [[Closure]] : the closure
(
index,inst)
as well as the internal slots required of all builtin functions:
- [[Prototype]] : %FunctionPrototype%
- [[Extensible]] :
true - [[Realm]] : the current Realm Record
- [[ScriptOrModule]] :
GetActiveScriptOrModule
Exported Functions also have the following data properties:
- the
lengthproperty is set to the exported function's signature's arity - the
nameis set toToString(index)
WebAssembly Exported Functions have a [[Call]](this, argValues) method defined as:
- Let
sigbe thefunction typeof the function's [[Closure]]. - If
sigcontains ani64(as argument or result), aTypeErroris thrown each time the [[Call]] method is invoked. - Let
argsbe an empty list of coerced values. - Let
inAritybe the number of arguments andoutAritybe the number of results insig. - For all values
vinargValues, in the order of their appearance: - If the length of
argsis less thaninArity, appendToWebAssemblyValue(v)toargs. - While the length of
argsis less thaninArity, appendToWebAssemblyValue(undefined)toargs. - Let
retbe the result of callingEval.invokepassing [[Closure]], andargs. - If
outArityis 0, returnundefined. - Otherwise, return
ToJSValue(v), wherevis the singular element ofret.
[[Call]](this, argValues) executes in the [[Realm]] of the callee Exported Function. This corresponds to the requirements of builtin function objects in JavaScript.
Exported Functions do not have a [[Construct]] method and thus it is not possible to
call one with the new operator.
A WebAssembly.Memory object contains a single linear memory
which can be simultaneously referenced by multiple Instance objects. Each
Memory object has two internal slots:
- [[Memory]] : a
Memory.memory - [[BufferObject]] : the current
ArrayBufferwhose [[ArrayBufferByteLength]] matches the current byte length of [[Memory]]
The WebAssembly.Memory constructor has the signature:
new Memory(memoryDescriptor)
If the NewTarget is undefined, a TypeError
exception is thrown (i.e., this constructor cannot be called as a function without new).
If Type(memoryDescriptor) is not Object, a TypeError
is thrown.
Let initial be ToNonWrappingUint32(Get(memoryDescriptor, "initial")).
If HasProperty("maximum"),
then let maximum be ToNonWrappingUint32(Get(memoryDescriptor, "maximum")).
If maximum is smaller than initial, then throw a RangeError.
Otherwise, let maximum be None.
Let memory be the result of calling
Memory.create
given arguments initial and maximum. Note that initial and maximum are
specified in units of WebAssembly pages (64KiB).
Return the result of CreateMemoryObject(memory).
Given a Memory.memory
m, to create a WebAssembly.Memory:
Let buffer be a new ArrayBuffer whose
[[ArrayBufferData]]
aliases m and whose
[[ArrayBufferByteLength]]
is set to the byte length of m.
Any attempts to detach buffer other than
the detachment performed by m.grow shall throw a
TypeError
Return a new WebAssembly.Memory instance with [[Memory]] set to m and
[[BufferObject]] set to buffer.
The initial value of the @@toStringTag
property is the String value "WebAssembly.Memory".
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
The grow method has the signature:
grow(delta)
Let M be the this value. If M is not a WebAssembly.Memory,
a TypeError
is thrown.
Let d be ToNonWrappingUint32(delta).
Let ret be the current size of memory in pages (before resizing).
Perform Memory.grow
with delta d. On failure, a
RangeError
is thrown.
Perform DetachArrayBuffer(M.[[BufferObject]]).
Assign to M.[[BufferObject]] a new ArrayBuffer whose
[[ArrayBufferData]]
aliases M.[[Memory]] and whose
[[ArrayBufferByteLength]]
is set to the new byte length of M.[[Memory]].
Return ret as a Number value.
This is an accessor property whose [[Set]] is Undefined and whose [[Get]] accessor function performs the following steps:
If this is not a WebAssembly.Memory, a TypeError
is thrown. Otherwise return M.[[BufferObject]].
A WebAssembly.Table object contains a single table
which can be simultaneously referenced by multiple Instance objects. Each
Table object has two internal slots:
- [[Table]] : a
Table.table - [[Values]] : an array whose elements are either
nullor Exported Function Exotic Object
The WebAssembly.Table constructor has the signature:
new Table(tableDescriptor)
If the NewTarget is undefined, a TypeError
exception is thrown (i.e., this constructor cannot be called as a function without new).
If Type(tableDescriptor) is not Object, a TypeError
is thrown.
Let element be the result of calling Get(tableDescriptor, "element").
If element is not the string "anyfunc", a TypeError
is thrown.
(Note: this check is intended to be relaxed in the
future 🦄 to allow different element types.)
Let initial be ToNonWrappingUint32(Get(tableDescriptor, "initial")).
If HasProperty("maximum"),
then let maximum be ToNonWrappingUint32(Get(tableDescriptor, "maximum")). Otherwise, let maximum be None.
If maximum is not None and is smaller than initial, then throw a RangeError.
Let table be the result of calling
Table.create
given arguments AnyFuncType, initial and maximum.
Let values be a new empty array of initial elements, all with value
null.
Return a new WebAssemby.Table instance with [[Table]] set to table and
[[Values]] set to values.
This is an accessor property whose [[Set]] is Undefined and whose [[Get]] accessor function performs the following steps:
Let T be the this value. If T is not a WebAssembly.Table, a TypeError
is thrown.
Return T.[[Values]].length.
The grow method has the signature:
grow(delta)
Let T be the this value. If T is not a WebAssembly.Table,
a TypeError
is thrown.
Let d be ToNonWrappingUint32(delta).
Let ret be the current length of the table (before resizing).
Perform Table.grow,
with delta d. On failure, a
RangeError
is thrown.
Return ret as a Number value.
This method has the following signature
get(index)
Let T be the this value. If T is not a WebAssembly.Table, a TypeError
is thrown.
Let i be the result of ToNonWrappingUint32(index).
If i is greater or equal than the length of T.[[Values]], a RangeError is thrown.
Return T.[[Values]][i].
This method has the following signature
set(index, value)
Let T be the this value. If T is not a WebAssembly.Table, a TypeError
is thrown.
If value is not an Exported Function Exotic Object
or null, throw a TypeError.
Let i be the result of ToNonWrappingUint32(index).
If i is greater or equal than the length of T.[[Values]], a RangeError is thrown.
If value is null, let elem be Uninitialized;
otherwise, let elem be value.[[Closure]].
Set T.[[Table]][i] to elem.
Set T.[[Values]][i] to value.
Return undefined.
The initial value of the @@toStringTag
property is the String value "WebAssembly.Table".
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
To coerce a WebAssembly value
to a JavaScript value:
Assert: the WebAssembly value's type is not i64.
- given a WebAssembly
i32is interpreted as a signed integer, converted (losslessly) to an IEEE754 double and then returned as a JavaScript Number - given a WebAssembly
f32(single-precision IEEE754), convert (losslessly) to a IEEE754 double, possibly canonicalize NaN, and return as a JavaScript Number - given a WebAssembly
f64, possibly canonicalize NaN and return as a JavaScript Number
If the WebAssembly value is optional, then given None, return JavaScript value
undefined.
To coerce a JavaScript value to a given WebAssembly value type,
Assert: the target value type is not i64.
- coerce to
i32viaToInt32(v) - coerce to
f32by first applyingToNumber(v)and then converting the resulting IEEE754 64-bit double to a 32-bit float usingroundTiesToEven - coerce to
f64viaToNumber(v)
If the value type is optional, then given None, the JavaScript value is
ignored.
To convert a JavaScript value v to an unsigned integer in the range [0, UINT32_MAX]:
Let i be ToInteger(v).
If i is negative or greater than UINT32_MAX,
RangeError
is thrown.
Return i.
Given demo.was (encoded to demo.wasm):
(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:
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()
);