From 50a896f4c0a2ab3eeadea74bef364c6924bdf5fa Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Mon, 13 Jul 2026 15:55:25 +0200 Subject: [PATCH] webapi: tighten DOM allocation lifetimes Use the call arena only for the AbortSignal dependent list that must survive re-entrant abort handlers, and move scratch-only DOM reads to the local arena. Store BeforeUnloadEvent.returnValue in the event-owned arena so it remains valid without accumulating in the longer-lived frame arena. These allocator changes bound temporary memory to the shortest safe lifetime while preserving existing Web API behavior. Add coverage for replacing BeforeUnloadEvent.returnValue. --- src/browser/tests/events.html | 13 +++++++++++++ src/browser/webapi/AbortSignal.zig | 2 +- src/browser/webapi/element/Html.zig | 2 +- src/browser/webapi/event/BeforeUnloadEvent.zig | 4 ++-- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/browser/tests/events.html b/src/browser/tests/events.html index 6be2ee8f3..3b451a90c 100644 --- a/src/browser/tests/events.html +++ b/src/browser/tests/events.html @@ -940,3 +940,16 @@ child.removeEventListener('click', listener); } + + diff --git a/src/browser/webapi/AbortSignal.zig b/src/browser/webapi/AbortSignal.zig index 5ad2f9758..7b13a22c5 100644 --- a/src/browser/webapi/AbortSignal.zig +++ b/src/browser/webapi/AbortSignal.zig @@ -106,7 +106,7 @@ pub fn abort(self: *AbortSignal, reason_: ?Reason, exec: *const Execution) !void var to_dispatch: std.ArrayList(Dependend) = .{}; for (self._dependents.items) |dep| { if (try dep.markAborted(self._reason, exec)) { - try to_dispatch.append(exec.arena, dep); + try to_dispatch.append(exec.call_arena, dep); } } diff --git a/src/browser/webapi/element/Html.zig b/src/browser/webapi/element/Html.zig index d55396311..c2776a1f0 100644 --- a/src/browser/webapi/element/Html.zig +++ b/src/browser/webapi/element/Html.zig @@ -380,7 +380,7 @@ pub fn getAccessKeyLabel(self: *HtmlElement, frame: *Frame) ![]const u8 { if (codepoints != 1) { return ""; } - return std.fmt.allocPrint(frame.call_arena, "Alt+{s}", .{value}); + return std.fmt.allocPrint(frame.local_arena, "Alt+{s}", .{value}); } pub fn getPopover(self: *HtmlElement) ?[]const u8 { diff --git a/src/browser/webapi/event/BeforeUnloadEvent.zig b/src/browser/webapi/event/BeforeUnloadEvent.zig index 00b2fdbff..4c1372cf6 100644 --- a/src/browser/webapi/event/BeforeUnloadEvent.zig +++ b/src/browser/webapi/event/BeforeUnloadEvent.zig @@ -71,8 +71,8 @@ pub fn getReturnValue(self: *const BeforeUnloadEvent) []const u8 { return self._return_value; } -pub fn setReturnValue(self: *BeforeUnloadEvent, value: []const u8, frame: *Frame) !void { - self._return_value = try frame.dupeString(value); +pub fn setReturnValue(self: *BeforeUnloadEvent, value: []const u8) !void { + self._return_value = try self._proto._arena.dupe(u8, value); } pub const JsApi = struct {