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

Dependent module support #3019

Open
lukaslihotzki opened this issue Aug 3, 2022 · 2 comments · May be fixed by #3034
Open

Dependent module support #3019

lukaslihotzki opened this issue Aug 3, 2022 · 2 comments · May be fixed by #3034

Comments

@lukaslihotzki
Copy link
Contributor

Motivation

Rust crates should be able to abstract worker and worklet handling without requiring extra effort by the application developer. For worker and worklet creation, a URL pointing to the worker module is needed. This worker module typically contains custom code supplied by the Rust crate that creates the corresponding worker. If the worker needs to execute the Rust code of the application, the worker module needs to import the main module generated by wasm_bindgen, so the WASM imports are available. Dependent module support would allow Rust crates to put their worker modules into the final package during the build process.

Proposed Solution

The macro wasm_bindgen::dependent_module! takes a local file name to a JS module as input. Additionally, the macro generates an import statement to the main module currently generated by wasm_bindgen code. This import statement is then prepended to the module code. The resulting file is put in the output directory during the build process, similarly to snippets. In contrast to snippets, these modules are not imported by the main module. Instead, the macro resolves to code that returns the URL string to the corresponding file during run time. The macro caller can then use this URL string to create workers or worklets.

Alternatives

Dependent module URLs can also be built at run time by querying the main module URL (for example, with import.meta.url), and then creating a blob or data URL with the import statement and constant code concatenated. The proposed wasm-audio-worklet example contains a concise implementation of this approach that only works with --target web. The wasm-mt and wasm_thread crates use similar, but more complex techniques that also work with --target no-modules by manually fetching the source code of the main module, so no import statements are needed.

Generating dependent modules at run time is the inferior solution, because it is opaque to wasm_bindgen. For example, Rust crates using wasm_bindgen::dependent_module! don't need to care about the different targets of wasm_bindgen. Also, build time bundlers can optimize or pack dependent modules. Additionally, run-time JS code generation introduces potential security vulnerabilities (like eval), so it should be avoided. In contrast, build-time dependent modules can even be used with restrictive CSP headers.

Additional Context

Packing is currently needed for worklets in Firefox, because import statements are currently broken there. As mentioned before, this problem can be solved by manually fetching code. However, the main module can also contain imports, so you would need to write a complete ES module packer which is executed at run time. When dependent modules are generated during the build, you can use existing tools for packing.

@stefnotch
Copy link

stefnotch commented May 25, 2023

The Firefox issue has been closed and is going to ship with the next Firefox version. Would that let us close this issue?

@daxpedda
Copy link
Collaborator

Worker modules, which presumably will ship in Firefox v114, will make this feature not necessary to spawn conveniently spawn worker modules.

Though some code will still have to be generated during runtime, which this feature would avoid.

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

Successfully merging a pull request may close this issue.

3 participants