Howdy, all. We're using componentize-js as a library within a project we're working on. We've implemented the Wasi logging interface on the host atop our wasmtime embed with a custom log
host function and would like to make it available for use/to call on the javascript guest. This was easy to do in Rust with cargo component, but how can we import it for use within componentize? Essentially, our project just compiles the component (calling componentize
) and we run the Wasm component on our runtime host elsewhere.
If the world being componentized has a logging import, then it should just work from there. Implementing that import is then handled via importing the WASI interface as a JS ES module import - import { log } from 'wasi:logging/logging'; log('trace', 'context', 'msg');
.
@Guy Bedford ah yeah, similar to how I did things in Rust before we moved to cargo-component. Of course. Does the JS have to know about the dep wits (like logging) on a path anywhere?
when running componentize, you will want to point it to the world to build eg via --wit wit
where the directory contains a world importing the logging interface
if the interface is versioned then you must also import it with the exact version included as well
--wit takes in a directory, perfect. That's what I was looking for. Yep, on versions.
Thanks @Guy Bedford. Will close once it works, trying these bits out now.
we had only been feeding it the file(s) directly. +1
Hey! I'm working with @Zeeshan Lakhani on this. The imports aren't resolving how we would expect, and we may be missing something. We are using componentize-js
as a library like this:
const jsSource = readFileSync("src/subtract.js").toString();
const witWorld = readFileSync("wit/world.wit").toString();
const witPath = fileURLToPath(new URL("./wit", import.meta.url));
const { component } = await componentize(jsSource, witWorld, { witPath });
await writeFile("output", component);
The wit
directory contains the following:
.
├── logging
│ ├── logging.wit
│ └── world.wit
└── world.wit
where the top-level world.wit
is our world and the logging subdirectory contains the wits from the logging proposal: https://github.com/WebAssembly/wasi-logging/tree/main/wit.
Our world contains:
package fission:subtract@0.1.0;
world math {
import wasi:logging/logging;
export subtract: func(a: s32, b: s32) -> s32;
}
When we run that, we get this error:
file:///Users/brian/code/fission/writing-functions-blogpost-2024/js/node_modules/@bytecodealliance/componentize-js/lib/spidermonkey-embedding-splicer.js:3470
throw new ComponentError(variant26.val);
^
ComponentError: package not found
--> component.wit:4:10
|
4 | import wasi:logging/logging;
| ^-----------
at spliceBindings (file:///Users/brian/code/fission/writing-functions-blogpost-2024/js/node_modules/@bytecodealliance/componentize-js/lib/spidermonkey-embedding-splicer.js:3470:11)
at componentize (file:///Users/brian/code/fission/writing-functions-blogpost-2024/js/node_modules/@bytecodealliance/componentize-js/src/componentize.js:36:64)
at async file:///Users/brian/code/fission/writing-functions-blogpost-2024/js/index.js:23:23
Are we arranging or importing the wit dependencies incorrectly?
cc'ing @Guy Bedford on the :point_of_information:
witWorld
in this case should be eitherimports
or wasi:logging/imports
I believe as the name of the world being built.
also the logging
folder should be nested inside of deps/logging
not logging
I think
cargo install wasm-tools && wasm-tools component wit ./wit
is another way to validate the local WIT folder
Thanks @Guy Bedford! Re-organizing the directory structure was indeed needed. Instead of imports
or wasi:logging/imports
, we used our world name math
and that worked out with the second param as an object:
const jsSource = readFileSync("src/subtract.js").toString();
const witPath = fileURLToPath(new URL("./wit", import.meta.url));
const { component } = await componentize(jsSource, {
witPath,
worldName: "math",
});
await writeFile("output/subtract.wasm", component)
That built, and the WIT interface on the component looks correct:
package root:component;
world root {
import wasi:logging/logging;
export subtract: func(a: s32, b: s32) -> s32;
}
However, the logging function doesn't execute as expected. We embed Wasmtime in our runtime and implement logging in our host. Logging works with Wasm components we have generated with Rust, using the same wasi-logging
deps.
Glancing at the Rust and JS sourced WATs, we see wasi:logging/logging
in the opening sections of the component. But perhaps we are missing something? Attaching the WATs here, with the JS one truncated because it's awful large:
rust.wat
js_truncated.wat
The JS subtract function without logging runs fine on our runtime, but throws and error:
cannot execute wasm module: error while executing at wasm backtrace:\n 0: 0x57e856 - <unknown>!<wasm function 6690>\n 1: 0x5812c9 - <unknown>!<wasm function 7284>\n 2: 0x330a8c - <unknown>!<wasm function 590>\n 3: 0x57dc74 - <unknown>!subtract"
Another thing we noticed is the JS WAT does not contain the WASI imports that are in the Rust one (for example wasi:io/streams@0.2.0
). Does componentize-js
default to adding these through the preview adapter?
Can you share the JS you are calling here?
when the logging function call is made
Yep! This is our JS code:
// @ts-ignore
import { log } from "wasi:logging/logging";
export function subtract(a, b) {
const result = a - b;
log("trace", "guest:js:subtract", result);
return result;
}
The third parameter should be a string - can you try putting String(result)
in the third argument position just to be sure you're calling it correctly?
although it should say expected a string
as a JS error in that case I think
oh you don't have error handling so that JS error is turning into a panic
you can enable stdOut with enableStdout: true
to get the error
or you could wrap the log(...)
call in a try { ... } catch { ... }
to validate its error
@Guy Bedford just jumping on, derp on the string :). With enablestdout, we'll see the right error on the js side then? very cool.
incorrect bindgen errors that are panics should log to stderr I believe with that enabled yes
dope, thank you
if you're still having issues feel free to share a full replication and I can take a look
@Guy Bedford that was it! Duh, a string. Thanks for helping us debug this. :)
Last updated: Dec 23 2024 at 12:05 UTC