aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/patches
ModeNameSize
-rw-r--r--0001-keep-kitty-images-across-a-screen-clear.patch1995logstatsplainblame
-rw-r--r--0002-dont-export-weak-calloc-free-from-the-static-lib.patch1340logstatsplainblame
-rw-r--r--README.md4041logstatsplainblame

Patches to the vendored libghostty-vt

D12 vendors libghostty-vt pinned by commit, "with a patches file if we ever need one". This is that file.

Patches are applied to the vendored tree in this repository, which is committed, so a normal make vendor build already has them. The .patch files here exist for provenance: they say what we changed, why, and what has to be re-applied when the vendored version is bumped. vendor/*.vendor.json lists them under patches.

Re-vendoring is therefore: drop in the new upstream tree, apply each patch in order, resolve anything that has moved, rebuild, run make test.

contrib/vendor-check says when that is worth doing: it compares the pin in vendor/*.vendor.json against upstream and lists the commits touching the terminal core, so watching upstream is one command rather than a browser tab. ship mentions it after every release.

0001 — keep kitty images across a screen clear

Terminal.eraseDisplay called kitty_images.delete(..., .{ .all = true }) for both ED 2 and ED 3, where the true means "and free the image data for anything no longer placed".

The kitty graphics protocol separates transmitting an image (a=t, which stores it under an id) from placing it (a=p, which puts it on screen), so that a program can upload once and place many times — that is the whole point of having two verbs, and the reason the delete command distinguishes d=a (placements) from d=A (placements and data). Freeing the data on a screen clear breaks it: any full-screen program that clears and redraws loses every image it uploaded, and every later placement of that id draws nothing at all.

Found with a bouncing-DVD screensaver that transmits ten frames up front and then places one per frame. It works in kitty; under us it drew nothing, and the reason was three layers down.

The patch removes only the freeing. Placements on the cleared screen still go — clearing the screen should clear what is on it — and the image store still bounds itself the way it always did, with a 320MB limit and LRU eviction on insert, which is exactly the mechanism that makes keeping them safe.

Worth sending upstream.

0002 — don't export weak calloc/free from the static library

pkg/wuffs/src/main.zig exported weak, hidden calloc/free stubs whenever !builtin.link_libc. callocStub returns null unconditionally. They exist because wuffs' generated wuffs_foo__bar__alloc() helpers are the only code referencing libc's allocator, we never call them, and linker GC usually strips them — the stubs are there in case it doesn't.

The comment says "weak so that any real definition wins". That holds when the real definition comes from a shared libc, but not from a static archive: once the linker pulls this member in for some other symbol, the weak calloc here satisfies the reference, so it never searches libc.a for musl's strong one. Every calloc in the consuming program then returns NULL, and free becomes a no-op.

We only hit this in the browser demo, which is the one build that has to pass -Dsimd=false (highway emits RVV intrinsics that do not compile for rv64gc), and GhosttyZig.zig sets link_libc = if (cfg.simd) true else null — so the demo's library is the only one of ours built without libc, and the guest links it statically against musl. The symptom was slosh: cannot start session main in the demo: the first calloc in kdl.c:node_new returned NULL and the store into it faulted, which killed the session server before its socket existed. The host build (libc linked, stubs never exported) was unaffected, which is why every test on this machine passed.

The patch adds and builtin.output_mode == .Exe. The stubs still do their job in a final link with no libc, and a library — whose consumer is the thing that owns the choice of allocator — no longer interposes on it. web/demo/boot-check is the regression test; it caught this in twenty seconds once it was run.

Worth sending upstream.