From 31dc6c639719e1d9a50af01ca04d6dac7a0cfacc Mon Sep 17 00:00:00 2001 From: Oleksandr Kozachuk <201152+ok2@users.noreply.github.com> Date: Wed, 29 Jul 2026 15:57:08 +0200 Subject: [PATCH] =?UTF-8?q?fix(core):=20no=20SystemTime=20on=20wasm32=20?= =?UTF-8?q?=E2=80=94=20fixed=20boot=20seed=20+=20UTIME=20Forth=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/core/src/outer.rs | 45 +++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/crates/core/src/outer.rs b/crates/core/src/outer.rs index 71c5121..b9cdb5d 100644 --- a/crates/core/src/outer.rs +++ b/crates/core/src/outer.rs @@ -393,6 +393,11 @@ impl ForthVM { substitutions: Arc::new(Mutex::new(HashMap::new())), search_order: Arc::new(Mutex::new(vec![1])), next_wid: Arc::new(Mutex::new(2)), + // SystemTime::now() PANICS on wasm32-unknown-unknown (no time + // source), which turned VM construction into an `unreachable` + // trap in the browser. Seed from the wall clock only where one + // exists; wasm hosts start deterministic and reseed via RND-SEED. + #[cfg(not(target_arch = "wasm32"))] rng_state: { use std::time::{SystemTime, UNIX_EPOCH}; let seed = SystemTime::now() @@ -404,6 +409,8 @@ impl ForthVM { seed })) }, + #[cfg(target_arch = "wasm32")] + rng_state: Arc::new(Mutex::new(0xDEAD_BEEF_CAFE_BABE)), compile_frames: Vec::new(), compiling_word_addr: 0, }; @@ -5383,20 +5390,30 @@ impl ForthVM { /// UTIME ( -- ud ) push microseconds since epoch as a double-cell value. fn register_utime(&mut self) -> anyhow::Result<()> { let func: HostFn = Box::new(move |ctx: &mut dyn HostAccess| { - use std::time::{SystemTime, UNIX_EPOCH}; - let us = SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap_or_default() - .as_micros() as u64; - let lo = us as i32; - let hi = (us >> 32) as i32; - // Push double: lo first (deeper), then hi on top - let sp = ctx.get_dsp(); - let new_sp = sp - 2 * CELL_SIZE; - ctx.mem_write_i32(new_sp as u32, hi as i32); - ctx.mem_write_slice(new_sp as u32 + 4, &lo.to_le_bytes()); - ctx.set_dsp((new_sp as i32) as u32); - Ok(()) + // SystemTime::now() panics on wasm32-unknown-unknown; fail as a + // catchable Forth error instead of poisoning the VM with a trap. + #[cfg(target_arch = "wasm32")] + { + let _ = ctx; + Err(anyhow::anyhow!("UTIME: no time source on this platform")) + } + #[cfg(not(target_arch = "wasm32"))] + { + use std::time::{SystemTime, UNIX_EPOCH}; + let us = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_micros() as u64; + let lo = us as i32; + let hi = (us >> 32) as i32; + // Push double: lo first (deeper), then hi on top + let sp = ctx.get_dsp(); + let new_sp = sp - 2 * CELL_SIZE; + ctx.mem_write_i32(new_sp as u32, hi as i32); + ctx.mem_write_slice(new_sp as u32 + 4, &lo.to_le_bytes()); + ctx.set_dsp((new_sp as i32) as u32); + Ok(()) + } }); self.register_host_primitive("UTIME", false, func)?;