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

web: Allow building an MVP vanilla WASM module #18528

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

danielhjacobs
Copy link
Contributor

I'm not sure whether this itself will be controversial. By itself, this update changes nothing in the development or CI pipelines by default.

Instead, it adds an environment variable, BUILD_WASM_MVP, which when set will cause npm run build:dual-wasm and/or npm run build:repro to create a truly vanilla WASM module by using nightly Rust to disable all the WebAssembly extensions. With this set, the version of Ruffle that gets built can run on Pale Moon and Safari versions as old as 14.1.

What this doesn't do (yet) is use this environment variable on CI or in the Firefox Docker script. Doing that is a matter of debate. Once we unpin CI from Rust 1.81, if we don't use this environment variable on CI, Ruffle will stop working on those older browsers. We can use this on CI temporarily as long as we want to keep supporting those browsers.

@danielhjacobs
Copy link
Contributor Author

We had wanted to wait for a wasm-bindgen update, but rustwasm/wasm-bindgen#4213 was replaced by rustwasm/wasm-bindgen#4235, which only disables reference type transformations for the bundler target (and updates CI to Rust v1.82). rustwasm/wasm-bindgen#4227 was closed as not planned. On that issue, daxpedda suggested wasm32v1-none. I pointed to #18412. daxpedda said

Arc and Mutex should be replaced with Rc and RefCell unless you are using multi-threading. HashMap can be replaced with hashbrown and so on.
If Ruffle intends to continue supporting older versions of Safari with newer versions of Rust and therefore LLVM, it should definitely consider supporting wasm32v1-none.

However, getting wgpu no_std compatible would require quite some work, and I don't know about other dependencies.

With that in mind, we're back to the issue of either using nightly Rust, or dropping support for Safari versions 15 or below and Pale Moon

daxpedda doesn't want to disable the transformations because:

disabling those would only be a temporary solution, e.g. if multi-value gets properly enabled by LLVM it would be emitted by Rust and not wasm-bindgen. This will continue as more and more proposals will be enabled by default which older versions of Safari don't support.

@torokati44
Copy link
Member

or dropping support for Safari versions 15 or below and Pale Moon

The former will only get less and less relevant over time, while the latter may (?) end up having this support added...?

@danielhjacobs
Copy link
Contributor Author

If we're dropping support for Safari 15 officially, there's an extra consideration we haven't talked about. All the current features are Safari 16+, right? Do we need dual-wasm then?

@torokati44
Copy link
Member

Interestingly, if we go the nightly route (which I'm not a fan of, BTW) the -Z build-std=std,panic_abort options would also be fairly beneficial for the build with extensions enabled, because a lot of naive memcpy-ing and memset-ing in std (in Vec for instance, while decoding videos) would be a lot faster using the bulk-memory extension.

@danielhjacobs
Copy link
Contributor Author

while the latter may (?) end up having this support added

That's down to whether https://repo.palemoon.org/MoonchildProductions/UXP/issues/2647 gets fixed. Also worth considering, although I said "all the current features are Safari 16+", I don't know which other ones are unsupported by Pale Moon.

@danielhjacobs danielhjacobs added A-web Area: Web & Extensions T-feature Type: New Feature (that Flash doesn't have) labels Nov 8, 2024
@danielhjacobs
Copy link
Contributor Author

danielhjacobs commented Nov 8, 2024

The former will only get less and less relevant over time

The general consensus is that this should at most be a temporary solution. macOS Catalina and iPhone models 7 and below can't upgrade to Safari 16+. Do we have any ideas on market share there?

@danielhjacobs
Copy link
Contributor Author

danielhjacobs commented Nov 8, 2024

@danielhjacobs
Copy link
Contributor Author

danielhjacobs commented Nov 8, 2024

Downloaded this as a CSV, did some calculations:

https://gs.statcounter.com/os-version-market-share/ios/mobile-tablet/worldwide

"Percent of iOS supported" represents what percent of iOS users Ruffle currently supports.
"Percent iOS supported without iOS 14" represents what percent of iOS users Ruffle would support with reference-types enabled if it worked on Safari 15 as it should.
"Percent iOS supported without iOS 14-15" represents what percent of iOS users Ruffle supports with reference-types enabled since it doesn't seem to work on Safari 15, at least for wgpu.
"Percent iOS 16.4+" represents what percent of iOS users can use the WASM module with extensions.

Month Percent iOS 14(.1+) Percent iOS 15 Percent iOS 16 Percent iOS 17 Percent iOS 18 Percent of iOS supported Percent iOS supported without iOS 14 Percent iOS supported without iOS 14-15 Percent iOS 16.0-3 Percent iOS 16.4+
2023-10 2.22 9.94 65.87 18.11 0 96.14 93.92 83.98 14.4 69.58
2023-11 1.95 9.56 54.09 30.74 0 96.34 94.39 84.83 13.38 71.45
2023-12 1.76 9.16 30.61 54.45 0 95.98 94.22 85.06 12.31 72.75
2024-01 1.7 8.82 27.16 58.34 0 96.02 94.32 85.5 11.33 74.17
2024-02 1.72 9.1 23.74 61.41 0 95.97 94.25 85.15 10.27 74.88
2024-03 1.61 8.88 20.79 64.66 0 95.94 94.33 85.45 9.3 76.15
2024-04 1.48 8.39 18.89 67.26 0 96.02 94.54 86.15 8.48 77.67
2024-05 1.35 7.77 16.77 70.46 0 96.35 95 87.23 7.59 79.64
2024-06 1.3 7.24 15.45 72.06 0.27 96.32 95.02 87.78 7 80.78
2024-07 1.41 7.19 14.29 72.59 0.66 96.14 94.73 87.54 6.39 81.15
2024-08 1.4 6.75 13.35 73.5 1.05 96.05 94.65 87.9 5.99 81.91
2024-09 1.02 6.31 12.14 69.46 7.15 96.08 95.06 88.75 5.41 83.34
2024-10 0.86 5.41 10.76 55.92 20.28 93.23 92.37 86.96 4.73 82.23

@torokati44
Copy link
Member

@danielhjacobs
Copy link
Contributor Author

danielhjacobs commented Nov 11, 2024

Pale Moon logs this when I log individual extension support:

WebAssembly extension "Bulk Memory" is NOT supported.
WebAssembly extension "SIMD" is NOT supported.
WebAssembly extension "Saturated Float-to-Int" is NOT supported.
WebAssembly extension "Sign Extensions" is supported.  
WebAssembly extension "Reference Types" is NOT supported.

Also, when I add multiValue, it logs WebAssembly extension "MultiValue" is NOT supported.

diff --git a/web/packages/core/src/load-ruffle.ts b/web/packages/core/src/load-ruffle.ts
index 6b474f61a..f0aadac41 100644
--- a/web/packages/core/src/load-ruffle.ts
+++ b/web/packages/core/src/load-ruffle.ts
@@ -35,15 +35,31 @@ async function fetchRuffle(
     setPolyfillsOnLoad();
 
     // NOTE: Keep this list in sync with $RUSTFLAGS in the CI build config!
-    const extensionsSupported: boolean = (
-        await Promise.all([
-            bulkMemory(),
-            simd(),
-            saturatedFloatToInt(),
-            signExtensions(),
-            referenceTypes(),
-        ])
-    ).every(Boolean);
+    const extensions = [
+        { name: "Bulk Memory", check: bulkMemory },
+        { name: "SIMD", check: simd },
+        { name: "Saturated Float-to-Int", check: saturatedFloatToInt },
+        { name: "Sign Extensions", check: signExtensions },
+        { name: "Reference Types", check: referenceTypes },
+    ];
+
+    const extensionsSupport = await Promise.all(
+        extensions.map(async (extension) => ({
+            name: extension.name,
+            supported: await extension.check(),
+        }))
+    );
+
+    let extensionsSupported = true;
+
+    extensionsSupport.forEach(({ name, supported }) => {
+        if (!supported) {
+            console.log(`WebAssembly extension "${name}" is NOT supported.`);
+            extensionsSupported = false;
+        } else {
+            console.log(`WebAssembly extension "${name}" is supported.`);
+        }
+    });
 
     if (!extensionsSupported) {
         console.log(

@danielhjacobs
Copy link
Contributor Author

Note that in testing, iOS 16.3 and below don't work with Rust 1.82+ without this workaround, so it's not just iOS 15-.

? [
process.env["NIGHTLY_VERSION"]
? `+nightly-${process.env["NIGHTLY_VERSION"]}`
: "+nightly",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is the following commands should work in CI:

rustup install nightly-2024-12-02
rustup target add wasm32-unknown-unknown --toolchain nightly-2024-12-02
BUILD_WASM_MVP=1 NIGHTLY_VERSION=2024-12-02 npm run build:repro

@danielhjacobs
Copy link
Contributor Author

danielhjacobs commented Dec 3, 2024

It appears that following the most recent wasm-bindgen update this PR is only necessary on browsers which do not have reference-types support. From what I know, of the browsers we currently support, that only eliminates support for Safari 14.1, Pale Moon, and Basilisk.

Pale Moon and Basilisk can currently support Flash anyway. On sites which use the polyfill they won't use Ruffle. Sites which use the Ruffle API or sites which use the polyfill if the user hasn't installed Flash will break on those browsers without this PR if we bump Rust back to stable. We can merge #18838 to add an appropriate error message.

Safari 14.1 on iOS has an ~1% market share among iOS users.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-web Area: Web & Extensions T-feature Type: New Feature (that Flash doesn't have)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants