WebAssembly JavaScript Interface

Editor’s Draft,

More details about this document
This version:
https://webassembly.github.io/spec/js-api/
Latest published version:
https://www.w3.org/TR/wasm-js-api-2/
Feedback:
GitHub
Inline In Spec
Editor:
Ms2ger (Igalia)
Issue Tracking:
GitHub Issues

Abstract

This document provides an explicit JavaScript API for interacting with WebAssembly.

This is part of a collection of related documents: the Core WebAssembly Specification, the WebAssembly JS Interface, and the WebAssembly Web API.

Status of this document

This is a public copy of the editors’ draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don’t cite this document other than as work in progress.

GitHub Issues are preferred for discussion of this specification. All issues and comments are archived.

This document was produced by the WebAssembly Working Group.

This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 03 November 2023 W3C Process Document.

This API provides a way to access WebAssembly [WEBASSEMBLY] through a bridge to explicitly construct modules from JavaScript [ECMASCRIPT].

1. Sample API Usage

This section is non-normative.

Given demo.wat (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()
);

2. Notation

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.

3. Internal storage

3.1. Interaction of the WebAssembly Store with JavaScript

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 associated store. 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 identified with 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.

3.2. WebAssembly JS Object Caches

Note: There are several WebAssembly objects that may have a corresponding JavaScript object. The correspondence is stored in a per-agent mapping from WebAssembly addresses 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 maps:

4. The WebAssembly Namespace

dictionary WebAssemblyInstantiatedSource {
    required Module module;
    required Instance instance;
};

dictionary WebAssemblyCompileOptions {
    USVString? importedStringConstants;
    sequence<USVString> builtins;
};

[Exposed=*]
namespace WebAssembly {
    boolean validate(BufferSource bytes, optional WebAssemblyCompileOptions options);
    Promise<Module> compile(BufferSource bytes, optional WebAssemblyCompileOptions options);

    Promise<WebAssemblyInstantiatedSource> instantiate(
        BufferSource bytes, optional object importObject, optional WebAssemblyCompileOptions options);

    Promise<Instance> instantiate(
        Module moduleObject, optional object importObject);

    readonly attribute Tag JSTag;
};
To compile a WebAssembly module from source bytes bytes, perform the following steps:
  1. Let module be module_decode(bytes). If module is error, return error.

  2. If module_validate(module) is error, return error.

  3. Return module.

To validate builtins and imported string for a WebAssembly module from module module, enabled builtins builtinSetNames, and importedStringModule, perform the following steps:
  1. If validating builtin set names for builtinSetNames is false, return false.

  2. For each import of module_imports(module),

    1. If importedStringModule is not null and import[0] equals importedStringModule,

      1. Let importExternType be import[2]

      2. Let stringExternType be global const (ref extern)

      3. If match_externtype(stringExternType, importExternType) is false, return false

    2. Else,

      1. If validating a import for builtin with import and builtinSetNames is false, return false.

  3. Return true.

The validate(bytes, options) method, when invoked, performs the following steps:
  1. Let stableBytes be a copy of the bytes held by the buffer bytes.

  2. Compile stableBytes as a WebAssembly module and store the results as module.

  3. If module is error, return false.

  4. Let builtinSetNames be options["builtins"]

  5. Let importedStringModule be options["importedStringConstants"]

  6. If validating builtins and imported strings for module with builtinSetNames and importedStringModule returns false, return false.

  7. Return true.

A Module object represents a single WebAssembly module. Each Module object has the following internal slots:

To construct a WebAssembly module object from a module module, source bytes bytes, enabled builtins builtinSetNames, and importedStringModule, perform the following steps:
  1. Let moduleObject be a new Module object.

  2. Set moduleObject.[[Module]] to module.

  3. Set moduleObject.[[Bytes]] to bytes.

  4. Set moduleObject.[[BuiltinSets]] to builtinSetNames.

  5. Set moduleObject.[[ImportedStringModule]] to importedStringModule.

  6. Return moduleObject.

To asynchronously compile a WebAssembly module from source bytes bytes and WebAssemblyCompileOptions options using optional task source taskSource, perform the following steps:
  1. Let promise be a new promise.

  2. Run the following steps in parallel:

    1. Compile the WebAssembly module bytes and store the result as module.

    2. Queue a task to perform the following steps. If taskSource was provided, queue the task on that task source.

      1. If module is error, reject promise with a CompileError exception.

      2. Let builtinSetNames be options["builtins"]

      3. Let importedStringModule be options["importedStringConstants"]

      4. If validating builtins and imported strings for module with builtinSetNames and importedStringModule is false, reject promise with a CompileError exception.

      5. Otherwise,

        1. Construct a WebAssembly module object from module, bytes, builtinSetNames, importedStringModule, and let moduleObject be the result.

        2. Resolve promise with moduleObject.

  3. Return promise.

The compile(bytes, options) method, when invoked, performs the following steps:
  1. Let stableBytes be a copy of the bytes held by the buffer bytes.

  2. Asynchronously compile a WebAssembly module from stableBytes using options and return the result.

To instantiate imported strings with module module and importedStringModule, perform the following steps:
  1. Assert: importedStringModule is not null.

  2. Let exportsObject be ! OrdinaryObjectCreate(null).

    1. If externtype is of the form func functype,

  3. For each (moduleName, componentName, externtype) of module_imports(module),

    1. If moduleName does not equal importedStringModule, then continue.

    2. Let stringConstant be componentName.

    3. Let status be ! CreateDataProperty(exportsObject, stringConstant, stringConstant).

    4. Assert: status is true.

  4. Return exportsObject.

To read the imports from a WebAssembly module module from imports object importObject, enabled builtins builtinSetNames, and importedStringModule, perform the following steps:
  1. If module.imports is not empty, and importObject is undefined, throw a TypeError exception.

  2. Let builtinOrStringImports be the ordered map « ».

  3. For each builtinSetName of builtinSetNames,

    1. Assert: builtinOrStringImports does not contain builtinSetName

    2. If builtinSetName does not refer to a builtin set, then continue.

    3. Let exportsObject be the result of instantiate a builtin set with builtinSetName

    4. Let builtinSetQualifiedName be builtinSetName prefixed with "wasm:"

    5. Set builtinOrStringImports[builtinSetQualifiedName] to exportsObject

  4. If importedStringModule is not null,

    1. Let exportsObject be the result of instantiate imported strings with module and importedStringModule

    2. Set builtinOrStringImports[importedStringModule] to exportsObject

  5. Let imports be « ».

  6. For each (moduleName, componentName, externtype) of module_imports(module),

    1. If builtinOrStringImports contains moduleName,

      1. Let o be builtinOrStringImports[moduleName]

    2. Else,

      1. Let o be ? Get(importObject, moduleName).

    3. If Type(o) is not Object, throw a TypeError exception.

    4. Let v be ? Get(o, componentName).

    5. If externtype is of the form func functype,

      1. If IsCallable(v) is false, throw a LinkError exception.

      2. 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.

      3. Otherwise,

        1. Create a host function from v and functype, and let funcaddr be the result.

        2. Let index be the number of external functions in imports. This value index is known as the index of the host function funcaddr.

      4. Let externfunc be the external value func funcaddr.

      5. Append externfunc to imports.

    6. If externtype is of the form global mut valtype,

      1. If v implements Global,

        1. Let globaladdr be v.[[Global]].

      2. Otherwise,

        1. If valtype is i64 and Type(v) is not BigInt,

          1. Throw a LinkError exception.

        2. If valtype is one of i32, f32 or f64 and Type(v) is not Number,

          1. Throw a LinkError exception.

        3. If valtype is v128,

          1. Throw a LinkError exception.

        4. Let value be ToWebAssemblyValue(v, valtype). If this operation throws a TypeError, catch it, and throw a LinkError exception.

        5. Let store be the surrounding agent's associated store.

        6. Let (store, globaladdr) be global_alloc(store, const valtype, value).

        7. Set the surrounding agent's associated store to store.

      3. Let externglobal be global globaladdr.

      4. Append externglobal to imports.

    7. If externtype is of the form mem memtype,

      1. If v does not implement Memory, throw a LinkError exception.

      2. Let externmem be the external value mem v.[[Memory]].

      3. Append externmem to imports.

    8. If externtype is of the form table tabletype,

      1. If v does not implement Table, throw a LinkError exception.

      2. Let tableaddr be v.[[Table]].

      3. Let externtable be the external value table tableaddr.

      4. Append externtable to imports.

    9. If externtype is of the form tag attribute functype,

      1. Assert: attribute is exception.

      2. If v does not implement Tag, throw a LinkError exception.

      3. Let tagaddr be v.[[Address]].

      4. Let externtag be the external value tag tagaddr.

      5. Append externtag to imports.

  7. 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.

To create an exports object from a WebAssembly module module and instance instance, perform the following steps:
  1. Let exportsObject be ! OrdinaryObjectCreate(null).

  2. For each (name, externtype) of module_exports(module),

    1. Let externval be instance_export(instance, name).

    2. Assert: externval is not error.

    3. If externtype is of the form func functype,

      1. Assert: externval is of the form func funcaddr.

      2. Let func funcaddr be externval.

      3. Let func be the result of creating a new Exported Function from funcaddr.

      4. Let value be func.

    4. If externtype is of the form global mut globaltype,

      1. Assert: externval is of the form global globaladdr.

      2. Let global globaladdr be externval.

      3. Let global be a new Global object created from globaladdr.

      4. Let value be global.

    5. If externtype is of the form mem memtype,

      1. Assert: externval is of the form mem memaddr.

      2. Let mem memaddr be externval.

      3. Let memory be a new Memory object created from memaddr.

      4. Let value be memory.

    6. If externtype is of the form table tabletype,

      1. Assert: externval is of the form table tableaddr.

      2. Let table tableaddr be externval.

      3. Let table be a new Table object created from tableaddr.

      4. Let value be table.

    7. If externtype is of the form tag attribute functype,

      1. Assert: attribute is exception.

      2. Assert: externval is of the form tag tagaddr.

      3. Let tag tagaddr be externval.

      4. Let tag be a new Tag object created from tagaddr.

      5. Let value be tag.

    8. Let status be ! CreateDataProperty(exportsObject, name, value).

    9. 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.

  3. Perform ! SetIntegrityLevel(exportsObject, "frozen").

  4. Return exportsObject.

To initialize an instance object 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.

  2. Set instanceObject.[[Instance]] to instance.

  3. Set instanceObject.[[Exports]] to exportsObject.

To instantiate the core of a WebAssembly module from a module module and imports imports, perform the following steps:
  1. Let store be the surrounding agent's associated store.

  2. Let result be module_instantiate(store, module, imports).

  3. 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 the WebAssembly error mapping.

  4. Let (store, instance) be result.

  5. Set the surrounding agent's associated store to store.

  6. Return instance.

To asynchronously instantiate a WebAssembly module from a Module moduleObject and imports importObject, perform the following steps:
  1. Let promise be a new promise.

  2. Let module be moduleObject.[[Module]].

  3. Let builtinSetNames be moduleObject.[[BuiltinSets]].

  4. Let importedStringModule be moduleObject.[[ImportedStringModule]].

  5. 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.

  6. 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.

      2. Let instanceObject be a new Instance.

      3. Initialize instanceObject from module and instance. If this throws an exception, catch it, reject promise with the exception, and terminate these substeps.

      4. Resolve promise with instanceObject.

  7. Return promise.

To instantiate a promise of a module promiseOfModule with imports importObject, perform the following steps:
  1. Let promise be a new promise.

  2. Upon fulfillment of promiseOfModule with value module:

    1. Instantiate the WebAssembly module module importing importObject, and let innerPromise be the result.

    2. Upon fulfillment of innerPromise with value instance.

      1. Let result be the WebAssemblyInstantiatedSource value «[ "module" → module, "instance" → instance ]».

      2. Resolve promise with result.

    3. Upon rejection of innerPromise with reason reason:

      1. Reject promise with reason.

  3. Upon rejection of promiseOfModule with reason reason:

    1. Reject promise with reason.

  4. Return promise.

The instantiate(bytes, importObject, options) method, when invoked, performs the following steps:
  1. Let stableBytes be a copy of the bytes held by the buffer bytes.

  2. Asynchronously compile a WebAssembly module from stableBytes using options and let promiseOfModule be the result.

  3. Instantiate promiseOfModule with imports importObject and return the result.

The instantiate(moduleObject, importObject) method, when invoked, performs the following steps:
  1. Asynchronously instantiate the WebAssembly module moduleObject importing importObject, and return the result.

Note: A follow-on streaming API is documented in the WebAssembly Web API.

The getter of the JSTag attribute of the WebAssembly Namespace, when invoked, performs the following steps:

  1. Let JSTagAddr be the result of getting the JavaScript exception tag.

  2. Let JSTagObject be the result of creating a Tag object from JSTagAddr.

  3. Return JSTagObject.

4.1. Modules

enum ImportExportKind {
  "function",
  "table",
  "memory",
  "global",
  "tag"
};

dictionary ModuleExportDescriptor {
  required USVString name;
  required ImportExportKind kind;
  // Note: Other fields such as signature may be added in the future.
};

dictionary ModuleImportDescriptor {
  required USVString module;
  required USVString name;
  required ImportExportKind kind;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Module {
  constructor(BufferSource bytes, optional WebAssemblyCompileOptions options);
  static sequence<ModuleExportDescriptor> exports(Module moduleObject);
  static sequence<ModuleImportDescriptor> imports(Module moduleObject);
  static sequence<ArrayBuffer> customSections(Module moduleObject, DOMString sectionName);
};
The string value of the extern type type is
The exports(moduleObject) method, when invoked, performs the following steps:
  1. Let module be moduleObject.[[Module]].

  2. Let exports be « ».

  3. For each (name, type) of module_exports(module),

    1. Let kind be the string value of the extern type type.

    2. Let obj be «[ "name" → name, "kind" → kind ]».

    3. Append obj to exports.

  4. Return exports.

The imports(moduleObject) method, when invoked, performs the following steps:
  1. Let module be moduleObject.[[Module]].

  2. Let builtinSetNames be moduleObject.[[BuiltinSets]].

  3. Let importedStringModule be moduleObject.[[ImportedStringModule]].

  4. Let imports be « ».

  5. For each (moduleName, name, type) of module_imports(module),

    1. If find a builtin for (moduleName, name, type) and builtinSetNames is not null, then continue

    2. If importedStringModule is not null and moduleName equals importedStringModule, then continue

    3. Let kind be the string value of the extern type type.

    4. Let obj be «[ "module" → moduleName, "name" → name, "kind" → kind ]».

    5. Append obj to imports.

  6. Return imports.

The customSections(moduleObject, sectionName) method, when invoked, performs the following steps:
  1. Let bytes be moduleObject.[[Bytes]].

  2. Let customSections be « ».

  3. For each custom section customSection of bytes, interpreted according to the module grammar,

    1. Let name be the name of customSection, decoded as UTF-8.

    2. Assert: name is not failure (moduleObject.[[Module]] is valid).

    3. 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 to customSections.

  4. Return customSections.

The Module(bytes, options) constructor, when invoked, performs the following steps:
  1. Let stableBytes be a copy of the bytes held by the buffer bytes.

  2. Compile the WebAssembly module stableBytes and store the result as module.

  3. If module is error, throw a CompileError exception.

  4. Let builtinSetNames be options["builtins"]

  5. Let importedStringModule be options["importedStringConstants"]

  6. If validating builtins and imported strings for module with builtinSetNames and importedStringModule returns false, throw a CompileError exception.

  7. Set this.[[Module]] to module.

  8. Set this.[[Bytes]] to stableBytes.

  9. Set this.[[BuiltinSets]] to builtinSetNames.

  10. 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.

4.2. Instances

[LegacyNamespace=WebAssembly, Exposed=*]
interface Instance {
  constructor(Module module, optional object importObject);
  readonly attribute object exports;
};
The Instance(module, importObject) constructor, when invoked, runs the following steps:
  1. Let module be module.[[Module]].

  2. Let builtinSetNames be module.[[BuiltinSets]].

  3. Let importedStringModule be module.[[ImportedStringModule]].

  4. Read the imports of module with imports importObject, builtinSetNames, and importedStringModule, and let imports be the result.

  5. Instantiate the core of a WebAssembly module module with imports, and let instance be the result.

  6. 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.

The getter of the exports attribute of Instance returns this.[[Exports]].

4.3. Memories

dictionary MemoryDescriptor {
  required [EnforceRange] unsigned long initial;
  [EnforceRange] unsigned long maximum;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Memory {
  constructor(MemoryDescriptor descriptor);
  unsigned long grow([EnforceRange] unsigned long delta);
  ArrayBuffer toFixedLengthBuffer();
  ArrayBuffer toResizableBuffer();
  readonly attribute ArrayBuffer buffer;
};

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:

To create a fixed length 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.

  2. Let buffer be a new ArrayBuffer with the internal slots [[ArrayBufferData]], [[ArrayBufferByteLength]], and [[ArrayBufferDetachKey]].

  3. Set buffer.[[ArrayBufferData]] to block.

  4. Set buffer.[[ArrayBufferByteLength]] to the length of block.

  5. Set buffer.[[ArrayBufferDetachKey]] to "WebAssembly.Memory".

  6. Return buffer.

To create a resizable memory buffer 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.

  2. Let length be the length of block.

  3. If maxsize > (65536 × 65536),

    1. Throw a RangeError exception.

  4. Let buffer be a new ArrayBuffer with the internal slots [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferMaxByteLength]], and [[ArrayBufferDetachKey]].

  5. Set buffer.[[ArrayBufferData]] to block.

  6. Set buffer.[[ArrayBufferByteLength]] to length.

  7. Set buffer.[[ArrayBufferMaxByteLength]] is maxsize.

  8. Set buffer.[[ArrayBufferDetachKey]] to "WebAssembly.Memory".

  9. Return buffer.

To initialize a memory object memory from a memory address memaddr, perform the following steps:
  1. Let map be the surrounding agent's associated Memory object cache.

  2. Assert: map[memaddr] doesn’t exist.

  3. Let buffer be the result of creating a fixed length memory buffer from memaddr.

  4. Set memory.[[Memory]] to memaddr.

  5. Set memory.[[BufferObject]] to buffer.

  6. Set map[memaddr] to memory.

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.

  2. If map[memaddr] exists,

    1. Return map[memaddr].

  3. Let memory be a new Memory.

  4. Initialize memory from memaddr.

  5. Return memory.

The Memory(descriptor) constructor, when invoked, performs the following steps:
  1. Let initial be descriptor["initial"].

  2. If descriptor["maximum"] exists, let maximum be descriptor["maximum"]; otherwise, let maximum be empty.

  3. If maximum is not empty and maximum < initial, throw a RangeError exception.

  4. Let memtype be { min initial, max maximum }.

  5. Let store be the surrounding agent's associated store.

  6. Let (store, memaddr) be mem_alloc(store, memtype). If allocation fails, throw a RangeError exception.

  7. Set the surrounding agent's associated store to store.

  8. Initialize this from memaddr.

To refresh the Memory buffer of memaddr, perform the following steps:
  1. Let map be the surrounding agent's associated Memory object cache.

  2. Assert: map[memaddr] exists.

  3. Let memory be map[memaddr].

  4. Let buffer be memory.[[BufferObject]].

  5. If IsFixedLengthArrayBuffer(buffer) is true,

    1. Perform ! DetachArrayBuffer(buffer, "WebAssembly.Memory").

    2. Let buffer be the result of creating a fixed length memory buffer from memaddr.

    3. Set memory.[[BufferObject]] to buffer.

  6. Otherwise,

    1. Let block be a Data Block which is identified with the underlying memory of memaddr.

    2. Set buffer.[[ArrayBufferData]] to block.

    3. Set buffer.[[ArrayBufferByteLength]] to the length of block.

To grow the memory buffer associated with a memory address memaddr by delta, perform the following steps:
  1. Let store be the surrounding agent's associated store.

  2. Let ret be the mem_size(store, memaddr).

  3. Let store be mem_grow(store, memaddr, delta).

  4. If store is error, throw a RangeError exception.

  5. Set the surrounding agent's associated store to store.

  6. Refresh the memory buffer of memaddr.

  7. Return ret.

The grow(delta) method, when invoked, performs the following steps:
  1. Let memaddr be this.[[Memory]].

  2. Return the result of growing the memory buffer associated with memaddr by delta.

Immediately after a WebAssembly memory.grow instruction executes, perform the following steps:

  1. If the top of the stack is not i32.const (−1),

    1. Let frame be the current frame.

    2. Assert: due to validation, frame.module.memaddrs[0] exists.

    3. Let memaddr be the memory address frame.module.memaddrs[0].

    4. Refresh the memory buffer of memaddr.

The toFixedLengthBuffer() method, when invoked, performs the following steps:
  1. Let buffer be this.[[BufferObject]].

  2. If IsFixedLengthArrayBuffer(buffer) is true, return buffer.

  3. Let memaddr be this.[[Memory]].

  4. Let fixedBuffer be the result of creating a fixed length memory buffer from memaddr.

  5. Perform ! DetachArrayBuffer(buffer, "WebAssembly.Memory").

  6. Set this.[[BufferObject]] to fixedBuffer.

  7. Return fixedBuffer.

The toResizableBuffer() method, when invoked, performs the following steps:
  1. Let buffer be this.[[BufferObject]].

  2. If IsFixedLengthArrayBuffer(buffer) is false, return buffer.

  3. Let memaddr be this.[[Memory]].

  4. Let store be the surrounding agent's associated store.

  5. Let memtype be mem_type(store, memaddr).

  6. If memtype has a max,

    1. Let maxsize be the max value in memtype.

  7. Otherwise,

    1. Let maxsize be 65536 × 65536.

  8. Let resizableBuffer be the result of creating a resizable memory buffer from memaddr and maxsize.

  9. Perform ! DetachArrayBuffer(buffer, "WebAssembly.Memory").

  10. Set this.[[BufferObject]] to resizableBuffer.

  11. Return resizableBuffer.

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.

The abstract operation HostResizeArrayBuffer 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.

    2. Assert: buffer is the [[BufferObject]] of exactly one value in map.

    3. For each memaddrmem in map,

      1. If SameValue(mem.[[BufferObject]], buffer) is true,

        1. Assert: buffer.[[ArrayBufferByteLength]] modulo 65536 is 0.

        2. Let lengthDelta be newLength - buffer.[[ArrayBufferByteLength]].

        3. If lengthDelta < 0 or lengthDelta modulo 65536 is not 0,

          1. Throw a RangeError exception.

        4. Let delta be lengthDelta ÷ 65536.

        5. Grow the memory buffer associated with memaddr by delta.

    4. Return handled.

  2. Otherwise, return unhandled.

The getter of the buffer attribute of Memory returns this.[[BufferObject]].

4.4. Tables

enum TableKind {
  "externref",
  "anyfunc",
  // Note: More values may be added in future iterations,
  // e.g., typed function references, typed GC references
};

dictionary TableDescriptor {
  required TableKind element;
  required [EnforceRange] unsigned long initial;
  [EnforceRange] unsigned long maximum;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Table {
  constructor(TableDescriptor descriptor, optional any value);
  unsigned long grow([EnforceRange] unsigned long delta, optional any value);
  any get([EnforceRange] unsigned long index);
  undefined set([EnforceRange] unsigned long index, optional any value);
  readonly attribute unsigned long length;
};

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.

To initialize a table object table from a table address tableaddr, perform the following steps:
  1. Let map be the surrounding agent's associated Table object cache.

  2. Assert: map[tableaddr] doesn’t exist.

  3. Set table.[[Table]] to tableaddr.

  4. Set map[tableaddr] to table.

To create a table object from a table address tableaddr, perform the following steps:
  1. Let map be the surrounding agent's associated Table object cache.

  2. If map[tableaddr] exists,

    1. Return map[tableaddr].

  3. Let table be a new Table.

  4. Initialize table from tableaddr.

  5. Return table.

The Table(descriptor, value) constructor, when invoked, performs the following steps:
  1. Let elementType be ToValueType(descriptor["element"]).

  2. If elementType is not a reftype,

    1. Throw a TypeError exception.

  3. Let initial be descriptor["initial"].

  4. If descriptor["maximum"] exists, let maximum be descriptor["maximum"]; otherwise, let maximum be empty.

  5. If maximum is not empty and maximum < initial, throw a RangeError exception.

  6. If value is missing,

    1. Let ref be DefaultValue(elementType).

    2. Assert: ref is not error.

  7. Otherwise,

    1. Let ref be ? ToWebAssemblyValue(value, elementType).

  8. Let type be the table type {min initial, max maximum} elementType.

  9. Let store be the surrounding agent's associated store.

  10. Let (store, tableaddr) be table_alloc(store, type, ref).

  11. Set the surrounding agent's associated store to store.

  12. Initialize this from tableaddr.

The grow(delta, value) method, when invoked, performs the following steps:
  1. Let tableaddr be this.[[Table]].

  2. Let store be the surrounding agent's associated store.

  3. Let initialSize be table_size(store, tableaddr).

  4. Let (limits, elementType) be table_type(tableaddr).

  5. If value is missing,

    1. Let ref be DefaultValue(elementType).

    2. If ref is error, throw a TypeError exception.

  6. Otherwise,

    1. Let ref be ? ToWebAssemblyValue(value, elementType).

  7. Let result be table_grow(store, tableaddr, delta, ref).

  8. If result is error, throw a RangeError exception.

    Note: The above exception can happen due to either insufficient memory or an invalid size parameter.

  9. Set the surrounding agent's associated store to result.

  10. Return initialSize.

The getter of the length attribute of Table, when invoked, performs the following steps:
  1. Let tableaddr be this.[[Table]].

  2. Let store be the surrounding agent's associated store.

  3. Return table_size(store, tableaddr).

The get(index) method, when invoked, performs the following steps:
  1. Let tableaddr be this.[[Table]].

  2. Let store be the surrounding agent's associated store.

  3. Let (limits, elementType) be table_type(store, tableaddr).

  4. If elementType is exnref,

    1. Throw a TypeError exception.

  5. Let result be table_read(store, tableaddr, index).

  6. If result is error, throw a RangeError exception.

  7. Return ToJSValue(result).

The set(index, value) method, when invoked, performs the following steps:
  1. Let tableaddr be this.[[Table]].

  2. Let store be the surrounding agent's associated store.

  3. Let (limits, elementType) be table_type(store, tableaddr).

  4. If elementType is exnref,

    1. Throw a TypeError exception.

  5. If value is missing,

    1. Let ref be DefaultValue(elementType).

    2. If ref is error, throw a TypeError exception.

  6. Otherwise,

    1. Let ref be ? ToWebAssemblyValue(value, elementType).

  7. Let store be the surrounding agent's associated store.

  8. Let store be table_write(store, tableaddr, index, ref).

  9. If store is error, throw a RangeError exception.

  10. Set the surrounding agent's associated store to store.

4.5. Globals

enum ValueType {
  "i32",
  "i64",
  "f32",
  "f64",
  "v128",
  "externref",
  "anyfunc",
};

Note: this type may be extended with additional cases in future versions of WebAssembly.

dictionary GlobalDescriptor {
  required ValueType value;
  boolean mutable = false;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Global {
  constructor(GlobalDescriptor descriptor, optional any v);
  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:

To initialize a global object global from a global address globaladdr, perform the following steps:
  1. Let map be the surrounding agent's associated Global object cache.

  2. Assert: map[globaladdr] doesn’t exist.

  3. Set global.[[Global]] to globaladdr.

  4. Set map[globaladdr] to global.

To create a global object from a global address globaladdr, perform the following steps:
  1. Let map be the surrounding agent's associated Global object cache.

  2. If map[globaladdr] exists,

    1. Return map[globaladdr].

  3. Let global be a new Global.

  4. Initialize global from globaladdr.

  5. Return global.

The algorithm ToValueType(s) performs the following steps:
  1. If s equals "i32", return i32.

  2. If s equals "i64", return i64.

  3. If s equals "f32", return f32.

  4. If s equals "f64", return f64.

  5. If s equals "v128", return v128.

  6. If s equals "anyfunc", return funcref.

  7. If s equals "externref", return externref.

  8. Assert: This step is not reached.

The algorithm DefaultValue(valuetype) performs the following steps:
  1. If valuetype equals externref, return ToWebAssemblyValue(undefined, valuetype).

  2. Return val_default(valuetype).

The Global(descriptor, v) constructor, when invoked, performs the following steps:
  1. Let mutable be descriptor["mutable"].

  2. Let valuetype be ToValueType(descriptor["value"]).

  3. If valuetype is v128 or exnref,

    1. Throw a TypeError exception.

  4. If v is missing,

    1. Let value be DefaultValue(valuetype).

    2. Assert: value is not error.

  5. Otherwise,

    1. Let value be ToWebAssemblyValue(v, valuetype).

  6. If mutable is true, let globaltype be var valuetype; otherwise, let globaltype be const valuetype.

  7. Let store be the current agent’s associated store.

  8. Let (store, globaladdr) be global_alloc(store, globaltype, value).

  9. Set the current agent’s associated store to store.

  10. Initialize this from globaladdr.

The algorithm GetGlobalValue(Global global) performs the following steps:
  1. Let store be the current agent’s associated store.

  2. Let globaladdr be global.[[Global]].

  3. Let globaltype be global_type(store, globaladdr).

  4. If globaltype is of the form mut valuetype where valuetype is v128 or exnref, throw a TypeError.

  5. Let value be global_read(store, globaladdr).

  6. Return ToJSValue(value).

The getter of the value attribute of Global, when invoked, performs the following steps:
  1. Return GetGlobalValue(this).

The setter of the value attribute of Global, when invoked, performs the following steps:

  1. Let store be the current agent’s associated store.

  2. Let globaladdr be this.[[Global]].

  3. Let mut valuetype be global_type(store, globaladdr).

  4. If valuetype is v128 or exnref, throw a TypeError.

  5. If mut is const, throw a TypeError.

  6. Let value be ToWebAssemblyValue(the given value, valuetype).

  7. Let store be global_write(store, globaladdr, value).

  8. If store is error, throw a RangeError exception.

  9. Set the current agent’s associated store to store.

The valueOf() method, when invoked, performs the following steps:
  1. Return GetGlobalValue(this).

4.6. Exported Functions

A WebAssembly function is made available in JavaScript as an Exported Function. 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.

The name of the WebAssembly function funcaddr is found by performing the following steps:
  1. Let store be the surrounding agent's associated store.

  2. Let funcinst be store.funcs[funcaddr].

  3. If funcinst is of the form {type functype, hostcode hostfunc},

    1. Assert: hostfunc is a JavaScript object and IsCallable(hostfunc) is true.

    2. Let index be the index of the host function funcaddr.

  4. Otherwise,

    1. Let moduleinst be funcinst.module.

    2. Assert: funcaddr is contained in moduleinst.funcaddrs.

    3. Let index be the index of moduleinst.funcaddrs where funcaddr is found.

  5. Return ! ToString(index).

To create a new Exported Function from a WebAssembly function address funcaddr, perform the following steps:
  1. Let map be the surrounding agent's associated Exported Function cache.

  2. If map[funcaddr] exists,

    1. Return map[funcaddr].

  3. Let steps be "call the Exported Function funcaddr with arguments."

  4. Let realm be the current Realm.

  5. Let store be the surrounding agent's associated store.

  6. Let functype be func_type(store, funcaddr).

  7. Let [paramTypes] → [resultTypes] be functype.

  8. Let arity be paramTypes’s size.

  9. Let name be the name of the WebAssembly function funcaddr.

  10. Let function be ! CreateBuiltinFunction(steps, arity, name, « [[FunctionAddress]] », realm).

  11. Set function.[[FunctionAddress]] to funcaddr.

  12. Set map[funcaddr] to function.

  13. Return function.

To call an Exported Function 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.

  2. Let functype be func_type(store, funcaddr).

  3. Let [parameters] → [results] be functype.

  4. If parameters or results contain v128 or exnref, throw a TypeError.

    Note: the above error is thrown each time the [[Call]] method is invoked.

  5. Let args be « ».

  6. Let i be 0.

  7. For each t of parameters,

    1. If argValues’s size > i, let arg be argValues[i].

    2. Otherwise, let arg be undefined.

    3. Append ToWebAssemblyValue(arg, t) to args.

    4. Set i to i + 1.

  8. Let (store, ret) be the result of func_invoke(store, funcaddr, args).

  9. Set the surrounding agent's associated store to store.

  10. If ret is error, throw an exception. This exception should be a WebAssembly RuntimeError exception, unless otherwise indicated by the WebAssembly error mapping.

  11. If ret is THROW ref.exn exnaddr, then

    1. Let tagaddr be exn_tag(store, exnaddr).

    2. Let payload be exn_read(store, exnaddr).

    3. Let jsTagAddr be the result of getting the JavaScript exception tag.

    4. If tagaddr is equal to jsTagAddr,

      1. Throw the result of retrieving a host value from payload[0].

    5. Otherwise,

      1. Let exception be a new Exception created from exnaddr.

      2. Throw exception.

  12. Let outArity be the size of ret.

  13. If outArity is 0, return undefined.

  14. Otherwise, if outArity is 1, return ToJSValue(ret[0]).

  15. Otherwise,

    1. Let values be « ».

    2. For each r of ret,

      1. Append ToJSValue(r) to values.

    3. Return CreateArrayFromList(values).

Note: 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.

To run a host function from the JavaScript object func, type functype, and list of WebAssembly values arguments, perform the following steps:
  1. Let [parameters] → [results] be functype.

  2. If parameters or results contain v128 or exnref, throw a TypeError.

  3. Let jsArguments be « ».

  4. For each arg of arguments,

    1. Append ! ToJSValue(arg) to jsArguments.

  5. Let ret be ? Call(func, undefined, jsArguments).

  6. Let resultsSize be results’s size.

  7. If resultsSize is 0, return « ».

  8. Otherwise, if resultsSize is 1, return « ? ToWebAssemblyValue(ret, results[0]) ».

  9. Otherwise,

    1. Let method be ? GetMethod(ret, %Symbol.iterator%).

    2. If method is undefined, throw a TypeError.

    3. Let values be ? IteratorToList(? GetIteratorFromMethod(ret, method)).

    4. Let wasmValues be a new, empty list.

    5. If values’s size is not resultsSize, throw a TypeError exception.

    6. For each value and resultType in values and results, paired linearly,

      1. Append ToWebAssemblyValue(value, resultType) to wasmValues.

    7. Return wasmValues.

To create a host function from the JavaScript object func and type functype, perform the following steps:
  1. Assert: IsCallable(func).

  2. Let stored settings be the incumbent settings object.

  3. Let hostfunc be a host function which performs the following steps when called with arguments arguments:

    1. Let realm be func’s associated Realm.

    2. Let relevant settings be realm’s settings object.

    3. Prepare to run script with relevant settings.

    4. Prepare to run a callback with stored settings.

    5. Let result be the result of running a host function from func, functype, and arguments.

    6. Clean up after running a callback with stored settings.

    7. Clean up after running script with relevant settings.

    8. Assert: result.[[Type]] is throw or normal.

    9. Let store be the surrounding agent's associated store.

    10. If result.[[Type]] is throw, then:

      1. Let v be result.[[Value]].

      2. If v implements Exception,

        1. Let address be v.[[Address]].

      3. Otherwise,

        1. Let type be the result of getting the JavaScript exception tag.

        2. Let payload be ! ToWebAssemblyValue(v, externref).

        3. Let (store, address) be exn_alloc(store, type, « payload »).

        4. Set the surrounding agent's associated store to store.

      4. Execute the WebAssembly instructions (ref.exn address) (throw_ref).

    11. Otherwise, return result.[[Value]].

  4. Let (store, funcaddr) be func_alloc(store, functype, hostfunc).

  5. Set the surrounding agent's associated store to store.

  6. Return funcaddr.

The algorithm ToJSValue(w) coerces a WebAssembly value to a JavaScript value by performing the following steps:
  1. Assert: w is not of the form v128.const v128.

  2. Assert: w is not of the form ref.exn exnaddr.

  3. If w is of the form i64.const u64,

    1. Let i64 be signed_64(u64).

    2. Return (i64 interpreted as a mathematical value).

  4. If w is of the form i32.const i32,

    1. Let i32 be signed_32(i32).

    2. Return 𝔽(i32 interpreted as a mathematical value).

  5. If w is of the form f32.const f32,

    1. If f32 is +∞ or −∞, return +∞𝔽 or -∞𝔽, respectively.

    2. If f32 is nan, return NaN.

    3. Return 𝔽(f32 interpreted as a mathematical value).

  6. If w is of the form f64.const f64,

    1. If f64 is +∞ or −∞, return +∞𝔽 or -∞𝔽, respectively.

    2. If f64 is nan, return NaN.

    3. Return 𝔽(f64 interpreted as a mathematical value).

  7. If w is of the form ref.null t, return null.

  8. If w is of the form ref.i31 u31,

    1. Let i31 be signed_31(u31).

    2. Let return 𝔽(i31).

  9. If w is of the form ref.struct structaddr, return the result of creating a new Exported GC Object from structaddr and "struct".

  10. If w is of the form ref.array arrayaddr, return the result of creating a new Exported GC Object from arrayaddr and "array".

  11. If w is of the form ref.func funcaddr, return the result of creating a new Exported Function from funcaddr.

  12. If w is of the form ref.host hostaddr, return the result of retrieving a host value from hostaddr.

  13. 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.

For retrieving a host value from an host address hostaddr, perform the following steps:

  1. Let map be the surrounding agent's associated host value cache.

  2. Assert: map[hostaddr] exists.

  3. Return map[hostaddr].

The algorithm ToWebAssemblyValue(v, type) coerces a JavaScript value to a WebAssembly value by performing the following steps:
  1. Assert: type is not v128.

  2. Assert: type is not exnref.

  3. If type is i64,

    1. Let i64 be ? ToBigInt64(v).

    2. Let u64 be the unsigned integer such that i64 is signed_64(u64).

    3. Return i64.const u64.

  4. If type is i32,

    1. Let i32 be ? ToInt32(v).

    2. Let u32 be the unsigned integer such that i32 is signed_32(u32).

    3. Return i32.const u32.

  5. If type is f32,

    1. Let number be ? ToNumber(v).

    2. If number is NaN,

      1. Let n be an implementation-defined integer such that canon32n < 2signif(32).

      2. Let f32 be nan(n).

    3. Otherwise,

      1. Let f32 be number rounded to the nearest representable value using IEEE 754-2008 round to nearest, ties to even mode. [IEEE-754]

    4. Return f32.const f32.

  6. If type is f64,

    1. Let number be ? ToNumber(v).

    2. If number is NaN,

      1. Let n be an implementation-defined integer such that canon64n < 2signif(64).

      2. Let f64 be nan(n).

    3. Otherwise,

      1. Let f64 be number.

    4. Return f64.const f64.

  7. If type is of the form ref null heaptype,

    1. If v is null,

      1. Let r be ref.null heaptype.

    2. Else if match_valtype(type, ref null extern),

      1. Let ref be ToWebAssemblyValue(v, ref any).

      2. Let r be ref.extern ref.

    3. Else if v is an Exported Function and match_valtype(type, ref null func),

      1. Let funcaddr be the value of v’s [[FunctionAddress]] internal slot.

      2. Let r be ref.func funcaddr.

    4. Else if v is a Number and v is equal to ? ToInt32(v) and (v) < 230 and (v) ⩾ -230,

      1. Let i31 ? ToInt32(v).

      2. Let u31 be the unsigned integer such that i31 is signed_31(i31).

      3. Let r be ref.i31 u31.

    5. Else if v is an Exported GC Object,

      1. Let objectaddr be the value of v’s [[ObjectAddress]] internal slot.

      2. Let objectkind be the value of v’s [[ObjectKind]] internal slot.

      3. If objectkind is "array",

        1. Let r be ref.array objectaddr.

      4. If objectkind is "struct",

        1. Let r be ref.struct objectaddr.

    6. Else,

      1. Let map be the surrounding agent's associated host value cache.

      2. If a host address hostaddr exists such that map[hostaddr] is the same as v,

        1. Return ref.host hostaddr.

      3. Let host address hostaddr be the smallest address such that map[hostaddr] exists is false.

      4. Set map[hostaddr] to v.

      5. Let r be ref.host hostaddr.

    7. Let store be the current agent’s associated store.

    8. Let actualtype be ref_type(store, r).

    9. If match_valtype(actualtype, type) is false,

      1. Throw a TypeError.

    10. Return r.

  8. Assert: This step is not reached.

4.7. Tags

The tag_alloc(store, parameters) algorithm creates a new tag address for parameters in store and returns the updated store and the tag address.

4.7.1. Tag types

dictionary TagType {
  required sequence<ValueType> parameters;
};

[LegacyNamespace=WebAssembly, Exposed=(Window,Worker,Worklet)]
interface Tag {
  constructor(TagType type);
};

A Tag value represents an exception tag.

To initialize a Tag object tag from a tag address tagAddress, perform the following steps:

  1. Let map be the surrounding agent's associated Tag object cache.

  2. Assert: map[tagAddress] doesn’t exist.

  3. Set tag.[[Address]] to tagAddress.

  4. Set map[tagAddress] to tag.

To create a Tag object from a tag address tagAddress, perform the following steps:

  1. Let map be the surrounding agent's associated Tag object cache.

  2. If map[tagAddress] exists,

    1. Return map[tagAddress].

  3. Let tag be a new Tag.

  4. Initialize tag from tagAddress.

  5. Return tag.

The new Tag(type) constructor steps are:

  1. Let parameters be type["parameters"].

  2. Let wasmParameters be «».

  3. For each type of parameters,

    1. Append ToValueType(type) to wasmParameters.

  4. Let store be the current agent’s associated store.

  5. Let (store, tagAddress) be tag_alloc(store, wasmParameters).

  6. Set the current agent’s associated store to store.

  7. Initialize this from tagAddress.

4.8. Garbage Collected Objects

A WebAssembly struct or array is made available in JavaScript as an Exported GC Object. 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.

The [[GetPrototypeOf]] internal method of an Exported GC Object O takes no arguments and returns null. It performs the following steps when called:
  1. Return null.

The [[SetPrototypeOf]] internal method of an Exported GC Object O takes argument V (an Object or null) and returns a boolean. It performs the following steps when called:
  1. Return false.

The [[IsExtensible]] internal method of an Exported GC Object O takes no arguments and returns a boolean. It performs the following steps when called:
  1. Return false.

The [[PreventExtensions]] internal method of an Exported GC Object O takes no arguments and returns a boolean. It performs the following steps when called:
  1. Return false.

The [[GetOwnProperty]] internal method of an Exported GC Object O takes argument P (a property key) and returns undefined. It performs the following steps when called:
  1. Return undefined.

The [[DefineOwnProperty]] internal method of an Exported GC Object O takes arguments P (a property key) and Desc (a property descriptor) and returns a boolean. It performs the following steps when called:
  1. Return false.

The [[HasProperty]] internal method of an Exported GC Object O takes argument P (a property key) and returns a boolean. It performs the following steps when called:
  1. Return false.

The [[Get]] internal method of an Exported GC Object O takes arguments P (a property key) and Receiver (an ECMAScript language value) and returns undefined. It performs the following steps when called:
  1. Return undefined.

The [[Set]] internal method of an Exported GC Object O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and throws an exception. It performs the following steps when called:
  1. Throw a TypeError.

The [[Delete]] internal method of an Exported GC Object O takes argument P (a property key) and throws an exception. It performs the following steps when called:
  1. Throw a TypeError.

The [[OwnPropertyKeys]] internal method of an Exported GC Object O takes no arguments and returns a list. It performs the following steps when called:
  1. Let keys be a new empty list.

  2. Return keys.

To create a new Exported GC Object from a WebAssembly object address objectaddr and a string objectkind, perform the following steps:
  1. Assert: objectkind is either "array" or "struct".

  2. Let map be the surrounding agent's associated exported GC object cache.

  3. If map[objectaddr] exists,

    1. Return map[objectaddr].

  4. Let object be MakeBasicObject(« [[ObjectAddress]] »).

  5. Set object.[[ObjectAddress]] to objectaddr.

  6. Set object.[[ObjectKind]] to objectkind.

  7. Set object.[[GetPrototypeOf]] as specified in [[GetPrototypeOf]] internal method of an Exported GC Object.

  8. Set object.[[SetPrototypeOf]] as specified in [[SetPrototypeOf]] internal method of an Exported GC Object.

  9. Set object.[[IsExtensible]] as specified in [[IsExtensible]] internal method of an Exported GC Object.

  10. Set object.[[PreventExtensions]] as specified in [[PreventExtensions]] internal method of an Exported GC Object.

  11. Set object.[[GetOwnProperty]] as specified in [[GetOwnProperty]] internal method of an Exported GC Object.

  12. Set object.[[DefineOwnProperty]] as specified in [[DefineOwnProperty]] internal method of an Exported GC Object.

  13. Set object.[[HasProperty]] as specified in [[HasProperty]] internal method of an Exported GC Object.

  14. Set object.[[Get]] as specified in [[Get]] internal method of an Exported GC Object.

  15. Set object.[[Set]] as specified in [[Set]] internal method of an Exported GC Object.

  16. Set object.[[Delete]] as specified in [[Delete]] internal method of an Exported GC Object.

  17. Set object.[[OwnPropertyKeys]] as specified in [[OwnPropertyKeys]] internal method of an Exported GC Object.

  18. Set map[objectaddr] to object.

  19. Return object.

4.9. Exceptions

dictionary ExceptionOptions {
  boolean traceStack = false;
};

[LegacyNamespace=WebAssembly, Exposed=(Window,Worker,Worklet)]
interface Exception {
  constructor(Tag exceptionTag, sequence<any> payload, optional ExceptionOptions options = {});
  any getArg([EnforceRange] unsigned long index);
  boolean is(Tag exceptionTag);
  readonly attribute (DOMString or undefined) stack;
};

An Exception value represents an exception.

To initialize an Exception object exn from an Exception address exnAddress, perform the following steps:

  1. Let map be the surrounding agent's associated Exception object cache.

  2. Assert: map[exnAddress] doesn’t exist.

  3. Set exn.[[Address]] to exnAddress.

  4. Set map[exnAddress] to exn.

  5. Let store be the surrounding agent's associated store.

  6. Let tagaddr be exn_tag(store, exnAddress).

  7. Let payload be exn_read(store, exnAddress).

  8. Set exn.[[Type]] to tagaddr.

  9. Set exn.[[Payload]] to payload.

  10. Set exn.[[Stack]] to undefined.

To create an Exception object from a exception address exnAddress, perform the following steps:

  1. Let map be the surrounding agent's associated Exception object cache.

  2. If map[exnAddress] exists,

    1. Return map[exnAddress].

  3. Let exn be a new Exception.

  4. Initialize exn from exnAddress.

  5. Return exn.

The new Exception(exceptionTag, payload, options) constructor steps are:

  1. Let JSTagAddr be the result of getting the JavaScript exception tag.

  2. If exceptionTag.[[Address]] is equal to JSTagAddr,

    1. Throw a TypeError.

  3. Let store be the surrounding agent's associated store.

  4. Let [types] → [] be tag_type(store, exceptionTag.[[Address]]).

  5. If types’s size is not payload’s size,

    1. Throw a TypeError.

  6. Let wasmPayload be « ».

  7. For each value and resultType of payload and types, paired linearly,

    1. If resultType is v128 or exnref,

      1. Throw a TypeError.

    2. Append ? ToWebAssemblyValue(value, resultType) to wasmPayload.

  8. Let (store, exceptionAddr) be exn_alloc(store, exceptionTag.[[Address]], wasmPayload)

  9. Set the surrounding agent's associated store to store.

  10. Initialize this from exceptionAddr.

  11. If options["traceStack"] is true,

    1. Set this.[[Stack]] to either a DOMString representation of the current call stack or undefined.

The getArg(index) method steps are:

  1. Let store be the surrounding agent's associated store.

  2. Let tagaddr be exn_tag(store, this.[[Address]]).

  3. Let payload be exn_read(store, this.[[Address]]).

  4. Assert: tagaddr is equal to this.[[Type]].

  5. If indexpayload’s size,

    1. Throw a RangeError.

  6. Let [types] → [] be tag_type(store, tagaddr).

  7. If types[index] is v128 or exnref,

    1. Throw a TypeError.

  8. Return ToJSValue(payload[index]).

The is(exceptionTag) method steps are:

  1. If this.[[Type]] is not equal to exceptionTag.[[Address]],

    1. Return false.

  2. Return true.

The stack getter steps are:

  1. Return this.[[Stack]].

4.9.1. JavaScript exceptions

The JavaScript exception tag 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 » → « ».

To get the JavaScript exception tag, 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

  2. Let store be the surrounding agent's associated store.

  3. Let (store, tagAddress) be tag_alloc(store, « externref » → « »).

  4. Set the current agent’s associated store to store.

  5. Set the current agent’s associated JavaScript exception tag to tagAddress.

  6. return tagAddress.

4.10. Error Objects

WebAssembly defines the following Error classes: CompileError, LinkError, and RuntimeError.

When the namespace object for the WebAssembly namespace is created, the following steps must be run:
  1. Let namespaceObject be the namespace object.

  2. For each error of « "CompileError", "LinkError", "RuntimeError" »,

    1. Let constructor be a new object, implementing the NativeError Object Structure, with NativeError set to error.

    2. ! DefineMethodProperty(namespaceObject, error, constructor, false).

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.

5. Builtins

The JS-API defines sets of builtin functions which can be imported through 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 name that is used in WebAssemblyCompileOptions, and a qualified name with a wasm: prefix that is used during import lookup.

To get the builtins for a builtin set with builtinSetName, perform the following steps:
  1. Return a list of (name, funcType, steps) for the set with name builtinSetName defined within this section.

To find a builtin with import and enabled builtins builtinSetNames, perform the following steps:
  1. Assert: validate builtin set names builtinSetNames is true.

  2. Let importModuleName be import[0]

  3. Let importName be import[1]

  4. For each builtinSetName of builtinSetNames,

    1. If builtinSetName does not refer to a builtin set, then continue.

    2. Let builtinSetQualifiedName be builtinSetName prefixed with "wasm:"

    3. If importModuleName equals builtinSetQualifiedName

      1. Let builtins be the result of get the builtins for a builtin set builtinSetName

      2. For each builtin of builtins

        1. Let builtinName be builtin[0]

        2. If importName equals builtinName, return (builtinSetName, builtin).

  5. Return null.

To validate builtin set names with builtinSetNames, perform the following steps:
  1. If builtinSetNames contains any duplicates, return false.

  2. Return false.

To create a builtin function from type funcType and execution steps steps, perform the following steps:
  1. Let stored settings be the incumbent settings object.

  2. Let hostfunc be a host function which executes steps when called.

  3. Let (store, funcaddr) be func_alloc(store, functype, hostfunc).

  4. Set the surrounding agent's associated store to store.

  5. Return funcaddr.

To instantiate a builtin set with name builtinSetName, perform the following steps:
  1. Let builtins be the result of get the builtins for a builtin set builtinSetName

  2. Let exportsObject be ! OrdinaryObjectCreate(null).

    1. If externtype is of the form func functype,

  3. For each (name, funcType, steps) of builtins,

    1. Let funcaddr be the result fo create a builtin function with funcType and steps

    2. Let func be the result of creating a new Exported Function from funcaddr.

    3. Let value be func.

    4. Let status be ! CreateDataProperty(exportsObject, name, value).

    5. Assert: status is true.

  4. Return exportsObject.

To validate an import for builtins with import, enabled builtins builtinSetNames, perform the following steps:
  1. Assert: validate builtin set names builtinSetNames is true.

  2. Let maybeBuiltin be the result of finding a builtin for import and builtinSetNames

  3. If maybeBuiltin is null, return true.

  4. Let importExternType be import[2]

  5. Let builtinFuncType be maybeBuiltin[0][1]

  6. Let builtinExternType be func |builtinFuncType|

  7. Return match_externtype(builtinExternType, importExternType)

5.1. String Builtins

String builtins adapt the interface of the String builtin object. The name for this set is 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.

5.1.1. Abstract operations

The UnwrapString(v) abstract operation, when invoked, performs the following steps:

  1. If Type(v) is not String

    1. Throw a RuntimeError exception as if a trap was executed.

  2. Return v

The FromCharCode(v) abstract operation, when invoked, performs the following steps:

  1. Assert: v is of type i32.

  2. Return ! Call(String.fromCharCode, undefined, « ToJSValue(v) »).

The CharCodeAt(string, index) abstract operation, when invoked, performs the following steps:

  1. Assert: index is of type i32.

  2. Return ! Call(String.prototype.charCodeAt, string, « ToJSValue(index) »).

5.1.2. cast

The funcType of this builtin is (func (param externref) (result externref)).

When this builtin is invoked with parameter v, the following steps must be run:
  1. Return ? UnwrapString(v)

5.1.3. test

The funcType of this builtin is (func (param externref) (result i32)).

When this builtin is invoked with parameter v, the following steps must be run:
  1. If Type(v) is not String

    1. Return 0

  2. Return 1

5.1.4. fromCharCodeArray

The funcType of this builtin is (func (param (ref null (array (mut i16))) i32 i32) (result externref)).

Note: This function only takes a mutable i16 array defined in its own recursion group.

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.

  2. Let length be the number of elements in array.

  3. If start > end or end > length

    1. Throw a RuntimeError exception as if a trap was executed.

  4. Let result be the empty string.

  5. Let i be start.

  6. While i < end:

    1. Let charCode be the value of the element stored at index i in array.

    2. Let charCodeString be FromCharCode(charCode).

    3. Let result be the concatenation of result and charCodeString.

    4. Set i to i + 1.

  7. Return result.

5.1.5. intoCharCodeArray

The funcType of this builtin is (func (param externref (ref null (array (mut i16))) i32) (result i32)).

Note: This function only takes a mutable i16 array defined in its own recursion group.

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.

  2. Let string be ? UnwrapString(string).

  3. Let stringLength be the length of string.

  4. Let arrayLength be the number of elements in array.

  5. If start + stringLength > arrayLength

    1. Throw a RuntimeError exception as if a trap was executed.

  6. Let i be 0.

  7. While i < stringLength:

    1. Let charCode be CharCodeAt(string, i).

    2. Set the element at index start + i in array to ToWebAssemblyValue(charCode).

    3. Set i to i + 1.

  8. Return stringLength.

5.1.6. fromCharCode

The funcType of this builtin is (func (param i32) (result externref)).

When this builtin is invoked with parameter v, the following steps must be run:
  1. Return FromCharCode(v).

5.1.7. fromCodePoint

The funcType of this builtin is (func (param i32) (result externref)).

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.

  2. Return ! Call(String.fromCodePoint, undefined, « ToJSValue(v) »).

5.1.8. charCodeAt

The type of this function is (func (param externref i32) (result i32)).

When this builtin is invoked with parameters string and index, the following steps must be run:
  1. Let string be ? UnwrapString(string).

  2. Let length be the length of string.

  3. If index >= length

    1. Throw a RuntimeError exception as if a trap was executed.

  4. Return CharCodeAt(string, index).

5.1.9. codePointAt

The type of this function is (func (param externref i32) (result i32)).

When this builtin is invoked with parameters string and index, the following steps must be run:
  1. Let string be ? UnwrapString(string).

  2. Let length be the length of string.

  3. If index >= length

    1. Throw a RuntimeError exception as if a trap was executed.

  4. Return ! Call(String.prototype.codePointAt, string, « ToJSValue(index) »).

5.1.10. length

The funcType of this builtin is (func (param externref) (result i32)).

When this builtin is invoked with parameter v, the following steps must be run:
  1. Let string be ? UnwrapString(v).

  2. Return the length of string.

5.1.11. concat

The funcType of this builtin is (func (param externref externref) (result externref)).

When this builtin is invoked with parameters first and second, the following steps must be run:
  1. Let first be ? UnwrapString(first).

  2. Let second be ? UnwrapString(second).

  3. Return ! Call(String.prototype.concat, first, « second »).

5.1.12. substring

The funcType of this builtin is (func (param externref i32 i32) (result externref)).

When this builtin is invoked with parameters string, start, and end, the following steps must be run:
  1. Let string be ? UnwrapString(string).

  2. Let length be the length of string.

  3. If start > end or start > length

    1. Return the empty string.

  4. Return ! Call(String.prototype.substring, string, « ToJSValue(start), ToJSValue(end) »).

5.1.13. equals

The funcType of this builtin is (func (param externref externref) (result i32)).

Note: Explicitly allow null strings to be compared for equality as that is meaningful.

When this builtin is invoked with parameters first and second, the following steps must be run:

  1. If first is not null and Type(first) is not String

    1. Throw a RuntimeError exception as if a trap was executed.

  2. If second is not null and Type(second) is not String

    1. Throw a RuntimeError exception as if a trap was executed.

  3. If ! IsStrictlyEqual(first, second) is true

    1. Return 1.

  4. Return 0.

5.1.14. compare

The funcType of this builtin is (func (param externref externref) (result i32)).

When this builtin is invoked with parameters first and second, the following steps must be run:

  1. Let first be ? UnwrapString(first).

  2. Let second be ? UnwrapString(second).

  3. If ! IsStrictlyEqual(first, second) is true

    1. Return 0.

  4. If ! IsLessThan(first, second, true) is true

    1. Return -1.

  5. Return 1.

6. Error Condition Mappings to JavaScript

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.

6.1. Stack Overflow

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.

6.2. Out of Memory

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.

A failed allocation of a large table or memory may either result in In a future revision, we may reconsider more reliable and recoverable errors for allocations of large amounts of memory.

See Issue 879 for further discussion.

7. 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 one of the following limits with a CompileError. In practice, an implementation may run out of resources for valid modules below these limits.

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.

8. Security and Privacy Considerations

This section is non-normative.

This document defines a host environment for WebAssembly. It enables a WebAssembly instance to import JavaScript objects and functions from an import object, but otherwise provides no access to the embedding environment. Thus a WebAssembly instance is bound to the same constraints as JavaScript.

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Conformant Algorithms

Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the meaning of the key word ("must", "should", "may", etc) used in introducing the algorithm.

Conformance requirements phrased as algorithms or specific steps can be implemented in any manner, so long as the end result is equivalent. In particular, the algorithms defined in this specification are intended to be easy to understand and are not intended to be performant. Implementers are encouraged to optimize.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[ECMASCRIPT]
ECMAScript Language Specification. URL: https://tc39.es/ecma262/multipage/
[ENCODING]
Anne van Kesteren. Encoding Standard. Living Standard. URL: https://encoding.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBASSEMBLY]
WebAssembly Core Specification. Draft. URL: https://webassembly.github.io/spec/core/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

Informative References

[IEEE-754]
IEEE Standard for Floating-Point Arithmetic. 29 August 2008. URL: http://ieeexplore.ieee.org/servlet/opac?punumber=4610933

IDL Index

dictionary WebAssemblyInstantiatedSource {
    required Module module;
    required Instance instance;
};

dictionary WebAssemblyCompileOptions {
    USVString? importedStringConstants;
    sequence<USVString> builtins;
};

[Exposed=*]
namespace WebAssembly {
    boolean validate(BufferSource bytes, optional WebAssemblyCompileOptions options);
    Promise<Module> compile(BufferSource bytes, optional WebAssemblyCompileOptions options);

    Promise<WebAssemblyInstantiatedSource> instantiate(
        BufferSource bytes, optional object importObject, optional WebAssemblyCompileOptions options);

    Promise<Instance> instantiate(
        Module moduleObject, optional object importObject);

    readonly attribute Tag JSTag;
};

enum ImportExportKind {
  "function",
  "table",
  "memory",
  "global",
  "tag"
};

dictionary ModuleExportDescriptor {
  required USVString name;
  required ImportExportKind kind;
  // Note: Other fields such as signature may be added in the future.
};

dictionary ModuleImportDescriptor {
  required USVString module;
  required USVString name;
  required ImportExportKind kind;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Module {
  constructor(BufferSource bytes, optional WebAssemblyCompileOptions options);
  static sequence<ModuleExportDescriptor> exports(Module moduleObject);
  static sequence<ModuleImportDescriptor> imports(Module moduleObject);
  static sequence<ArrayBuffer> customSections(Module moduleObject, DOMString sectionName);
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Instance {
  constructor(Module module, optional object importObject);
  readonly attribute object exports;
};

dictionary MemoryDescriptor {
  required [EnforceRange] unsigned long initial;
  [EnforceRange] unsigned long maximum;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Memory {
  constructor(MemoryDescriptor descriptor);
  unsigned long grow([EnforceRange] unsigned long delta);
  ArrayBuffer toFixedLengthBuffer();
  ArrayBuffer toResizableBuffer();
  readonly attribute ArrayBuffer buffer;
};

enum TableKind {
  "externref",
  "anyfunc",
  // Note: More values may be added in future iterations,
  // e.g., typed function references, typed GC references
};

dictionary TableDescriptor {
  required TableKind element;
  required [EnforceRange] unsigned long initial;
  [EnforceRange] unsigned long maximum;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Table {
  constructor(TableDescriptor descriptor, optional any value);
  unsigned long grow([EnforceRange] unsigned long delta, optional any value);
  any get([EnforceRange] unsigned long index);
  undefined set([EnforceRange] unsigned long index, optional any value);
  readonly attribute unsigned long length;
};

enum ValueType {
  "i32",
  "i64",
  "f32",
  "f64",
  "v128",
  "externref",
  "anyfunc",
};

dictionary GlobalDescriptor {
  required ValueType value;
  boolean mutable = false;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Global {
  constructor(GlobalDescriptor descriptor, optional any v);
  any valueOf();
  attribute any value;
};

dictionary TagType {
  required sequence<ValueType> parameters;
};

[LegacyNamespace=WebAssembly, Exposed=(Window,Worker,Worklet)]
interface Tag {
  constructor(TagType type);
};

dictionary ExceptionOptions {
  boolean traceStack = false;
};

[LegacyNamespace=WebAssembly, Exposed=(Window,Worker,Worklet)]
interface Exception {
  constructor(Tag exceptionTag, sequence<any> payload, optional ExceptionOptions options = {});
  any getArg([EnforceRange] unsigned long index);
  boolean is(Tag exceptionTag);
  readonly attribute (DOMString or undefined) stack;
};

Issues Index

A failed allocation of a large table or memory may either result in In a future revision, we may reconsider more reliable and recoverable errors for allocations of large amounts of memory.

See Issue 879 for further discussion.