Welcome to the first post in a series discussing post-MVP features coming to WebAssembly via the proposals process. There are some exciting things coming up and today we'll be looking at the ECMAScript Module Integration of WebAssembly Modules.

The proposal (Phase 2) adds support for importing and loading WebAssembly Modules declaratively with the familiar JavaScript import statement or the <script type="module"> tag.

Currently WebAssembly Modules must be loaded via one of four methods:

const source = fetch('add.wasm');

// 1. Should be used only if the module needs to be
//    compiled before instantiating.
//    Returns a Promise<WebAssembly.Module>.
source
  .then(response => response.arrayBuffer())
  .then(bytes => WebAssembly.compile(bytes))

// 2. Otherwise just use this.
//    Returns a Promise<ResultObject>.
source
  .then(response => response.arrayBuffer())
  .then(bytes => WebAssembly.instantiate(bytes))

// The previous two are nice and all but newer variants which
// begin compilation while the binary is still busy downloading
// are AWESOME and more efficient! โญ

// 5. Returns a Promise<WebAssembly.Module>.
WebAssembly.compileStreaming(source)

// 4. Returns a Promise<ResultObject>.
WebAssembly.instantiateStreaming(source) 

The ResultObject contains the compiled WebAssembly module property for convenience which can be instantiated again or passed around, but also the instance property. We can access any of the functions exported by the WebAssembly module via the instance.exports object.

For example, let's say that the add function was exported from add.wasm above. We'd invoke it from the result object, say obj, with obj.instance.exports.add(2, 3). But with the ES Modules Integration proposal, things would become far less cumbersome:

import { add } from './add.wasm';

console.log(add(2, 3));

Short and sweet.

Next time we'll be looking at the WebAssembly Threads proposal with new atomic memory instructions for safely accessing memory from multiple threads.