From acd9e032a147f4aa7ad49110dc2f4fb945e7a9bb Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Sun, 27 Sep 2026 20:14:04 -0300 Subject: Keep a pane's filesystem state on the Pane instead of a slot-indexed table addr, limit, the event queue and its readers, pty/data's queue, a waiting run and the /log announcement flag lived in p.fs.panes[slot], reset when the pane went; a reused slot is how the bug class came in. acme keeps the same state on its Window (editors/acme/dat.h:226-266), so now Pane.fs holds it: announced, retired (noteRetire, which still answers a waiting run and drops the listener count first) and freed with the pane itself. Co-Authored-By: Claude Opus 5.5 --- test/fs_bench.zig | 4 ++-- test/output.zig | 4 ++-- test/panes.zig | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'test') diff --git a/test/fs_bench.zig b/test/fs_bench.zig index 74b7b5da..00601ca3 100644 --- a/test/fs_bench.zig +++ b/test/fs_bench.zig @@ -285,7 +285,7 @@ pub fn main(init: std.process.Init) !void { const initial_bytes = pane.file.?.content.len; key_body_bytes = initial_bytes; if (scripted) { - keys.core.fs.panes[keys.file_id].readers = 1; + keys.core.panes[keys.file_id].?.fs.readers = 1; keys.core.fs.listeners = 1; } counting.allocations = 0; @@ -297,7 +297,7 @@ pub fn main(init: std.process.Init) !void { const elapsed = nowNs() - start; if (pane.file.?.content.len != initial_bytes + key_reps or pane.cur_col != key_reps or !std.mem.allEqual(u8, pane.file.?.content[0..key_reps], 'x')) return error.MissingKeystroke; - const events = &keys.core.fs.panes[keys.file_id].events; + const events = &keys.core.panes[keys.file_id].?.fs.events; if (scripted) for (0..key_reps) |i| { var buf: [64]u8 = undefined; const expected = try std.fmt.bufPrint(&buf, "KI{d} {d} 0 1 x\n", .{ i, i + 1 }); diff --git a/test/output.zig b/test/output.zig index 7c80e105..cda5f556 100644 --- a/test/output.zig +++ b/test/output.zig @@ -1082,7 +1082,7 @@ test "identical result refresh keeps warm content caches without allocation" { try std.testing.expectEqual(id, source.search_pane.?); try std.testing.expectEqual(@as(usize, 1), source.search_row.?); try std.testing.expectEqual(result.serial, p.look_walk_owner.?); - try std.testing.expect(p.fs.panes[id].events.empty()); + try std.testing.expect(p.panes[id].?.fs.events.empty()); } try panes.Output.fillResults(p, 0, "/tmp", .{ .query = .references }, "changed", try p.gpa.dupe(u8, "short\n"), null); @@ -1099,7 +1099,7 @@ test "identical result refresh keeps warm content caches without allocation" { try std.testing.expectEqual(@as(usize, 0), file.scroll); try std.testing.expectEqual(@as(i32, 0), result.hscroll); try std.testing.expect(source.search_row == null); - const events = &p.fs.panes[id].events; + const events = &p.panes[id].?.fs.events; try std.testing.expect(std.mem.startsWith(u8, events.peek().?, "KD")); events.pop(); try std.testing.expect(std.mem.startsWith(u8, events.peek().?, "KI")); diff --git a/test/panes.zig b/test/panes.zig index 2f307cb5..e865641f 100644 --- a/test/panes.zig +++ b/test/panes.zig @@ -946,7 +946,7 @@ const ClickCursorTests = struct { defer _ = pardes.ctlfs.handle(p, .{ .tag = 0, .op = .release, .node = event_node, .handle = opened.handle }); for ([_]pardes.Mouse.Button{ .middle, .right }) |button| { - const events = &p.fs.panes[0].events; + const events = &p.panes[0].?.fs.events; while (!events.empty()) events.pop(); click(p, button, x + 2, y + 2); const selected = events.peek() orelse return error.MissingSelectionGesture; -- cgit v1.3