Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9b10723a95 | |||
| 4769987b20 |
@@ -5,6 +5,22 @@ All notable changes to WAFER are documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [0.2.4] - 2026-08-06
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **Errors from host words in the browser build read like Forth errors
|
||||||
|
again.** A host word signals failure by throwing across the JS
|
||||||
|
boundary, and the browser runtime reported the exception with its
|
||||||
|
`Debug` form, so an empty-stack `RESIZE` came back as
|
||||||
|
`call_func(134) failed: JsValue(Error: Stack underflow ...)` trailed by
|
||||||
|
an engine stack trace. The thrown message is the Forth message, so it
|
||||||
|
is now surfaced verbatim — `Stack underflow`, exactly what the native
|
||||||
|
CLI prints. Exceptions that carry no message keep the call context,
|
||||||
|
since those are genuine runtime faults rather than Forth throws.
|
||||||
|
`CATCH` was never affected: it reads the throw code from its own
|
||||||
|
channel, not from the message.
|
||||||
|
|
||||||
## [0.2.3] - 2026-08-06
|
## [0.2.3] - 2026-08-06
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
Generated
+3
-3
@@ -1589,7 +1589,7 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wafer"
|
name = "wafer"
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@@ -1600,7 +1600,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wafer-core"
|
name = "wafer-core"
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"insta",
|
"insta",
|
||||||
@@ -1615,7 +1615,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wafer-web"
|
name = "wafer-web"
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ members = ["crates/*"]
|
|||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
repository = "https://github.com/ok2/wafer"
|
repository = "https://github.com/ok2/wafer"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ license.workspace = true
|
|||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wafer-core = { path = "../core", version = "0.2.3" }
|
wafer-core = { path = "../core", version = "0.2.4" }
|
||||||
wasmtime = { workspace = true }
|
wasmtime = { workspace = true }
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
clap = { version = "4", features = ["derive"] }
|
clap = { version = "4", features = ["derive"] }
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ workspace = true
|
|||||||
crate-type = ["cdylib", "rlib"]
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wafer-core = { path = "../core", version = "0.2.3", default-features = false, features = ["crypto"] }
|
wafer-core = { path = "../core", version = "0.2.4", default-features = false, features = ["crypto"] }
|
||||||
wasm-bindgen = "0.2"
|
wasm-bindgen = "0.2"
|
||||||
js-sys = "0.3"
|
js-sys = "0.3"
|
||||||
send_wrapper = { workspace = true }
|
send_wrapper = { workspace = true }
|
||||||
|
|||||||
@@ -38,6 +38,23 @@ impl WebHostAccess {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An exception on its way back out of compiled code. Host words rethrow the
|
||||||
|
/// Forth message (`Stack underflow`, an `ABORT"` text, a `THROW` description),
|
||||||
|
/// so surface exactly that and nothing else — the JS `Error` carries the whole
|
||||||
|
/// engine stack in its message, which is noise to a Forth programmer. Anything
|
||||||
|
/// without a message is a genuine runtime fault and keeps the call context.
|
||||||
|
fn call_error(fn_index: u32, e: &JsValue) -> anyhow::Error {
|
||||||
|
match Reflect::get(e, &"message".into())
|
||||||
|
.ok()
|
||||||
|
.and_then(|m| m.as_string())
|
||||||
|
.and_then(|m| m.lines().next().map(str::trim).map(str::to_string))
|
||||||
|
.filter(|m| !m.is_empty())
|
||||||
|
{
|
||||||
|
Some(msg) => anyhow::anyhow!("{msg}"),
|
||||||
|
None => anyhow::anyhow!("call_func({fn_index}) failed: {e:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HostAccess for WebHostAccess {
|
impl HostAccess for WebHostAccess {
|
||||||
fn mem_read_i32(&mut self, addr: u32) -> i32 {
|
fn mem_read_i32(&mut self, addr: u32) -> i32 {
|
||||||
let view = js_sys::Int32Array::new(&self.buffer());
|
let view = js_sys::Int32Array::new(&self.buffer());
|
||||||
@@ -134,7 +151,7 @@ impl HostAccess for WebHostAccess {
|
|||||||
.dyn_into()
|
.dyn_into()
|
||||||
.map_err(|_| anyhow::anyhow!("table entry {fn_index} is not a function"))?;
|
.map_err(|_| anyhow::anyhow!("table entry {fn_index} is not a function"))?;
|
||||||
func.call0(&JsValue::NULL)
|
func.call0(&JsValue::NULL)
|
||||||
.map_err(|e| anyhow::anyhow!("call_func({fn_index}) failed: {e:?}"))?;
|
.map_err(|e| call_error(fn_index, &e))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -406,7 +423,7 @@ impl Runtime for WebRuntime {
|
|||||||
.dyn_into()
|
.dyn_into()
|
||||||
.map_err(|_| anyhow::anyhow!("table entry {fn_index} is not callable"))?;
|
.map_err(|_| anyhow::anyhow!("table entry {fn_index} is not callable"))?;
|
||||||
func.call0(&JsValue::NULL)
|
func.call0(&JsValue::NULL)
|
||||||
.map_err(|e| anyhow::anyhow!("call_func({fn_index}) failed: {e:?}"))?;
|
.map_err(|e| call_error(fn_index, &e))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user