rustwasm / wasm-bindgen

Facilitating high-level interactions between Wasm modules and JavaScript
https://rustwasm.github.io/docs/wasm-bindgen/
Apache License 2.0
7.76k stars 1.07k forks source link

Following upgrade to wasm-bindgen 0.2.95, Ruffle no longer works on Safari 15 and below #4227

Open danielhjacobs opened 1 day ago

danielhjacobs commented 1 day ago

Describe the Bug

We compile two wasm modules, one with target features for bulk-memory, simd128, nontrapping-fptoint, sign-ext, and reference-types and one without those target features. The one without those target features no longer works on Safari 15 and below. I suspect that may be caused by the combination of https://releases.rs/docs/1.82.0/#compatibility-notes (The WebAssembly target features multivalue and reference-types are now both enabled by default) and https://github.com/rustwasm/wasm-bindgen/blob/main/CHANGELOG.md#changed-2 ("Implicitly enable reference type and multivalue transformations if the module already makes use of the corresponding target features"), though it could be an unrelated issue. We'd like to try to generate a vanilla module like the one we created before, with those transformations disabled, but the Rust upgrade notes say "Generating a WebAssembly module that disables default features requires -Zbuild-stdsupport from Cargo", and looking at https://doc.rust-lang.org/cargo/reference/unstable.html#build-std, that's still an unstable feature, so I looked to wasm-bindgen for a way to at least disable the transformation but I don't see one.

This is the script that builds the WASM modules: https://github.com/ruffle-rs/ruffle/blob/master/web/packages/core/tools/build_wasm.ts

This is the code that determines which module to load: https://github.com/ruffle-rs/ruffle/blob/master/web/packages/core/src/load-ruffle.ts#L38-L52

Steps to Reproduce

  1. Go to https://ruffle.rs/demo/ with Safari 15
  2. The error reported by someone using that browser says RuntimeError: Out of bounds table access (evaluating 'b._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h281f2f93d3d6cf28(n,e,t)')

Expected Behavior

The vanilla WASM module that loads should work on browsers without WebAssembly extensions.

Actual Behavior

The application panics.

danielhjacobs commented 1 day ago

The code we use is as follows:

    if (extensions) {
        rustFlags.push(
            "-C",
            "target-feature=+bulk-memory,+simd128,+nontrapping-fptoint,+sign-ext,+reference-types",
        );
        wasmBindgenFlags.push("--reference-types");
        wasmOptFlags.push("--enable-reference-types");
    }

My initial thought was to change it to this:

    if (extensions) {
        rustFlags.push(
            "-C",
            "target-feature=+bulk-memory,+simd128,+nontrapping-fptoint,+sign-ext",
        );
        wasmBindgenFlags.push("--reference-types");
        wasmOptFlags.push("--enable-reference-types");
    } else {
        rustFlags.push(
            "-C",
            "target-feature=-reference-types,-multivalue",
        );
    }

But I'm not sure that will work based on the note that "Generating a WebAssembly module that disables default features requires -Zbuild-std support from Cargo"

RunDevelopment commented 18 hours ago

Not a maintainer, but maybe I can help.

As you already pointed out, disabling default features is not possible without nightly. So your only options in that regard are to either use nightly and rebuild std, or downgrade and pin Rust 1.81. The downgrade and pin path seems to be what other projects are doing btw.

However, while wasm bindgen can't disable those features AFAIK, it can generate JS glue code that doesn't use those features. Right now, WBG will automatically enable its code gen for multivalue and reference-types when those features are detected in the compiled binary. So there is currently #4213 to disable that, but the main maintainer of this repo is quite busy right now, so it might take a little until the fix is merged and released.