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.
This commit is contained in:
Francis Bouvier
2026-07-13 15:55:25 +02:00
committed by Karl Seguin
parent 8f42b72d18
commit 50a896f4c0
4 changed files with 17 additions and 4 deletions

View File

@@ -940,3 +940,16 @@
child.removeEventListener('click', listener);
}
</script>
<script id=beforeUnloadEventReturnValue>
{
const event = document.createEvent('BeforeUnloadEvent');
testing.expectEqual('', event.returnValue);
event.returnValue = 'first';
testing.expectEqual('first', event.returnValue);
event.returnValue = 'replacement';
testing.expectEqual('replacement', event.returnValue);
}
</script>

View File

@@ -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);
}
}

View File

@@ -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 {

View File

@@ -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 {