Importing Emscripten Worker

I am in the process of adding worker support to an emscripen module (working fine) but am getting a “cannot be accessed from origin” error.

You can see the failing page here: https://observablehq.com/@gordonsmith/graphviz-wasm-worker-example
While the non worker version is working fine here: https://observablehq.com/@gordonsmith/graphviz-wasm-example

All links seem to be good - smells like a CORS issue, but the WASM file is also loaded in a CORS kinda way…

The reason this happens is that scripts passed to the Worker constructor must obey the same-origin policy and as far as I know you can’t get around this with CORS.

I don’t know of any really clean solutions to this. I have a notebook that relies on WASM running in a worker, but the relevant scripts are bundled using webpack which I’ve configured to inline the worker script. You can see that in the end result here, there’s a giant string on line 280 containing the worker script which gets loaded by the function from 283 to the end.

I haven’t read it in detail, but this article appears to give a readable explanation of the inlining technique and how you might make use of it yourself.

2 Likes

Here’s an exceptionally dirty hack to make it work:

Diff:

The hack works by passing a string object to wasmFolder which, when concatenated with ‘worker.min.js’, will return the worker object URL. The URL has a ‘#’ suffix so that anything that’s appended will have no effect.
When wasmFolder gets passed via postMessage to the worker, it will instead evaluate to base.

Note that the path passed to require.resolve() ends with “.” to keep resolve() from appending a “.js” suffix.

2 Likes

Thanks for that - I was hoping to avoid bundling the worker into my main bundle and instead load it at runtime as I plan on having a single package which dynamically loads each c++ piece on demand (assuming I add more!).

I had seen the in-lining “trick” before, but dismissed it as I have to dynamically load the wasm anyway.

Impressive you got it working at all (hack or no hack).

Before I go any further I need to see if moving it into a worker will actually improve performance enough to justify it (and I can now do some quick benchmarks here).

Thx again.

1 Like