wasm: use the browser clock only on wasm32-unknown-unknown, not on WASI

`now_ms` in layout, `now_unix` in engine, formats and pdf gated
`js_sys::Date::now()` on `target_arch = "wasm32"`, which also matches
wasm32-wasip1 and wasm32-wasip1-threads. There js-sys has no host to call,
so it panics ("cannot call wasm-bindgen imported functions on non-wasm
targets"), and since `layout()` times itself with `now_ms`, every document
laid out on WASI aborts. `std::time` works on WASI, so these now use the
browser clock only on wasm32-unknown-unknown, the gate wordcraft-docx
already uses.
This commit is contained in:
Alex Wine
2026-10-20 12:11:57 -06:00
parent d1b0bfc3f9
commit f4299ff644
8 changed files with 16 additions and 16 deletions
+2 -2
View File
@@ -28,8 +28,8 @@ regex-automata = { workspace = true }
image = { workspace = true }
zeroize = { workspace = true }
[target.'cfg(target_arch = "wasm32")'.dependencies]
# The browser clock for `now_iso` (`SystemTime::now()` panics on wasm32).
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
# The browser clock for `now_iso` (`SystemTime::now()` panics on wasm32-unknown-unknown).
js-sys = "0.3"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
+2 -2
View File
@@ -427,12 +427,12 @@ pub fn iso_from_unix_secs(secs: u64) -> String {
/// Seconds since the Unix epoch (UTC): the system clock, or the browser's on the web.
pub fn now_unix() -> u64 {
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
{
std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).map(|d| d.as_secs()).unwrap_or(0)
}
// `SystemTime::now()` panics on wasm32-unknown-unknown, so ask the browser's clock.
#[cfg(target_arch = "wasm32")]
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
{
let ms = js_sys::Date::now();
// Clamp a NaN or pre-epoch clock to 0 rather than fail.
+2 -2
View File
@@ -19,8 +19,8 @@ encoding_rs = { workspace = true }
chardetng = { workspace = true }
log = { workspace = true }
[target.'cfg(target_arch = "wasm32")'.dependencies]
# The browser clock (`SystemTime::now()` panics on wasm32): ODT change dates.
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
# The browser clock (`SystemTime::now()` panics on wasm32-unknown-unknown): ODT change dates.
js-sys = "0.3"
[dev-dependencies]
+2 -2
View File
@@ -809,13 +809,13 @@ fn now_iso() -> String {
/// Seconds since the Unix epoch: the system clock, or the browser's on the web.
fn now_unix() -> i64 {
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
{
use std::time::{SystemTime, UNIX_EPOCH};
SystemTime::now().duration_since(UNIX_EPOCH).ok().and_then(|d| i64::try_from(d.as_secs()).ok()).unwrap_or(0)
}
// `SystemTime::now()` panics on wasm32-unknown-unknown, so ask the browser's clock.
#[cfg(target_arch = "wasm32")]
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
{
let ms = js_sys::Date::now();
if ms.is_finite() && ms > 0.0 { (ms / 1000.0) as i64 } else { 0 }
+2 -2
View File
@@ -22,6 +22,6 @@ serde_json = { workspace = true }
image = { workspace = true }
log = { workspace = true }
[target.'cfg(target_arch = "wasm32")'.dependencies]
# The browser clock (`SystemTime::now()`/`Instant::now()` panic on wasm32).
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
# The browser clock (`SystemTime::now()`/`Instant::now()` panic on wasm32-unknown-unknown).
js-sys = "0.3"
+2 -2
View File
@@ -4571,13 +4571,13 @@ pub fn is_floating(o: &InlineObject) -> bool {
/// Milliseconds since an arbitrary epoch (monotonic on native; the browser's clock on the web).
pub fn now_ms() -> f64 {
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
{
static T0: std::sync::OnceLock<std::time::Instant> = std::sync::OnceLock::new();
T0.get_or_init(std::time::Instant::now).elapsed().as_secs_f64() * 1000.0
}
// `Instant::now()` panics on wasm32-unknown-unknown, so ask the browser's clock.
#[cfg(target_arch = "wasm32")]
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
{
let ms = js_sys::Date::now();
if ms.is_finite() { ms } else { 0.0 }
+2 -2
View File
@@ -20,8 +20,8 @@ image = { workspace = true }
thiserror = { workspace = true }
log = { workspace = true }
[target.'cfg(target_arch = "wasm32")'.dependencies]
# The browser clock (`SystemTime::now()` panics on wasm32).
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
# The browser clock (`SystemTime::now()` panics on wasm32-unknown-unknown).
js-sys = "0.3"
[dev-dependencies]
+2 -2
View File
@@ -443,14 +443,14 @@ fn parse_iso(s: &str) -> Option<Civil> {
/// The system clock, or the browser's on the web.
fn now_unix() -> Option<i64> {
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
{
use std::time::{SystemTime, UNIX_EPOCH};
let secs = SystemTime::now().duration_since(UNIX_EPOCH).ok()?.as_secs();
i64::try_from(secs).ok()
}
// `SystemTime::now()` panics on wasm32-unknown-unknown, so ask the browser's clock.
#[cfg(target_arch = "wasm32")]
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
{
let ms = js_sys::Date::now();
(ms.is_finite() && ms > 0.0).then(|| (ms / 1000.0) as i64)