From 088263780131dd920688f974e62d1253c4901a89 Mon Sep 17 00:00:00 2001 From: Timon Date: Tue, 30 Jun 2026 22:07:17 +0000 Subject: [PATCH] Auto-recover from corrupt Wasm builds that emit undefined `env` imports (#4287) Co-authored-by: Keavon Chambers --- tools/cargo-run/src/frontend.rs | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/tools/cargo-run/src/frontend.rs b/tools/cargo-run/src/frontend.rs index c165ef13e0..98b21bf53b 100644 --- a/tools/cargo-run/src/frontend.rs +++ b/tools/cargo-run/src/frontend.rs @@ -10,6 +10,10 @@ pub fn frontend_dir() -> PathBuf { workspace_dir().join("frontend") } +fn wasm_glue_path() -> PathBuf { + frontend_dir().join("wrapper").join("pkg").join(format!("{OUT_NAME}.js")) +} + pub fn setup() -> Result<(), Error> { let frontend = frontend_dir(); let node_modules = frontend.join("node_modules"); @@ -52,7 +56,13 @@ pub fn build_wasm_steps(release: bool, native: bool) -> Vec { cmd!("cargo", "build", "--lib", "--package", WRAPPER_CRATE, "--target", WASM_TARGET) .arg_if(release, "--release") .args_if(native, ["--no-default-features", "--features", "native"]) - .dir(workspace_dir()), + .dir(workspace_dir()) + .before_spawn(|_| { + if is_build_corrupted() { + clean_wasm(); + } + Ok(()) + }), cmd!("wasm-bindgen", "--target", "web", "--out-name", OUT_NAME, "--out-dir", &pkg_dir, &wasm_artifact) .arg_if(release, "--no-demangle") .arg_if(!release, "--debug"), @@ -66,6 +76,25 @@ pub fn build_wasm_steps(release: bool, native: bool) -> Vec { steps } +pub fn clean_wasm() -> bool { + let wasm_target_dir = target_dir().join(WASM_TARGET); + eprintln!("The Wasm build emitted undefined `env` imports, a sign of corrupt incremental artifacts (typically from an interrupted build)."); + eprintln!("Fixing by wiping `{}` and rebuilding...", wasm_target_dir.display()); + match std::fs::remove_dir_all(&wasm_target_dir) { + Ok(()) => {} + Err(e) if e.kind() == std::io::ErrorKind::NotFound => {} + Err(e) => eprintln!("warning: could not fully clean `{}`: {e}", wasm_target_dir.display()), + } + true +} + +pub fn is_build_corrupted() -> bool { + let Ok(js) = std::fs::read_to_string(wasm_glue_path()) else { + return false; + }; + js.contains("from \"env\"") || js.contains("from 'env'") +} + pub fn vite() -> Expression { utils::node_bin("vite/bin/vite.js").dir(frontend_dir()).env("CARGO_TARGET_DIR", target_dir()) }