Skip to content

The Imports Object

Not every WebAssembly module is self-contained. When a module needs to call a JavaScript function, read from shared memory, or access a global value managed by the host, it declares those dependencies with (import ...) statements. At instantiation time, JavaScript must supply matching values — this is the imports object.

An import declaration names the thing being imported and describes its type. The first two string arguments form a two-level namespace: a module name (the outer key) and a field name (the inner key):

(module
(import "env" "log" (func $log (param i32)))
)

Here "env" is the module namespace and "log" is the field name. The declaration says: “this module requires a function called log inside the env namespace; that function must accept one i32 argument.”

The imports object passed to WebAssembly.instantiate() mirrors that two-level namespace — the outer key is the module name and the inner key is the field name:

const importObject = {
env: {
log: (n) => console.log(n)
}
};

Each inner value must match the type declared in the WAT. A function import needs a JS function; a memory import needs a WebAssembly.Memory; a global import needs a WebAssembly.Global.

Here is a complete WAT module that imports the log function and calls it from an exported run function:

(module
(import "env" "log" (func $log (param i32)))
(func (export "run")
i32.const 42
call $log))

The run function pushes the constant 42 onto the stack, then calls $log — which consumes that value and passes it to whatever JS function was provided in the imports object.

On the JavaScript side:

const { instance } = await WebAssembly.instantiate(bytes, {
env: { log: (n) => console.log('Wasm says:', n) }
});
instance.exports.run(); // prints: Wasm says: 42
WebAssembly

Functions are the most common import, but the same mechanism works for memory, globals, and tables:

// Import a shared Memory
const memory = new WebAssembly.Memory({ initial: 1 });
const importObject = {
env: {
memory,
log: (n) => console.log(n)
}
};

A WebAssembly.Memory import lets JavaScript and Wasm share the same ArrayBuffer, making it possible to pass strings, arrays, and other structured data back and forth by reading and writing raw bytes. Globals and tables follow the same pattern — declare them in WAT with (import ...) and supply the matching WebAssembly.Global or WebAssembly.Table instance in the imports object.

In `(import "env" "log" ...)`, which is the module namespace?
What is the shape of the imports object for `(import "env" "log" (func ...))`?
What error is thrown when the imports object is missing a required import?