Skip to content

Commit 3019b5e

Browse files
committed
Add examples for how to use esm and raw host bindings
1 parent 9c2c53e commit 3019b5e

File tree

1 file changed

+67
-3
lines changed

1 file changed

+67
-3
lines changed

src/compiler.md

+67-3
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,14 @@ Optimization levels can also be tweaked manually: `--optimizeLevel` \(0-3\) indi
5353
Typical output formats are WebAssembly binary \(.wasm, `--outFile`\) and/or text format \(.wat, `--textFile`\). Often, both are used in tandem to run and also inspect generated code.
5454

5555
```
56-
--outFile, -o Specifies the output file. File extension indicates format.
57-
--textFile, -t Specifies the text output file (.wat).
58-
--tsdFile, -d Specifies the TypeScript definition output file (.d.ts).
56+
--outFile, -o Specifies the WebAssembly output file (.wasm).
57+
--textFile, -t Specifies the WebAssembly text output file (.wat).
58+
--bindings, -b Specifies the bindings to generate (.js + .d.ts).
59+
60+
esm JavaScript bindings & typings for ESM integration.
61+
raw Like esm, but exports just the instantiate function.
62+
Useful where modules are meant to be instantiated
63+
multiple times or non-ESM imports must be provided.
5964
```
6065

6166
### Debugging
@@ -320,6 +325,65 @@ export function getObjectField(target: ComplexObject): string | null {
320325

321326
Also note that exporting an entire `class` has no effect at the module boundary (yet), and it is instead recommended to expose only the needed functionality as shown in the example above. Supported elements at the boundary are globals, functions and enums.
322327

328+
### Using esm bindings
329+
330+
Bindings generated with `--bindings esm` perform all the steps from compilation over instantiation to exporting the final interface. To do so, a few assumptions had to be made:
331+
332+
* The WebAssembly binary is located next to the JavaScript bindings file using the same name but with a `.wasm` extension.
333+
```
334+
build/mymodule.js
335+
build/mymodule.wasm
336+
```
337+
338+
* JavaScript globals in `globalThis` can be accessed directly via the `env` module namespace. For example, `console.log` can be manually imported through:
339+
```ts
340+
@external("env", "console.log")
341+
declare function consoleLog(s: string): void
342+
```
343+
Note that this is just an example and `console.log` is already provided by the standard library when called from an AssemblyScript file. Other global functions not already provided by the standard library may require an import as of this example, though.
344+
345+
* Imports from other namespaces than `env`, i.e. `(import "module" "name")`, become an `import { name } from "module"` within the binding. Importing a custom function from a JavaScript file next to the bindings file can be achieved through:
346+
```ts
347+
@external("./otherfile.js", "myFunction")
348+
declare function myFunction(...): ...
349+
```
350+
Similarly, importing a custom function from, say, a Node.js dependency can be achieved through:
351+
```ts
352+
@external("othermodule", "myFunction")
353+
declare function myFunction(...): ...
354+
```
355+
356+
These assumptions cannot be intercepted or customized since, to provide static ESM exports from the bindings file directly, instantiation must start immediately when the bindings file is imported. If customization is required, `--bindings raw` can be used instead.
357+
358+
### Using raw bindings
359+
360+
The signature of the single `instantiate` function exported by `--bindings raw` is:
361+
362+
```ts
363+
export async function instantiate(module: WebAssembly.Module, imports?: WebAssembly.Imports): AdaptedExports
364+
```
365+
366+
Note that the function does not make any assumptions on how the module is to be compiled, but instead expects a readily compiled `WebAssembly.Module` as in this example:
367+
368+
```ts
369+
import { instantiate } from "./module.js"
370+
const exports = await instantiate(await WebAssembly.compileStreaming(fetch("./module.wasm")), { /* imports */ })
371+
```
372+
Unlike `--bindings esm`, raw bindings also do not make any assumptions on how imports are resolved, so these must be provided manually as part of the imports object. For example, to achieve a similar result as with esm bindings, but now customizable:
373+
374+
```ts
375+
import { instantiate } from "./module.js"
376+
import { myFunction } from "./otherfile.js"
377+
export const {
378+
myExport1,
379+
myExport2,
380+
...
381+
} = await instantiate(await WebAssembly.compileStreaming(fetch("./module.wasm")), {
382+
"./otherfile.js": {
383+
myFunction
384+
}
385+
})
386+
```
323387

324388
## Debugging
325389

0 commit comments

Comments
 (0)