fix(wasm): finalize config without desktop shell lookup

The Node smoke test expected shaper info logs after the default logger
became errors-only. Its failure also exposed config finalization calling
an unsupported passwd lookup on wasm and returning Unexpected before
normalization completed.

Skip shell defaults on wasm, matching upstream Zig. Assert successful
config finalization and window-width clamping in the Node test. Check
shaper output directly while verifying that info logs stay suppressed.
Document these behaviors in the wasm port notes.

Test Plan:
- cargo test -p ghostty-wasm --test node (passed)
- cargo test -p ghostty-config --lib (291 passed)
- cargo clippy --target wasm32-unknown-unknown -p ghostty-wasm -- -D warnings
- cargo clippy; cargo clippy --benches; cargo clippy --tests
- cargo +nightly fmt, followed by the native Clippy checks again
- git diff --check

Related-commit: 4fb9faa667
This commit is contained in:
ddidderr committed 2026-10-12 22:17:15 +02:00
1 parent 62e1209b37
commit 7cec74e18b
3 files changed
+17 -4

No files matched your search

+3 -1
View File
@@ -4594,7 +4594,9 @@ impl Config {
// If we are missing either a command or home directory, we need
// to look up defaults which is kind of expensive. We only do this
// on desktop (and not in tests, like the Zig `builtin.is_test`).
if !cfg!(test) && (self.command.is_none() || wd == WorkingDirectory::Home) {
if !cfg!(any(test, target_arch = "wasm32"))
&& (self.command.is_none() || wd == WorkingDirectory::Home)
{
self.lookup_shell_defaults(probable_cli, &mut wd)?;
}
wd.finalize();
+9 -3
View File
@@ -127,11 +127,12 @@ const liveValues = (zigjs) => zigjs.values.slice(7).filter((v) => v !== null).le
{
const cfg = x.config_new();
assert.ok(cfg);
const s = host.writeString('font-size = 18\nwindow-padding-x = 7\nnot-a-key = 1\n');
const s = host.writeString('font-size = 18\nwindow-padding-x = 7\nwindow-width = 1\nnot-a-key = 1\n');
x.config_load_string(cfg, s.ptr, s.len);
s.free();
assert.strictEqual(x.config_diagnostics_count(cfg), 1);
x.config_finalize(cfg);
assert.deepStrictEqual(logs, [], 'config finalization must succeed without desktop shell lookup');
const cap = 1 << 16;
const out = x.wasm_alloc(cap);
const n = x.config_format(cfg, out, cap);
@@ -140,6 +141,8 @@ const liveValues = (zigjs) => zigjs.values.slice(7).filter((v) => v !== null).le
x.wasm_free(out, cap);
assert.match(text, /font-size = 18/);
assert.match(text, /window-padding-x = 7/);
// Width clamping happens after shell defaults: finalization must reach it.
assert.match(text, /window-width = 10\n/);
x.config_free(cfg);
}
@@ -202,10 +205,13 @@ const liveValues = (zigjs) => zigjs.values.slice(7).filter((v) => v !== null).le
x.glyph_free(gg);
assert.strictEqual(canvases[0].lastText.t, 'é');
// shaper_test prints through a terminal and logs the shaped runs
// shaper_test prints through a terminal and shapes its rows. The default
// errors-only logger suppresses the info records for those shaped runs.
const st = host.writeString('hello é');
x.shaper_test(sh, face, st.ptr, st.len);
assert.ok(logs.some((l) => l.startsWith('info(')), logs.join('\n'));
assert.deepStrictEqual(logs, [], 'shaper info logs must be suppressed');
assert.ok(x.shaper_shape(sh, face, outp, 16) > 0, 'shaper_test prepared a run');
assert.strictEqual(new Uint32Array(instance.exports.memory.buffer, outp, 2)[1], 0x68);
// ---- deferred face ----
const d = x.deferred_face_new(f.ptr, f.len, 0);
+5
View File
@@ -84,6 +84,9 @@ Differences/extras: `region_free`/`glyph_free` (Zig: "global free"),
`config_diagnostics_count`, `ghostty_wasm_init`, `wasm_alloc/free`.
`shaper_test` takes a `Face` (Zig takes a stale `GroupCache`) and prints into a
`ghostty-terminal` Terminal.
Config finalization skips desktop shell and home-directory lookup on wasm,
matching Zig, but still applies normalization such as minimum window dimensions.
The wasm logger forwards errors only, so `shaper_test` info records are suppressed.
## Deviations from the (stale) Zig web_canvas code
- Zig refers to `Atlas.Format.rgba` and a 7-field `Metrics` that no longer
@@ -104,6 +107,8 @@ Differences/extras: `region_free`/`glyph_free` (Zig: "global free"),
`target/wasm-test`) and runs `tests/node_test.js` under node with a fake
canvas: config parse/finalize/format, atlas, face metrics/glyph_index/
render, emoji presentation, shaper clustering, deferred face, debug canvas.
It checks that config finalization completes without errors and clamps window
dimensions, and that `shaper_test` prepares a run without emitting info logs.
Skipped if node or the wasm32 target is missing.
- Not ported: Zig tests in Atlas.Wasm (`toHostOwned`, stale).