How to import an extern JS function when compiling wasm to the nodejs target?

So I'm trying to create a node package by compiling some rust code to webassembly. Since I intend to use this with Node, and no bundler, I'm using

wasm-pack build --target nodejs

This generates a node module that I'm able to require() but I'm still having one issue regarding extern JS functions imports for the webassembly module. I have the following extern functions:

#[wasm_bindgen]
extern "C" {
    fn fetchElmJson(pkg: &str, version: &str) -> String;
    fn listAvailableVersions(pkg: &str) -> Vec<JsValue>;
}

Unfortunately, when I import my my wasm package in my main JS app, I didn't find anyway to make those extern functions available to the wasm package.

// package.json of my main app
{
  "name": "elm-deps",
  "dependencies": {
    // "elm-solve-deps-wasm": "file:../pkg" // during dev
    "elm-solve-deps-wasm": "0.1.0"
  }
}
// index.js
function fetchElmJson(pkg, version) { ... }
function listAvailableVersions(pkg) { ... }
let wasm = require("elm-solve-deps-wasm");
wasm.init();
// The solve call fails saying that the function fetchElmJson is not defined.
wasm.solve(...);
...

It makes sense to me that functions defined in my index.html would not be available inside the wasm package I import. But then, how can we make extern function available when compiling the wasm to a node module?

Any idea on how to do this cleanly? I haven't found any clue in the wasm book, the wasm-pack book or the wasm-bindgen book. All other approaches I tried brought their own complications.

It seems so obvious to me to be wanting to have extern functions provided by package users instead of package implementers that I don't understand why there isn't an explanation of how to do this. And that makes me question if what I'm trying to do is right, or if I should do it in a completely different way.

And that makes me question if what I'm trying to do is right, or if I should do it in a completely different way.

That's probably it.

I've just found that it's possible to pass a JS function as argument and call it thanks to the js_sys crate:

#[wasm_bindgen]
pub fn call_js(f: &js_sys::Function) {
    let this = JsValue::null();
    let x = JsValue::from_str("some argument");
    let _ = f.call1(&this, &x);
}

So it's probably what I want instead of trying to bring "extern" JS functions from user imports.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.