mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-07-30 09:16:07 -04:00
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:
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@ pub fn getLastModified(self: *const Document, frame: *Frame) ![]const u8 {
|
||||
if (localtime_r(×tamp, &tm) == null) {
|
||||
return error.InvalidArgument;
|
||||
}
|
||||
return std.fmt.allocPrint(frame.call_arena, "{d:0>2}/{d:0>2}/{d} {d:0>2}:{d:0>2}:{d:0>2}", .{
|
||||
return std.fmt.allocPrint(frame.local_arena, "{d:0>2}/{d:0>2}/{d} {d:0>2}:{d:0>2}:{d:0>2}", .{
|
||||
@as(u32, @intCast(tm.tm_mon + 1)),
|
||||
@as(u32, @intCast(tm.tm_mday)),
|
||||
tm.tm_year + 1900,
|
||||
|
||||
@@ -60,7 +60,7 @@ pub fn getWholeText(self: *Text, frame: *Frame) ![]const u8 {
|
||||
var current: ?*Node = first;
|
||||
while (current) |cur| : (current = cur.nextSibling()) {
|
||||
if (!isExclusiveTextNode(cur)) break;
|
||||
try buf.appendSlice(frame.call_arena, cur._type.cdata._data.str());
|
||||
try buf.appendSlice(frame.local_arena, cur._type.cdata._data.str());
|
||||
}
|
||||
return buf.items;
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ pub const JsApi = struct {
|
||||
};
|
||||
|
||||
var names: std.ArrayList([]const u8) = .{};
|
||||
const arena = exec.call_arena;
|
||||
const arena = exec.local_arena;
|
||||
|
||||
const len = self.length(frame);
|
||||
for (0..len) |i| {
|
||||
|
||||
@@ -141,9 +141,9 @@ pub const JsApi = struct {
|
||||
// element's data-* attributes, in attribute order.
|
||||
fn getNames(self: *DOMStringMap, exec: *const js.Execution) !js.Array {
|
||||
var names: std.ArrayList([]const u8) = .empty;
|
||||
for (try self._element._attributes.getNames(exec.call_arena)) |attr_name| {
|
||||
const camel = (try kebabToCamel(exec.call_arena, attr_name)) orelse continue;
|
||||
try names.append(exec.call_arena, camel);
|
||||
for (try self._element._attributes.getNames(exec.local_arena)) |attr_name| {
|
||||
const camel = (try kebabToCamel(exec.local_arena, attr_name)) orelse continue;
|
||||
try names.append(exec.local_arena, camel);
|
||||
}
|
||||
|
||||
var arr = exec.js.local.?.newArray(@intCast(names.items.len));
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user