diff --git a/packages/cli/src/config/web.rs b/packages/cli/src/config/web.rs index b3dea5631..8e1343f9f 100644 --- a/packages/cli/src/config/web.rs +++ b/packages/cli/src/config/web.rs @@ -62,6 +62,16 @@ pub(crate) struct WasmOptConfig { /// Enable memory packing #[serde(default = "false_bool")] pub(crate) memory_packing: bool, + + /// Extra arguments to pass to wasm-opt + /// + /// For example, to enable simd, you can set this to `["--enable-simd"]`. + /// + /// You can also disable features by prefixing them with `--disable-`, e.g. `["--disable-bulk-memory"]`. + /// + /// Currently only --enable and --disable flags are supported. + #[serde(default)] + pub(crate) extra_features: Vec, } /// The wasm-opt level to use for release web builds [default: Z] diff --git a/packages/cli/src/wasm_opt.rs b/packages/cli/src/wasm_opt.rs index fa3607c0d..0d6e30a3f 100644 --- a/packages/cli/src/wasm_opt.rs +++ b/packages/cli/src/wasm_opt.rs @@ -26,9 +26,12 @@ pub async fn optimize(input_path: &Path, output_path: &Path, cfg: &WasmOptConfig } async fn run_locally(input_path: &Path, output_path: &Path, cfg: &WasmOptConfig) -> Result<()> { + // defaults needed by wasm-bindgen. + // wasm is a moving target, and we add these by default since they progressively get enabled by default. let mut args = vec![ - // needed by wasm-bindgen "--enable-reference-types", + "--enable-bulk-memory", + "--enable-mutable-globals", ]; if cfg.memory_packing { @@ -43,6 +46,10 @@ async fn run_locally(input_path: &Path, output_path: &Path, cfg: &WasmOptConfig) args.push("--debuginfo"); } + for extra in &cfg.extra_features { + args.push(extra); + } + let level = match cfg.level { WasmOptLevel::Z => "-Oz", WasmOptLevel::S => "-Os", @@ -72,6 +79,8 @@ async fn run_from_lib( output_path: &Path, options: &WasmOptConfig, ) -> Result<()> { + use std::str::FromStr; + let mut level = match options.level { WasmOptLevel::Z => wasm_opt::OptimizationOptions::new_optimize_for_size_aggressively(), WasmOptLevel::S => wasm_opt::OptimizationOptions::new_optimize_for_size(), @@ -84,8 +93,30 @@ async fn run_from_lib( level .enable_feature(wasm_opt::Feature::ReferenceTypes) + .enable_feature(wasm_opt::Feature::BulkMemory) + .enable_feature(wasm_opt::Feature::MutableGlobals) .add_pass(wasm_opt::Pass::MemoryPacking) - .debug_info(options.debug) + .debug_info(options.debug); + + for arg in options.extra_features.iter() { + if arg.starts_with("--enable-") { + let feature = arg.trim_start_matches("--enable-"); + if let Ok(feature) = wasm_opt::Feature::from_str(feature) { + level.enable_feature(feature); + } else { + tracing::warn!("Unknown wasm-opt feature: {}", feature); + } + } else if arg.starts_with("--disable-") { + let feature = arg.trim_start_matches("--disable-"); + if let Ok(feature) = wasm_opt::Feature::from_str(feature) { + level.disable_feature(feature); + } else { + tracing::warn!("Unknown wasm-opt feature: {}", feature); + } + } + } + + level .run(input_path, output_path) .map_err(|err| crate::Error::Other(anyhow::anyhow!(err)))?;