GoogleChromeLabs/wasm-bindgen-rayon

Support for remotely-hosted workerHelper script?

josephrocca opened this issue ยท 9 comments

I've just published this and as shown in the readme I've uploaded it here:

https://deno.land/x/wasm_image_decoder@v0.0.1

But when trying to use it I get an error because the worker script is hosted on the deno.land origin rather than on the origin on which the module is being used.

I think this might be a relatively easy fix. It would just require changing this:

const worker = new Worker(import.meta.url, {
  type: 'module'
});

to this:

let scriptBlob = await fetch(import.meta.url).then(r => r.blob());
const worker = new Worker(URL.createObjectURL(scriptBlob), {
  type: 'module'
});

I edited workerHelpers.no-bundler.js with the above change and it works fine.

Can you foresee any problems with this change? And if not, would you accept a PR for this?

Can you foresee any problems with this change?

It's a common workaround, yeah, but problems might arise if a website uses CSP policy that allows only scripts from the same origin and forbids any unsafe-eval / blobs.

@RReverser I wonder then whether it might make sense to detect the error and at least try the fetch/blob approach? Here are the full details of the error:

{
  code: 18,
  message: "Failed to construct 'Worker': Script at 'https://deno.land/x/wasm_image_decoder@v0.0.1/wasm/snippets/wasm-bindgen-rayon-258f06ee9665d26e/src/workerHelpers.no-bundler.js' cannot be accessed from origin 'http://127.0.0.1:3002'.",
  name: "SecurityError",
}

Would it be enough to add a try/catch and try the fetch/blob approach on e.code === 18?

I don't know... I'd like to support Deno, but I'd really rather not add lots of branches with different behaviour since that complicates testing - I already feel bad about the bundler/no-bundler JS split, and hoping to remove it when it becomes possible.

Can you share more about what you're doing - are you using this crate from Deno itself or just using deno.land as a CDN in a browser? Maybe better understanding of the issues will help to find a better solution.

I'm just using deno.land as an easy place to host immutable JS code. The module works in Deno and the browser, so this issue isn't really about Deno support - it's about supporting usage in browser and browser-like runtimes where the module is imported from a remote location.

So the idea is that basically no matter where you are (Deno, browser, Observable notebook, etc.), you can just write something like:

let decode = (await import("https://deno.land/x/wasm_image_decoder@v0.0.3/mod.js")).default;
let buf = await fetch("https://i.imgur.com/LYVUrUf.jpg").then(r => r.arrayBuffer());
let result = decode(buf);
console.log(result);

and you've decoded your image.

No pressure on this though - feel free to close if it's not something that you want to support for now ๐Ÿ‘

Right, that makes sense - as I said above, I was just trying to figure out if you're using deno.land as any other CDN (e.g. unpkg.com etc.), or this was something necessary specifically for Deno support.

The module works in Deno

TIL! Maybe I should document that in README, I haven't looked into whether it would "just work" or require further modifications :)

I guess there's little harm in adding the Blob-based approach to specifically no-bundler use-case - after all, the primary reason it exists is to make simple hosted demos easier, while most other users would likely use bundlers for optimisations.

So yeah, I'd accept such PR - but please make sure to also revoke the created Blob URL once Worker is ready, so that browser could free the associated memory.

UPD: Oh, and make sure to add explanatory comment - as you might've noticed, I'm trying to document each hack in detail to make future maintainability easier :)

Okay great! I'll submit a PR soon. Would you like me to try/catch and use the fetch/blob as a backup, or just use the fetch/blob approach?

Also, I should clarify in case you test the above example code soon: It won't work in Deno until we get wasm threads support, which should happen next month. But generally speaking, any code that runs in the browser will run in Deno - so long as it doesn't use things that are specific to a "headful" runtime, like the document object, for example. Deno tries to be as close to a browser as possible. (Though you're right to suspect that modifications might be required, since it's still early days for Deno with a few big things left unsupported - wasm threads being one)

just use the fetch/blob approach?

Just one - as I said, better to keep code simpler and with fewer branches.

It won't work in Deno until we get wasm threads support, which should happen month. But generally speaking, any code that runs in the browser will run in Deno

Ah well, that's the thing I tried to figure out - whether it already "just works" :) Other than that, I'm aware of Deno's design / premise.

I'll just mention since you said you're not familiar with Github's review process - FWIW it's best not to close issues on Github before they're implemented (or deemed unnecessary). If you're resolving issue in a PR, then you just need to say Closes #1234 in a commit message and Github will auto-close it when PR is merged.

I've reopened this issue and updated your PR's description instead.