dlemstra / magick-wasm

The WASM library for ImageMagick
Apache License 2.0
571 stars 38 forks source link

Please allow `initializeImageMagick` to take an already existing `WebAssembly.Module` #134

Closed johnspurlock closed 10 months ago

johnspurlock commented 10 months ago

Is your feature request related to a problem? Please describe.

No response

Describe the solution you'd like

Hi there, great library! I'm running in an environment that, for security reasons, does not allow instantiating wasm modules from arbitrary byte arrays. Instead, it allows you to upload the wasm bytes at deployment time and will make a variable of type WebAssembly.Module available in the runtime as part of that deployment.

Could you please add the ability to provide this WebAssembly.Module as the argument to initializeImageMagick? (in addition to the existing URL and Uint8Array)

It is usually fairly simple to add a path that stores the module and passes it directly to the WebAssembly.Instance ctor wherever you do the WebAssembly instantiation. Only thing to keep in mind is that the importObject needs to be passed as the 2nd arg to the ctor, since it was not available earlier.

I tried to hunt down where you are doing the WebAssembly loading but could not find it!

Thanks! - John

Describe alternatives you've considered

No response

Additional context

No response

dlemstra commented 10 months ago

This library uses emscripten to compile and load the web assembly module. What kind of environment are you running in and would it be possible for me to create such an environment that I can use to try any changes that I make?

I have found a setting called instantiateWasm in the settings (https://emscripten.org/docs/api_reference/module.html) and an example here: https://github.com/emscripten-core/emscripten/blob/main/test/manual_wasm_instantiate.html. Would that work for your situation?

johnspurlock commented 10 months ago

Thank you - that instantiateWasm callback looks promising. You could build support for passing a WebAssembly.Module to initializeImageMagick on top of that. When arg is instanceof WebAssembly.Module, the callback implementation would look something like:

Module.instantiateWasm = function(imports, successCallback) {
  // module is the arg to initializeImageMagick
  // important to use the 2nd constructor arg to pass the imports here
  const instance = new WebAssembly.Instance(module, imports); 
  successCallback(instance);
}

As for testing, I suppose the easiest way to test would be in a browser, once you have the wasm bytes as a Uint8Array:

const module = await WebAssembly.compile(bytes); 
initializeImageMagick(module);
dlemstra commented 10 months ago

Thanks for helping out. I just made a proof of concept with the code that you provided. I was able to load the wasm library by passing the module and then run all my unit tests. This will become available in the next release. Is this something that you need quickly or can you wait for the next release that could take a month?

johnspurlock commented 10 months ago

Oh great! Next release is totally fine, I copied index.js from the 0.0.27 npm package locally and made a few hacky edits for now - but will be easier going forward for new releases if this is natively supported.

Thanks again!