string-reverse-upper (reverse() + toUpper()) in JavaScript, with WebAssembly composition
This folder contains a Javascript project that can be built into a WebAssembly component binary.
This is a node CLI and browser based example implementation of running a component that exports the reversed-upper interface from a JavaScript application.
It uses jco to:
- Generate a WebAssembly component (
jco componentize) that can be executed anywhere WebAssembly components run - Generate JavaScript bindings (
jco transpile) that execute the core functionality (in browser or compliant JS runtimes like NodeJS) - Build a component that composes with another component
For another example of using jco with components in multiple environments, see the jco example.
Component Interface
This component uses functionality provided by another binary to export new functionality, with the following interface:
package example:string-reverse-upper@0.1.0; @since(version = 0.1.0) interface reversed-upper { reverse-and-uppercase: func(s: string) -> string; } world revup { // // NOTE, the import below translates to: // <namespace>:<package>/<interface>@<package version> // import example:string-reverse/reverse@0.1.0; export reversed-upper; }
Note
You can read more about [the WIT syntax][wit] online.
Quickstart
Dependencies
First, install required project-level dependencies:
pnpm installNote
We recommend pnpm due to it's security-focused and space-saving features.
Along with projet related dependencies, since this is a compound component (this component is composed with another),
we'll need to install the WebAssembly Composition tool (wac), which we will use later to compose components.
Building the WebAssembly binary (pre-composition)
Then, build the component with jco:
pnpm run buildA WebAssembly binary will be written to string-reverse-upper.incomplete.wasm.
Note that this binary is still not complete (hence the name) -- it imports functionality that is not yet defined/accessible in any way.
We can confirm this incompleteness with jco via the compiled binary itself, by running jco wit:
jco wit string-reverse-upper.incomplete.wasmYou should see output like:
package root:component; world root { import example:string-reverse/reverse@0.1.0; export example:string-reverse-upper/reversed-upper@0.1.0; }
Just like our wit/component.wit, this component imports functionality, but that functionality must be provided by something (in WebAssembly Component-Model terms, either the host or another component).
Composing in the reverse() functionality from another WebAssembly binary
Since the string-reverse-upper.incomplete.wasm we just built component uses (depends on) another component, we must compose the component with the functionality we need.
The component we will be composing with our as-of-yet incomplete binary must satisfy the imported interface (example:string-reverse/reverse@0.1.0, defined in wit/deps/string-reverse-wit).
pnpm run composeWarning
This step is the one that uses wac -- ensure it's installed!
Running the command above will produce a string-reverse-upper.wasm file (this time, that is complete).
After running component composition, there will be a component with all its imports satisfied, called string-reverse-upper.composed.wasm.
We can confirm this with jco wit:
jco wit string-reverse-upper.incomplete.wasmYou should see output like:
package root:component;
world root {
export example:string-reverse-upper/reversed-upper@0.1.0;
}
Transpiling the composed (complete) component to run it from native JS
We can transpile that composed component to a JS module with jco:
pnpm run transpileTranspilation produces files in dist/transpiled that enable the WebAssembly component (string-reverse.wasm) to run in any compliant JS runtime:
dist
└── transpiled
├── interfaces
│ └── example-string-reverse-upper-reversed-upper.d.ts
├── string-reverse-upper.core2.wasm
├── string-reverse-upper.core.wasm
├── string-reverse-upper.d.ts
└── string-reverse-upper.js
With this transpiled code available, we can now run native NodeJS code that will use the WebAssembly module:
pnpm run transpiled-js
Note
You might have noticed that Typescript declaration files were also produced.
As Typescript transpiles to Javascript, you can build WebAssembly components with Typescript
granted you bring a transpiler (like tsc), and use the generated declaration files.