wasm-bindgen generated javascript contained an export named '__wbg_buffer_24f0cc96e872e2fe' but not one named '__wbg_buffer_85e60d809f6cd4e8', and the generated wasm references both.
Check out this commit: https://github.com/kyren/gfx/commit/043fec9bd77f0cfdad430a823df29c1ab824e84e
If you have nix you can run ./web_test/build.sh, otherwise just do the steps in the script:
cd to 'examples' and run:
cargo build --release --target=wasm32-unknown-unknown --bin quad --features gl
then cd .. and run wasm-bindgen like so:
wasm-bindgen --target no-modules --no-typescript --out-dir ./web_test ./target/release/wasm32-unknown-unknown/release/quad.wasm
Serve the web_test folder (serve.py serves on port 4000 if you have nix) and load index.html, and you will see:
LinkError: import object field '__wbg_buffer_85e60d809f6cd4e8' is not a Function
Definitions for both __wbg_buffer_85e60d809f6cd4e8 and __wbg_buffer_24f0cc96e872e2fe should be included in the exported javascript, or the wasm should only reference the exported one.
When building in release, there is a missing function definition and a javascript "LinkError". Also there is a somewhat misleading error message:
`WebAssembly.instantiateStreaming` failed. Assuming this is because your server does not serve wasm with `application/wasm` MIME type`
(It does say "Assuming", but it still threw me off for a bit).
This only happens in release, and according to IRC discussions with @alexcrichton it seems to be linker related and potentially a rustc bug? Enabling LTO apparently is a workaround, as is compiling with the 'cdylib' crate type instead of 'bin'.
For some follow-up, this should be fixed upstream in rust-lang/rust at https://github.com/rust-lang/rust/pull/60526.
The bug here is sort of subtle but has to do with the linker. The problem is that the __wbindgen_describe_* symbol for the WebAssembly::Memory::buffer API was missing from the final wasm binary, so wasm-bindgen didn't generate bindings for that method. (this is the __wbg_buffer_85e60d809f6cd4e8 symbol, the __wbg_buffer_24f0cc96e872e2fe is a buffer property accessor for a differnet type).
The WebAssembly::Memory::buffer API is "special" because it's only called internally by js-sys and it's also in a different object file codegen-wise. Because of ThinLTO in release mode the code for the method itself is inlined into Uint8Array::view, which means that the object file containing the descriptor for the __wbg_buffer_85e60d809f6cd4e8 is never actually referenced directly.
Linkers don't actually include object files in archives unless a symbol is referenced, so the archive of js-sys didn't have its object file included which contained the descriptor for __wbg_buffer_85e60d809f6cd4e8. Typically this is handled by passing flags to the linker in the cdylib crate type to export more symbols than lld would otherwise, but these flags weren't passed for the binary crate type.
The fix in https://github.com/rust-lang/rust/pull/60526 is to pass the flags for all crate types, meaning that even for the binary crate type we'll forcibly export the descriptor symbols.
Just a heads up, the fix has just reached stable :tada:
Thanks for the heads up! I think this is fixed to the best of our ability so I'm gonna close this.
Most helpful comment
Thanks for the heads up! I think this is fixed to the best of our ability so I'm gonna close this.