-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
WASM loader does not expose importObject #647
Comments
Yep. I kinda like the way webpack is planning to approach this (I think): imports in WASM files get mapped to module imports the same way imports in JS do. The problem is that the current Rust wasm backend always generates only a single import, and it's always called For example: #[wasm_module = "./externs.js"]
extern {
fn test1();
} The env name appears to be hardcoded in binaryen which is what Rust uses to do the compilation to wasm. This issue seemed somewhat related: WebAssembly/binaryen#943 |
You're correct, this is the right approach. WASM modules will eventually be ES modules, so imports/exports should work the same as they do in JS. I will likely be championing this over the next few months. Work will be tracked in WebAssembly/design#1087
The webpack folks also brought this up. If no one responds with a plan to address this, I'll bring it up in our biweekly WASM toolchain meeting (which is next Tuesday) and see if I can figure out what the plan is. |
In the shorter term, koute/stdweb#93 would allow rust code using the #[no_mangle]
pub fn call_js_function(x: i32) {
js! {
var js_function = require("./code.js").js_function;
js_function( @{x} );
}
} The It won't be possible to implement this without access to |
I've made an experimental (and really, really hacky) Parcel plugin here to compile Rust to WebAssembly using cargo-web. Compiling through it one can use the Even if WASM modules will eventually be treated as ES modules it would make sense to support customizing the imports until that future comes (or at least make it possible to do it from a plugin). |
This is also required for emscripten wasm support. At first I tried to register a custom BundleLoader, but bundle loaders are registered by file extension. bundler.addBundleLoader('emscripten',require.resolve('./EmscriptenLoader')); Would it be possible to add an option to specify a bundle loader in an Asset or Packager? |
@devongovett, @linclark FWIW y'all probably already found this, but on the Rust side of things this is tracked at https://github.com/rust-lang-nursery/rust-wasm/issues/29 where we very much don't want to have anything using |
@devongovett, can we expect any progress on this? |
Any update on this? I'm not sure how to use rust + wasm-bindgen with parcel and typescript. wasm-bindgen relies on imports being passed to the WebAssembly module. Circumventing the bundler and loading the wasm bundle at runtime doesn't seem possible without writing a parcel plugin to do something about the static files. |
It would be really nice to have support for I feel that you shouldn't have to compile WASM modules already knowing the paths of JS files they use. It would be nice to simply have them as standalone binary modules to which you can pass in imports they need to run (in keeping with the JS Besides, this would also open up support for wasm_bindgen as well as other existing WASM compilers. @hitecherik and I thought perhaps a syntax like this would be preferable (and compatible with the current import syntax)... const module = await import("module.wasm")(importObject);
module.foo(); |
I created a plugin to try and do just this based on @catsigma's parcel-plugin-wasm.rs. In order to get it working, I used The trouble is, this approach uses that generated module as a "bundle loader" which are used by Parcel per file type/extension. This means that if I have two Rust entry points, one of those is going to be loaded with an imports object that doesn't match the generated wasm module's public API (unless they happen to expose the exact same API). I created an issue about this against my plugin. I would love to come up with a way to treat wasm modules more like "regular" modules and be able to use more than one Rust library/entry in a project. My current thinking is to have my plugin import * as wasm from './example_bg';
/**
* @returns {void}
*/
export function run() {
wasm.run();
}
// ... a bunch of wasm bindgen stuff ... I think what I should be able to do is have my custom asset plugin emit a loader based on the import * as __exports from './example';
let wasm;
function init(module) {
let result;
const imports = { './example': __exports };
// like what gets emitted by `wasm-pack --target web`
// except the __exports object is just the imported / bindgen-generated module
}
export default init; I guess here's where I kind of stop being able to track what should happen. What do I so with the I'm interested in doing the work, and have some time available to do it. Any help/guidance would be greatly appreciated. |
Hi, I'm back. This plugin that I worked up:
|
mostly for record keeping; me vs javascript tooling round 5000 tried to drop the preprocessing in parcel-plugin-wasm.rs by going with --target web turns out that doesn't make any sense didn't realize this until _after_ writing it though; i've now seen way more parcel innards than i ever thought i'd need too (somehow the actual type of the generated field for assets is just not documented — reading the other assets to figure it out actually hurts more than it helps) ((also, parcel uses flow but not for these parts)) import.meta also made things pretty irritating (babel/babel#11364) went on an hour long detour through all the wasm-pack/wasm-bindgen options and how to best expose/use them through the plugin tried to use the bundler option (when not running on Node) also explodes in spectacular fashion; somehow parcel's wasm load just doesn't pass in imports I'm actually starting to think the find and replace scheme that's used right now is actually optimal.. So, really, it's parcel's fault. Webpack does the right thing here: parcel-bundler/parcel#647 I was going to say that this plugin (parcel-plugin-wasm-pack) manages to do better but really they do the exact same thing in a slightly less clumsy way: https://github.com/mysterycommand/parcel-plugin-wasm-pack/blob/f204a708d964127aaa1e5d278f41a44f5d76393b/src/WasmPackAsset.js#L174-L179 They do have tests though which is commendable
WebAssembly modules are able to import foreign Javascript functions and memory objects that are passed in the second parameter of
WebAssembly.instantiate(...)
. Unfortunately the current WASM loader is hard-coded to callinstantiate
with no import object.https://github.com/parcel-bundler/parcel/blob/master/src/builtins/loaders/wasm-loader.js
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate
The simplest solution would be to have the WASM loader instead run
WebAssembly.compile(...)
and return the compiledWebAssembly.Module
, so the user can callWebAssembly.instantiate(...)
with whatever parameters they need. I think that's how Webpacks wasm loader works.The text was updated successfully, but these errors were encountered: