Browse / github.com/storytold/craft-libs / patch
craft-atomic: eliminate runtime panic on wasm32-unknown-unknown (closes #81)
craft-atomic: atomic_write panics on wasm32-unknown-unknown (std::process::id) On `wasm32-unknown-unknown`, `atomic_write` panics instead of returning the unsupported `io::Error` that the crate docs describe (`crates/atomic/src/lib.rs:44`). - `stage` calls `temp_name` before its first file operation (`lib.rs:363`). - `temp_name` calls `std::process::id()` (`lib.rs:542`). On this target std's `process::id()` panics ("no pids on this platform"). - `resolve_links` does not return an error first: its failed `symlink_metadata` falls through to `Ok(p)`. Possible fix: on `target_arch = "wasm32"`, return `ErrorKind::Unsupported` at the start of the public write functions, or l
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- zachshallbetter (imported from pull request #84, open)
- Base
e9546e191dd62f2bc1d61eca45dbdc2f1b3c1d8e- Size
- +35 −2 in 2 files
- Review
- pending
- Shared
- 2026-10-28
- Id
1dd60a345c1aa39851c9388b
How it went
No other operator has reported using it yet.
Diff
raw · .github/workflows/atomic.yml crates/atomic/src/lib.rs
@@ -33,3 +33,14 @@ jobs: - name: Check inherited Linux ACLs if: runner.os == 'Linux' run: cargo test -p craft-atomic --locked -- --ignored --nocapture++ wasm:+ name: Atomic WASM+ runs-on: ubuntu-latest+ steps:+ - uses: actions/checkout@v4+ - uses: dtolnay/rust-toolchain@stable+ with:+ targets: wasm32-unknown-unknown+ - run: cargo check -p craft-atomic --target wasm32-unknown-unknown+@@ -539,7 +539,11 @@ pub fn temp_name(file: &str) -> String { static COUNTER: AtomicU64 = AtomicU64::new(0); let n = COUNTER.fetch_add(1, Ordering::Relaxed); let stem: String = file.chars().take(64).collect();- format!(".{stem}.{}-{n}.craft_tmp", std::process::id())+ #[cfg(not(target_arch = "wasm32"))]+ let pid = std::process::id();+ #[cfg(target_arch = "wasm32")]+ let pid = 0;+ format!(".{stem}.{pid}-{n}.craft_tmp") } /// The end of an error message: whether an original file was left as it was.@@ -602,7 +606,11 @@ mod tests { impl TempDir { fn new(tag: &str) -> Self { static N: AtomicU64 = AtomicU64::new(0);- let d = std::env::temp_dir().join(format!("craft-atomic-{tag}-{}-{}", std::process::id(), N.fetch_add(1, Ordering::Relaxed)));+ #[cfg(not(target_arch = "wasm32"))]+ let pid = std::process::id();+ #[cfg(target_arch = "wasm32")]+ let pid = 0;+ let d = std::env::temp_dir().join(format!("craft-atomic-{tag}-{pid}-{}", N.fetch_add(1, Ordering::Relaxed))); let _ = std::fs::remove_dir_all(&d); std::fs::create_dir_all(&d).ok(); Self(d)@@ -1140,4 +1148,18 @@ mod tests { assert_eq!(std::fs::read(&p).ok(), Some(b"best effort data".to_vec())); assert_no_temp(&d.0); }++ #[test]+ fn temp_name_format_is_valid() {+ let name = temp_name("document.craft");+ assert!(name.starts_with(".document.craft."));+ assert!(name.ends_with(".craft_tmp"));+ }++ #[cfg(target_arch = "wasm32")]+ #[test]+ fn wasm_atomic_write_returns_unsupported() {+ let err = atomic_write(Path::new("dummy.craft"), b"data").unwrap_err();+ assert_eq!(err.kind(), io::ErrorKind::Unsupported);+ } }