WASM interface Q

All,

I’m reviewing the tutorial for CF Workers / WASM here:

https://developers.cloudflare.com/workers/templates/boilerplates/rustwasm/

And I have a question regarding the following code:

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

/**
 * Fetch and log a request
 * @param {Request} request
 */
async function handleRequest(request) {
  const { parse } = wasm_bindgen  // <-- This,
  await wasm_bindgen(wasm)        // <-- and this
  const output = parse()
  let res = new Response(output, { status: 200 })
  res.headers.set('Content-type', 'text/html')
  return res
}

What exactly are the two lines I’ve pointed out doing? I suspect the first line is declaring parse() for JS, but the second line is doing … ?

Also, where is the module name used? e.g. if I upload a WASM resource, MYWASM, do I then do the following:

    const { parse } = MYWASM
    await wasm_bindgen(MYWASM)

That just doesn’t look right. Any pointers? Do I really have to await generating the bindings for each call?

Thanks,

Jason

Ok, let me try asking this in a different way:

Has anyone successfully used WASM from a Worker? Mind sharing your event handler code?

Thanks,

Jason

1 Like

I should preface this with “not a javascript expert”.

  const { parse } = wasm_bindgen  // <-- This,

This imports this function from Rust:

#[wasm_bindgen]
pub fn parse() -> String {

that is, this wasm_bindgen exposes a list of functions, and I believe this is using object destructuring to create a function named parse that corresponds to the parse exposed by wasm_bindgen.

  await wasm_bindgen(wasm)        // <-- and this

This actually loads the bound wasm.

You can see some similar stuff in https://rustwasm.github.io/wasm-bindgen/examples/without-a-bundler.html, but I believe that’s using ES module syntax.

If you did it by hand, including the bindings, sure. But there’s not really a reason to; that’s why Wrangler exists :slight_smile:

In my code, I just changed parse to the name of my function, and called it with the right arguments later on. It’s not a great idea to go back and forth and back and forth between JS and wasm anyway, so all the logic lives inside a single “main function” in the wasm.

Hope that helps.

Ahhh, ok. Thanks so much for the clarification! The CF Workers syntax is different from e.g. the MDN examples. And I think I had it stuck in my head that it was more similar to KV resources in that let ret = MYWASM.parse(...) was what I looking for. I’m guessing there’s a certain amount of presumed JS knowledge that I don’t have. :slight_smile:

Yeah, the Workers project I started with, I got a lot of inconsistent results between “push X, download Y, why is X != Y?” So ended up throwing out all of the “spooky action at a distance” and just used a Makefile and a shell script [0]. From then on, I got consistent results, because make clean deleted the build/ directory where I concatenated the individual scripts. Therefore I knew exactly what was going into the deployed script. I controlled which JS fragments to include in which target scripts based on Linux kernel kconfig-style configuration and I prepend the non-git-tracked secrets so API keys and such are never in the source history. It’s been working beautifully, but no, it’s not wrangler. I realize I’m on my own in that respect, but I prefer the dependable simplicity.

Agreed for sure, I’m looking at adding a single function call to do some complex math and return the result. Only one call per request will be necessary, so I seem to be on the right track there. If CF’s V8 engine supports WASM’s SIMD accelerated instructions, I’m in a really good place.

[0] Yes, I freely admit that this is completely due to my lack of familiarity with JS :-))

1 Like

Did you happen to file bugs? I’m sure the team would love to check them out.

Ha! That’s nice of you to assume the error was in the tool. :slight_smile: . I’m fairly certain it was EBKAC [0]. I basically decided to skip the JS ecosystem learning curve. e.g. minification was preventing me from doing basic debugging (line numbers and variable names went away), and I didn’t know how to disable it back then. Also, didn’t know how to remove cached minified objects and some of my problems seems to originate around stale code remaining in the deployed script.

Honestly, the only bug I’ve consistently run into that I still think might be legit is the inconsistent state that seems to happen between using the CF Workers Web interface and then switching to uploading via wrangler/curl API. I’ve just completely given up on the web interface because it didn’t feel consistent to me . Once I did that, I always had the code I expected running actually deployed.

I just went to “Launch Editor” to provide a clear example of what I’m referring to, but it seems CF is already on it. It’s being deprecated in favor of a new interface. Which I’ve also not used because I don’t want my-worker._____.workers.dev domain. I really wish I could skip setting that up…

The last thing I need is another place for a deployed script to hide, “oh ■■■■, I accidentally uploaded the new version to the domain I never use!”

[0] Error Between Keyboard and Chair

2 Likes