mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
terminal: add some integrity assertions
This commit is contained in:
@ -848,6 +848,7 @@ pub fn clearPrompt(self: *Screen) void {
|
||||
while (clear_it.next()) |p| {
|
||||
const row = p.rowAndCell().row;
|
||||
p.page.data.clearCells(row, 0, p.page.data.size.cols);
|
||||
p.page.data.assertIntegrity();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1133,6 +1134,7 @@ pub fn manualStyleUpdate(self: *Screen) !void {
|
||||
|
||||
/// Append a grapheme to the given cell within the current cursor row.
|
||||
pub fn appendGrapheme(self: *Screen, cell: *Cell, cp: u21) !void {
|
||||
defer self.cursor.page_pin.page.data.assertIntegrity();
|
||||
self.cursor.page_pin.page.data.appendGrapheme(
|
||||
self.cursor.page_row,
|
||||
cell,
|
||||
|
@ -185,6 +185,15 @@ pub const Page = struct {
|
||||
InvalidStyleCount,
|
||||
};
|
||||
|
||||
/// A helper that can be used to assert the integrity of the page
|
||||
/// when runtime safety is enabled. This is a no-op when runtime
|
||||
/// safety is disabled. This uses the libc allocator.
|
||||
pub fn assertIntegrity(self: *Page) void {
|
||||
if (comptime std.debug.runtime_safety) {
|
||||
self.verifyIntegrity(std.heap.c_allocator) catch unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
/// Verifies the integrity of the page data. This is not fast,
|
||||
/// but it is useful for assertions, deserialization, etc. The
|
||||
/// allocator is only used for temporary allocations -- all memory
|
||||
@ -280,6 +289,31 @@ pub const Page = struct {
|
||||
return IntegrityError.InvalidGraphemeCount;
|
||||
}
|
||||
|
||||
// There is allowed to be exactly one zero ref count style for
|
||||
// the active style. If we see this, we should add it to our seen
|
||||
// styles so the math is correct.
|
||||
{
|
||||
const id_map = self.styles.id_map.map(self.memory);
|
||||
var it = id_map.iterator();
|
||||
while (it.next()) |entry| {
|
||||
const style_val = self.styles.lookupId(self.memory, entry.key_ptr.*).?.*;
|
||||
const md = self.styles.upsert(self.memory, style_val) catch unreachable;
|
||||
if (md.ref == 0) {
|
||||
const gop = try styles_seen.getOrPut(entry.key_ptr.*);
|
||||
if (gop.found_existing) {
|
||||
log.warn(
|
||||
"page integrity violation zero ref style seen multiple times id={}",
|
||||
.{entry.key_ptr.*},
|
||||
);
|
||||
return IntegrityError.MismatchedStyleRef;
|
||||
}
|
||||
|
||||
gop.value_ptr.* = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Our unique styles seen should exactly match the style count.
|
||||
if (styles_seen.count() != self.styles.count(self.memory)) {
|
||||
log.warn(
|
||||
@ -1729,9 +1763,10 @@ test "Page verifyIntegrity styles extra" {
|
||||
.bold = true,
|
||||
} });
|
||||
|
||||
_ = try page.styles.upsert(page.memory, .{ .flags = .{
|
||||
const md2 = try page.styles.upsert(page.memory, .{ .flags = .{
|
||||
.italic = true,
|
||||
} });
|
||||
md2.ref += 1;
|
||||
|
||||
// Write
|
||||
for (0..page.capacity.cols) |x| {
|
||||
|
Reference in New Issue
Block a user