web: Build two WASM modules, with/without extensions, load the appropriate one

This commit is contained in:
TÖRÖK Attila 2021-12-09 15:58:12 +01:00 committed by Mike Welsh
parent c4d013c884
commit ab69c12649
5 changed files with 55 additions and 10 deletions

View File

@ -1,2 +0,0 @@
[target.wasm32-unknown-unknown]
rustflags=["--cfg=web_sys_unstable_apis"]

View File

@ -9,15 +9,30 @@
"pkg/"
],
"scripts": {
"build": "npm run build:cargo && npm run build:wasm-bindgen && npm run build:wasm-opt && npm run build:ts",
"build": "npm run build:ruffle_web && npm run build:ruffle_web-wasm_extensions && npm run build:ts",
"//1": "# Unfortunately, we have to set $RUSTFLAGS here, instead of in .cargo/config.toml (for example), because it's not possible to specify them per-profile; see cargo issue #7878.",
"//2": "# Enabling 'build-std' would also be great, but it's not stable yet.",
"build:ruffle_web": "cross-env OUT_NAME=ruffle_web RUSTFLAGS=\"--cfg=web_sys_unstable_apis\" npm run build:cargo_bindgen_opt",
"build:ruffle_web-wasm_extensions": "echo \"Building module with WebAssembly extensions\" && cross-env OUT_NAME=ruffle_web-wasm_extensions RUSTFLAGS=\"--cfg=web_sys_unstable_apis -C target-feature=+bulk-memory,+simd128,+nontrapping-fptoint,+sign-ext\" npm run build:cargo_bindgen_opt",
"//3": "# This just chains together the three commands after it.",
"build:cargo_bindgen_opt": "npm run build:cargo && npm run build:wasm-bindgen && npm run build:wasm-opt",
"build:cargo": "cross-env-shell \"cargo build --release --target wasm32-unknown-unknown --features \\\"$CARGO_FEATURES\\\"\"",
"build:wasm-bindgen": "wasm-bindgen ../../../target/wasm32-unknown-unknown/release/ruffle_web.wasm --target web --out-dir ./pkg --out-name ruffle_web",
"build:wasm-opt": "wasm-opt -o ./pkg/ruffle_web_bg.wasm -O -g ./pkg/ruffle_web_bg.wasm || npm run build:wasm-opt-failed",
"build:wasm-bindgen": "cross-env-shell \"wasm-bindgen ../../../target/wasm32-unknown-unknown/release/ruffle_web.wasm --target web --out-dir ./pkg --out-name $OUT_NAME\"",
"build:wasm-opt": "cross-env-shell \"wasm-opt -o ./pkg/${OUT_NAME}_bg.wasm -O -g ./pkg/${OUT_NAME}_bg.wasm || npm run build:wasm-opt-failed\"",
"build:wasm-opt-failed": "echo 'NOTE: Since wasm-opt could not be found (or it failed), the resulting module might not perform that well, but it should still work.' && echo ; [ \"$CI\" != true ] # > nul",
"build:ts": "tsc -d && node tools/set_version.js",
"docs": "typedoc",
"test": "cross-env TS_NODE_COMPILER_OPTIONS={\\\"module\\\":\\\"commonjs\\\"} mocha"
},
"dependencies": {
"wasm-feature-detect": "^1.2.11"
},
"devDependencies": {
"@types/mocha": "^9.0.0",
"@typescript-eslint/eslint-plugin": "^5.8.1",

View File

@ -2,7 +2,12 @@
* Conditional ruffle loader
*/
import init, { Ruffle } from "../pkg/ruffle_web";
import {
bulkMemory,
simd,
saturatedFloatToInt,
signExtensions,
} from "wasm-feature-detect";
import { setPolyfillsOnLoad } from "./js-polyfills";
import { publicPath } from "./public-path";
import { Config } from "./config";
@ -27,13 +32,40 @@ async function fetchRuffle(config: Config): Promise<typeof Ruffle> {
// libraries, if needed.
setPolyfillsOnLoad();
// NOTE: Keep this list in sync with $RUSTFLAGS in the CI build config!
const extensionsSupported: boolean = (
await Promise.all([
bulkMemory(),
simd(),
saturatedFloatToInt(),
signExtensions(),
])
).every(Boolean);
if (!extensionsSupported) {
console.log(
"Some WebAssembly extensions are NOT available, falling back to the vanilla WebAssembly module"
);
}
__webpack_public_path__ = publicPath(config);
// Note: The argument passed to import() has to be a simple string literal,
// otherwise some bundler will get confused and won't include the module?
const { default: init, Ruffle } = await (extensionsSupported
? import("../pkg/ruffle_web-wasm_extensions")
: import("../pkg/ruffle_web"));
await init();
return Ruffle;
}
let lastLoaded: Promise<typeof Ruffle> | null = null;
type Ruffle =
| typeof import("../pkg/ruffle_web")["Ruffle"]
| typeof import("../pkg/ruffle_web-wasm_extensions")["Ruffle"];
let lastLoaded: Promise<Ruffle> | null = null;
/**
* Obtain an instance of `Ruffle`.
@ -44,7 +76,7 @@ let lastLoaded: Promise<typeof Ruffle> | null = null;
* @returns A ruffle constructor that may be used to create new Ruffle
* instances.
*/
export function loadRuffle(config: Config): Promise<typeof Ruffle> {
export function loadRuffle(config: Config): Promise<Ruffle> {
if (lastLoaded == null) {
lastLoaded = fetchRuffle(config);
}

View File

@ -2,7 +2,7 @@
"extends": "@tsconfig/recommended/tsconfig.json",
"compilerOptions": {
"target": "es2017",
"module": "es2015",
"module": "es2020",
"moduleResolution": "node",
"strict": true,
"outDir": "pkg",

View File

@ -2,7 +2,7 @@
"extends": "@tsconfig/recommended/tsconfig.json",
"compilerOptions": {
"target": "es2017",
"module": "es2015",
"module": "es2020",
"moduleResolution": "node",
"strict": true,
},