Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A flag to not use module-level global variables in web-target #3731

Open
alamminsalo opened this issue Dec 3, 2023 · 6 comments
Open

A flag to not use module-level global variables in web-target #3731

alamminsalo opened this issue Dec 3, 2023 · 6 comments

Comments

@alamminsalo
Copy link

Motivation

Lets say a user wants to create an audio plugin system using webassembly which uses a common interface that a plugin must implement in order to load. Currently, when loading multiple plugins using an AudioWorkletProcessor script, 'wasm' variable is set on first call on __wbg_init. This means subsequent loading of next plugin leads to using the already set 'wasm' variable, making it bit challenging to implement such system. Note that AudioWorkletProcessor scripts cannot use dynamic imports, making it hard to get fresh module by for example setting url parameters to bypass cache.

I fixed the problem by wrapping the generated .js file inside a function that returns __wbg_init, initSync and defined Rust types. However, this means I need to redo the modification the module each time it is generated.

Proposed Solution

A flag for web target that allows to load initialize multiple different instances of wasm blobs using the same module. My take was to wrap it inside a function but maybe there is another alternative approach that makes it possible to not break web target api.

Alternative Solutions

In case there is a simple fix that can be implemented using the current codebase, let me know!

@daxpedda
Copy link
Collaborator

daxpedda commented Dec 4, 2023

AFAIK audio worklets support dynamic imports for a while now. Which browser are you experiencing this on?

@alamminsalo
Copy link
Author

alamminsalo commented Dec 5, 2023

Chrome and Firefox both throw error of "TypeError: import() is disallowed on WorkletGlobalScope." for the following initialization code (in AudioWorkletProcessor).

const wasm = await import(`../wasm/default?t=${Date.now()}`);
await wasm.default(bytes);

Where ../wasm/default.js is the generated js file with __wbg_init etc.

@daxpedda
Copy link
Collaborator

daxpedda commented Dec 5, 2023

Ah right, I looked it up again, static imports are supported but not dynamic ones.

I think in general we should not be using any global variables in the no-modules target, but I didn't look into how that could be done, but AFAIK it should be possible.
We were also discussing before to completely remove the no-modules target in #3355, so that would pose a problem for you.

Generally speaking though, it is considered a bad idea to use wasm-bindgen to produce modules for a plugin system, because the JS bindings can do whatever they want. Usually the solution is to develop a proper plugin API that plugins can use so they are properly sandboxed.

@SIGSTACKFAULT
Copy link

SIGSTACKFAULT commented Dec 23, 2023

just now had a related problem in which the wasm object is re-used if, on a single-page web app, you navigate away from the page with wasm and back. a quick partial solution would be to add a way to destroy the wasm object held in the generated module e.g.,

export function __wbg_reset(){
    wasm = null
}

that way next time you run the __wbg_init you'll get a brand new wasm object

@daxpedda
Copy link
Collaborator

Sounds like a B/F cache problem to me.

@linonetwo
Copy link

A workaround is in #3818

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants