Stream: general

Topic: import host-impl'ed wasi:logging into componentize-js?


view this post on Zulip Zeeshan Lakhani (Feb 22 2024 at 01:18):

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.

view this post on Zulip Guy Bedford (Feb 22 2024 at 01:33):

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');.

view this post on Zulip Zeeshan Lakhani (Feb 22 2024 at 01:45):

@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?

view this post on Zulip Guy Bedford (Feb 22 2024 at 01:46):

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

view this post on Zulip Guy Bedford (Feb 22 2024 at 01:46):

if the interface is versioned then you must also import it with the exact version included as well

view this post on Zulip Zeeshan Lakhani (Feb 22 2024 at 01:46):

--wit takes in a directory, perfect. That's what I was looking for. Yep, on versions.

view this post on Zulip Zeeshan Lakhani (Feb 22 2024 at 01:47):

Thanks @Guy Bedford. Will close once it works, trying these bits out now.

view this post on Zulip Zeeshan Lakhani (Feb 22 2024 at 02:21):

we had only been feeding it the file(s) directly. +1

view this post on Zulip Brian Ginsburg (Feb 22 2024 at 19:52):

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-jsas 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?

view this post on Zulip Zeeshan Lakhani (Feb 22 2024 at 20:10):

cc'ing @Guy Bedford on the :point_of_information:

view this post on Zulip Guy Bedford (Feb 22 2024 at 20:38):

witWorld in this case should be eitherimports or wasi:logging/imports I believe as the name of the world being built.

view this post on Zulip Guy Bedford (Feb 22 2024 at 20:40):

also the logging folder should be nested inside of deps/logging not logging I think

view this post on Zulip Guy Bedford (Feb 22 2024 at 20:40):

cargo install wasm-tools && wasm-tools component wit ./wit is another way to validate the local WIT folder

view this post on Zulip Brian Ginsburg (Feb 23 2024 at 00:39):

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?

view this post on Zulip Guy Bedford (Feb 23 2024 at 00:49):

Can you share the JS you are calling here?

view this post on Zulip Guy Bedford (Feb 23 2024 at 00:49):

when the logging function call is made

view this post on Zulip Brian Ginsburg (Feb 23 2024 at 00:50):

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;
}

view this post on Zulip Guy Bedford (Feb 23 2024 at 00:51):

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?

view this post on Zulip Guy Bedford (Feb 23 2024 at 00:54):

although it should say expected a string as a JS error in that case I think

view this post on Zulip Guy Bedford (Feb 23 2024 at 00:57):

oh you don't have error handling so that JS error is turning into a panic

view this post on Zulip Guy Bedford (Feb 23 2024 at 00:58):

you can enable stdOut with enableStdout: true to get the error

view this post on Zulip Guy Bedford (Feb 23 2024 at 00:59):

or you could wrap the log(...) call in a try { ... } catch { ... } to validate its error

view this post on Zulip Zeeshan Lakhani (Feb 23 2024 at 00:59):

@Guy Bedford just jumping on, derp on the string :). With enablestdout, we'll see the right error on the js side then? very cool.

view this post on Zulip Guy Bedford (Feb 23 2024 at 01:00):

incorrect bindgen errors that are panics should log to stderr I believe with that enabled yes

view this post on Zulip Zeeshan Lakhani (Feb 23 2024 at 01:01):

dope, thank you

view this post on Zulip Guy Bedford (Feb 23 2024 at 01:02):

if you're still having issues feel free to share a full replication and I can take a look

view this post on Zulip Brian Ginsburg (Feb 23 2024 at 01:03):

@Guy Bedford that was it! Duh, a string. Thanks for helping us debug this. :)


Last updated: Dec 23 2024 at 12:05 UTC