mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-10-10 05:11:46 -04:00
refactor: Introduce Arena wrapper
Introduces a ArenaAllocator wrappre (lp.Arena). This is groundwork for better memory tracking and reporting memory usage to v8. This is almost purely a mechanical change to lay a foundation for a follow up PR that will address https://github.com/lightpanda-io/browser/issues/3027 Some code became a bit leaner: a pooled arena can release itself (it has a reference to the ArenaPool). Some code became uglier: The Frame has a `_local_arena: *lp.Arena` and a `local_arena: Allocator` (same with call_arena, and same with a few other types) so that consumers aren't impacted (they continue to use `frame.local_arena`).
This commit is contained in:
123 files changed
+971
-961
No files matched your search
@@ -0,0 +1,79 @@
|
||||
// Copyright (C) 2023-2026 Lightpanda (Selecy SAS)
|
||||
//
|
||||
// Francis Bouvier <francis@lightpanda.io>
|
||||
// Pierre Tachoire <pierre@lightpanda.io>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
// An arena checked out of an ArenaPool. Owners hold the *Arena and release it
|
||||
// when they're done with it; everything downstream takes the plain Allocator
|
||||
// from allocator().
|
||||
//
|
||||
// Never copy an Arena by value: the Allocator it hands out points back into it.
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const ArenaPool = @import("ArenaPool.zig");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||
|
||||
const Arena = @This();
|
||||
|
||||
const IS_DEBUG = builtin.mode == .Debug;
|
||||
|
||||
// In Debug, don't pool and don't retain capacity. Both can mask UAF.
|
||||
pub const SAFETY = IS_DEBUG == true and builtin.is_test == false;
|
||||
|
||||
_arena: ArenaAllocator,
|
||||
pool: *ArenaPool,
|
||||
bucket: *ArenaPool.Bucket,
|
||||
|
||||
// Only meaningful while this arena sits in its bucket's free list.
|
||||
next: ?*Arena,
|
||||
|
||||
debug: if (IS_DEBUG) []const u8 else void = if (IS_DEBUG) "" else {},
|
||||
|
||||
pub fn allocator(self: *Arena) Allocator {
|
||||
return self._arena.allocator();
|
||||
}
|
||||
|
||||
pub fn release(self: *Arena) void {
|
||||
self.pool.release(self);
|
||||
}
|
||||
|
||||
pub fn reset(self: *Arena, retain: usize) void {
|
||||
_ = self._arena.reset(if (comptime SAFETY) .free_all else .{ .retain_with_limit = retain });
|
||||
}
|
||||
|
||||
pub fn resetRetain(self: *Arena) void {
|
||||
_ = self._arena.reset(if (comptime SAFETY) .free_all else .retain_capacity);
|
||||
}
|
||||
|
||||
pub fn alloc(self: *Arena, comptime T: type, n: usize) ![]T {
|
||||
return self.allocator().alloc(T, n);
|
||||
}
|
||||
|
||||
pub fn create(self: *Arena, comptime T: type) !*T {
|
||||
return self.allocator().create(T);
|
||||
}
|
||||
|
||||
pub fn dupe(self: *Arena, comptime T: type, m: []const T) ![]T {
|
||||
return self.allocator().dupe(T, m);
|
||||
}
|
||||
|
||||
pub fn dupeZ(self: *Arena, comptime T: type, m: []const T) ![:0]T {
|
||||
return self.allocator().dupeZ(T, m);
|
||||
}
|
||||
+42
-61
@@ -20,6 +20,8 @@ const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const Arena = @import("Arena.zig");
|
||||
|
||||
const log = lp.log;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||
@@ -27,26 +29,17 @@ const ArenaAllocator = std.heap.ArenaAllocator;
|
||||
const ArenaPool = @This();
|
||||
|
||||
const IS_DEBUG = builtin.mode == .Debug;
|
||||
|
||||
// In Debug, disable pooling to better catch UAF.
|
||||
const SAFETY = IS_DEBUG == true and builtin.is_test == false;
|
||||
const SAFETY = Arena.SAFETY;
|
||||
|
||||
pub const BucketSize = enum { tiny, small, medium, large };
|
||||
|
||||
const Bucket = struct {
|
||||
free_list: ?*Entry = null,
|
||||
pub const Bucket = struct {
|
||||
free_list: ?*Arena = null,
|
||||
free_list_len: u16 = 0,
|
||||
free_list_max: u16,
|
||||
retain_bytes: usize,
|
||||
};
|
||||
|
||||
const Entry = struct {
|
||||
next: ?*Entry,
|
||||
arena: ArenaAllocator,
|
||||
bucket: *Bucket,
|
||||
debug: if (IS_DEBUG) []const u8 else void = if (IS_DEBUG) "" else {},
|
||||
};
|
||||
|
||||
pub const Config = struct {
|
||||
tiny: Config.Bucket = .{ .max = 512, .retain = 1024 },
|
||||
small: Config.Bucket = .{ .max = 128, .retain = 4 * 1024 },
|
||||
@@ -65,7 +58,7 @@ medium: Bucket,
|
||||
large: Bucket,
|
||||
allocator: Allocator,
|
||||
mutex: std.Io.Mutex = .init,
|
||||
entry_pool: std.heap.MemoryPool(Entry),
|
||||
entry_pool: std.heap.MemoryPool(Arena),
|
||||
|
||||
_leak_track: if (IS_DEBUG) std.StringHashMapUnmanaged(isize) else void = if (IS_DEBUG) .empty else {},
|
||||
|
||||
@@ -101,7 +94,7 @@ pub fn deinit(self: *ArenaPool) void {
|
||||
var entry = bucket.free_list;
|
||||
while (entry) |e| {
|
||||
entry = e.next;
|
||||
e.arena.deinit();
|
||||
e._arena.deinit();
|
||||
}
|
||||
}
|
||||
self.entry_pool.deinit(self.allocator);
|
||||
@@ -110,7 +103,7 @@ pub fn deinit(self: *ArenaPool) void {
|
||||
// Acquire an arena from the pool.
|
||||
// - Pass a BucketSize (.tiny, .small, .medium, .large) for explicit bucket selection
|
||||
// - Pass a usize for automatic bucket selection based on expected size
|
||||
pub fn acquire(self: *ArenaPool, size_or_bucket: anytype, debug: []const u8) !Allocator {
|
||||
pub fn acquire(self: *ArenaPool, size_or_bucket: anytype, debug: []const u8) !*Arena {
|
||||
const bucket_size: BucketSize = blk: {
|
||||
const T = @TypeOf(size_or_bucket);
|
||||
if (T == BucketSize or T == @TypeOf(.enum_literal)) {
|
||||
@@ -147,7 +140,7 @@ pub fn acquire(self: *ArenaPool, size_or_bucket: anytype, debug: []const u8) !Al
|
||||
gop.value_ptr.* += 1;
|
||||
}
|
||||
lp.metrics.arena_hit.incr(bucket_size);
|
||||
return entry.arena.allocator();
|
||||
return entry;
|
||||
}
|
||||
|
||||
lp.metrics.arena_miss.incr(bucket_size);
|
||||
@@ -155,9 +148,10 @@ pub fn acquire(self: *ArenaPool, size_or_bucket: anytype, debug: []const u8) !Al
|
||||
const entry = try self.entry_pool.create(self.allocator);
|
||||
entry.* = .{
|
||||
.next = null,
|
||||
.pool = self,
|
||||
.bucket = bucket,
|
||||
.debug = if (IS_DEBUG) debug else {},
|
||||
.arena = ArenaAllocator.init(self.allocator),
|
||||
._arena = ArenaAllocator.init(self.allocator),
|
||||
};
|
||||
|
||||
if (IS_DEBUG) {
|
||||
@@ -167,13 +161,12 @@ pub fn acquire(self: *ArenaPool, size_or_bucket: anytype, debug: []const u8) !Al
|
||||
}
|
||||
gop.value_ptr.* += 1;
|
||||
}
|
||||
return entry.arena.allocator();
|
||||
return entry;
|
||||
}
|
||||
|
||||
// Universal release - determines bucket from the Entry automatically
|
||||
pub fn release(self: *ArenaPool, allocator: Allocator) void {
|
||||
const arena: *ArenaAllocator = @ptrCast(@alignCast(allocator.ptr));
|
||||
const entry: *Entry = @fieldParentPtr("arena", arena);
|
||||
// Prefer Arena.release(). Determines the bucket from the Arena automatically.
|
||||
pub fn release(self: *ArenaPool, entry: *Arena) void {
|
||||
const arena = &entry._arena;
|
||||
const bucket = entry.bucket;
|
||||
|
||||
if (IS_DEBUG) {
|
||||
@@ -208,18 +201,6 @@ pub fn release(self: *ArenaPool, allocator: Allocator) void {
|
||||
bucket.free_list_len += 1;
|
||||
}
|
||||
|
||||
pub fn reset(_: *const ArenaPool, allocator: Allocator, retain: usize) void {
|
||||
const arena: *ArenaAllocator = @ptrCast(@alignCast(allocator.ptr));
|
||||
// In Debug, free_all, it's less likely to hide things
|
||||
_ = arena.reset(if (comptime SAFETY) .free_all else .{ .retain_with_limit = retain });
|
||||
}
|
||||
|
||||
pub fn resetRetain(_: *const ArenaPool, allocator: Allocator) void {
|
||||
const arena: *ArenaAllocator = @ptrCast(@alignCast(allocator.ptr));
|
||||
// In Debug, free_all, it's less likely to hide things
|
||||
_ = arena.reset(if (comptime SAFETY) .free_all else .retain_capacity);
|
||||
}
|
||||
|
||||
const testing = std.testing;
|
||||
test "ArenaPool: basic acquire and release" {
|
||||
var pool = ArenaPool.init(testing.allocator, .{});
|
||||
@@ -230,17 +211,17 @@ test "ArenaPool: basic acquire and release" {
|
||||
const large = try pool.acquire(.large, "test-large");
|
||||
|
||||
// All three must be distinct arenas
|
||||
try testing.expect(tiny.ptr != medium.ptr);
|
||||
try testing.expect(medium.ptr != large.ptr);
|
||||
try testing.expect(tiny != medium);
|
||||
try testing.expect(medium != large);
|
||||
|
||||
_ = try tiny.alloc(u8, 64);
|
||||
_ = try medium.alloc(u8, 1024);
|
||||
_ = try large.alloc(u8, 4096);
|
||||
|
||||
// Universal release works for all buckets
|
||||
pool.release(tiny);
|
||||
pool.release(medium);
|
||||
pool.release(large);
|
||||
tiny.release();
|
||||
medium.release();
|
||||
large.release();
|
||||
|
||||
try testing.expectEqual(1, pool.tiny.free_list_len);
|
||||
try testing.expectEqual(1, pool.medium.free_list_len);
|
||||
@@ -252,20 +233,20 @@ test "ArenaPool: reuse from correct bucket" {
|
||||
defer pool.deinit();
|
||||
|
||||
const tiny1 = try pool.acquire(.tiny, "test");
|
||||
pool.release(tiny1);
|
||||
tiny1.release();
|
||||
try testing.expectEqual(1, pool.tiny.free_list_len);
|
||||
|
||||
// Next acquire with .tiny should reuse from tiny bucket
|
||||
const tiny2 = try pool.acquire(.tiny, "test");
|
||||
try testing.expectEqual(0, pool.tiny.free_list_len);
|
||||
try testing.expectEqual(tiny1.ptr, tiny2.ptr);
|
||||
try testing.expectEqual(tiny1, tiny2);
|
||||
|
||||
// acquire with .medium should NOT get the tiny arena
|
||||
const medium = try pool.acquire(.medium, "test-medium");
|
||||
try testing.expect(medium.ptr != tiny2.ptr);
|
||||
try testing.expect(medium != tiny2);
|
||||
|
||||
pool.release(tiny2);
|
||||
pool.release(medium);
|
||||
tiny2.release();
|
||||
medium.release();
|
||||
}
|
||||
|
||||
test "ArenaPool: respects per-bucket max limits" {
|
||||
@@ -282,11 +263,11 @@ test "ArenaPool: respects per-bucket max limits" {
|
||||
const t3 = try pool.acquire(.tiny, "t3");
|
||||
|
||||
// Release all 3, but only 1 should be kept (tiny_max = 1)
|
||||
pool.release(t1);
|
||||
t1.release();
|
||||
try testing.expectEqual(1, pool.tiny.free_list_len);
|
||||
pool.release(t2);
|
||||
t2.release();
|
||||
try testing.expectEqual(1, pool.tiny.free_list_len); // still 1, t2 discarded
|
||||
pool.release(t3);
|
||||
t3.release();
|
||||
try testing.expectEqual(1, pool.tiny.free_list_len); // still 1, t3 discarded
|
||||
|
||||
// Acquire 3 medium arenas
|
||||
@@ -295,9 +276,9 @@ test "ArenaPool: respects per-bucket max limits" {
|
||||
const m3 = try pool.acquire(.medium, "m3");
|
||||
|
||||
// Release all 3, but only 2 should be kept (medium_max = 2)
|
||||
pool.release(m1);
|
||||
pool.release(m2);
|
||||
pool.release(m3);
|
||||
m1.release();
|
||||
m2.release();
|
||||
m3.release();
|
||||
try testing.expectEqual(2, pool.medium.free_list_len);
|
||||
}
|
||||
|
||||
@@ -311,7 +292,7 @@ test "ArenaPool: reset clears memory without releasing" {
|
||||
@memset(buf, 0xFF);
|
||||
|
||||
// reset() frees arena memory but keeps the allocator in-flight.
|
||||
pool.reset(alloc, 0);
|
||||
alloc.reset(0);
|
||||
|
||||
// The free list must stay empty; the allocator was not released.
|
||||
try testing.expectEqual(0, pool.medium.free_list_len);
|
||||
@@ -321,7 +302,7 @@ test "ArenaPool: reset clears memory without releasing" {
|
||||
@memset(buf2, 0x00);
|
||||
try testing.expectEqual(@as(u8, 0x00), buf2[0]);
|
||||
|
||||
pool.release(alloc);
|
||||
alloc.release();
|
||||
}
|
||||
|
||||
test "ArenaPool: deinit with entries in free list" {
|
||||
@@ -333,8 +314,8 @@ test "ArenaPool: deinit with entries in free list" {
|
||||
const a2 = try pool.acquire(.medium, "test2");
|
||||
_ = try a1.alloc(u8, 256);
|
||||
_ = try a2.alloc(u8, 512);
|
||||
pool.release(a1);
|
||||
pool.release(a2);
|
||||
a1.release();
|
||||
a2.release();
|
||||
try testing.expectEqual(1, pool.tiny.free_list_len);
|
||||
try testing.expectEqual(1, pool.medium.free_list_len);
|
||||
|
||||
@@ -351,9 +332,9 @@ test "ArenaPool: small bucket" {
|
||||
const s2 = try pool.acquire(.small, "s2");
|
||||
const s3 = try pool.acquire(.small, "s3");
|
||||
|
||||
pool.release(s1);
|
||||
pool.release(s2);
|
||||
pool.release(s3);
|
||||
s1.release();
|
||||
s2.release();
|
||||
s3.release();
|
||||
|
||||
try testing.expectEqual(2, pool.small.free_list_len);
|
||||
}
|
||||
@@ -371,10 +352,10 @@ test "ArenaPool: size-based acquire" {
|
||||
// > 16KB -> large
|
||||
const d = try pool.acquire(20000, "fits-large");
|
||||
|
||||
pool.release(a);
|
||||
pool.release(b);
|
||||
pool.release(c);
|
||||
pool.release(d);
|
||||
a.release();
|
||||
b.release();
|
||||
c.release();
|
||||
d.release();
|
||||
|
||||
try testing.expectEqual(1, pool.tiny.free_list_len);
|
||||
try testing.expectEqual(1, pool.small.free_list_len);
|
||||
|
||||
+24
-27
@@ -30,9 +30,6 @@ const lp = @import("lightpanda");
|
||||
|
||||
const CDP = @import("cdp/CDP.zig");
|
||||
|
||||
const ArenaPool = @import("ArenaPool.zig");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
const DoublyLinkedList = std.DoublyLinkedList;
|
||||
|
||||
const Inbox = @This();
|
||||
@@ -47,16 +44,16 @@ queue: DoublyLinkedList = .{},
|
||||
// a syncRequest and we want the following non-nested tick to pick it up again.
|
||||
terminated: bool = false,
|
||||
|
||||
pub fn deinit(self: *Inbox, arena_pool: *ArenaPool) void {
|
||||
pub fn deinit(self: *Inbox) void {
|
||||
self.mutex.lockUncancelable(lp.io);
|
||||
defer self.mutex.unlock(lp.io);
|
||||
while (self.queue.popFirst()) |node| {
|
||||
const msg: *Message = @fieldParentPtr("node", node);
|
||||
msg.deinit(arena_pool);
|
||||
msg.deinit();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(self: *Inbox, arena: Allocator, payload: Message.Payload) void {
|
||||
pub fn push(self: *Inbox, arena: *lp.Arena, payload: Message.Payload) void {
|
||||
const msg = arena.create(Message) catch |err| switch (err) {
|
||||
error.OutOfMemory => @panic("OOM"),
|
||||
};
|
||||
@@ -109,7 +106,7 @@ pub fn popIf(self: *Inbox, predicate: *const fn (*Message) bool) ?*Message {
|
||||
}
|
||||
|
||||
pub const Message = struct {
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
payload: Payload,
|
||||
node: DoublyLinkedList.Node = .{},
|
||||
|
||||
@@ -145,8 +142,8 @@ pub const Message = struct {
|
||||
input: CDP.InputMessage,
|
||||
};
|
||||
|
||||
pub fn deinit(self: *const Message, pool: *ArenaPool) void {
|
||||
pool.release(self.arena);
|
||||
pub fn deinit(self: *const Message) void {
|
||||
self.arena.release();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -155,7 +152,7 @@ test "Inbox: push then pop returns FIFO order" {
|
||||
const arena_pool = &testing.test_app.arena_pool;
|
||||
|
||||
var inbox = Inbox{};
|
||||
defer inbox.deinit(&testing.test_app.arena_pool);
|
||||
defer inbox.deinit();
|
||||
|
||||
{
|
||||
const arena = try arena_pool.acquire(.tiny, "inbox test");
|
||||
@@ -174,17 +171,17 @@ test "Inbox: push then pop returns FIFO order" {
|
||||
|
||||
{
|
||||
const m = inbox.pop().?;
|
||||
defer m.deinit(arena_pool);
|
||||
defer m.deinit();
|
||||
try testing.expectEqual("first", m.payload.ping);
|
||||
}
|
||||
{
|
||||
const m = inbox.pop().?;
|
||||
defer m.deinit(arena_pool);
|
||||
defer m.deinit();
|
||||
try testing.expectEqual("second", m.payload.ping);
|
||||
}
|
||||
{
|
||||
const m = inbox.pop().?;
|
||||
defer m.deinit(arena_pool);
|
||||
defer m.deinit();
|
||||
try testing.expectEqual(@as(?anyerror, null), m.payload.disconnect);
|
||||
}
|
||||
try testing.expect(inbox.pop() == null);
|
||||
@@ -203,7 +200,7 @@ test "Inbox: deinit frees remaining items" {
|
||||
inbox.push(arena, .{ .disconnect = error.PeerClosed });
|
||||
}
|
||||
|
||||
inbox.deinit(&testing.test_app.arena_pool);
|
||||
inbox.deinit();
|
||||
// Memory leaks would be caught by the test runner.
|
||||
}
|
||||
|
||||
@@ -221,14 +218,14 @@ fn testIsPing(msg: *Message) bool {
|
||||
|
||||
test "Inbox: popIf on empty queue returns null" {
|
||||
var inbox = Inbox{};
|
||||
defer inbox.deinit(&testing.test_app.arena_pool);
|
||||
defer inbox.deinit();
|
||||
try testing.expect(inbox.popIf(testAlwaysTrue) == null);
|
||||
}
|
||||
|
||||
test "Inbox: popIf with no match leaves queue intact" {
|
||||
const arena_pool = &testing.test_app.arena_pool;
|
||||
var inbox = Inbox{};
|
||||
defer inbox.deinit(arena_pool);
|
||||
defer inbox.deinit();
|
||||
|
||||
{
|
||||
const arena = try arena_pool.acquire(.tiny, "popif test");
|
||||
@@ -244,12 +241,12 @@ test "Inbox: popIf with no match leaves queue intact" {
|
||||
// Original FIFO order preserved.
|
||||
{
|
||||
const m = inbox.pop().?;
|
||||
defer m.deinit(arena_pool);
|
||||
defer m.deinit();
|
||||
try testing.expectEqual("first", m.payload.ping);
|
||||
}
|
||||
{
|
||||
const m = inbox.pop().?;
|
||||
defer m.deinit(arena_pool);
|
||||
defer m.deinit();
|
||||
try testing.expectEqual("second", m.payload.ping);
|
||||
}
|
||||
try testing.expect(inbox.pop() == null);
|
||||
@@ -258,7 +255,7 @@ test "Inbox: popIf with no match leaves queue intact" {
|
||||
test "Inbox: popIf with always-true predicate behaves like pop" {
|
||||
const arena_pool = &testing.test_app.arena_pool;
|
||||
var inbox = Inbox{};
|
||||
defer inbox.deinit(arena_pool);
|
||||
defer inbox.deinit();
|
||||
|
||||
{
|
||||
const arena = try arena_pool.acquire(.tiny, "popif test");
|
||||
@@ -271,12 +268,12 @@ test "Inbox: popIf with always-true predicate behaves like pop" {
|
||||
|
||||
{
|
||||
const m = inbox.popIf(testAlwaysTrue).?;
|
||||
defer m.deinit(arena_pool);
|
||||
defer m.deinit();
|
||||
try testing.expectEqual("a", m.payload.ping);
|
||||
}
|
||||
{
|
||||
const m = inbox.popIf(testAlwaysTrue).?;
|
||||
defer m.deinit(arena_pool);
|
||||
defer m.deinit();
|
||||
try testing.expectEqual("b", m.payload.ping);
|
||||
}
|
||||
try testing.expect(inbox.popIf(testAlwaysTrue) == null);
|
||||
@@ -285,7 +282,7 @@ test "Inbox: popIf with always-true predicate behaves like pop" {
|
||||
test "Inbox: popIf cherry-picks middle, preserves order of remainder" {
|
||||
const arena_pool = &testing.test_app.arena_pool;
|
||||
var inbox = Inbox{};
|
||||
defer inbox.deinit(arena_pool);
|
||||
defer inbox.deinit();
|
||||
|
||||
{
|
||||
const arena = try arena_pool.acquire(.tiny, "popif test");
|
||||
@@ -303,19 +300,19 @@ test "Inbox: popIf cherry-picks middle, preserves order of remainder" {
|
||||
// testIsPing skips the disconnect at the head and picks the middle.
|
||||
{
|
||||
const m = inbox.popIf(testIsPing).?;
|
||||
defer m.deinit(arena_pool);
|
||||
defer m.deinit();
|
||||
try testing.expectEqual("middle", m.payload.ping);
|
||||
}
|
||||
|
||||
// Remaining two disconnects pop in original order.
|
||||
{
|
||||
const m = inbox.pop().?;
|
||||
defer m.deinit(arena_pool);
|
||||
defer m.deinit();
|
||||
try testing.expect(m.payload.disconnect == null);
|
||||
}
|
||||
{
|
||||
const m = inbox.pop().?;
|
||||
defer m.deinit(arena_pool);
|
||||
defer m.deinit();
|
||||
try testing.expect(m.payload.disconnect.? == error.PeerClosed);
|
||||
}
|
||||
try testing.expect(inbox.pop() == null);
|
||||
@@ -324,7 +321,7 @@ test "Inbox: popIf cherry-picks middle, preserves order of remainder" {
|
||||
test "Inbox: popIf picks first match in FIFO order" {
|
||||
const arena_pool = &testing.test_app.arena_pool;
|
||||
var inbox = Inbox{};
|
||||
defer inbox.deinit(arena_pool);
|
||||
defer inbox.deinit();
|
||||
|
||||
{
|
||||
const arena = try arena_pool.acquire(.tiny, "popif test");
|
||||
@@ -340,6 +337,6 @@ test "Inbox: popIf picks first match in FIFO order" {
|
||||
}
|
||||
|
||||
const m = inbox.popIf(testIsPing).?;
|
||||
defer m.deinit(arena_pool);
|
||||
defer m.deinit();
|
||||
try testing.expectEqual("first", m.payload.ping);
|
||||
}
|
||||
+10
-10
@@ -77,10 +77,10 @@ pub fn eventTargetWithAllocator(_: *const Factory, allocator: Allocator, child:
|
||||
}
|
||||
|
||||
// this is a root object
|
||||
pub fn event(_: *const Factory, arena: Allocator, typ: String, child: anytype) !*@TypeOf(child) {
|
||||
pub fn event(_: *const Factory, arena: *lp.Arena, typ: String, child: anytype) !*@TypeOf(child) {
|
||||
const chain = try PrototypeChain(
|
||||
&.{ Event, @TypeOf(child) },
|
||||
).allocate(arena);
|
||||
).allocate(arena.allocator());
|
||||
|
||||
// Special case: Event has a _type_string field, so we need manual setup
|
||||
const event_ptr = chain.get(0);
|
||||
@@ -90,10 +90,10 @@ pub fn event(_: *const Factory, arena: Allocator, typ: String, child: anytype) !
|
||||
return chain.get(1);
|
||||
}
|
||||
|
||||
pub fn uiEvent(_: *const Factory, arena: Allocator, typ: String, child: anytype) !*@TypeOf(child) {
|
||||
pub fn uiEvent(_: *const Factory, arena: *lp.Arena, typ: String, child: anytype) !*@TypeOf(child) {
|
||||
const chain = try PrototypeChain(
|
||||
&.{ Event, UIEvent, @TypeOf(child) },
|
||||
).allocate(arena);
|
||||
).allocate(arena.allocator());
|
||||
|
||||
// Special case: Event has a _type_string field, so we need manual setup
|
||||
const event_ptr = chain.get(0);
|
||||
@@ -104,10 +104,10 @@ pub fn uiEvent(_: *const Factory, arena: Allocator, typ: String, child: anytype)
|
||||
return chain.get(2);
|
||||
}
|
||||
|
||||
pub fn mouseEvent(_: *const Factory, arena: Allocator, typ: String, mouse: MouseEvent, child: anytype) !*@TypeOf(child) {
|
||||
pub fn mouseEvent(_: *const Factory, arena: *lp.Arena, typ: String, mouse: MouseEvent, child: anytype) !*@TypeOf(child) {
|
||||
const chain = try PrototypeChain(
|
||||
&.{ Event, UIEvent, MouseEvent, @TypeOf(child) },
|
||||
).allocate(arena);
|
||||
).allocate(arena.allocator());
|
||||
|
||||
// Special case: Event has a _type_string field, so we need manual setup
|
||||
const event_ptr = chain.get(0);
|
||||
@@ -236,7 +236,7 @@ fn AutoPrototypeChain(comptime types: []const type) type {
|
||||
};
|
||||
}
|
||||
|
||||
fn eventInit(arena: Allocator, typ: String, value: anytype) !Event {
|
||||
fn eventInit(arena: *lp.Arena, typ: String, value: anytype) !Event {
|
||||
// Round to 2ms for privacy (browsers do this)
|
||||
// Same (already coarsened) clock as the performance time origin, so the
|
||||
// timeStamp getter can report it relative to that origin.
|
||||
@@ -255,7 +255,7 @@ pub fn blob(_: *const Factory, arena: Allocator, child: anytype) !*@TypeOf(child
|
||||
// Special case: Blob has slice and mime fields, so we need manual setup
|
||||
const chain = try PrototypeChain(
|
||||
&.{ Blob, @TypeOf(child) },
|
||||
).allocate(arena);
|
||||
).allocate(arena.allocator());
|
||||
|
||||
const blob_ptr = chain.get(0);
|
||||
blob_ptr.* = .{
|
||||
@@ -270,8 +270,8 @@ pub fn blob(_: *const Factory, arena: Allocator, child: anytype) !*@TypeOf(child
|
||||
return chain.get(1);
|
||||
}
|
||||
|
||||
pub fn abstractRange(_: *const Factory, arena: Allocator, child: anytype, frame: *Frame) !*@TypeOf(child) {
|
||||
const chain = try PrototypeChain(&.{ AbstractRange, @TypeOf(child) }).allocate(arena);
|
||||
pub fn abstractRange(_: *const Factory, arena: *lp.Arena, child: anytype, frame: *Frame) !*@TypeOf(child) {
|
||||
const chain = try PrototypeChain(&.{ AbstractRange, @TypeOf(child) }).allocate(arena.allocator());
|
||||
|
||||
const doc = frame.document.asNode();
|
||||
const abstract_range = chain.get(0);
|
||||
|
||||
+41
-41
@@ -298,10 +298,12 @@ arena: Allocator,
|
||||
// An arena with a lifetime for at least the scope of one Zig invocation from
|
||||
// JS. Prefer local_arena where possible. Use call_arena when allocations may
|
||||
// need to call back into JS (event dispatch, forEach callback, ....)
|
||||
_call_arena: *lp.Arena,
|
||||
call_arena: Allocator,
|
||||
|
||||
// An arena with a lifetime guaranteed to be for exactly 1 invoking of a Zig
|
||||
// function from JS. Best arena to use, when possible.
|
||||
_local_arena: *lp.Arena,
|
||||
local_arena: Allocator,
|
||||
|
||||
parent: ?*Frame,
|
||||
@@ -358,10 +360,10 @@ pub fn init(self: *Frame, frame_id: u32, page: *Page, opts: InitOpts) !void {
|
||||
|
||||
const session = page.session;
|
||||
const call_arena = try session.getArena(.medium, "call_arena");
|
||||
errdefer session.releaseArena(call_arena);
|
||||
errdefer call_arena.release();
|
||||
|
||||
const local_arena = try session.getArena(.medium, "local_arena");
|
||||
errdefer session.releaseArena(local_arena);
|
||||
errdefer local_arena.release();
|
||||
|
||||
const factory = &page.factory;
|
||||
const document = (try factory.document(Node.Document.HTMLDocument{
|
||||
@@ -376,8 +378,10 @@ pub fn init(self: *Frame, frame_id: u32, page: *Page, opts: InitOpts) !void {
|
||||
.parent = parent,
|
||||
.document = document,
|
||||
.window = undefined,
|
||||
.call_arena = call_arena,
|
||||
.local_arena = local_arena,
|
||||
._call_arena = call_arena,
|
||||
._local_arena = local_arena,
|
||||
.call_arena = call_arena.allocator(),
|
||||
.local_arena = local_arena.allocator(),
|
||||
._frame_id = frame_id,
|
||||
._page = page,
|
||||
._session = session,
|
||||
@@ -491,7 +495,7 @@ pub fn deinit(self: *Frame) void {
|
||||
const page = self._page;
|
||||
|
||||
if (self._queued_navigation) |qn| {
|
||||
page.releaseArena(qn.arena);
|
||||
qn.arena.release();
|
||||
}
|
||||
|
||||
while (self._message_ports.first) |node| {
|
||||
@@ -549,8 +553,8 @@ pub fn deinit(self: *Frame) void {
|
||||
self._script_manager.deinit();
|
||||
self._style_manager.deinit();
|
||||
|
||||
page.releaseArena(self.call_arena);
|
||||
page.releaseArena(self.local_arena);
|
||||
self._call_arena.release();
|
||||
self._local_arena.release();
|
||||
}
|
||||
|
||||
pub fn trackWorker(self: *Frame, worker: *Worker) !void {
|
||||
@@ -614,14 +618,10 @@ pub fn headersForRequest(self: *Frame, headers: *HttpClient.Headers) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getArena(self: *Frame, size_or_bucket: anytype, debug: []const u8) !Allocator {
|
||||
pub fn getArena(self: *Frame, size_or_bucket: anytype, debug: []const u8) !*lp.Arena {
|
||||
return self._session.getArena(size_or_bucket, debug);
|
||||
}
|
||||
|
||||
pub fn releaseArena(self: *Frame, allocator: Allocator) void {
|
||||
return self._session.releaseArena(allocator);
|
||||
}
|
||||
|
||||
pub fn isSameOrigin(self: *const Frame, url: [:0]const u8) bool {
|
||||
const current_origin = self.origin orelse return false;
|
||||
|
||||
@@ -705,11 +705,11 @@ pub fn navigate(self: *Frame, request_url: [:0]const u8, opts: NavigateOpts) !vo
|
||||
return error.BlobNotFound;
|
||||
};
|
||||
const parse_arena = try self.getArena(.medium, "Frame.parseBlob");
|
||||
defer self.releaseArena(parse_arena);
|
||||
defer parse_arena.release();
|
||||
// A script executed mid-parse can revoke the blob URL, letting GC
|
||||
// free the buffer under the parser; parse a copy.
|
||||
const html = try parse_arena.dupe(u8, blob._slice);
|
||||
var parser = Parser.init(parse_arena, self.document.asNode(), self, .{ .allow_declarative_shadow = true });
|
||||
var parser = Parser.init(parse_arena.allocator(), self.document.asNode(), self, .{ .allow_declarative_shadow = true });
|
||||
parser.parse(html);
|
||||
} else {
|
||||
self.document.injectBlank(self) catch |err| {
|
||||
@@ -805,7 +805,7 @@ pub fn navigate(self: *Frame, request_url: [:0]const u8, opts: NavigateOpts) !vo
|
||||
try transfer.req.headers.add(hdr);
|
||||
}
|
||||
if (opts.referer) |ref| {
|
||||
const ref_header = try std.mem.concatWithSentinel(transfer.arena, u8, &.{ "Referer: ", ref }, 0);
|
||||
const ref_header = try std.mem.concatWithSentinel(transfer.arena.allocator(), u8, &.{ "Referer: ", ref }, 0);
|
||||
try transfer.req.headers.add(ref_header);
|
||||
}
|
||||
}
|
||||
@@ -865,14 +865,14 @@ pub fn scheduleNavigation(self: *Frame, request_url: []const u8, opts: NavigateO
|
||||
return;
|
||||
}
|
||||
const arena = try self._session.getArena(.small, "scheduleNavigation");
|
||||
errdefer self._session.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return self.scheduleNavigationWithArena(arena, request_url, opts, nt);
|
||||
}
|
||||
|
||||
// Don't name the first parameter "self", because the target of this navigation
|
||||
// might change inside the function. So the code should be explicit about the
|
||||
// frame that it's acting on.
|
||||
fn scheduleNavigationWithArena(originator: *Frame, arena: Allocator, request_url: []const u8, opts: NavigateOpts, nt: Navigation) !void {
|
||||
fn scheduleNavigationWithArena(originator: *Frame, arena: *lp.Arena, request_url: []const u8, opts: NavigateOpts, nt: Navigation) !void {
|
||||
const resolved_url, const is_about_blank = blk: {
|
||||
if (URL.isCompleteHTTPUrl(request_url)) {
|
||||
break :blk .{ try arena.dupeZ(u8, request_url), false };
|
||||
@@ -900,7 +900,7 @@ fn scheduleNavigationWithArena(originator: *Frame, arena: Allocator, request_url
|
||||
};
|
||||
|
||||
const u = try URL.resolve(
|
||||
arena,
|
||||
arena.allocator(),
|
||||
frame_base,
|
||||
request_url,
|
||||
.{ .encoding = originator.charset },
|
||||
@@ -926,7 +926,7 @@ fn scheduleNavigationWithArena(originator: *Frame, arena: Allocator, request_url
|
||||
std.mem.eql(u8, target.url, resolved_url) and
|
||||
std.mem.indexOfScalar(u8, resolved_url, '#') != null)
|
||||
{
|
||||
session.releaseArena(arena);
|
||||
arena.release();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -949,7 +949,7 @@ fn scheduleNavigationWithArena(originator: *Frame, arena: Allocator, request_url
|
||||
try target.queueHashChange(old_url, target.url);
|
||||
|
||||
// don't defer this, the caller is responsible for freeing it on error
|
||||
session.releaseArena(arena);
|
||||
arena.release();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -997,7 +997,7 @@ fn scheduleNavigationWithArena(originator: *Frame, arena: Allocator, request_url
|
||||
};
|
||||
|
||||
if (target._queued_navigation) |existing| {
|
||||
session.releaseArena(existing.arena);
|
||||
existing.arena.release();
|
||||
}
|
||||
|
||||
target._queued_navigation = qn;
|
||||
@@ -1535,7 +1535,7 @@ fn frameDataCallback(transfer: *HttpClient.Transfer, data: []const u8) !void {
|
||||
}
|
||||
|
||||
switch (self._parse_state) {
|
||||
.html => |*html| try html.buffer.appendSlice(html.arena, data),
|
||||
.html => |*html| try html.buffer.appendSlice(html.arena.allocator(), data),
|
||||
.text => |*buf| {
|
||||
// we have to escape the data...
|
||||
var v = data;
|
||||
@@ -1596,15 +1596,15 @@ fn frameDoneCallback(ctx: *anyopaque) !void {
|
||||
};
|
||||
|
||||
const parse_arena = try self.getArena(.medium, "Frame.parse");
|
||||
defer self.releaseArena(parse_arena);
|
||||
defer parse_arena.release();
|
||||
|
||||
var parser = Parser.init(parse_arena, self.document.asNode(), self, .{ .allow_declarative_shadow = true });
|
||||
var parser = Parser.init(parse_arena.allocator(), self.document.asNode(), self, .{ .allow_declarative_shadow = true });
|
||||
|
||||
switch (self._parse_state) {
|
||||
.html => |*html| {
|
||||
{
|
||||
defer {
|
||||
self.releaseArena(html.arena);
|
||||
html.arena.release();
|
||||
self._parse_state = .complete;
|
||||
}
|
||||
|
||||
@@ -1629,7 +1629,7 @@ fn frameDoneCallback(ctx: *anyopaque) !void {
|
||||
self._parse_state = .{ .raw_done = buf.items };
|
||||
|
||||
// Use empty an HTML containing the image.
|
||||
const html = try std.mem.concat(parse_arena, u8, &.{
|
||||
const html = try std.mem.concat(parse_arena.allocator(), u8, &.{
|
||||
"<html><head><meta charset=\"utf-8\"></head><body><img src=\"",
|
||||
self.url,
|
||||
"\"></body></html>",
|
||||
@@ -1656,7 +1656,7 @@ fn frameDoneCallback(ctx: *anyopaque) !void {
|
||||
},
|
||||
.err => |err| {
|
||||
// Generate a pseudo HTML page indicating the failure.
|
||||
const html = try std.mem.concat(parse_arena, u8, &.{
|
||||
const html = try std.mem.concat(parse_arena.allocator(), u8, &.{
|
||||
"<html><head><meta charset=\"utf-8\"></head><body><h1>Navigation failed</h1><p>Reason: ",
|
||||
@errorName(err),
|
||||
"</p></body></html>",
|
||||
@@ -2177,9 +2177,9 @@ pub fn loadExternalStylesheet(self: *Frame, link: *Element.Html.Link, href: []co
|
||||
const element = link.asElement();
|
||||
|
||||
const arena = try session.getArena(.medium, "Frame.loadExternalStylesheet");
|
||||
defer session.releaseArena(arena);
|
||||
defer arena.release();
|
||||
|
||||
const resolved = URL.resolve(arena, self.base(), href, .{ .encoding = self.charset }) catch |err| {
|
||||
const resolved = URL.resolve(arena.allocator(), self.base(), href, .{ .encoding = self.charset }) catch |err| {
|
||||
log.warn(.http, "external stylesheet resolve", .{ .err = err, .href = href });
|
||||
try self.fireElementEvent(element, comptime .wrap("error"));
|
||||
return;
|
||||
@@ -2208,7 +2208,7 @@ pub fn loadExternalStylesheet(self: *Frame, link: *Element.Html.Link, href: []co
|
||||
sm.is_evaluating = true;
|
||||
defer sm.endEvaluationWindow(was_evaluating);
|
||||
|
||||
var response = http_client.syncRequest(arena, .{
|
||||
var response = http_client.syncRequest(arena.allocator(), .{
|
||||
.url = resolved,
|
||||
.method = .GET,
|
||||
.frame_id = self._frame_id,
|
||||
@@ -2223,7 +2223,7 @@ pub fn loadExternalStylesheet(self: *Frame, link: *Element.Html.Link, href: []co
|
||||
log.warn(.http, "external stylesheet fetch", .{ .err = err, .url = resolved });
|
||||
return self.fireElementEvent(element, comptime .wrap("error"));
|
||||
};
|
||||
defer response.deinit(arena);
|
||||
defer response.deinit(arena.allocator());
|
||||
|
||||
if (response.status < 200 or response.status >= 300) {
|
||||
log.info(.http, "external stylesheet status", .{ .status = response.status, .url = resolved });
|
||||
@@ -2967,7 +2967,7 @@ const ParseState = union(enum) {
|
||||
complete,
|
||||
err: anyerror,
|
||||
html: struct {
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
buffer: std.ArrayList(u8),
|
||||
},
|
||||
text: std.ArrayList(u8),
|
||||
@@ -2976,9 +2976,9 @@ const ParseState = union(enum) {
|
||||
raw_done: []const u8,
|
||||
download: Download,
|
||||
|
||||
fn deinit(self: *ParseState, frame: *Frame) void {
|
||||
fn deinit(self: *ParseState, _: *Frame) void {
|
||||
switch (self.*) {
|
||||
.html => |html| frame.releaseArena(html.arena),
|
||||
.html => |html| html.arena.release(),
|
||||
// Only reached when a frame is torn down mid-download (the normal
|
||||
// completion path in frameDoneCallback already closes the file and
|
||||
// transitions to .complete).
|
||||
@@ -3143,7 +3143,7 @@ const Navigation = union(NavigationType) {
|
||||
};
|
||||
|
||||
pub const QueuedNavigation = struct {
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
url: [:0]const u8,
|
||||
opts: NavigateOpts,
|
||||
is_about_blank: bool,
|
||||
@@ -3365,7 +3365,7 @@ pub fn submitForm(self: *Frame, submitter_: ?*Element, form_: ?*Element.Html.For
|
||||
const is_post = std.mem.eql(u8, method, "post");
|
||||
|
||||
const arena = try self._session.getArena(.medium, "submitForm");
|
||||
errdefer self._session.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
// Get charset from accept-charset attribute or fall back to document charset
|
||||
const charset: []const u8 = blk: {
|
||||
@@ -3394,8 +3394,8 @@ pub fn submitForm(self: *Frame, submitter_: ?*Element, form_: ?*Element.Html.For
|
||||
break :blk .urlencode;
|
||||
};
|
||||
|
||||
var buf = std.Io.Writer.Allocating.init(arena);
|
||||
try form_data.write(.{ .encoding = encoding, .charset = charset, .allocator = arena }, &buf.writer);
|
||||
var buf = std.Io.Writer.Allocating.init(arena.allocator());
|
||||
try form_data.write(.{ .encoding = encoding, .charset = charset, .allocator = arena.allocator() }, &buf.writer);
|
||||
|
||||
var action = blk: {
|
||||
if (submit_button) |s| {
|
||||
@@ -3413,13 +3413,13 @@ pub fn submitForm(self: *Frame, submitter_: ?*Element, form_: ?*Element.Html.For
|
||||
opts.body = buf.written();
|
||||
opts.header = switch (encoding) {
|
||||
.urlencode => "Content-Type: application/x-www-form-urlencoded",
|
||||
.formdata => |b| try std.fmt.allocPrintSentinel(arena, "Content-Type: multipart/form-data; boundary={s}", .{b}, 0),
|
||||
.formdata => |b| try std.fmt.allocPrintSentinel(arena.allocator(), "Content-Type: multipart/form-data; boundary={s}", .{b}, 0),
|
||||
// Per WHATWG HTML §4.10.21.6, text/plain submissions include the form's
|
||||
// resolved encoding (accept-charset or document charset).
|
||||
.plaintext => try std.fmt.allocPrintSentinel(arena, "Content-Type: text/plain; charset={s}", .{charset}, 0),
|
||||
.plaintext => try std.fmt.allocPrintSentinel(arena.allocator(), "Content-Type: text/plain; charset={s}", .{charset}, 0),
|
||||
};
|
||||
} else {
|
||||
action = try URL.concatQueryString(arena, action, buf.written());
|
||||
action = try URL.concatQueryString(arena.allocator(), action, buf.written());
|
||||
}
|
||||
|
||||
return self.scheduleNavigationWithArena(arena, action, opts, .{ .form = target_frame });
|
||||
|
||||
+9
-11
@@ -72,6 +72,7 @@ factory: Factory,
|
||||
|
||||
// The arena for this Page's lifetime. Document / Frame / Factory / DOM
|
||||
// objects allocate out of this.
|
||||
_frame_arena: *lp.Arena,
|
||||
frame_arena: Allocator,
|
||||
|
||||
// Origin map for same-origin context sharing. Entries live for the Page's
|
||||
@@ -150,13 +151,14 @@ pub fn getViewport(self: *const Page) Viewport {
|
||||
// Initialize a Page and its root Frame.
|
||||
pub fn init(self: *Page, session: *Session, frame_id: u32) !void {
|
||||
const frame_arena = try session.arena_pool.acquire(.large, "Page.frame_arena");
|
||||
errdefer session.arena_pool.release(frame_arena);
|
||||
errdefer frame_arena.release();
|
||||
|
||||
self.* = .{
|
||||
.session = session,
|
||||
.frame = undefined,
|
||||
.frame_arena = frame_arena,
|
||||
.factory = Factory.init(frame_arena),
|
||||
._frame_arena = frame_arena,
|
||||
.frame_arena = frame_arena.allocator(),
|
||||
.factory = Factory.init(frame_arena.allocator()),
|
||||
.globals = .init(session.browser.app.allocator),
|
||||
};
|
||||
self.queued_navigation = &self.queued_navigation_1;
|
||||
@@ -228,7 +230,7 @@ pub fn deinit(self: *Page) void {
|
||||
self.origins = .empty;
|
||||
}
|
||||
|
||||
session.arena_pool.release(self.frame_arena);
|
||||
self._frame_arena.release();
|
||||
}
|
||||
|
||||
pub fn recordJsError(self: *Page, err: anyerror) void {
|
||||
@@ -236,14 +238,10 @@ pub fn recordJsError(self: *Page, err: anyerror) void {
|
||||
lp.metrics.js_errors.incr(if (err == error.JsException) .js_exception else .other);
|
||||
}
|
||||
|
||||
pub fn getArena(self: *Page, size_or_bucket: anytype, debug: []const u8) !Allocator {
|
||||
pub fn getArena(self: *Page, size_or_bucket: anytype, debug: []const u8) !*lp.Arena {
|
||||
return self.session.getArena(size_or_bucket, debug);
|
||||
}
|
||||
|
||||
pub fn releaseArena(self: *Page, allocator: Allocator) void {
|
||||
return self.session.releaseArena(allocator);
|
||||
}
|
||||
|
||||
pub fn getOrCreateOrigin(self: *Page, key_: ?[]const u8) !*js.Origin {
|
||||
const session = self.session;
|
||||
const key = key_ orelse {
|
||||
@@ -255,7 +253,7 @@ pub fn getOrCreateOrigin(self: *Page, key_: ?[]const u8) !*js.Origin {
|
||||
return js.Origin.init(session.browser.app, session.browser.env.isolate, &opaque_origin);
|
||||
};
|
||||
|
||||
const gop = try self.origins.getOrPut(session.arena, key);
|
||||
const gop = try self.origins.getOrPut(session.arena.allocator(), key);
|
||||
if (gop.found_existing) {
|
||||
const origin = gop.value_ptr.*;
|
||||
origin.rc += 1;
|
||||
@@ -320,7 +318,7 @@ pub fn scheduleNavigation(self: *Page, frame: *Frame) !void {
|
||||
}
|
||||
}
|
||||
|
||||
return list.append(self.session.arena, frame);
|
||||
return list.append(self.session.arena.allocator(), frame);
|
||||
}
|
||||
|
||||
pub fn findFrameByFrameId(self: *Page, frame_id: u32) ?*Frame {
|
||||
|
||||
@@ -79,7 +79,7 @@ pub fn waitForFrameCDP(self: *Runner, frame_id: u32, timeout_ms: u32, until: lp.
|
||||
pub fn waitForAll(self: *Runner, timeout_ms: u32, opts: WaitForFrameOpts) !void {
|
||||
const session = self.session;
|
||||
const arena = try session.getArena(.tiny, "Runner.waitForAll");
|
||||
defer session.releaseArena(arena);
|
||||
defer arena.release();
|
||||
|
||||
var pages_to_wait: usize = 0;
|
||||
for (session.pages.items) |page| {
|
||||
@@ -332,10 +332,10 @@ fn _tick(self: *Runner, comptime is_cdp: bool, timeout_ms: u32, conditions: []Wa
|
||||
pub fn waitForSelector(self: *Runner, frame_id: u32, input: [:0]const u8, timeout_ms: u32) !*Node.Element {
|
||||
const session = self.session;
|
||||
const arena = try session.getArena(.small, "Runner.waitForSelector");
|
||||
defer session.releaseArena(arena);
|
||||
defer arena.release();
|
||||
|
||||
const timer: std.Io.Timestamp = .now(lp.io, .boot);
|
||||
const selector = try Selector.parseLeaky(arena, input);
|
||||
const selector = try Selector.parseLeaky(arena.allocator(), input);
|
||||
|
||||
while (true) {
|
||||
if (session.isCancelled()) {
|
||||
|
||||
@@ -113,7 +113,7 @@ pub fn preloadScript(self: *ScriptManager, element: ?*Element.Html, url: []const
|
||||
|
||||
const frame = self.frame;
|
||||
const arena = try frame.getArena(.large, "SM.preloadScript");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const owned_url = try arena.dupeZ(u8, url);
|
||||
|
||||
@@ -242,10 +242,10 @@ pub fn addFromElement(self: *ScriptManager, comptime from_parser: bool, script_e
|
||||
|
||||
const arena = try frame.getArena(.large, "SM.addFromElement");
|
||||
errdefer if (handover == false) {
|
||||
frame.releaseArena(arena);
|
||||
arena.release();
|
||||
};
|
||||
|
||||
const remote_url = try URL.resolve(arena, base_url, src, .{ .encoding = frame.charset });
|
||||
const remote_url = try URL.resolve(arena.allocator(), base_url, src, .{ .encoding = frame.charset });
|
||||
script_element._executed = true;
|
||||
|
||||
const mode: Script.Extra.FrameExtra.Mode = blk: {
|
||||
@@ -304,7 +304,7 @@ pub fn addFromElement(self: *ScriptManager, comptime from_parser: bool, script_e
|
||||
// The adopted Script has its own arena; ours held only the URL
|
||||
// resolution, which nothing below needs.
|
||||
handover = true;
|
||||
frame.releaseArena(arena);
|
||||
arena.release();
|
||||
|
||||
if (pre.complete and mode == .async) {
|
||||
// The fetch already finished, so no doneCallback will move it
|
||||
@@ -354,7 +354,7 @@ pub fn addFromElement(self: *ScriptManager, comptime from_parser: bool, script_e
|
||||
script.status = pre.status;
|
||||
script.complete = true;
|
||||
} else {
|
||||
const response = try self.base.client.syncRequest(arena, .{
|
||||
const response = try self.base.client.syncRequest(arena.allocator(), .{
|
||||
.url = remote_url,
|
||||
.method = .GET,
|
||||
.frame_id = frame._frame_id,
|
||||
@@ -430,7 +430,7 @@ fn addInlineScript(self: *ScriptManager, script_element: *Element.Html.Script, k
|
||||
|
||||
const frame = self.frame;
|
||||
const arena = try frame.getArena(source_len + @sizeOf(Script) + 1, "SM.addInlineScript");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const source = blk: {
|
||||
const buf = try arena.alloc(u8, source_len + 1);
|
||||
@@ -627,7 +627,7 @@ test "ScriptManager: waitForPreload stops when teardown is pending" {
|
||||
.raw = try message_arena.dupe(u8, "{}"),
|
||||
.input = .{ .method = "Target.closeTarget" },
|
||||
} });
|
||||
defer client.inbox.pop().?.deinit(client.arena_pool);
|
||||
defer client.inbox.pop().?.deinit();
|
||||
|
||||
try testing.expect(sm.waitForPreload(url) == null);
|
||||
}
|
||||
@@ -185,14 +185,10 @@ pub fn getHeaders(self: *ScriptManagerBase) !http.Headers {
|
||||
return headers;
|
||||
}
|
||||
|
||||
fn acquireArena(self: *ScriptManagerBase, size_or_bucket: anytype, debug: []const u8) !Allocator {
|
||||
fn acquireArena(self: *ScriptManagerBase, size_or_bucket: anytype, debug: []const u8) !*lp.Arena {
|
||||
return self.owner.session().getArena(size_or_bucket, debug);
|
||||
}
|
||||
|
||||
fn releaseArena(self: *ScriptManagerBase, arena: Allocator) void {
|
||||
self.owner.session().releaseArena(arena);
|
||||
}
|
||||
|
||||
pub fn scriptList(self: *ScriptManagerBase, script: *const Script) *std.DoublyLinkedList {
|
||||
return switch (script.extra) {
|
||||
.import, .import_async => &self.async_scripts,
|
||||
@@ -239,7 +235,7 @@ pub fn preloadImport(self: *ScriptManagerBase, url: [:0]const u8, referrer: []co
|
||||
errdefer _ = self.imported_modules.remove(url);
|
||||
|
||||
const arena = try self.acquireArena(.large, "SM.preloadImport");
|
||||
errdefer self.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const script = try arena.create(Script);
|
||||
script.* = .{
|
||||
@@ -431,7 +427,7 @@ pub fn getAsyncImport(self: *ScriptManagerBase, url: [:0]const u8, cb: ImportAsy
|
||||
}
|
||||
|
||||
const arena = try self.acquireArena(.large, "SM.getAsyncImport");
|
||||
errdefer self.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const script = try arena.create(Script);
|
||||
script.* = .{
|
||||
@@ -614,7 +610,7 @@ pub const Script = struct {
|
||||
status: u16 = 0,
|
||||
source: Source,
|
||||
url: []const u8,
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
extra: Extra,
|
||||
node: std.DoublyLinkedList.Node,
|
||||
manager: *ScriptManagerBase,
|
||||
@@ -691,7 +687,7 @@ pub const Script = struct {
|
||||
};
|
||||
|
||||
pub fn deinit(self: *Script) void {
|
||||
self.manager.releaseArena(self.arena);
|
||||
self.arena.release();
|
||||
}
|
||||
|
||||
pub fn startCallback(transfer: *HttpClient.Transfer) !void {
|
||||
@@ -754,7 +750,7 @@ pub const Script = struct {
|
||||
lp.assert(self.source.remote.capacity == 0, "ScriptManagerBase.Header buffer", .{ .capacity = self.source.remote.capacity });
|
||||
var buffer: std.ArrayList(u8) = .empty;
|
||||
if (transfer.getContentLength()) |cl| {
|
||||
try buffer.ensureTotalCapacity(self.arena, cl);
|
||||
try buffer.ensureTotalCapacity(self.arena.allocator(), cl);
|
||||
}
|
||||
self.source = .{ .remote = buffer };
|
||||
return .proceed;
|
||||
@@ -769,7 +765,7 @@ pub const Script = struct {
|
||||
}
|
||||
|
||||
fn _dataCallback(self: *Script, _: *HttpClient.Transfer, data: []const u8) !void {
|
||||
try self.source.remote.appendSlice(self.arena, data);
|
||||
try self.source.remote.appendSlice(self.arena.allocator(), data);
|
||||
}
|
||||
|
||||
pub fn doneCallback(ctx: *anyopaque) !void {
|
||||
@@ -1148,7 +1144,7 @@ test "ScriptManagerBase: waitForImport stops when teardown is pending" {
|
||||
.raw = try message_arena.dupe(u8, "{}"),
|
||||
.input = .{ .method = "Target.disposeBrowserContext" },
|
||||
} });
|
||||
defer client.inbox.pop().?.deinit(client.arena_pool);
|
||||
defer client.inbox.pop().?.deinit();
|
||||
|
||||
try testing.expectError(error.SyncWaitInterrupted, sm.waitForImport(url));
|
||||
}
|
||||
+12
-17
@@ -39,7 +39,6 @@ const SharedWorkerGlobalScope = @import("webapi/SharedWorkerGlobalScope.zig");
|
||||
|
||||
const log = lp.log;
|
||||
const ArenaPool = App.ArenaPool;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const IS_DEBUG = builtin.mode == .Debug;
|
||||
|
||||
// A Session represents a browsing context group (cookie jar, session storage,
|
||||
@@ -50,7 +49,7 @@ const IS_DEBUG = builtin.mode == .Debug;
|
||||
const Session = @This();
|
||||
|
||||
browser: *Browser,
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
history: History,
|
||||
navigation: *Navigation,
|
||||
storage_shed: storage.Shed,
|
||||
@@ -161,9 +160,9 @@ pub fn init(self: *Session, browser: *Browser, notification: *Notification) !voi
|
||||
const arena_pool = browser.arena_pool;
|
||||
|
||||
const arena = try arena_pool.acquire(.small, "Session");
|
||||
errdefer arena_pool.release(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const navigation = try Factory.chainedWithAllocator(arena, .{
|
||||
const navigation = try Factory.chainedWithAllocator(arena.allocator(), .{
|
||||
EventTarget{ ._type = undefined },
|
||||
Navigation{ ._proto = undefined },
|
||||
});
|
||||
@@ -211,7 +210,7 @@ pub fn deinit(self: *Session) void {
|
||||
self.bridge_store.deinit(allocator);
|
||||
}
|
||||
self._console_messages.deinit();
|
||||
self.arena_pool.release(self.arena);
|
||||
self.arena.release();
|
||||
}
|
||||
|
||||
/// Register the console listener so `drainConsoleMessages` returns output. Idempotent.
|
||||
@@ -285,7 +284,7 @@ fn allocatePage(self: *Session, frame_id: u32) !*Page {
|
||||
|
||||
// Tear down and free a Page allocated via allocatePage.
|
||||
fn queuePageDestruction(self: *Session, page: *Page) void {
|
||||
self._page_destruction_queue.append(self.arena, page) catch @panic("OOM");
|
||||
self._page_destruction_queue.append(self.arena.allocator(), page) catch @panic("OOM");
|
||||
}
|
||||
|
||||
fn retire(self: *Session, page: *Page) void {
|
||||
@@ -348,7 +347,7 @@ fn installNewActivePage(self: *Session, frame_id: u32) !*Frame {
|
||||
const page = try self.allocatePage(frame_id);
|
||||
errdefer self.queuePageDestruction(page);
|
||||
|
||||
try self.pages.append(self.arena, page);
|
||||
try self.pages.append(self.arena.allocator(), page);
|
||||
errdefer _ = self.pages.pop();
|
||||
|
||||
const frame = &page.frame;
|
||||
@@ -390,7 +389,7 @@ pub fn closePage(self: *Session, frame_id: u32) void {
|
||||
// We queue then process so that there is a single place (processDestroyQueues)
|
||||
// where pages get destroyed.
|
||||
pub fn closeAllPages(self: *Session) void {
|
||||
self._page_destruction_queue.ensureUnusedCapacity(self.arena, self.pages.items.len) catch @panic("OOM");
|
||||
self._page_destruction_queue.ensureUnusedCapacity(self.arena.allocator(), self.pages.items.len) catch @panic("OOM");
|
||||
for (self.pages.items) |page| {
|
||||
page.frame.abortTransfers();
|
||||
self._page_destruction_queue.appendAssumeCapacity(page);
|
||||
@@ -399,14 +398,10 @@ pub fn closeAllPages(self: *Session) void {
|
||||
self.processDestroyQueues();
|
||||
}
|
||||
|
||||
pub fn getArena(self: *Session, size_or_bucket: anytype, debug: []const u8) !Allocator {
|
||||
pub fn getArena(self: *Session, size_or_bucket: anytype, debug: []const u8) !*lp.Arena {
|
||||
return self.arena_pool.acquire(size_or_bucket, debug);
|
||||
}
|
||||
|
||||
pub fn releaseArena(self: *Session, allocator: Allocator) void {
|
||||
self.arena_pool.release(allocator);
|
||||
}
|
||||
|
||||
// The live page for a top-level browsing context, by its root frame id.
|
||||
pub fn livePage(self: *Session, frame_id: u32) ?*Page {
|
||||
for (self.pages.items) |page| {
|
||||
@@ -594,7 +589,7 @@ fn processPageQueuedNavigation(self: *Session, page: *Page) !void {
|
||||
|
||||
if (qn.is_about_blank) {
|
||||
// Defer about:blank to second pass
|
||||
try about_blank_queue.append(self.arena, frame);
|
||||
try about_blank_queue.append(self.arena.allocator(), frame);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -643,7 +638,7 @@ fn processPageQueuedNavigation(self: *Session, page: *Page) !void {
|
||||
|
||||
fn processFrameNavigation(self: *Session, frame: *Frame, qn: *QueuedNavigation) !void {
|
||||
frame._queued_navigation = null;
|
||||
defer self.releaseArena(qn.arena);
|
||||
defer qn.arena.release();
|
||||
|
||||
// A popup whose window was close()'d is parked in page.closed_frames and
|
||||
// torn down at Page.deinit. It must never be navigated. This navigation
|
||||
@@ -782,7 +777,7 @@ fn processRootQueuedNavigation(self: *Session, page: *Page) !void {
|
||||
// The qn arena is consumed here regardless of success — frame.navigate
|
||||
// dupes the URL into the page's own arena, so we can release the qn
|
||||
// arena as soon as navigate returns.
|
||||
defer self.arena_pool.release(qn.arena);
|
||||
defer qn.arena.release();
|
||||
|
||||
if (is_synthetic) {
|
||||
return self.replaceRootImmediate(current_frame._frame_id, qn.url, qn.opts);
|
||||
@@ -844,7 +839,7 @@ pub fn initiateRootNavigation(self: *Session, frame_id: u32, url: [:0]const u8,
|
||||
live.replacement = page;
|
||||
|
||||
errdefer live.replacement = null;
|
||||
try self.pages.append(self.arena, page);
|
||||
try self.pages.append(self.arena.allocator(), page);
|
||||
errdefer _ = self.pages.pop();
|
||||
|
||||
if (comptime IS_DEBUG) {
|
||||
|
||||
@@ -53,7 +53,7 @@ const RuleList = std.MultiArrayList(VisibilityRule);
|
||||
|
||||
frame: *Frame,
|
||||
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
|
||||
// Bucketed rules for fast lookup - keyed by rightmost selector part
|
||||
id_rules: std.StringHashMapUnmanaged(RuleList) = .empty,
|
||||
@@ -89,7 +89,7 @@ pub fn init(frame: *Frame) !StyleManager {
|
||||
}
|
||||
|
||||
pub fn deinit(self: *StyleManager) void {
|
||||
self.frame.releaseArena(self.arena);
|
||||
self.arena.release();
|
||||
}
|
||||
|
||||
const IS_DEBUG = builtin.mode == .Debug;
|
||||
@@ -118,7 +118,7 @@ fn parseSheet(self: *StyleManager, build_arena: Allocator, sheet: *CSSStyleSheet
|
||||
|
||||
const owner_node = sheet.getOwnerNode() orelse return;
|
||||
if (owner_node.is(Element.Html.Style)) |style| {
|
||||
const text = try style.asNode().getTextContentAlloc(self.arena);
|
||||
const text = try style.asNode().getTextContentAlloc(self.arena.allocator());
|
||||
var it = CssParser.parseStylesheet(text);
|
||||
while (it.next()) |parsed_rule| {
|
||||
switch (parsed_rule) {
|
||||
@@ -475,7 +475,7 @@ fn addRawRule(self: *StyleManager, build_arena: Allocator, selector_text: []cons
|
||||
|
||||
if (!props.isRelevant()) return;
|
||||
|
||||
const selectors = SelectorParser.parseList(self.arena, selector_text) catch return;
|
||||
const selectors = SelectorParser.parseList(self.arena.allocator(), selector_text) catch return;
|
||||
for (selectors) |selector| {
|
||||
const rightmost = if (selector.segments.len > 0) selector.segments[selector.segments.len - 1].compound else selector.first;
|
||||
const bucket_key = getBucketKey(rightmost) orelse continue;
|
||||
@@ -489,22 +489,22 @@ fn addRawRule(self: *StyleManager, build_arena: Allocator, selector_text: []cons
|
||||
|
||||
switch (bucket_key) {
|
||||
.id => |id| {
|
||||
const gop = try self.id_rules.getOrPut(self.arena, id);
|
||||
const gop = try self.id_rules.getOrPut(self.arena.allocator(), id);
|
||||
if (!gop.found_existing) gop.value_ptr.* = .{};
|
||||
try gop.value_ptr.append(self.arena, rule);
|
||||
try gop.value_ptr.append(self.arena.allocator(), rule);
|
||||
},
|
||||
.class => |class| {
|
||||
const gop = try self.class_rules.getOrPut(self.arena, class);
|
||||
const gop = try self.class_rules.getOrPut(self.arena.allocator(), class);
|
||||
if (!gop.found_existing) gop.value_ptr.* = .{};
|
||||
try gop.value_ptr.append(self.arena, rule);
|
||||
try gop.value_ptr.append(self.arena.allocator(), rule);
|
||||
},
|
||||
.tag => |tag| {
|
||||
const gop = try self.tag_rules.getOrPut(self.arena, tag);
|
||||
const gop = try self.tag_rules.getOrPut(self.arena.allocator(), tag);
|
||||
if (!gop.found_existing) gop.value_ptr.* = .{};
|
||||
try gop.value_ptr.append(self.arena, rule);
|
||||
try gop.value_ptr.append(self.arena.allocator(), rule);
|
||||
},
|
||||
.other => {
|
||||
try self.other_rules.append(self.arena, rule);
|
||||
try self.other_rules.append(self.arena.allocator(), rule);
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -536,7 +536,7 @@ fn rebuildIfDirty(self: *StyleManager) !void {
|
||||
self.layer_ids = .empty;
|
||||
self.next_anon_layer = 0;
|
||||
self.rule_layers = .empty;
|
||||
self.frame.releaseArena(build_arena);
|
||||
build_arena.release();
|
||||
}
|
||||
|
||||
self.dirty = false;
|
||||
@@ -546,31 +546,31 @@ fn rebuildIfDirty(self: *StyleManager) !void {
|
||||
const tag_rules_count = self.tag_rules.count();
|
||||
const other_rules_count = self.other_rules.len;
|
||||
|
||||
self.frame._session.arena_pool.resetRetain(self.arena);
|
||||
self.arena.resetRetain();
|
||||
|
||||
self.next_doc_order = 1;
|
||||
|
||||
self.id_rules = .empty;
|
||||
try self.id_rules.ensureTotalCapacity(self.arena, id_rules_count);
|
||||
try self.id_rules.ensureTotalCapacity(self.arena.allocator(), id_rules_count);
|
||||
|
||||
self.class_rules = .empty;
|
||||
try self.class_rules.ensureTotalCapacity(self.arena, class_rules_count);
|
||||
try self.class_rules.ensureTotalCapacity(self.arena.allocator(), class_rules_count);
|
||||
|
||||
self.tag_rules = .empty;
|
||||
try self.tag_rules.ensureTotalCapacity(self.arena, tag_rules_count);
|
||||
try self.tag_rules.ensureTotalCapacity(self.arena.allocator(), tag_rules_count);
|
||||
|
||||
self.other_rules = .{};
|
||||
try self.other_rules.ensureTotalCapacity(self.arena, other_rules_count);
|
||||
try self.other_rules.ensureTotalCapacity(self.arena.allocator(), other_rules_count);
|
||||
|
||||
const sheets = self.frame.document._style_sheets orelse return;
|
||||
for (sheets._sheets.items) |sheet| {
|
||||
self.parseSheet(build_arena, sheet) catch |err| {
|
||||
self.parseSheet(build_arena.allocator(), sheet) catch |err| {
|
||||
log.err(.browser, "StyleManager parseSheet", .{ .err = err });
|
||||
return err;
|
||||
};
|
||||
}
|
||||
|
||||
try self.finalizeLayerRanks(build_arena);
|
||||
try self.finalizeLayerRanks(build_arena.allocator());
|
||||
}
|
||||
|
||||
// Check if an element is hidden based on options.
|
||||
@@ -946,7 +946,7 @@ fn addRule(self: *StyleManager, build_arena: Allocator, style_rule: *CSSStyleRul
|
||||
}
|
||||
|
||||
// Parse the selector list
|
||||
const selectors = SelectorParser.parseList(self.arena, selector_text) catch return;
|
||||
const selectors = SelectorParser.parseList(self.arena.allocator(), selector_text) catch return;
|
||||
if (selectors.len == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -974,22 +974,22 @@ fn addRule(self: *StyleManager, build_arena: Allocator, style_rule: *CSSStyleRul
|
||||
// Add to appropriate bucket
|
||||
switch (bucket_key) {
|
||||
.id => |id| {
|
||||
const gop = try self.id_rules.getOrPut(self.arena, id);
|
||||
const gop = try self.id_rules.getOrPut(self.arena.allocator(), id);
|
||||
if (!gop.found_existing) gop.value_ptr.* = .{};
|
||||
try gop.value_ptr.append(self.arena, rule);
|
||||
try gop.value_ptr.append(self.arena.allocator(), rule);
|
||||
},
|
||||
.class => |class| {
|
||||
const gop = try self.class_rules.getOrPut(self.arena, class);
|
||||
const gop = try self.class_rules.getOrPut(self.arena.allocator(), class);
|
||||
if (!gop.found_existing) gop.value_ptr.* = .{};
|
||||
try gop.value_ptr.append(self.arena, rule);
|
||||
try gop.value_ptr.append(self.arena.allocator(), rule);
|
||||
},
|
||||
.tag => |tag| {
|
||||
const gop = try self.tag_rules.getOrPut(self.arena, tag);
|
||||
const gop = try self.tag_rules.getOrPut(self.arena.allocator(), tag);
|
||||
if (!gop.found_existing) gop.value_ptr.* = .{};
|
||||
try gop.value_ptr.append(self.arena, rule);
|
||||
try gop.value_ptr.append(self.arena.allocator(), rule);
|
||||
},
|
||||
.other => {
|
||||
try self.other_rules.append(self.arena, rule);
|
||||
try self.other_rules.append(self.arena.allocator(), rule);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ fn htmlAsChildrenInner(frame: *Frame, node: *Node, html: []const u8, opts: Fragm
|
||||
// XML.
|
||||
pub fn xmlDocument(frame: *Frame, xml: []const u8) !?*Document.XMLDocument {
|
||||
const arena = try frame.getArena(.medium, "parse.xmlDocument");
|
||||
defer frame.releaseArena(arena);
|
||||
defer arena.release();
|
||||
|
||||
const previous_parse_mode = frame._parse_mode;
|
||||
frame._parse_mode = .fragment;
|
||||
@@ -111,7 +111,7 @@ pub fn xmlDocument(frame: *Frame, xml: []const u8) !?*Document.XMLDocument {
|
||||
|
||||
const doc = try frame._factory.document(Document.XMLDocument{ ._proto = undefined });
|
||||
const doc_node = doc.asNode();
|
||||
var parser = Parser.init(arena, doc_node, frame, .{});
|
||||
var parser = Parser.init(arena.allocator(), doc_node, frame, .{});
|
||||
parser.parseXML(xml);
|
||||
if (parser.terminated) {
|
||||
return error.ExecutionTerminated;
|
||||
|
||||
@@ -38,9 +38,9 @@ pub fn scriptHint(frame: *Frame, element: ?*Element.Html, href: []const u8) bool
|
||||
}
|
||||
|
||||
const arena = frame.getArena(.small, "preload.scriptHint") catch return false;
|
||||
defer frame.releaseArena(arena);
|
||||
defer arena.release();
|
||||
|
||||
const resolved = URL.resolve(arena, frame.base(), href, .{ .encoding = frame.charset }) catch return false;
|
||||
const resolved = URL.resolve(arena.allocator(), frame.base(), href, .{ .encoding = frame.charset }) catch return false;
|
||||
if (!isRemoteScheme(resolved)) {
|
||||
return false;
|
||||
}
|
||||
@@ -79,9 +79,9 @@ pub fn prescan(frame: *Frame, html: []const u8) void {
|
||||
return;
|
||||
}
|
||||
const arena = frame.getArena(.small, "preload.prescan") catch return;
|
||||
defer frame.releaseArena(arena);
|
||||
defer arena.release();
|
||||
|
||||
var scan = Prescan{ .frame = frame, .base = frame.base(), .arena = arena };
|
||||
var scan = Prescan{ .frame = frame, .base = frame.base(), .arena = arena.allocator() };
|
||||
Parser.prescan(html, frame.charset, &scan, Prescan.callback);
|
||||
}
|
||||
|
||||
|
||||
@@ -274,7 +274,7 @@ pub fn findClickActivationTarget(target: *Node, bubbles: bool) ?*Node {
|
||||
|
||||
fn runJavascriptUrl(frame: *Frame, source: []const u8) !void {
|
||||
const arena = try frame.getArena(.tiny, "javascript-url");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const task = try arena.create(JavascriptUrlTask);
|
||||
task.* = .{
|
||||
@@ -292,7 +292,7 @@ fn runJavascriptUrl(frame: *Frame, source: []const u8) !void {
|
||||
|
||||
const JavascriptUrlTask = struct {
|
||||
frame: *Frame,
|
||||
arena: std.mem.Allocator,
|
||||
arena: *lp.Arena,
|
||||
source: []const u8,
|
||||
|
||||
fn run(ptr: *anyopaque) !?u32 {
|
||||
@@ -320,7 +320,7 @@ const JavascriptUrlTask = struct {
|
||||
}
|
||||
|
||||
fn deinit(self: *JavascriptUrlTask) void {
|
||||
self.frame.releaseArena(self.arena);
|
||||
self.arena.release();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ heap_profiler: ?*v8.HeapProfiler = null,
|
||||
templates: []*const v8.FunctionTemplate,
|
||||
|
||||
// Arena for the lifetime of the context
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
|
||||
// The call_arena for this context. For main world contexts this is
|
||||
// frame.call_arena. For isolated world contexts this is a separate arena
|
||||
@@ -205,7 +205,7 @@ pub fn deinit(self: *Context) void {
|
||||
}
|
||||
|
||||
const env = self.env;
|
||||
defer env.app.arena_pool.release(self.arena);
|
||||
defer self.arena.release();
|
||||
|
||||
// Unlink any IndexedDB gate participants first: the session-scoped engine
|
||||
// must never wake a waiter into this scheduler once it's torn down.
|
||||
@@ -353,7 +353,7 @@ pub fn module(self: *Context, comptime want_result: bool, local: *const js.Local
|
||||
// gop will _always_ initiated if cacheable == true
|
||||
var gop: std.StringHashMapUnmanaged(ModuleEntry).GetOrPutResult = undefined;
|
||||
if (cacheable) {
|
||||
gop = try self.module_cache.getOrPut(arena, url);
|
||||
gop = try self.module_cache.getOrPut(arena.allocator(), url);
|
||||
if (gop.found_existing) {
|
||||
if (gop.value_ptr.module) |cache_mod| {
|
||||
if (gop.value_ptr.module_promise == null) {
|
||||
@@ -514,7 +514,7 @@ fn compileModule(local: *const js.Local, src: []const u8, name: []const u8) !js.
|
||||
// we always want to track its identity (so that, if this module imports other
|
||||
// modules, we can resolve the full URL), and preload any dependent modules.
|
||||
fn postCompileModule(self: *Context, mod: js.Module, url: [:0]const u8, local: *const js.Local) !void {
|
||||
try self.module_identifier.putNoClobber(self.arena, mod.getIdentityHash(), url);
|
||||
try self.module_identifier.putNoClobber(self.arena.allocator(), mod.getIdentityHash(), url);
|
||||
|
||||
// Non-async modules are blocking. We can download them in parallel, but
|
||||
// they need to be processed serially. So we want to get the list of
|
||||
@@ -534,7 +534,7 @@ fn postCompileModule(self: *Context, mod: js.Module, url: [:0]const u8, local: *
|
||||
return err;
|
||||
},
|
||||
};
|
||||
const nested_gop = try self.module_cache.getOrPut(self.arena, normalized_specifier);
|
||||
const nested_gop = try self.module_cache.getOrPut(self.arena.allocator(), normalized_specifier);
|
||||
if (!nested_gop.found_existing) {
|
||||
const owned_specifier = try self.arena.dupeZ(u8, normalized_specifier);
|
||||
nested_gop.key_ptr.* = owned_specifier;
|
||||
@@ -636,7 +636,7 @@ pub fn dynamicModuleCallback(
|
||||
};
|
||||
|
||||
const normalized_specifier = self.script_manager.resolveSpecifier(
|
||||
self.arena, // might need to survive until the module is loaded
|
||||
self.arena.allocator(), // might need to survive until the module is loaded
|
||||
resource,
|
||||
specifier,
|
||||
) catch |err| switch (err) {
|
||||
@@ -749,7 +749,7 @@ fn _resolveModuleCallback(self: *Context, referrer: js.Module, specifier: [:0]co
|
||||
};
|
||||
|
||||
const normalized_specifier = try self.script_manager.resolveSpecifier(
|
||||
self.arena,
|
||||
self.arena.allocator(),
|
||||
referrer_path,
|
||||
specifier,
|
||||
);
|
||||
@@ -804,7 +804,7 @@ const DynamicModuleResolveState = struct {
|
||||
};
|
||||
|
||||
fn _dynamicModuleCallback(self: *Context, specifier: [:0]const u8, referrer: []const u8, local: *const js.Local) !js.Promise {
|
||||
const gop = try self.module_cache.getOrPut(self.arena, specifier);
|
||||
const gop = try self.module_cache.getOrPut(self.arena.allocator(), specifier);
|
||||
if (gop.found_existing) {
|
||||
if (gop.value_ptr.resolver_promise) |rp| {
|
||||
return local.toLocal(rp);
|
||||
|
||||
@@ -255,7 +255,7 @@ fn _createContext(self: *Env, global: anytype, params: ContextParams) !*Context
|
||||
const is_frame = T == *Frame;
|
||||
|
||||
const context_arena = try self.app.arena_pool.acquire(.medium, params.debug_name);
|
||||
errdefer self.app.arena_pool.release(context_arena);
|
||||
errdefer context_arena.release();
|
||||
|
||||
const isolate = self.isolate;
|
||||
var hs: js.HandleScope = undefined;
|
||||
@@ -340,7 +340,7 @@ fn _createContext(self: *Env, global: anytype, params: ContextParams) !*Context
|
||||
.local_arena = params.local_arena,
|
||||
.microtask_queue = microtask_queue,
|
||||
.script_manager = if (comptime is_frame) &global._script_manager.base else &global._script_manager,
|
||||
.scheduler = .init(context_arena),
|
||||
.scheduler = .init(context_arena.allocator()),
|
||||
.identity = params.identity,
|
||||
.identity_arena = params.identity_arena,
|
||||
.execution = undefined,
|
||||
|
||||
@@ -76,14 +76,10 @@ pub fn dupeString(self: *const Execution, value: []const u8) ![]const u8 {
|
||||
return self.arena.dupe(u8, value);
|
||||
}
|
||||
|
||||
pub fn getArena(self: *const Execution, size_or_bucket: anytype, debug: []const u8) !Allocator {
|
||||
pub fn getArena(self: *const Execution, size_or_bucket: anytype, debug: []const u8) !*lp.Arena {
|
||||
return self.page.getArena(size_or_bucket, debug);
|
||||
}
|
||||
|
||||
pub fn releaseArena(self: *const Execution, allocator: Allocator) void {
|
||||
self.page.releaseArena(allocator);
|
||||
}
|
||||
|
||||
pub fn headersForRequest(self: *const Execution, headers: *HttpClient.Headers) !void {
|
||||
return switch (self.js.global) {
|
||||
inline else => |g| g.headersForRequest(headers),
|
||||
|
||||
@@ -91,7 +91,7 @@ pub fn persist(self: Module) !Global {
|
||||
var ctx = self.local.ctx;
|
||||
var global: v8.Global = undefined;
|
||||
v8.v8__Global__New(ctx.isolate.handle, self.handle, &global);
|
||||
try ctx.global_modules.append(ctx.arena, global);
|
||||
try ctx.global_modules.append(ctx.arena.allocator(), global);
|
||||
return .{ .handle = global };
|
||||
}
|
||||
|
||||
|
||||
@@ -24,18 +24,17 @@
|
||||
// separately via js.Identity - Session has the main world Identity, and
|
||||
// IsolatedWorlds have their own Identity instances.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
const js = @import("js.zig");
|
||||
|
||||
const App = @import("../../App.zig");
|
||||
|
||||
const v8 = js.v8;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const Origin = @This();
|
||||
|
||||
rc: usize = 1,
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
|
||||
// The key, e.g. lightpanda.io:443
|
||||
key: []const u8,
|
||||
@@ -46,7 +45,7 @@ security_token: v8.Global,
|
||||
|
||||
pub fn init(app: *App, isolate: js.Isolate, key: []const u8) !*Origin {
|
||||
const arena = try app.arena_pool.acquire(.tiny, "Origin");
|
||||
errdefer app.arena_pool.release(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
var hs: js.HandleScope = undefined;
|
||||
hs.init(isolate);
|
||||
@@ -67,7 +66,7 @@ pub fn init(app: *App, isolate: js.Isolate, key: []const u8) !*Origin {
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Origin, app: *App) void {
|
||||
pub fn deinit(self: *Origin, _: *App) void {
|
||||
v8.v8__Global__Reset(&self.security_token);
|
||||
app.arena_pool.release(self.arena);
|
||||
self.arena.release();
|
||||
}
|
||||
@@ -601,7 +601,7 @@ const CloneDelegate = struct {
|
||||
const handle = message orelse break :blk null;
|
||||
const str = js.String{ .local = local, .handle = handle };
|
||||
// the exception can outlive this call; dupe onto the context arena
|
||||
break :blk str.toSliceWithAlloc(local.ctx.arena) catch null;
|
||||
break :blk str.toSliceWithAlloc(local.ctx.arena.allocator()) catch null;
|
||||
};
|
||||
throwDataCloneException(local, msg);
|
||||
}
|
||||
|
||||
@@ -782,7 +782,7 @@ pub fn unknownObjectPropertyCallback(comptime JsApi: type) *const fn (?*const v8
|
||||
|
||||
fn logUnknownProperty(local: *const js.Local, key: []const u8) !void {
|
||||
const ctx = local.ctx;
|
||||
const gop = try ctx.unknown_properties.getOrPut(ctx.arena, key);
|
||||
const gop = try ctx.unknown_properties.getOrPut(ctx.arena.allocator(), key);
|
||||
if (gop.found_existing) {
|
||||
gop.value_ptr.count += 1;
|
||||
} else {
|
||||
|
||||
@@ -26,15 +26,13 @@ const Node = @import("Node.zig");
|
||||
const Range = @import("Range.zig");
|
||||
const StaticRange = @import("StaticRange.zig");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const AbstractRange = @This();
|
||||
|
||||
pub const _prototype_root = true;
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_type: Type,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_end_offset: u32,
|
||||
_start_offset: u32,
|
||||
_frame_loader_id: u32,
|
||||
@@ -55,7 +53,7 @@ pub fn deinit(self: *AbstractRange, page: *Page) void {
|
||||
frame._live_ranges.remove(&self._range_link);
|
||||
}
|
||||
}
|
||||
page.releaseArena(self._arena);
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *AbstractRange, page: *Page) void {
|
||||
|
||||
+11
-12
@@ -26,7 +26,6 @@ const Mime = @import("../Mime.zig");
|
||||
|
||||
const Writer = std.Io.Writer;
|
||||
const Execution = js.Execution;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
/// https://w3c.github.io/FileAPI/#blob-section
|
||||
/// https://developer.mozilla.org/en-US/docs/Web/API/Blob
|
||||
@@ -37,7 +36,7 @@ pub const _prototype_root = true;
|
||||
_type: Type,
|
||||
_rc: lp.RC,
|
||||
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
|
||||
/// Immutable slice of blob.
|
||||
/// Note that another blob may hold a pointer/slice to this,
|
||||
@@ -82,7 +81,7 @@ const InitOptions = struct {
|
||||
pub fn init(parts_: ?[]const js.Value, opts_: ?InitOptions, page: *Page) !*Blob {
|
||||
const session = page.session;
|
||||
const arena = try session.getArena(.large, "Blob");
|
||||
errdefer session.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const self = try arena.create(Blob);
|
||||
self.* = try buildValue(arena, parts_, opts_ orelse .{});
|
||||
@@ -92,13 +91,13 @@ pub fn init(parts_: ?[]const js.Value, opts_: ?InitOptions, page: *Page) !*Blob
|
||||
// The Blob value for `parts`, with everything it references copied to
|
||||
// `arena`. Callers either arena.create it (init) or embed it as the root of
|
||||
// a {Blob, File} chain.
|
||||
pub fn buildValue(arena: Allocator, parts_: ?[]const js.Value, opts: InitOptions) !Blob {
|
||||
const mime = try Mime.serialize(arena, opts.type);
|
||||
pub fn buildValue(arena: *lp.Arena, parts_: ?[]const js.Value, opts: InitOptions) !Blob {
|
||||
const mime = try Mime.serialize(arena.allocator(), opts.type);
|
||||
|
||||
const data = blk: {
|
||||
if (parts_) |blob_parts| {
|
||||
const use_native_endings = std.mem.eql(u8, opts.endings, "native");
|
||||
var w: Writer.Allocating = .init(arena);
|
||||
var w: Writer.Allocating = .init(arena.allocator());
|
||||
for (blob_parts) |js_val| {
|
||||
const part = try js_val.toStringSmart();
|
||||
try writePartWithEndings(part, use_native_endings, &w.writer);
|
||||
@@ -118,28 +117,28 @@ pub fn buildValue(arena: Allocator, parts_: ?[]const js.Value, opts: InitOptions
|
||||
};
|
||||
}
|
||||
|
||||
pub fn buildValueFromBytes(arena: Allocator, data: []const u8, content_type: []const u8) !Blob {
|
||||
pub fn buildValueFromBytes(arena: *lp.Arena, data: []const u8, content_type: []const u8) !Blob {
|
||||
return .{
|
||||
._rc = .{},
|
||||
._arena = arena,
|
||||
._type = .generic,
|
||||
._slice = try arena.dupe(u8, data),
|
||||
._mime = try Mime.serialize(arena, content_type),
|
||||
._mime = try Mime.serialize(arena.allocator(), content_type),
|
||||
};
|
||||
}
|
||||
|
||||
/// Creates a new Blob from raw byte slices (for internal Zig use).
|
||||
pub fn initFromBytes(data: []const u8, content_type: []const u8, page: *Page) !*Blob {
|
||||
const arena = try page.getArena(data.len + content_type.len + 256, "Blob");
|
||||
errdefer page.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const self = try arena.create(Blob);
|
||||
self.* = try buildValueFromBytes(arena, data, content_type);
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Blob, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *Blob, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *Blob, page: *Page) void {
|
||||
@@ -160,7 +159,7 @@ pub fn structuredDeserialize(reader: *js.StructuredReader, page: *Page) !*Blob {
|
||||
const data = try reader.readBytes();
|
||||
|
||||
const arena = try page.getArena(data.len + mime.len + 256, "Blob.clone");
|
||||
errdefer page.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const self = try arena.create(Blob);
|
||||
self.* = .{
|
||||
|
||||
@@ -174,12 +174,12 @@ const PostMessageCallback = struct {
|
||||
// (never realloc) and teardown is deferred to the next tick, so walking
|
||||
// each channel list live during dispatch is safe.
|
||||
const arena = try page.getArena(.tiny, "BroadcastChannel.postMessage");
|
||||
defer page.releaseArena(arena);
|
||||
defer arena.release();
|
||||
|
||||
// Opaque origins have no string form and are unique per execution, so
|
||||
// the sender is the only same-origin context
|
||||
const executions = if (origin) |o|
|
||||
try page.executionsForOrigin(arena, o)
|
||||
try page.executionsForOrigin(arena.allocator(), o)
|
||||
else
|
||||
(&self.exec)[0..1];
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
const crypto = @import("../../sys/libcrypto.zig");
|
||||
|
||||
@@ -24,14 +23,13 @@ const js = @import("../js/js.zig");
|
||||
const Page = @import("../Page.zig");
|
||||
|
||||
const Execution = js.Execution;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
/// Represents a cryptographic key obtained from one of the SubtleCrypto methods
|
||||
/// generateKey(), deriveKey(), importKey(), or unwrapKey().
|
||||
const CryptoKey = @This();
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_arena: Allocator = undefined,
|
||||
_arena: *lp.Arena = undefined,
|
||||
/// Algorithm being used.
|
||||
_type: Type,
|
||||
/// Whether this is a secret (symmetric), public, or private key. Surfaced as
|
||||
@@ -105,7 +103,7 @@ pub const Usages = struct {
|
||||
/// are expected to be static strings. Takes ownership of `_vary.pkey`.
|
||||
pub fn init(exec: *const Execution, key: CryptoKey) !*CryptoKey {
|
||||
const arena = try exec.getArena(.tiny, "CryptoKey");
|
||||
errdefer exec.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const self = try arena.create(CryptoKey);
|
||||
self.* = key;
|
||||
@@ -117,12 +115,12 @@ pub fn init(exec: *const Execution, key: CryptoKey) !*CryptoKey {
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *CryptoKey, page: *Page) void {
|
||||
pub fn deinit(self: *CryptoKey, _: *Page) void {
|
||||
switch (self._vary) {
|
||||
.pkey => |pkey| crypto.EVP_PKEY_free(pkey),
|
||||
.none, .digest => {},
|
||||
}
|
||||
page.releaseArena(self._arena);
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *CryptoKey, page: *Page) void {
|
||||
|
||||
@@ -36,9 +36,9 @@ pub fn init(init_: ?js.Value, exec: *const js.Execution) !*DOMMatrix {
|
||||
|
||||
pub fn create(m: [16]f64, is_2d: bool, page: *Page) !*DOMMatrix {
|
||||
const arena = try page.getArena(.tiny, "DOMMatrix");
|
||||
errdefer page.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const self = try Factory.chainedWithAllocator(arena, .{
|
||||
const self = try Factory.chainedWithAllocator(arena.allocator(), .{
|
||||
RO.buildValue(arena, m, is_2d),
|
||||
DOMMatrix{ ._proto = undefined },
|
||||
});
|
||||
|
||||
@@ -23,15 +23,13 @@ const js = @import("../js/js.zig");
|
||||
const Page = @import("../Page.zig");
|
||||
const DOMMatrix = @import("DOMMatrix.zig");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const DOMMatrixReadOnly = @This();
|
||||
|
||||
pub const _prototype_root = true;
|
||||
|
||||
_type: Type,
|
||||
_rc: lp.RC,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
|
||||
// Stored column-major, matching the spec's mAB naming where A is the column
|
||||
// and B is the row:
|
||||
@@ -68,8 +66,8 @@ pub fn init(init_: ?js.Value, exec: *const js.Execution) !*DOMMatrixReadOnly {
|
||||
return createBare(parsed.m, parsed.is_2d, exec.page);
|
||||
}
|
||||
|
||||
pub fn deinit(self: *DOMMatrixReadOnly, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *DOMMatrixReadOnly, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn acquireRef(self: *DOMMatrixReadOnly) void {
|
||||
@@ -82,14 +80,14 @@ pub fn releaseRef(self: *DOMMatrixReadOnly, page: *Page) void {
|
||||
|
||||
pub fn createBare(m: [16]f64, is_2d: bool, page: *Page) !*DOMMatrixReadOnly {
|
||||
const arena = try page.getArena(.tiny, "DOMMatrix");
|
||||
errdefer page.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const self = try arena.create(DOMMatrixReadOnly);
|
||||
self.* = buildValue(arena, m, is_2d);
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn buildValue(arena: std.mem.Allocator, m: [16]f64, is_2d: bool) DOMMatrixReadOnly {
|
||||
pub fn buildValue(arena: *lp.Arena, m: [16]f64, is_2d: bool) DOMMatrixReadOnly {
|
||||
return .{
|
||||
._rc = .{},
|
||||
._arena = arena,
|
||||
|
||||
@@ -52,7 +52,7 @@ pub fn parseFromString(
|
||||
return switch (target_mime) {
|
||||
.@"text/html" => {
|
||||
const arena = try frame.getArena(.medium, "DOMParser.parseFromString");
|
||||
defer frame.releaseArena(arena);
|
||||
defer arena.release();
|
||||
|
||||
// DOMParser builds a detached Document. Borrow the same fragment
|
||||
// parse-mode that `Frame.parse` uses so frame-side hooks
|
||||
@@ -76,7 +76,7 @@ pub fn parseFromString(
|
||||
}
|
||||
|
||||
// Parse HTML into the document
|
||||
var parser = Parser.init(arena, doc.asNode(), frame, .{});
|
||||
var parser = Parser.init(arena.allocator(), doc.asNode(), frame, .{});
|
||||
parser.parse(normalized);
|
||||
if (parser.terminated) {
|
||||
return error.ExecutionTerminated;
|
||||
|
||||
@@ -33,9 +33,9 @@ pub fn init(x_: ?f64, y_: ?f64, z_: ?f64, w_: ?f64, exec: *const js.Execution) !
|
||||
|
||||
pub fn create(x: f64, y: f64, z: f64, w: f64, page: *Page) !*DOMPoint {
|
||||
const arena = try page.getArena(.tiny, "DOMPoint");
|
||||
errdefer page.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const self = try Factory.chainedWithAllocator(arena, .{
|
||||
const self = try Factory.chainedWithAllocator(arena.allocator(), .{
|
||||
RO.buildValue(arena, x, y, z, w),
|
||||
DOMPoint{ ._proto = undefined },
|
||||
});
|
||||
|
||||
@@ -24,15 +24,13 @@ const Page = @import("../Page.zig");
|
||||
const DOMPoint = @import("DOMPoint.zig");
|
||||
const Matrix = @import("DOMMatrixReadOnly.zig");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const DOMPointReadOnly = @This();
|
||||
|
||||
pub const _prototype_root = true;
|
||||
|
||||
_type: Type,
|
||||
_rc: lp.RC,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
|
||||
_x: f64,
|
||||
_y: f64,
|
||||
@@ -72,8 +70,8 @@ pub fn init(x_: ?f64, y_: ?f64, z_: ?f64, w_: ?f64, exec: *const js.Execution) !
|
||||
return createBare(x_ orelse 0, y_ orelse 0, z_ orelse 0, w_ orelse 1, exec.page);
|
||||
}
|
||||
|
||||
pub fn deinit(self: *DOMPointReadOnly, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *DOMPointReadOnly, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn acquireRef(self: *DOMPointReadOnly) void {
|
||||
@@ -86,14 +84,14 @@ pub fn releaseRef(self: *DOMPointReadOnly, page: *Page) void {
|
||||
|
||||
pub fn createBare(x: f64, y: f64, z: f64, w: f64, page: *Page) !*DOMPointReadOnly {
|
||||
const arena = try page.getArena(.tiny, "DOMPoint");
|
||||
errdefer page.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const self = try arena.create(DOMPointReadOnly);
|
||||
self.* = buildValue(arena, x, y, z, w);
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn buildValue(arena: Allocator, x: f64, y: f64, z: f64, w: f64) DOMPointReadOnly {
|
||||
pub fn buildValue(arena: *lp.Arena, x: f64, y: f64, z: f64, w: f64) DOMPointReadOnly {
|
||||
return .{
|
||||
._rc = .{},
|
||||
._arena = arena,
|
||||
|
||||
@@ -47,7 +47,7 @@ pub fn registerTypes() []const type {
|
||||
};
|
||||
}
|
||||
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
// Refcounted so the GC weak-finalizer (or page teardown) releases the pooled
|
||||
// arena exactly once; mirrors Blob's lifecycle.
|
||||
_rc: lp.RC = .{},
|
||||
@@ -61,7 +61,7 @@ _effect_allowed: []const u8 = "uninitialized",
|
||||
|
||||
pub fn init(frame: *Frame) !*DataTransfer {
|
||||
const arena = try frame.getArena(.medium, "DataTransfer");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const fl = try frame._factory.create(FileList{});
|
||||
try frame.trackFileList(fl);
|
||||
@@ -77,8 +77,8 @@ pub fn init(frame: *Frame) !*DataTransfer {
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *DataTransfer, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *DataTransfer, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn acquireRef(self: *DataTransfer) void {
|
||||
@@ -112,7 +112,7 @@ pub fn getData(self: *const DataTransfer, format: []const u8, frame: *Frame) ![]
|
||||
}
|
||||
|
||||
pub fn setData(self: *DataTransfer, format: []const u8, data: []const u8) !void {
|
||||
const norm = try normalizeFormat(self._arena, format);
|
||||
const norm = try normalizeFormat(self._arena.allocator(), format);
|
||||
const owned_data = try self._arena.dupe(u8, data);
|
||||
for (self._items.items) |it| {
|
||||
if (it._kind == .string and std.mem.eql(u8, it._type, norm)) {
|
||||
@@ -122,7 +122,7 @@ pub fn setData(self: *DataTransfer, format: []const u8, data: []const u8) !void
|
||||
}
|
||||
const it = try self._arena.create(DataTransferItem);
|
||||
it.* = .{ ._data_transfer = self, ._kind = .string, ._type = norm, ._payload = .{ .string = owned_data } };
|
||||
try self._items.append(self._arena, it);
|
||||
try self._items.append(self._arena.allocator(), it);
|
||||
}
|
||||
|
||||
pub fn clearData(self: *DataTransfer, format_: ?[]const u8, frame: *Frame) !void {
|
||||
@@ -158,11 +158,11 @@ pub fn addItem(self: *DataTransfer, data: js.Value, type_: ?[]const u8, frame: *
|
||||
return try self.addFileItem(file, frame);
|
||||
} else |_| {}
|
||||
|
||||
const owned_data = try data.toStringSliceWithAlloc(self._arena);
|
||||
const norm = try normalizeFormat(self._arena, type_ orelse "");
|
||||
const owned_data = try data.toStringSliceWithAlloc(self._arena.allocator());
|
||||
const norm = try normalizeFormat(self._arena.allocator(), type_ orelse "");
|
||||
const it = try self._arena.create(DataTransferItem);
|
||||
it.* = .{ ._data_transfer = self, ._kind = .string, ._type = norm, ._payload = .{ .string = owned_data } };
|
||||
try self._items.append(self._arena, it);
|
||||
try self._items.append(self._arena.allocator(), it);
|
||||
return it;
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ fn addFileItem(self: *DataTransfer, file: *File, frame: *Frame) !*DataTransferIt
|
||||
file._proto.acquireRef();
|
||||
const it = try self._arena.create(DataTransferItem);
|
||||
it.* = .{ ._data_transfer = self, ._kind = .file, ._type = file._proto.getType(), ._payload = .{ .file = file } };
|
||||
try self._items.append(self._arena, it);
|
||||
try self._items.append(self._arena.allocator(), it);
|
||||
try self.rebuildFiles(frame);
|
||||
return it;
|
||||
}
|
||||
|
||||
@@ -33,8 +33,6 @@ const WorkerGlobalScope = @import("WorkerGlobalScope.zig");
|
||||
|
||||
const MessageEvent = @import("event/MessageEvent.zig");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const DedicatedWorkerGlobalScope = @This();
|
||||
|
||||
pub const Proto = WorkerGlobalScope;
|
||||
@@ -54,7 +52,7 @@ _pending_messages: std.ArrayList(?js.Value.Global) = .empty,
|
||||
|
||||
pub fn init(worker: *Worker, url: [:0]const u8) !*DedicatedWorkerGlobalScope {
|
||||
return WorkerGlobalScope.init(
|
||||
worker._arena,
|
||||
worker._arena.allocator(),
|
||||
url,
|
||||
.dedicated,
|
||||
DedicatedWorkerGlobalScope{
|
||||
@@ -152,7 +150,7 @@ fn scheduleMessage(self: *DedicatedWorkerGlobalScope, cloned_data: ?js.Value.Glo
|
||||
const session = wgs._session;
|
||||
|
||||
const message_arena = try session.getArena(.tiny, "DedicatedWorkerGlobalScope.receiveMessage");
|
||||
errdefer session.releaseArena(message_arena);
|
||||
errdefer message_arena.release();
|
||||
|
||||
const callback = try message_arena.create(ReceiveMessageCallback);
|
||||
callback.* = .{
|
||||
@@ -184,7 +182,7 @@ pub fn drainPendingMessages(self: *DedicatedWorkerGlobalScope) void {
|
||||
|
||||
const ReceiveMessageCallback = struct {
|
||||
data: ?js.Value.Global,
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
worker_scope: *DedicatedWorkerGlobalScope,
|
||||
|
||||
fn cancelled(ctx: *anyopaque) void {
|
||||
@@ -196,7 +194,7 @@ const ReceiveMessageCallback = struct {
|
||||
}
|
||||
|
||||
fn deinit(self: *ReceiveMessageCallback) void {
|
||||
self.worker_scope._proto._session.releaseArena(self.arena);
|
||||
self.arena.release();
|
||||
}
|
||||
|
||||
fn run(ctx: *anyopaque) !?u32 {
|
||||
|
||||
@@ -1056,9 +1056,9 @@ fn writeInternal(self: *Document, text: []const []const u8, append_newline: bool
|
||||
defer frame._parse_mode = previous_parse_mode;
|
||||
|
||||
const arena = try frame.getArena(.medium, "Document.write");
|
||||
defer frame.releaseArena(arena);
|
||||
defer arena.release();
|
||||
|
||||
var parser = Parser.init(arena, fragment_node, frame, .{ .allow_declarative_shadow = true });
|
||||
var parser = Parser.init(arena.allocator(), fragment_node, frame, .{ .allow_declarative_shadow = true });
|
||||
parser.parseFragment(html);
|
||||
|
||||
// Extract children from wrapper HTML element (html5ever wraps fragments)
|
||||
@@ -1070,7 +1070,7 @@ fn writeInternal(self: *Document, text: []const []const u8, append_newline: bool
|
||||
|
||||
var it = if (first.is(Element.Html.Html) == null) fragment_node.childrenIterator() else first.childrenIterator();
|
||||
while (it.next()) |child| {
|
||||
try children_to_insert.append(arena, child);
|
||||
try children_to_insert.append(arena.allocator(), child);
|
||||
}
|
||||
|
||||
if (children_to_insert.items.len == 0) {
|
||||
|
||||
@@ -27,13 +27,12 @@ const EventTarget = @import("EventTarget.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Execution = js.Execution;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
pub const Event = @This();
|
||||
|
||||
pub const _prototype_root = true;
|
||||
_type: Type,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_bubbles: bool = false,
|
||||
_cancelable: bool = false,
|
||||
_composed: bool = false,
|
||||
@@ -107,18 +106,18 @@ pub const Options = struct {
|
||||
|
||||
pub fn init(typ: []const u8, opts_: ?Options, page: *Page) !*Event {
|
||||
const arena = try page.getArena(.tiny, "Event");
|
||||
errdefer page.releaseArena(arena);
|
||||
const str = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const str = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, str, opts_, false);
|
||||
}
|
||||
|
||||
pub fn initTrusted(typ: String, opts_: ?Options, page: *Page) !*Event {
|
||||
const arena = try page.getArena(.tiny, "Event.trusted");
|
||||
errdefer page.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, opts_, true);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, opts_: ?Options, comptime trusted: bool) !*Event {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, opts_: ?Options, comptime trusted: bool) !*Event {
|
||||
const opts = opts_ orelse Options{};
|
||||
|
||||
// Same (already coarsened) clock as the performance time origin, so the
|
||||
@@ -150,7 +149,7 @@ pub fn initEvent(
|
||||
}
|
||||
|
||||
self._initialized = true;
|
||||
self._type_string = try String.init(self._arena, event_string, .{});
|
||||
self._type_string = try String.init(self._arena.allocator(), event_string, .{});
|
||||
self._bubbles = bubbles orelse false;
|
||||
self._cancelable = cancelable orelse false;
|
||||
self._stop_propagation = false;
|
||||
@@ -162,8 +161,8 @@ pub fn acquireRef(self: *Event) void {
|
||||
self._rc.acquire();
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Event, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *Event, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *Event, page: *Page) void {
|
||||
|
||||
@@ -47,9 +47,9 @@ pub fn init(
|
||||
const opts = opts_ orelse InitOptions{};
|
||||
const session = page.session;
|
||||
const arena = try session.getArena(.large, "Blob");
|
||||
errdefer session.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const file = try Factory.chainedWithAllocator(arena, .{
|
||||
const file = try Factory.chainedWithAllocator(arena.allocator(), .{
|
||||
try Blob.buildValue(arena, parts_, .{
|
||||
.type = opts.type,
|
||||
.endings = opts.endings,
|
||||
@@ -90,9 +90,9 @@ pub fn structuredDeserialize(reader: *js.StructuredReader, page: *Page) !*File {
|
||||
const last_modified = try reader.readUint64();
|
||||
|
||||
const arena = try page.getArena(data.len + mime.len + name.len + 256, "Blob.clone");
|
||||
errdefer page.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const file = try Factory.chainedWithAllocator(arena, .{
|
||||
const file = try Factory.chainedWithAllocator(arena.allocator(), .{
|
||||
Blob{
|
||||
._rc = .{},
|
||||
._arena = arena,
|
||||
|
||||
@@ -38,7 +38,7 @@ pub const Proto = EventTarget;
|
||||
_rc: lp.RC = .{},
|
||||
_exec: *Execution,
|
||||
_proto: *EventTarget,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
|
||||
_ready_state: ReadyState = .empty,
|
||||
_result: ?Result = null,
|
||||
@@ -67,16 +67,16 @@ const Result = union(enum) {
|
||||
|
||||
pub fn init(exec: *Execution) !*FileReader {
|
||||
const arena = try exec.getArena(.tiny, "FileReader");
|
||||
errdefer exec.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
return exec._factory.eventTargetWithAllocator(arena, FileReader{
|
||||
return exec._factory.eventTargetWithAllocator(arena.allocator(), FileReader{
|
||||
._exec = exec,
|
||||
._arena = arena,
|
||||
._proto = undefined,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn deinit(self: *FileReader, page: *Page) void {
|
||||
pub fn deinit(self: *FileReader, _: *Page) void {
|
||||
if (self._on_abort) |func| func.release();
|
||||
if (self._on_error) |func| func.release();
|
||||
if (self._on_load) |func| func.release();
|
||||
@@ -84,7 +84,7 @@ pub fn deinit(self: *FileReader, page: *Page) void {
|
||||
if (self._on_load_start) |func| func.release();
|
||||
if (self._on_progress) |func| func.release();
|
||||
|
||||
page.releaseArena(self._arena);
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *FileReader, page: *Page) void {
|
||||
@@ -219,7 +219,7 @@ fn readInternal(self: *FileReader, blob: *Blob, read_type: ReadType) !void {
|
||||
.data_url => blk: {
|
||||
// Create data URL with base64 encoding
|
||||
const mime = if (blob._mime.len > 0) blob._mime else "application/octet-stream";
|
||||
const data_url = try encodeDataURL(self._arena, mime, data);
|
||||
const data_url = try encodeDataURL(self._arena.allocator(), mime, data);
|
||||
break :blk .{ .string = data_url };
|
||||
},
|
||||
};
|
||||
|
||||
@@ -54,11 +54,11 @@ pub fn pushState(_: *History, state: js.Value, _: ?[]const u8, _url: ?[]const u8
|
||||
const session = frame._session;
|
||||
const arena = session.arena;
|
||||
const url = if (_url) |u|
|
||||
try @import("../URL.zig").resolve(arena, frame.url, u, .{})
|
||||
try @import("../URL.zig").resolve(arena.allocator(), frame.url, u, .{})
|
||||
else
|
||||
try arena.dupeZ(u8, frame.url);
|
||||
|
||||
const json = state.toJson(arena) catch return error.DataClone;
|
||||
const json = state.toJson(arena.allocator()) catch return error.DataClone;
|
||||
_ = try session.navigation.pushEntry(url, .{ .source = .history, .value = json }, frame, true);
|
||||
|
||||
frame.url = url;
|
||||
@@ -76,11 +76,11 @@ pub fn replaceState(_: *History, state: js.Value, _: ?[]const u8, _url: ?[]const
|
||||
const session = frame._session;
|
||||
const arena = session.arena;
|
||||
const url = if (_url) |u|
|
||||
try @import("../URL.zig").resolve(arena, frame.url, u, .{})
|
||||
try @import("../URL.zig").resolve(arena.allocator(), frame.url, u, .{})
|
||||
else
|
||||
try arena.dupeZ(u8, frame.url);
|
||||
|
||||
const json = state.toJson(arena) catch return error.DataClone;
|
||||
const json = state.toJson(arena.allocator()) catch return error.DataClone;
|
||||
_ = try session.navigation.replaceEntry(url, .{ .source = .history, .value = json }, frame, true);
|
||||
|
||||
frame.url = url;
|
||||
|
||||
@@ -28,7 +28,6 @@ const Element = @import("Element.zig");
|
||||
const DOMRect = @import("DOMRect.zig");
|
||||
|
||||
const log = lp.log;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
pub fn registerTypes() []const type {
|
||||
return &.{
|
||||
@@ -40,7 +39,7 @@ pub fn registerTypes() []const type {
|
||||
const IntersectionObserver = @This();
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_callback: js.Function.Global,
|
||||
_observing: std.ArrayList(*Element) = .empty,
|
||||
_root: ?*Element = null,
|
||||
@@ -67,7 +66,7 @@ pub const ObserverInit = struct {
|
||||
|
||||
pub fn init(callback: js.Function.Global, options: ?ObserverInit, frame: *Frame) !*IntersectionObserver {
|
||||
const arena = try frame.getArena(.small, "IntersectionObserver");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const opts = options orelse ObserverInit{};
|
||||
const root_margin = if (opts.rootMargin) |rm| try arena.dupe(u8, rm) else "0px";
|
||||
@@ -113,7 +112,7 @@ pub fn deinit(self: *IntersectionObserver, page: *Page) void {
|
||||
// FinalizerCallback. We 100% own them.
|
||||
entry.deinit(page);
|
||||
}
|
||||
page.releaseArena(self._arena);
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *IntersectionObserver, page: *Page) void {
|
||||
@@ -132,12 +131,12 @@ pub fn observe(self: *IntersectionObserver, target: *Element, frame: *Frame) !vo
|
||||
}
|
||||
}
|
||||
|
||||
try self._observing.append(self._arena, target);
|
||||
try self._observing.append(self._arena.allocator(), target);
|
||||
if (self._observing.items.len == 1) {
|
||||
try Frame.observers.registerIntersectionObserver(frame, self);
|
||||
}
|
||||
|
||||
try self._tracked.put(self._arena, target, {});
|
||||
try self._tracked.put(self._arena.allocator(), target, {});
|
||||
|
||||
// Check intersection for this new target and schedule delivery
|
||||
try self.checkIntersection(target, frame);
|
||||
@@ -266,7 +265,7 @@ fn checkIntersection(self: *IntersectionObserver, target: *Element, frame: *Fram
|
||||
// document to fake a position (O(node count)) — so it only runs here.
|
||||
const data = try self.calculateIntersection(target, has_parent, frame);
|
||||
const arena = try frame.getArena(.tiny, "IntersectionObserverEntry");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const entry = try arena.create(IntersectionObserverEntry);
|
||||
entry.* = .{
|
||||
@@ -279,7 +278,7 @@ fn checkIntersection(self: *IntersectionObserver, target: *Element, frame: *Fram
|
||||
._bounding_client_rect = try DOMRect.create(data.bounding_client_rect, frame._factory),
|
||||
._intersection_ratio = data.intersection_ratio,
|
||||
};
|
||||
try self._pending_entries.append(self._arena, entry);
|
||||
try self._pending_entries.append(self._arena.allocator(), entry);
|
||||
_ = self._tracked.removeByPtr(tracked.key_ptr);
|
||||
}
|
||||
|
||||
@@ -317,7 +316,7 @@ pub fn deliverEntries(self: *IntersectionObserver, frame: *Frame) !void {
|
||||
|
||||
pub const IntersectionObserverEntry = struct {
|
||||
_rc: lp.RC = .{},
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_time: f64,
|
||||
_target: *Element,
|
||||
_bounding_client_rect: *DOMRect,
|
||||
@@ -326,8 +325,8 @@ pub const IntersectionObserverEntry = struct {
|
||||
_intersection_ratio: f64,
|
||||
_is_intersecting: bool,
|
||||
|
||||
pub fn deinit(self: *IntersectionObserverEntry, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *IntersectionObserverEntry, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *IntersectionObserverEntry, page: *Page) void {
|
||||
|
||||
@@ -28,7 +28,6 @@ const Element = @import("Element.zig");
|
||||
|
||||
const log = lp.log;
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
pub fn registerTypes() []const type {
|
||||
return &.{
|
||||
@@ -40,7 +39,7 @@ pub fn registerTypes() []const type {
|
||||
const MutationObserver = @This();
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_callback: js.Function.Global,
|
||||
_observing: std.ArrayList(Observing) = .empty,
|
||||
_pending_records: std.ArrayList(*MutationRecord) = .empty,
|
||||
@@ -76,7 +75,7 @@ pub const ObserveOptions = struct {
|
||||
|
||||
pub fn init(callback: js.Function.Global, frame: *Frame) !*MutationObserver {
|
||||
const arena = try frame.getArena(.small, "MutationObserver");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
const self = try arena.create(MutationObserver);
|
||||
self.* = .{
|
||||
._arena = arena,
|
||||
@@ -92,7 +91,7 @@ pub fn deinit(self: *MutationObserver, page: *Page) void {
|
||||
record.deinit(page);
|
||||
}
|
||||
self._callback.release();
|
||||
page.releaseArena(self._arena);
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *MutationObserver, page: *Page) void {
|
||||
@@ -165,7 +164,7 @@ pub fn observe(self: *MutationObserver, target: *Node, options: ObserveOptions,
|
||||
}
|
||||
}
|
||||
|
||||
try self._observing.append(arena, .{
|
||||
try self._observing.append(arena.allocator(), .{
|
||||
.target = target,
|
||||
.options = store_options,
|
||||
});
|
||||
@@ -242,7 +241,7 @@ pub fn notifyAttributeChange(
|
||||
._next_sibling = null,
|
||||
};
|
||||
|
||||
try self._pending_records.append(self._arena, record);
|
||||
try self._pending_records.append(self._arena.allocator(), record);
|
||||
|
||||
try Frame.observers.scheduleMutationDelivery(frame);
|
||||
break;
|
||||
@@ -286,7 +285,7 @@ pub fn notifyCharacterDataChange(
|
||||
._next_sibling = null,
|
||||
};
|
||||
|
||||
try self._pending_records.append(self._arena, record);
|
||||
try self._pending_records.append(self._arena.allocator(), record);
|
||||
|
||||
try Frame.observers.scheduleMutationDelivery(frame);
|
||||
break;
|
||||
@@ -330,7 +329,7 @@ pub fn notifyChildListChange(
|
||||
._next_sibling = next_sibling,
|
||||
};
|
||||
|
||||
try self._pending_records.append(self._arena, record);
|
||||
try self._pending_records.append(self._arena.allocator(), record);
|
||||
|
||||
try Frame.observers.scheduleMutationDelivery(frame);
|
||||
break;
|
||||
@@ -360,7 +359,7 @@ pub const MutationRecord = struct {
|
||||
_rc: lp.RC = .{},
|
||||
_type: Type,
|
||||
_target: *Node,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_attribute_name: ?[]const u8,
|
||||
_old_value: ?[]const u8,
|
||||
_added_nodes: []const *Node,
|
||||
@@ -374,8 +373,8 @@ pub const MutationRecord = struct {
|
||||
characterData,
|
||||
};
|
||||
|
||||
pub fn deinit(self: *MutationRecord, session: *Page) void {
|
||||
session.releaseArena(self._arena);
|
||||
pub fn deinit(self: *MutationRecord, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *MutationRecord, session: *Page) void {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../js/js.zig");
|
||||
@@ -25,14 +24,13 @@ const Page = @import("../Page.zig");
|
||||
const EventTarget = @import("EventTarget.zig");
|
||||
|
||||
const Execution = js.Execution;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const Notification = @This();
|
||||
|
||||
pub const Proto = EventTarget;
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_proto: *EventTarget,
|
||||
_title: []const u8,
|
||||
_body: []const u8 = "",
|
||||
@@ -61,10 +59,10 @@ const Options = struct {
|
||||
|
||||
pub fn init(title: []const u8, options_: ?Options, exec: *const Execution) !*Notification {
|
||||
const arena = try exec.getArena(.small, "Notification");
|
||||
errdefer exec.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const options = options_ orelse Options{};
|
||||
return exec._factory.eventTargetWithAllocator(arena, Notification{
|
||||
return exec._factory.eventTargetWithAllocator(arena.allocator(), Notification{
|
||||
._arena = arena,
|
||||
._proto = undefined,
|
||||
._title = try arena.dupe(u8, title),
|
||||
@@ -81,8 +79,8 @@ pub fn init(title: []const u8, options_: ?Options, exec: *const Execution) !*Not
|
||||
});
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Notification, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *Notification, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *Notification, page: *Page) void {
|
||||
|
||||
@@ -16,15 +16,12 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../js/js.zig");
|
||||
const Page = @import("../Page.zig");
|
||||
const Execution = js.Execution;
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
pub fn registerTypes() []const type {
|
||||
return &.{ Permissions, PermissionStatus };
|
||||
}
|
||||
@@ -48,7 +45,7 @@ const QueryDescriptor = struct {
|
||||
// 'prompt' (the default safe value — neither granted nor denied) when unset.
|
||||
pub fn query(_: *const Permissions, qd: QueryDescriptor, exec: *const Execution) !js.Promise {
|
||||
const arena = try exec.getArena(.tiny, "PermissionStatus");
|
||||
errdefer exec.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const state = exec.session.browser.permissions.get(qd.name) orelse .prompt;
|
||||
const status = try arena.create(PermissionStatus);
|
||||
@@ -62,12 +59,12 @@ pub fn query(_: *const Permissions, qd: QueryDescriptor, exec: *const Execution)
|
||||
|
||||
const PermissionStatus = struct {
|
||||
_rc: lp.RC = .{},
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_name: []const u8,
|
||||
_state: State,
|
||||
|
||||
pub fn deinit(self: *PermissionStatus, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *PermissionStatus, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *PermissionStatus, page: *Page) void {
|
||||
|
||||
@@ -41,7 +41,7 @@ pub fn init(frame: *Frame) !*Range {
|
||||
// frame's main document.
|
||||
pub fn initIn(container: *Node, frame: *Frame) !*Range {
|
||||
const arena = try frame.getArena(.medium, "Range");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
const range = try frame._factory.abstractRange(arena, Range{ ._proto = undefined }, frame);
|
||||
range._proto._start_container = container;
|
||||
range._proto._end_container = container;
|
||||
@@ -328,7 +328,7 @@ pub fn intersectsNode(self: *const Range, node: *Node) bool {
|
||||
|
||||
pub fn cloneRange(self: *const Range, frame: *Frame) !*Range {
|
||||
const arena = try frame.getArena(.medium, "Range.clone");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const clone = try frame._factory.abstractRange(arena, Range{ ._proto = undefined }, frame);
|
||||
clone._proto._end_offset = self._proto._end_offset;
|
||||
|
||||
@@ -33,7 +33,6 @@ const DOMRect = @import("DOMRect.zig");
|
||||
const Factory = @import("../Factory.zig");
|
||||
|
||||
const log = lp.log;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
pub fn registerTypes() []const type {
|
||||
return &.{
|
||||
@@ -46,7 +45,7 @@ pub fn registerTypes() []const type {
|
||||
const ResizeObserver = @This();
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_callback: js.Function.Global,
|
||||
_observations: std.ArrayList(Observation) = .empty,
|
||||
|
||||
@@ -63,7 +62,7 @@ const Options = struct {
|
||||
|
||||
pub fn init(callback: js.Function.Global, frame: *Frame) !*ResizeObserver {
|
||||
const arena = try frame.getArena(.small, "ResizeObserver");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const self = try arena.create(ResizeObserver);
|
||||
self.* = .{
|
||||
@@ -73,9 +72,9 @@ pub fn init(callback: js.Function.Global, frame: *Frame) !*ResizeObserver {
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *ResizeObserver, page: *Page) void {
|
||||
pub fn deinit(self: *ResizeObserver, _: *Page) void {
|
||||
self._callback.release();
|
||||
page.releaseArena(self._arena);
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn acquireRef(self: *ResizeObserver) void {
|
||||
@@ -95,7 +94,7 @@ pub fn observe(self: *ResizeObserver, target: *Element, options_: ?Options, fram
|
||||
}
|
||||
}
|
||||
|
||||
try self._observations.append(self._arena, .{ .target = target });
|
||||
try self._observations.append(self._arena.allocator(), .{ .target = target });
|
||||
if (self._observations.items.len == 1) {
|
||||
try Frame.observers.registerResizeObserver(frame, self);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ const WorkerGlobalScope = @import("WorkerGlobalScope.zig");
|
||||
const MessageEvent = @import("event/MessageEvent.zig");
|
||||
|
||||
const log = lp.log;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
|
||||
const SharedWorkerGlobalScope = @This();
|
||||
@@ -38,7 +37,7 @@ const SharedWorkerGlobalScope = @This();
|
||||
pub const Proto = WorkerGlobalScope;
|
||||
|
||||
_proto: *WorkerGlobalScope,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
|
||||
_url: [:0]const u8,
|
||||
_name: []const u8,
|
||||
@@ -55,7 +54,7 @@ _loader_id: u32,
|
||||
|
||||
_closed: bool = false,
|
||||
_script_loaded: bool = false,
|
||||
_script_arena: ?Allocator = null,
|
||||
_script_arena: ?*lp.Arena = null,
|
||||
_script_buffer: std.ArrayList(u8) = .empty,
|
||||
_http_transfer: ?*Transfer = null,
|
||||
|
||||
@@ -68,13 +67,13 @@ pub fn init(frame: *Frame, url: [:0]const u8, name: []const u8, worker_type: Wor
|
||||
const session = frame._session;
|
||||
|
||||
const arena = try session.getArena(.small, "SharedWorker");
|
||||
errdefer session.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const owned_url = try arena.dupeZ(u8, url);
|
||||
const frame_id = session.nextFrameId();
|
||||
const loader_id = session.nextLoaderId();
|
||||
const self = try WorkerGlobalScope.init(
|
||||
arena,
|
||||
arena.allocator(),
|
||||
owned_url,
|
||||
.shared,
|
||||
SharedWorkerGlobalScope{
|
||||
@@ -143,7 +142,7 @@ pub fn deinit(self: *SharedWorkerGlobalScope) void {
|
||||
self.releaseScriptArena();
|
||||
self.unregister();
|
||||
self._proto.deinit();
|
||||
self._proto._session.releaseArena(self._arena);
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn register(self: *SharedWorkerGlobalScope, lookup_key: []const u8) !void {
|
||||
@@ -152,7 +151,7 @@ pub fn register(self: *SharedWorkerGlobalScope, lookup_key: []const u8) !void {
|
||||
const key = try self._arena.dupe(u8, lookup_key);
|
||||
|
||||
const session = self._proto._session;
|
||||
try session.shared_workers.put(session.arena, key, self);
|
||||
try session.shared_workers.put(session.arena.allocator(), key, self);
|
||||
self._registry_key = key;
|
||||
}
|
||||
|
||||
@@ -172,7 +171,7 @@ pub fn connect(self: *SharedWorkerGlobalScope, client_exec: *js.Execution) !*Mes
|
||||
MessagePort.entangle(client_port, worker_port);
|
||||
|
||||
if (self._script_loaded == false) {
|
||||
try self._pending_connects.append(self._arena, worker_port);
|
||||
try self._pending_connects.append(self._arena.allocator(), worker_port);
|
||||
return client_port;
|
||||
}
|
||||
|
||||
@@ -214,7 +213,7 @@ fn httpHeaderCallback(transfer: *Transfer) !Transfer.HeaderResult {
|
||||
}
|
||||
|
||||
if (transfer.getContentLength()) |cl| {
|
||||
try self._script_buffer.ensureTotalCapacity(self._script_arena.?, cl);
|
||||
try self._script_buffer.ensureTotalCapacity(self._script_arena.?.allocator(), cl);
|
||||
}
|
||||
|
||||
return .proceed;
|
||||
@@ -222,7 +221,7 @@ fn httpHeaderCallback(transfer: *Transfer) !Transfer.HeaderResult {
|
||||
|
||||
fn httpDataCallback(transfer: *Transfer, data: []const u8) !void {
|
||||
const self: *SharedWorkerGlobalScope = @ptrCast(@alignCast(transfer.req.ctx));
|
||||
try self._script_buffer.appendSlice(self._script_arena.?, data);
|
||||
try self._script_buffer.appendSlice(self._script_arena.?.allocator(), data);
|
||||
}
|
||||
|
||||
fn httpDoneCallback(ctx: *anyopaque) !void {
|
||||
@@ -297,7 +296,7 @@ fn loadInitialScript(self: *SharedWorkerGlobalScope, script: []const u8) !void {
|
||||
}
|
||||
|
||||
js_context.page.recordJsError(err);
|
||||
const caught = try_catch.caughtOrError(self._script_arena.?, err);
|
||||
const caught = try_catch.caughtOrError(self._script_arena.?.allocator(), err);
|
||||
log.err(.browser, "shared worker script error", .{ .url = self._url, .caught = caught });
|
||||
return;
|
||||
},
|
||||
@@ -307,7 +306,7 @@ fn loadInitialScript(self: *SharedWorkerGlobalScope, script: []const u8) !void {
|
||||
}
|
||||
|
||||
js_context.page.recordJsError(err);
|
||||
const caught = try_catch.caughtOrError(self._script_arena.?, err);
|
||||
const caught = try_catch.caughtOrError(self._script_arena.?.allocator(), err);
|
||||
log.err(.browser, "shared worker module error", .{ .url = self._url, .caught = caught });
|
||||
return;
|
||||
},
|
||||
@@ -322,7 +321,7 @@ fn releaseScriptArena(self: *SharedWorkerGlobalScope) void {
|
||||
const arena = self._script_arena orelse return;
|
||||
self._script_arena = null;
|
||||
self._script_buffer = .empty;
|
||||
self._proto._session.releaseArena(arena);
|
||||
arena.release();
|
||||
}
|
||||
|
||||
fn drainPendingConnects(self: *SharedWorkerGlobalScope) void {
|
||||
@@ -339,7 +338,7 @@ fn scheduleConnect(self: *SharedWorkerGlobalScope, port: *MessagePort) !void {
|
||||
const session = wgs._session;
|
||||
|
||||
const connect_arena = try session.getArena(.tiny, "SharedWorkerGlobalScope.connect");
|
||||
errdefer session.releaseArena(connect_arena);
|
||||
errdefer connect_arena.release();
|
||||
|
||||
const callback = try connect_arena.create(ConnectCallback);
|
||||
callback.* = .{
|
||||
@@ -357,7 +356,7 @@ fn scheduleConnect(self: *SharedWorkerGlobalScope, port: *MessagePort) !void {
|
||||
|
||||
const ConnectCallback = struct {
|
||||
port: *MessagePort,
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
worker_scope: *SharedWorkerGlobalScope,
|
||||
|
||||
fn cancelled(ctx: *anyopaque) void {
|
||||
@@ -366,7 +365,7 @@ const ConnectCallback = struct {
|
||||
}
|
||||
|
||||
fn deinit(self: *ConnectCallback) void {
|
||||
self.worker_scope._proto._session.releaseArena(self.arena);
|
||||
self.arena.release();
|
||||
}
|
||||
|
||||
fn run(ctx: *anyopaque) !?u32 {
|
||||
|
||||
@@ -50,7 +50,7 @@ pub fn init(opts: StaticRangeInit, frame: *Frame) !*StaticRange {
|
||||
}
|
||||
|
||||
const arena = try frame.getArena(.medium, "StaticRange");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const static_range = try frame._factory.abstractRange(arena, StaticRange{ ._proto = undefined }, frame);
|
||||
const proto = static_range._proto;
|
||||
|
||||
@@ -27,7 +27,6 @@ const lp = @import("lightpanda");
|
||||
const js = @import("../js/js.zig");
|
||||
|
||||
const log = lp.log;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const CLAMP_MS = 4;
|
||||
const CLAMP_NESTING = 5;
|
||||
@@ -97,7 +96,7 @@ pub fn schedule(
|
||||
}
|
||||
|
||||
const arena = try exec.getArena(.tiny, "Timers.schedule");
|
||||
errdefer exec.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const timer_id = self._timer_id +% 1;
|
||||
self._timer_id = timer_id;
|
||||
@@ -191,7 +190,7 @@ const ScheduleCallback = struct {
|
||||
mode: Mode,
|
||||
exec: *js.Execution,
|
||||
timers: *Timers,
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
removed: bool = false,
|
||||
params: []const js.Value.Global,
|
||||
|
||||
@@ -205,7 +204,7 @@ const ScheduleCallback = struct {
|
||||
for (self.params) |param| {
|
||||
param.release();
|
||||
}
|
||||
self.exec.releaseArena(self.arena);
|
||||
self.arena.release();
|
||||
}
|
||||
|
||||
fn run(ptr: *anyopaque) !?u32 {
|
||||
|
||||
@@ -35,7 +35,6 @@ const TouchEvent = @import("event/TouchEvent.zig");
|
||||
const EventManagerBase = @import("../EventManagerBase.zig");
|
||||
|
||||
const log = lp.log;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
// This type is only included when the binary is built with the -Dwpt_extensions flag
|
||||
const WebDriver = @This();
|
||||
@@ -135,7 +134,7 @@ pub fn actionSequence(_: *const WebDriver, sources: js.Value, frame: *Frame) !js
|
||||
}
|
||||
|
||||
const arena = try frame.getArena(.tiny, "WebDriver.actionSequence");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const persisted = try sources.persist();
|
||||
errdefer persisted.release();
|
||||
@@ -164,7 +163,7 @@ pub fn actionSequence(_: *const WebDriver, sources: js.Value, frame: *Frame) !js
|
||||
|
||||
const ActionSequence = struct {
|
||||
frame: *Frame,
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
sources: js.Value.Global,
|
||||
resolver: js.PromiseResolver.Global,
|
||||
|
||||
@@ -211,7 +210,7 @@ const ActionSequence = struct {
|
||||
fn deinit(self: *ActionSequence) void {
|
||||
self.sources.release();
|
||||
self.resolver.release();
|
||||
self.frame.releaseArena(self.arena);
|
||||
self.arena.release();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -55,7 +55,6 @@ const Notification = @import("../../Notification.zig");
|
||||
const log = lp.log;
|
||||
const IS_DEBUG = builtin.mode == .Debug;
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Execution = js.Execution;
|
||||
|
||||
pub fn registerTypes() []const type {
|
||||
@@ -816,7 +815,7 @@ pub fn postMessage(self: *Window, message: js.Value, target_origin: ?[]const u8,
|
||||
const source_window = target_frame.js.getIncumbent().window;
|
||||
|
||||
const arena = try target_frame.getArena(.medium, "Window.postMessage");
|
||||
errdefer target_frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
// StructuredSerialize runs synchronously (per spec): clone the message into
|
||||
// the target window's realm now. The receiver gets a fresh, independent copy
|
||||
@@ -1079,13 +1078,13 @@ pub const Access = union(enum) {
|
||||
const PostMessageCallback = struct {
|
||||
frame: *Frame,
|
||||
source: *Window,
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
origin: []const u8,
|
||||
message: js.Value.Global,
|
||||
ports: []const *MessagePort,
|
||||
|
||||
fn deinit(self: *PostMessageCallback) void {
|
||||
self.frame.releaseArena(self.arena);
|
||||
self.arena.release();
|
||||
}
|
||||
|
||||
// Called by the scheduler if the task is dropped before it runs. `run` and
|
||||
|
||||
@@ -31,7 +31,6 @@ const ErrorEvent = @import("event/ErrorEvent.zig");
|
||||
const DedicatedWorkerGlobalScope = @import("DedicatedWorkerGlobalScope.zig");
|
||||
|
||||
const log = lp.log;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
|
||||
const Worker = @This();
|
||||
@@ -51,13 +50,13 @@ _loader_id: u32,
|
||||
|
||||
_proto: *EventTarget,
|
||||
_frame: *Frame,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_worker_scope: *DedicatedWorkerGlobalScope,
|
||||
|
||||
_url: [:0]const u8,
|
||||
_type: WorkerType = .classic,
|
||||
_script_loaded: bool = false,
|
||||
_script_arena: ?Allocator = null,
|
||||
_script_arena: ?*lp.Arena = null,
|
||||
_script_buffer: std.ArrayList(u8) = .empty,
|
||||
_http_transfer: ?*Transfer = null,
|
||||
|
||||
@@ -74,10 +73,10 @@ pub fn init(url: []const u8, options: ?WorkerOptions, frame: *Frame) !*Worker {
|
||||
const session = frame._session;
|
||||
|
||||
const arena = try session.getArena(.small, "Worker");
|
||||
errdefer session.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const resolved_url = try URL.resolve(arena, frame.base(), url, .{ .encoding = frame.charset });
|
||||
const self = try frame._page.factory.eventTargetWithAllocator(arena, Worker{
|
||||
const resolved_url = try URL.resolve(arena.allocator(), frame.base(), url, .{ .encoding = frame.charset });
|
||||
const self = try frame._page.factory.eventTargetWithAllocator(arena.allocator(), Worker{
|
||||
._arena = arena,
|
||||
._proto = undefined,
|
||||
._frame = frame,
|
||||
@@ -152,7 +151,7 @@ pub fn deinit(self: *Worker) void {
|
||||
}
|
||||
self.releaseScriptArena();
|
||||
self._worker_scope.deinit();
|
||||
self._frame._session.releaseArena(self._arena);
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn asEventTarget(self: *Worker) *EventTarget {
|
||||
@@ -172,7 +171,7 @@ fn httpHeaderCallback(transfer: *Transfer) !Transfer.HeaderResult {
|
||||
}
|
||||
|
||||
if (transfer.getContentLength()) |cl| {
|
||||
try self._script_buffer.ensureTotalCapacity(self._script_arena.?, cl);
|
||||
try self._script_buffer.ensureTotalCapacity(self._script_arena.?.allocator(), cl);
|
||||
}
|
||||
|
||||
return .proceed;
|
||||
@@ -180,7 +179,7 @@ fn httpHeaderCallback(transfer: *Transfer) !Transfer.HeaderResult {
|
||||
|
||||
fn httpDataCallback(transfer: *Transfer, data: []const u8) !void {
|
||||
const self: *Worker = @ptrCast(@alignCast(transfer.req.ctx));
|
||||
try self._script_buffer.appendSlice(self._script_arena.?, data);
|
||||
try self._script_buffer.appendSlice(self._script_arena.?.allocator(), data);
|
||||
}
|
||||
|
||||
fn httpDoneCallback(ctx: *anyopaque) !void {
|
||||
@@ -244,7 +243,7 @@ fn loadInitialScript(self: *Worker, script: []const u8) !void {
|
||||
}
|
||||
|
||||
js_context.page.recordJsError(err);
|
||||
const caught = try_catch.caughtOrError(self._script_arena.?, err);
|
||||
const caught = try_catch.caughtOrError(self._script_arena.?.allocator(), err);
|
||||
log.err(.browser, "worker script error", .{ .url = self._url, .caught = caught });
|
||||
self.fireErrorEvent(caught.exception orelse @errorName(err), null);
|
||||
return;
|
||||
@@ -255,7 +254,7 @@ fn loadInitialScript(self: *Worker, script: []const u8) !void {
|
||||
}
|
||||
|
||||
js_context.page.recordJsError(err);
|
||||
const caught = try_catch.caughtOrError(self._script_arena.?, err);
|
||||
const caught = try_catch.caughtOrError(self._script_arena.?.allocator(), err);
|
||||
log.err(.browser, "worker module error", .{ .url = self._url, .caught = caught });
|
||||
self.fireErrorEvent(caught.exception orelse @errorName(err), null);
|
||||
return;
|
||||
@@ -295,7 +294,7 @@ fn releaseScriptArena(self: *Worker) void {
|
||||
const arena = self._script_arena orelse return;
|
||||
self._script_arena = null;
|
||||
self._script_buffer = .empty;
|
||||
self._frame._session.releaseArena(arena);
|
||||
arena.release();
|
||||
}
|
||||
|
||||
// Fire an error event on the Worker object (parent context)
|
||||
@@ -356,7 +355,7 @@ pub fn receiveMessage(self: *Worker, data: js.Value) !void {
|
||||
};
|
||||
|
||||
const message_arena = try frame.getArena(.tiny, "Worker.receiveMessage");
|
||||
errdefer frame.releaseArena(message_arena);
|
||||
errdefer message_arena.release();
|
||||
|
||||
const callback = try message_arena.create(ReceiveMessageCallback);
|
||||
callback.* = .{
|
||||
@@ -411,7 +410,7 @@ fn getFunctionFromSetter(setter_: ?FunctionSetter) ?js.Function.Global {
|
||||
|
||||
const ReceiveMessageCallback = struct {
|
||||
data: anyerror!js.Value.Global,
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
worker: *Worker,
|
||||
|
||||
fn cancelled(ctx: *anyopaque) void {
|
||||
@@ -423,7 +422,7 @@ const ReceiveMessageCallback = struct {
|
||||
}
|
||||
|
||||
fn deinit(self: *ReceiveMessageCallback) void {
|
||||
self.worker._frame._session.releaseArena(self.arena);
|
||||
self.arena.release();
|
||||
}
|
||||
|
||||
fn run(ctx: *anyopaque) !?u32 {
|
||||
|
||||
@@ -73,6 +73,8 @@ _identity: JS.Identity = .{},
|
||||
_http_owner: HttpClient.Owner,
|
||||
|
||||
arena: Allocator,
|
||||
_call_arena: *lp.Arena,
|
||||
_local_arena: *lp.Arena,
|
||||
call_arena: Allocator,
|
||||
local_arena: Allocator,
|
||||
url: [:0]const u8,
|
||||
@@ -135,10 +137,10 @@ pub fn init(
|
||||
const session = frame._session;
|
||||
|
||||
const call_arena = try session.getArena(.small, "WorkerGlobalScope.call_arena");
|
||||
errdefer session.releaseArena(call_arena);
|
||||
errdefer call_arena.release();
|
||||
|
||||
const local_arena = try session.getArena(.small, "WorkerGlobalScope.local_arena");
|
||||
errdefer session.releaseArena(local_arena);
|
||||
errdefer local_arena.release();
|
||||
|
||||
const factory = frame._factory;
|
||||
const leaf = try Factory.chainedWithAllocator(arena, .{
|
||||
@@ -148,8 +150,10 @@ pub fn init(
|
||||
.arena = arena,
|
||||
.origin = frame.origin,
|
||||
.js = undefined,
|
||||
.call_arena = call_arena,
|
||||
.local_arena = local_arena,
|
||||
._call_arena = call_arena,
|
||||
._local_arena = local_arena,
|
||||
.call_arena = call_arena.allocator(),
|
||||
.local_arena = local_arena.allocator(),
|
||||
._frame = frame,
|
||||
._page = frame._page,
|
||||
._session = session,
|
||||
@@ -181,8 +185,8 @@ pub fn init(
|
||||
);
|
||||
|
||||
self.js = try session.browser.env.createWorkerContext(self, .{
|
||||
.call_arena = call_arena,
|
||||
.local_arena = local_arena,
|
||||
.call_arena = call_arena.allocator(),
|
||||
.local_arena = local_arena.allocator(),
|
||||
.identity_arena = arena,
|
||||
.identity = &self._identity,
|
||||
});
|
||||
@@ -216,8 +220,8 @@ pub fn deinit(self: *WorkerGlobalScope) void {
|
||||
|
||||
page.revokeBlobUrlsFor(self._frame_id);
|
||||
browser.env.destroyContext(self.js);
|
||||
session.releaseArena(self.call_arena);
|
||||
session.releaseArena(self.local_arena);
|
||||
self._call_arena.release();
|
||||
self._local_arena.release();
|
||||
}
|
||||
|
||||
pub fn base(self: *const WorkerGlobalScope) [:0]const u8 {
|
||||
@@ -393,11 +397,11 @@ pub fn importScripts(self: *WorkerGlobalScope, urls: []const [:0]const u8) !void
|
||||
|
||||
const session = self._session;
|
||||
const arena = try session.getArena(.large, "importScript");
|
||||
defer session.releaseArena(arena);
|
||||
defer arena.release();
|
||||
|
||||
for (urls) |url| {
|
||||
defer session.arena_pool.resetRetain(arena);
|
||||
try self.importScript(arena, url);
|
||||
defer arena.resetRetain();
|
||||
try self.importScript(arena.allocator(), url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
//! arena for its own result data so multiple evaluations don't grow
|
||||
//! the AST arena.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../js/js.zig");
|
||||
@@ -38,24 +37,22 @@ const xpath = struct {
|
||||
const Evaluator = @import("../xpath/Evaluator.zig");
|
||||
};
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const XPathExpression = @This();
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_expr: *const xpath.Ast.Expr,
|
||||
|
||||
pub fn init(expression: []const u8, frame: *Frame) !*XPathExpression {
|
||||
const arena = try frame.getArena(.tiny, "XPathExpression");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
// The AST borrows string slices from its input (literals, names,
|
||||
// var refs, function names). `expression` is materialized in the JS
|
||||
// call_arena and is reclaimed when the top-level call returns, so
|
||||
// dupe into our long-lived arena before parsing.
|
||||
const owned = try arena.dupe(u8, expression);
|
||||
const expr = try xpath.Parser.parse(arena, owned);
|
||||
const expr = try xpath.Parser.parse(arena.allocator(), owned);
|
||||
const xe = try arena.create(XPathExpression);
|
||||
xe.* = .{ ._arena = arena, ._expr = expr };
|
||||
return xe;
|
||||
@@ -74,14 +71,14 @@ pub fn evaluate(
|
||||
_ = result;
|
||||
|
||||
const arena = try frame.getArena(.medium, "XPathResult");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const eval_result = try xpath.Evaluator.evaluate(arena, self._expr, context_node, frame);
|
||||
const eval_result = try xpath.Evaluator.evaluate(arena.allocator(), self._expr, context_node, frame);
|
||||
return XPathResult.fromResult(arena, requested_type orelse XPathResult.ANY_TYPE, eval_result);
|
||||
}
|
||||
|
||||
pub fn deinit(self: *XPathExpression, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *XPathExpression, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn acquireRef(self: *XPathExpression) void {
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
//! `InvalidStateError` is what decision #4 captures and what most
|
||||
//! legacy XPath consumers expect.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../js/js.zig");
|
||||
@@ -49,8 +48,6 @@ const xpath = struct {
|
||||
const Evaluator = @import("../xpath/Evaluator.zig");
|
||||
};
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const XPathResult = @This();
|
||||
|
||||
// WHATWG type constants. ANY_TYPE is a request flag — at construction
|
||||
@@ -76,7 +73,7 @@ const Value = union(enum) {
|
||||
};
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_type: u16,
|
||||
_value: Value,
|
||||
_iter_pos: usize = 0,
|
||||
@@ -93,15 +90,15 @@ pub fn fromExpression(
|
||||
frame: *Frame,
|
||||
) !*XPathResult {
|
||||
const arena = try frame.getArena(.medium, "XPathResult");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
// The AST borrows string slices from its input (literals, names,
|
||||
// var refs, function names). `expression` is materialized in the JS
|
||||
// call_arena and is reclaimed when the top-level call returns, so
|
||||
// dupe into our long-lived arena before parsing.
|
||||
const owned = try arena.dupe(u8, expression);
|
||||
const expr = try xpath.Parser.parse(arena, owned);
|
||||
const result = try xpath.Evaluator.evaluate(arena, expr, context_node, frame);
|
||||
const expr = try xpath.Parser.parse(arena.allocator(), owned);
|
||||
const result = try xpath.Evaluator.evaluate(arena.allocator(), expr, context_node, frame);
|
||||
return fromResult(arena, requested_type, result);
|
||||
}
|
||||
|
||||
@@ -110,7 +107,7 @@ pub fn fromExpression(
|
||||
/// it on deinit. Used by `XPathExpression.evaluate` (which has its own
|
||||
/// AST cache and only allocates a fresh result arena).
|
||||
pub fn fromResult(
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
requested_type: u16,
|
||||
result: xpath.result.Result,
|
||||
) !*XPathResult {
|
||||
@@ -121,8 +118,8 @@ pub fn fromResult(
|
||||
.boolean => |b| .{ .boolean = b },
|
||||
.node_set => |ns| .{ .nodes = ns },
|
||||
},
|
||||
NUMBER_TYPE => .{ .number = try xpath.result.toNumber(arena, result) },
|
||||
STRING_TYPE => .{ .string = try xpath.result.toString(arena, result) },
|
||||
NUMBER_TYPE => .{ .number = try xpath.result.toNumber(arena.allocator(), result) },
|
||||
STRING_TYPE => .{ .string = try xpath.result.toString(arena.allocator(), result) },
|
||||
BOOLEAN_TYPE => .{ .boolean = xpath.result.toBoolean(result) },
|
||||
UNORDERED_NODE_ITERATOR_TYPE,
|
||||
ORDERED_NODE_ITERATOR_TYPE,
|
||||
@@ -159,8 +156,8 @@ pub fn fromResult(
|
||||
|
||||
// ----- lifecycle -----
|
||||
|
||||
pub fn deinit(self: *XPathResult, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *XPathResult, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn acquireRef(self: *XPathResult) void {
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
const js = @import("../../js/js.zig");
|
||||
const Page = @import("../../Page.zig");
|
||||
const Frame = @import("../../Frame.zig");
|
||||
|
||||
const log = lp.log;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const Animation = @This();
|
||||
|
||||
@@ -36,7 +34,7 @@ const PlayState = enum {
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_frame: *Frame,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
|
||||
_effect: ?js.Object.Global = null,
|
||||
_timeline: ?js.Object.Global = null,
|
||||
@@ -53,7 +51,7 @@ _playState: PlayState = .idle,
|
||||
// TODO add support for effect and timeline
|
||||
pub fn init(frame: *Frame) !*Animation {
|
||||
const arena = try frame.getArena(.tiny, "Animation");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const self = try arena.create(Animation);
|
||||
self.* = .{
|
||||
@@ -64,8 +62,8 @@ pub fn init(frame: *Frame) !*Animation {
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Animation, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *Animation, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *Animation, page: *Page) void {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const Page = @import("../../Page.zig");
|
||||
const Frame = @import("../../Frame.zig");
|
||||
@@ -29,7 +29,7 @@ const GenericIterator = @import("iterator.zig").Entry;
|
||||
// No need to go through a TreeWalker or add any filtering.
|
||||
const ChildNodes = @This();
|
||||
|
||||
_arena: std.mem.Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_last_index: usize,
|
||||
_last_length: ?u32,
|
||||
_last_node: ?*Node,
|
||||
@@ -42,7 +42,7 @@ pub const EntryIterator = GenericIterator(Iterator, null);
|
||||
|
||||
pub fn init(node: *Node, frame: *Frame) !*ChildNodes {
|
||||
const arena = try frame.getArena(.small, "ChildNodes");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const self = try arena.create(ChildNodes);
|
||||
self.* = .{
|
||||
@@ -56,8 +56,8 @@ pub fn init(node: *Node, frame: *Frame) !*ChildNodes {
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *const ChildNodes, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *const ChildNodes, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn length(self: *ChildNodes, frame: *const Frame) !u32 {
|
||||
|
||||
@@ -28,7 +28,6 @@ pub const ValueIterator = GenericIterator(Iterator, "1");
|
||||
pub const EntryIterator = GenericIterator(Iterator, null);
|
||||
|
||||
const Execution = js.Execution;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
// not registered in collections.zig, because this is one of the rare
|
||||
// collections that's also available in Worker
|
||||
@@ -44,15 +43,15 @@ pub fn registerTypes() []const type {
|
||||
pub const DOMStringList = @This();
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_items: []const []const u8,
|
||||
|
||||
pub fn acquireRef(self: *DOMStringList) void {
|
||||
self._rc.acquire();
|
||||
}
|
||||
|
||||
pub fn deinit(self: *DOMStringList, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *DOMStringList, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *DOMStringList, page: *Page) void {
|
||||
|
||||
@@ -16,26 +16,23 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../../js/js.zig");
|
||||
const Page = @import("../../Page.zig");
|
||||
const Frame = @import("../../Frame.zig");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const FontFace = @This();
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_family: []const u8,
|
||||
|
||||
pub fn init(family: []const u8, source: []const u8, frame: *Frame) !*FontFace {
|
||||
_ = source;
|
||||
|
||||
const arena = try frame.getArena(.tiny, "FontFace");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const self = try arena.create(FontFace);
|
||||
self.* = .{
|
||||
@@ -45,8 +42,8 @@ pub fn init(family: []const u8, source: []const u8, frame: *Frame) !*FontFace {
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *FontFace, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *FontFace, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *FontFace, page: *Page) void {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../../js/js.zig");
|
||||
@@ -28,28 +27,26 @@ const EventTarget = @import("../EventTarget.zig");
|
||||
|
||||
const FontFace = @import("FontFace.zig");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const FontFaceSet = @This();
|
||||
|
||||
pub const Proto = EventTarget;
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_proto: *EventTarget,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
|
||||
pub fn init(frame: *Frame) !*FontFaceSet {
|
||||
const arena = try frame.getArena(.tiny, "FontFaceSet");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
return frame._factory.eventTargetWithAllocator(arena, FontFaceSet{
|
||||
return frame._factory.eventTargetWithAllocator(arena.allocator(), FontFaceSet{
|
||||
._proto = undefined,
|
||||
._arena = arena,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn deinit(self: *FontFaceSet, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *FontFaceSet, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *FontFaceSet, page: *Page) void {
|
||||
|
||||
@@ -24,13 +24,11 @@ const Page = @import("../../Page.zig");
|
||||
|
||||
const html5ever = @import("../../parser/html5ever.zig");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const TextDecoder = @This();
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_fatal: bool,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_ignore_bom: bool,
|
||||
_bom_seen: bool,
|
||||
_decoder: ?*anyopaque, // Persistent streaming decoder
|
||||
@@ -58,7 +56,7 @@ pub fn init(label_: ?[]const u8, opts_: ?InitOpts, page: *Page) !*TextDecoder {
|
||||
}
|
||||
|
||||
const arena = try page.getArena(.large, "TextDecoder");
|
||||
errdefer page.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const opts = opts_ orelse InitOpts{};
|
||||
const self = try arena.create(TextDecoder);
|
||||
@@ -75,11 +73,11 @@ pub fn init(label_: ?[]const u8, opts_: ?InitOpts, page: *Page) !*TextDecoder {
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *TextDecoder, page: *Page) void {
|
||||
pub fn deinit(self: *TextDecoder, _: *Page) void {
|
||||
if (self._decoder) |decoder| {
|
||||
html5ever.encoding_decoder_free(decoder);
|
||||
}
|
||||
page.releaseArena(self._arena);
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *TextDecoder, page: *Page) void {
|
||||
@@ -104,7 +102,7 @@ pub fn getEncoding(self: *TextDecoder) ![]const u8 {
|
||||
if (self._lowercase_name.len > 0) {
|
||||
return self._lowercase_name;
|
||||
}
|
||||
self._lowercase_name = try std.ascii.allocLowerString(self._arena, self._encoding_name);
|
||||
self._lowercase_name = try std.ascii.allocLowerString(self._arena.allocator(), self._encoding_name);
|
||||
return self._lowercase_name;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../../js/js.zig");
|
||||
@@ -25,7 +24,6 @@ const Frame = @import("../../Frame.zig");
|
||||
const Event = @import("../Event.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#the-beforeunloadevent-interface
|
||||
const BeforeUnloadEvent = @This();
|
||||
@@ -39,18 +37,18 @@ const Options = Event.inheritOptions(BeforeUnloadEvent, struct {});
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, frame: *Frame) !*BeforeUnloadEvent {
|
||||
const arena = try frame.getArena(.tiny, "BeforeUnloadEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, _opts, false, frame);
|
||||
}
|
||||
|
||||
pub fn initTrusted(typ: String, _opts: ?Options, frame: *Frame) !*BeforeUnloadEvent {
|
||||
const arena = try frame.getArena(.tiny, "BeforeUnloadEvent.trusted");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, _opts, true, frame);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*BeforeUnloadEvent {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*BeforeUnloadEvent {
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
const event = try frame._factory.event(
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const Page = @import("../../Page.zig");
|
||||
const Event = @import("../Event.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const CloseEvent = @This();
|
||||
|
||||
@@ -43,18 +41,18 @@ const Options = Event.inheritOptions(CloseEvent, CloseEventOptions);
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, page: *Page) !*CloseEvent {
|
||||
const arena = try page.getArena(.tiny, "CloseEvent");
|
||||
errdefer page.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, _opts, false, page);
|
||||
}
|
||||
|
||||
pub fn initTrusted(typ: String, _opts: ?Options, page: *Page) !*CloseEvent {
|
||||
const arena = try page.getArena(.tiny, "CloseEvent.trusted");
|
||||
errdefer page.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, _opts, true, page);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, _opts: ?Options, trusted: bool, page: *Page) !*CloseEvent {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, _opts: ?Options, trusted: bool, page: *Page) !*CloseEvent {
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
const event = try page.factory.event(
|
||||
|
||||
@@ -41,8 +41,8 @@ const Options = Event.inheritOptions(CompositionEvent, CompositionEventOptions);
|
||||
|
||||
pub fn init(typ: []const u8, opts_: ?Options, frame: *Frame) !*CompositionEvent {
|
||||
const arena = try frame.getArena(.tiny, "CompositionEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
|
||||
const opts = opts_ orelse Options{};
|
||||
const event = try frame._factory.uiEvent(
|
||||
@@ -82,7 +82,7 @@ pub fn initCompositionEvent(
|
||||
|
||||
const arena = event._arena;
|
||||
event._initialized = true;
|
||||
event._type_string = try String.init(arena, typ, .{});
|
||||
event._type_string = try String.init(arena.allocator(), typ, .{});
|
||||
event._bubbles = bubbles orelse false;
|
||||
event._cancelable = cancelable orelse false;
|
||||
ui._view = view;
|
||||
|
||||
@@ -47,8 +47,8 @@ const Options = Event.inheritOptions(CookieChangeEvent, CookieChangeEventOptions
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, exec: *const Execution) !*CookieChangeEvent {
|
||||
const arena = try exec.getArena(.tiny, "CookieChangeEvent");
|
||||
errdefer exec.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
@@ -57,8 +57,8 @@ pub fn init(typ: []const u8, _opts: ?Options, exec: *const Execution) !*CookieCh
|
||||
type_string,
|
||||
CookieChangeEvent{
|
||||
._proto = undefined,
|
||||
._changed = try cloneListItems(arena, opts.changed),
|
||||
._deleted = try cloneListItems(arena, opts.deleted),
|
||||
._changed = try cloneListItems(arena.allocator(), opts.changed),
|
||||
._deleted = try cloneListItems(arena.allocator(), opts.deleted),
|
||||
},
|
||||
);
|
||||
|
||||
@@ -75,20 +75,20 @@ pub fn initSingle(
|
||||
exec: *const Execution,
|
||||
) !*CookieChangeEvent {
|
||||
const arena = try exec.getArena(.tiny, "CookieChangeEvent");
|
||||
errdefer exec.releaseArena(arena);
|
||||
const type_string = try String.init(arena, "change", .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), "change", .{});
|
||||
|
||||
const item = try arena.create(CookieStore.CookieListItem);
|
||||
item.* = .{
|
||||
.name = try String.init(arena, snapshot.name, .{}),
|
||||
.name = try String.init(arena.allocator(), snapshot.name, .{}),
|
||||
// Deletions report no value (the `deleted` accessor serializes the
|
||||
// resulting null as undefined); changes carry the new value.
|
||||
.value = if (kind == .deleted) null else try String.init(arena, snapshot.value, .{}),
|
||||
.value = if (kind == .deleted) null else try String.init(arena.allocator(), snapshot.value, .{}),
|
||||
.domain = if (snapshot.domain.len > 0 and snapshot.domain[0] == '.')
|
||||
try String.init(arena, snapshot.domain[1..], .{})
|
||||
try String.init(arena.allocator(), snapshot.domain[1..], .{})
|
||||
else
|
||||
null,
|
||||
.path = try String.init(arena, snapshot.path, .{}),
|
||||
.path = try String.init(arena.allocator(), snapshot.path, .{}),
|
||||
.expires = null,
|
||||
.secure = snapshot.secure,
|
||||
.sameSite = switch (snapshot.same_site) {
|
||||
|
||||
@@ -43,15 +43,15 @@ const Options = Event.inheritOptions(CustomEvent, CustomEventOptions);
|
||||
|
||||
pub fn init(typ: []const u8, opts_: ?Options, page: *Page) !*CustomEvent {
|
||||
const arena = try page.getArena(.tiny, "CustomEvent");
|
||||
errdefer page.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
|
||||
const opts = opts_ orelse Options{};
|
||||
const event = try page.factory.event(
|
||||
arena,
|
||||
type_string,
|
||||
CustomEvent{
|
||||
._arena = arena,
|
||||
._arena = arena.allocator(),
|
||||
._proto = undefined,
|
||||
._detail = opts.detail,
|
||||
},
|
||||
@@ -76,7 +76,7 @@ pub fn initCustomEvent(
|
||||
// This function can only be called after the constructor has called.
|
||||
// So we assume proto is initialized already by constructor.
|
||||
self._proto._initialized = true;
|
||||
self._proto._type_string = try String.init(self._proto._arena, event_string, .{});
|
||||
self._proto._type_string = try String.init(self._proto._arena.allocator(), event_string, .{});
|
||||
self._proto._bubbles = bubbles orelse false;
|
||||
self._proto._cancelable = cancelable orelse false;
|
||||
// Detail is stored separately.
|
||||
|
||||
@@ -41,8 +41,8 @@ const Options = Event.inheritOptions(DeviceMotionEvent, DeviceMotionEventOptions
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, frame: *Frame) !*DeviceMotionEvent {
|
||||
const arena = try frame.getArena(.tiny, "DeviceMotionEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
|
||||
const opts = _opts orelse Options{};
|
||||
const event = try frame._factory.event(
|
||||
|
||||
@@ -47,8 +47,8 @@ const Options = Event.inheritOptions(DeviceOrientationEvent, DeviceOrientationEv
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, frame: *Frame) !*DeviceOrientationEvent {
|
||||
const arena = try frame.getArena(.tiny, "DeviceOrientationEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
|
||||
const opts = _opts orelse Options{};
|
||||
const event = try frame._factory.event(
|
||||
|
||||
@@ -51,8 +51,8 @@ pub fn initTrusted(typ: []const u8, _opts: ?Options, frame: *Frame) !*DragEvent
|
||||
|
||||
fn initWithTrusted(typ: []const u8, _opts: ?Options, trusted: bool, frame: *Frame) !*DragEvent {
|
||||
const arena = try frame.getArena(.medium, "DragEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
|
||||
@@ -51,25 +51,25 @@ const Options = Event.inheritOptions(ErrorEvent, ErrorEventOptions);
|
||||
|
||||
pub fn init(typ: []const u8, opts_: ?Options, page: *Page) !*ErrorEvent {
|
||||
const arena = try page.getArena(.small, "ErrorEvent");
|
||||
errdefer page.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, opts_, false, page);
|
||||
}
|
||||
|
||||
pub fn initTrusted(typ: String, opts_: ?Options, page: *Page) !*ErrorEvent {
|
||||
const arena = try page.getArena(.small, "ErrorEvent.trusted");
|
||||
errdefer page.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, opts_, true, page);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, opts_: ?Options, trusted: bool, page: *Page) !*ErrorEvent {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, opts_: ?Options, trusted: bool, page: *Page) !*ErrorEvent {
|
||||
const opts = opts_ orelse Options{};
|
||||
|
||||
const event = try page.factory.event(
|
||||
arena,
|
||||
typ,
|
||||
ErrorEvent{
|
||||
._arena = arena,
|
||||
._arena = arena.allocator(),
|
||||
._proto = undefined,
|
||||
._message = if (opts.message) |str| try arena.dupe(u8, str) else "",
|
||||
._filename = if (opts.filename) |str| try arena.dupe(u8, str) else "",
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../../js/js.zig");
|
||||
@@ -27,7 +26,6 @@ const EventTarget = @import("../EventTarget.zig");
|
||||
const UIEvent = @import("UIEvent.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const FocusEvent = @This();
|
||||
|
||||
@@ -47,18 +45,18 @@ pub const Options = Event.inheritOptions(
|
||||
|
||||
pub fn initTrusted(typ: String, _opts: ?Options, frame: *Frame) !*FocusEvent {
|
||||
const arena = try frame.getArena(.tiny, "FocusEvent.trusted");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, _opts, true, frame);
|
||||
}
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, frame: *Frame) !*FocusEvent {
|
||||
const arena = try frame.getArena(.tiny, "FocusEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, _opts, false, frame);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*FocusEvent {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*FocusEvent {
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
const event = try frame._factory.uiEvent(
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../../js/js.zig");
|
||||
@@ -27,7 +26,6 @@ const Event = @import("../Event.zig");
|
||||
const FormData = @import("../net/FormData.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
/// https://developer.mozilla.org/en-US/docs/Web/API/FormDataEvent
|
||||
const FormDataEvent = @This();
|
||||
@@ -43,18 +41,18 @@ const Options = Event.inheritOptions(FormDataEvent, struct {
|
||||
|
||||
pub fn init(typ: []const u8, maybe_options: Options, frame: *Frame) !*FormDataEvent {
|
||||
const arena = try frame.getArena(.tiny, "FormDataEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, maybe_options, false, frame);
|
||||
}
|
||||
|
||||
pub fn initTrusted(typ: String, _opts: ?Options, frame: *Frame) !*FormDataEvent {
|
||||
const arena = try frame.getArena(.tiny, "FormDataEvent.trusted");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, _opts, true, frame);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, maybe_options: ?Options, trusted: bool, frame: *Frame) !*FormDataEvent {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, maybe_options: ?Options, trusted: bool, frame: *Frame) !*FormDataEvent {
|
||||
const options = maybe_options orelse Options{};
|
||||
|
||||
const event = try frame._factory.event(
|
||||
|
||||
@@ -38,8 +38,8 @@ const Options = Event.inheritOptions(GamepadEvent, GamepadEventOptions);
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, frame: *Frame) !*GamepadEvent {
|
||||
const arena = try frame.getArena(.tiny, "GamepadEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
|
||||
const opts = _opts orelse Options{};
|
||||
const event = try frame._factory.event(
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../../js/js.zig");
|
||||
@@ -25,7 +24,6 @@ const Frame = @import("../../Frame.zig");
|
||||
const Event = @import("../Event.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/HashChangeEvent
|
||||
const HashChangeEvent = @This();
|
||||
@@ -45,18 +43,18 @@ const Options = Event.inheritOptions(HashChangeEvent, HashChangeEventOptions);
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, frame: *Frame) !*HashChangeEvent {
|
||||
const arena = try frame.getArena(.tiny, "HashChangeEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, _opts, false, frame);
|
||||
}
|
||||
|
||||
pub fn initTrusted(typ: String, _opts: ?Options, frame: *Frame) !*HashChangeEvent {
|
||||
const arena = try frame.getArena(.tiny, "HashChangeEvent.trusted");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, _opts, true, frame);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*HashChangeEvent {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*HashChangeEvent {
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
const event = try frame._factory.event(
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../../js/js.zig");
|
||||
@@ -28,7 +27,6 @@ const UIEvent = @import("UIEvent.zig");
|
||||
const DataTransfer = @import("../DataTransfer.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const InputEvent = @This();
|
||||
|
||||
@@ -54,18 +52,18 @@ const Options = Event.inheritOptions(
|
||||
|
||||
pub fn initTrusted(typ: String, _opts: ?Options, frame: *Frame) !*InputEvent {
|
||||
const arena = try frame.getArena(.tiny, "InputEvent.trusted");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, _opts, true, frame);
|
||||
}
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, frame: *Frame) !*InputEvent {
|
||||
const arena = try frame.getArena(.tiny, "InputEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, _opts, false, frame);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*InputEvent {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*InputEvent {
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
const event = try frame._factory.uiEvent(
|
||||
|
||||
@@ -26,7 +26,6 @@ const Event = @import("../Event.zig");
|
||||
const UIEvent = @import("UIEvent.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const KeyboardEvent = @This();
|
||||
|
||||
@@ -297,18 +296,18 @@ const Options = Event.inheritOptions(
|
||||
|
||||
pub fn initTrusted(typ: String, _opts: ?Options, frame: *Frame) !*KeyboardEvent {
|
||||
const arena = try frame.getArena(.tiny, "KeyboardEvent.trusted");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, _opts, true, frame);
|
||||
}
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, frame: *Frame) !*KeyboardEvent {
|
||||
const arena = try frame.getArena(.tiny, "KeyboardEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, _opts, false, frame);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*KeyboardEvent {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*KeyboardEvent {
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
const event = try frame._factory.uiEvent(
|
||||
@@ -316,7 +315,7 @@ fn initWithTrusted(arena: Allocator, typ: String, _opts: ?Options, trusted: bool
|
||||
typ,
|
||||
KeyboardEvent{
|
||||
._proto = undefined,
|
||||
._key = try Key.fromString(arena, opts.key),
|
||||
._key = try Key.fromString(arena.allocator(), opts.key),
|
||||
._location = opts.location,
|
||||
._code = if (opts.code) |c| try arena.dupe(u8, c) else "",
|
||||
._repeat = opts.repeat,
|
||||
@@ -431,11 +430,11 @@ pub fn initKeyboardEvent(
|
||||
|
||||
const arena = event._arena;
|
||||
event._initialized = true;
|
||||
event._type_string = try String.init(arena, typ, .{});
|
||||
event._type_string = try String.init(arena.allocator(), typ, .{});
|
||||
event._bubbles = bubbles orelse false;
|
||||
event._cancelable = cancelable orelse false;
|
||||
ui._view = view;
|
||||
self._key = try Key.fromString(arena, key orelse "");
|
||||
self._key = try Key.fromString(arena.allocator(), key orelse "");
|
||||
self._location = location orelse 0;
|
||||
self._ctrl_key = ctrl_key orelse false;
|
||||
self._alt_key = alt_key orelse false;
|
||||
@@ -444,7 +443,7 @@ pub fn initKeyboardEvent(
|
||||
}
|
||||
|
||||
pub fn getModifierState(self: *const KeyboardEvent, str: []const u8) !bool {
|
||||
const key = try Key.fromString(self._proto._proto._arena, str);
|
||||
const key = try Key.fromString(self._proto._proto._arena.allocator(), str);
|
||||
|
||||
switch (key) {
|
||||
.Alt, .AltGraph => return self._alt_key,
|
||||
|
||||
@@ -27,7 +27,6 @@ const MessagePort = @import("../MessagePort.zig");
|
||||
const Window = @import("../Window.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
|
||||
const MessageEvent = @This();
|
||||
@@ -65,18 +64,18 @@ const Options = Event.inheritOptions(MessageEvent, MessageEventOptions);
|
||||
|
||||
pub fn init(typ: []const u8, opts_: ?Options, page: *Page) !*MessageEvent {
|
||||
const arena = try page.getArena(.small, "MessageEvent");
|
||||
errdefer page.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, opts_, false, page);
|
||||
}
|
||||
|
||||
pub fn initTrusted(typ: String, opts_: ?Options, page: *Page) !*MessageEvent {
|
||||
const arena = try page.getArena(.small, "MessageEvent.trusted");
|
||||
errdefer page.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, opts_, true, page);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, opts_: ?Options, trusted: bool, page: *Page) !*MessageEvent {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, opts_: ?Options, trusted: bool, page: *Page) !*MessageEvent {
|
||||
const opts = opts_ orelse Options{};
|
||||
|
||||
const event = try page.factory.event(
|
||||
|
||||
@@ -29,7 +29,6 @@ const UIEvent = @import("UIEvent.zig");
|
||||
const PointerEvent = @import("PointerEvent.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const MouseEvent = @This();
|
||||
|
||||
@@ -89,18 +88,18 @@ pub const Options = Event.inheritOptions(
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, frame: *Frame) !*MouseEvent {
|
||||
const arena = try frame.getArena(.tiny, "MouseEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, _opts, false, frame);
|
||||
}
|
||||
|
||||
pub fn initTrusted(typ: String, _opts: ?Options, frame: *Frame) !*MouseEvent {
|
||||
const arena = try frame.getArena(.tiny, "MouseEvent.trusted");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, _opts, true, frame);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*MouseEvent {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*MouseEvent {
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
const event = try frame._factory.uiEvent(
|
||||
@@ -242,7 +241,7 @@ pub fn initMouseEvent(
|
||||
}
|
||||
|
||||
event._initialized = true;
|
||||
event._type_string = try String.init(event._arena, typ, .{});
|
||||
event._type_string = try String.init(event._arena.allocator(), typ, .{});
|
||||
event._bubbles = bubbles orelse false;
|
||||
event._cancelable = cancelable orelse false;
|
||||
ui._view = view;
|
||||
|
||||
@@ -27,7 +27,6 @@ const NavigationHistoryEntry = @import("../navigation/NavigationHistoryEntry.zig
|
||||
const NavigationType = @import("../navigation/root.zig").NavigationType;
|
||||
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const NavigationCurrentEntryChangeEvent = @This();
|
||||
|
||||
@@ -49,19 +48,19 @@ const Options = Event.inheritOptions(
|
||||
|
||||
pub fn init(typ: []const u8, opts: Options, frame: *Frame) !*NavigationCurrentEntryChangeEvent {
|
||||
const arena = try frame.getArena(.tiny, "NavigationCurrentEntryChangeEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, opts, false, frame);
|
||||
}
|
||||
|
||||
pub fn initTrusted(typ: String, opts: Options, frame: *Frame) !*NavigationCurrentEntryChangeEvent {
|
||||
const arena = try frame.getArena(.tiny, "NavigationCurrentEntryChangeEvent.trusted");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, opts, true, frame);
|
||||
}
|
||||
|
||||
fn initWithTrusted(
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
typ: String,
|
||||
opts: Options,
|
||||
trusted: bool,
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../../js/js.zig");
|
||||
@@ -25,7 +24,6 @@ const Frame = @import("../../Frame.zig");
|
||||
const Event = @import("../Event.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/PageTransitionEvent
|
||||
const PageTransitionEvent = @This();
|
||||
@@ -43,18 +41,18 @@ const Options = Event.inheritOptions(PageTransitionEvent, PageTransitionEventOpt
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, frame: *Frame) !*PageTransitionEvent {
|
||||
const arena = try frame.getArena(.tiny, "PageTransitionEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, _opts, false, frame);
|
||||
}
|
||||
|
||||
pub fn initTrusted(typ: String, _opts: ?Options, frame: *Frame) !*PageTransitionEvent {
|
||||
const arena = try frame.getArena(.tiny, "PageTransitionEvent.trusted");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, _opts, true, frame);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*PageTransitionEvent {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*PageTransitionEvent {
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
const event = try frame._factory.event(
|
||||
|
||||
@@ -97,8 +97,8 @@ pub fn initTrusted(typ: []const u8, _opts: ?Options, frame: *Frame) !*PointerEve
|
||||
|
||||
fn initWithTrusted(typ: []const u8, _opts: ?Options, trusted: bool, frame: *Frame) !*PointerEvent {
|
||||
const arena = try frame.getArena(.tiny, "PointerEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
|
||||
const opts = _opts orelse Options{};
|
||||
const event = try frame._factory.mouseEvent(
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../../js/js.zig");
|
||||
@@ -25,7 +24,6 @@ const Frame = @import("../../Frame.zig");
|
||||
const Event = @import("../Event.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/PopStateEvent
|
||||
const PopStateEvent = @This();
|
||||
@@ -43,18 +41,18 @@ const Options = Event.inheritOptions(PopStateEvent, PopStateEventOptions);
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, frame: *Frame) !*PopStateEvent {
|
||||
const arena = try frame.getArena(.tiny, "PopStateEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, _opts, false, frame);
|
||||
}
|
||||
|
||||
pub fn initTrusted(typ: String, _opts: ?Options, frame: *Frame) !*PopStateEvent {
|
||||
const arena = try frame.getArena(.tiny, "PopStateEvent.trusted");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, _opts, true, frame);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*PopStateEvent {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*PopStateEvent {
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
const event = try frame._factory.event(
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const Page = @import("../../Page.zig");
|
||||
const Event = @import("../Event.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const ProgressEvent = @This();
|
||||
|
||||
@@ -43,18 +41,18 @@ const Options = Event.inheritOptions(ProgressEvent, ProgressEventOptions);
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, page: *Page) !*ProgressEvent {
|
||||
const arena = try page.getArena(.tiny, "ProgressEvent");
|
||||
errdefer page.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, _opts, false, page);
|
||||
}
|
||||
|
||||
pub fn initTrusted(typ: String, _opts: ?Options, page: *Page) !*ProgressEvent {
|
||||
const arena = try page.getArena(.tiny, "ProgressEvent.trusted");
|
||||
errdefer page.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, _opts, true, page);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, _opts: ?Options, trusted: bool, page: *Page) !*ProgressEvent {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, _opts: ?Options, trusted: bool, page: *Page) !*ProgressEvent {
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
const event = try page.factory.event(
|
||||
|
||||
@@ -41,8 +41,8 @@ const Options = Event.inheritOptions(PromiseRejectionEvent, PromiseRejectionEven
|
||||
|
||||
pub fn init(typ: []const u8, opts_: ?Options, page: *Page) !*PromiseRejectionEvent {
|
||||
const arena = try page.getArena(.tiny, "PromiseRejectionEvent");
|
||||
errdefer page.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
|
||||
const opts = opts_ orelse Options{};
|
||||
const event = try page.factory.event(
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../../js/js.zig");
|
||||
@@ -25,7 +24,6 @@ const Frame = @import("../../Frame.zig");
|
||||
const Event = @import("../Event.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/webstorage.html#the-storageevent-interface
|
||||
const StorageEvent = @This();
|
||||
@@ -49,18 +47,18 @@ const Options = Event.inheritOptions(StorageEvent, StorageEventOptions);
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, frame: *Frame) !*StorageEvent {
|
||||
const arena = try frame.getArena(.tiny, "StorageEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, _opts, false, frame);
|
||||
}
|
||||
|
||||
pub fn initTrusted(typ: String, _opts: ?Options, frame: *Frame) !*StorageEvent {
|
||||
const arena = try frame.getArena(.tiny, "StorageEvent.trusted");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, _opts, true, frame);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*StorageEvent {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*StorageEvent {
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
const event = try frame._factory.event(
|
||||
@@ -121,7 +119,7 @@ pub fn initStorageEvent(
|
||||
|
||||
const arena = event._arena;
|
||||
event._initialized = true;
|
||||
event._type_string = try String.init(arena, typ, .{});
|
||||
event._type_string = try String.init(arena.allocator(), typ, .{});
|
||||
event._bubbles = bubbles orelse false;
|
||||
event._cancelable = cancelable orelse false;
|
||||
self._key = if (key) |k| try arena.dupe(u8, k) else null;
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../../js/js.zig");
|
||||
@@ -26,7 +25,6 @@ const Event = @import("../Event.zig");
|
||||
const HtmlElement = @import("../element/Html.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
/// https://developer.mozilla.org/en-US/docs/Web/API/SubmitEvent
|
||||
const SubmitEvent = @This();
|
||||
@@ -44,18 +42,18 @@ const Options = Event.inheritOptions(SubmitEvent, SubmitEventOptions);
|
||||
|
||||
pub fn init(typ: []const u8, opts_: ?Options, frame: *Frame) !*SubmitEvent {
|
||||
const arena = try frame.getArena(.tiny, "SubmitEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, opts_, false, frame);
|
||||
}
|
||||
|
||||
pub fn initTrusted(typ: String, _opts: ?Options, frame: *Frame) !*SubmitEvent {
|
||||
const arena = try frame.getArena(.tiny, "SubmitEvent.trusted");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, _opts, true, frame);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*SubmitEvent {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*SubmitEvent {
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
const event = try frame._factory.event(
|
||||
|
||||
@@ -44,8 +44,8 @@ pub const Options = Event.inheritOptions(
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, frame: *Frame) !*TextEvent {
|
||||
const arena = try frame.getArena(.tiny, "TextEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
@@ -86,7 +86,7 @@ pub fn initTextEvent(
|
||||
|
||||
const arena = event._arena;
|
||||
event._initialized = true;
|
||||
event._type_string = try String.init(arena, typ, .{});
|
||||
event._type_string = try String.init(arena.allocator(), typ, .{});
|
||||
event._bubbles = bubbles orelse false;
|
||||
event._cancelable = cancelable orelse false;
|
||||
ui._view = view;
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../../js/js.zig");
|
||||
@@ -26,7 +25,6 @@ const Event = @import("../Event.zig");
|
||||
const HtmlElement = @import("../element/Html.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
/// https://html.spec.whatwg.org/multipage/popover.html#toggleevent
|
||||
const ToggleEvent = @This();
|
||||
@@ -48,18 +46,18 @@ const Options = Event.inheritOptions(ToggleEvent, ToggleEventOptions);
|
||||
|
||||
pub fn init(typ: []const u8, opts_: ?Options, frame: *Frame) !*ToggleEvent {
|
||||
const arena = try frame.getArena(.tiny, "ToggleEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
return initWithTrusted(arena, type_string, opts_, false, frame);
|
||||
}
|
||||
|
||||
pub fn initTrusted(typ: String, _opts: ?Options, frame: *Frame) !*ToggleEvent {
|
||||
const arena = try frame.getArena(.tiny, "ToggleEvent.trusted");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return initWithTrusted(arena, typ, _opts, true, frame);
|
||||
}
|
||||
|
||||
fn initWithTrusted(arena: Allocator, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*ToggleEvent {
|
||||
fn initWithTrusted(arena: *lp.Arena, typ: String, _opts: ?Options, trusted: bool, frame: *Frame) !*ToggleEvent {
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
const event = try frame._factory.event(
|
||||
|
||||
@@ -60,8 +60,8 @@ pub fn initTrusted(typ: []const u8, _opts: ?Options, frame: *Frame) !*TouchEvent
|
||||
|
||||
fn initWithTrusted(typ: []const u8, _opts: ?Options, trusted: bool, frame: *Frame) !*TouchEvent {
|
||||
const arena = try frame.getArena(.tiny, "TouchEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
|
||||
const opts = _opts orelse Options{};
|
||||
const event = try frame._factory.uiEvent(
|
||||
|
||||
@@ -58,8 +58,8 @@ pub const Options = Event.inheritOptions(
|
||||
|
||||
pub fn init(typ: []const u8, _opts: ?Options, frame: *Frame) !*UIEvent {
|
||||
const arena = try frame.getArena(.tiny, "UIEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
|
||||
const opts = _opts orelse Options{};
|
||||
const event = try frame._factory.event(
|
||||
@@ -151,7 +151,7 @@ pub fn initUIEvent(
|
||||
}
|
||||
|
||||
event._initialized = true;
|
||||
event._type_string = try String.init(event._arena, typ, .{});
|
||||
event._type_string = try String.init(event._arena.allocator(), typ, .{});
|
||||
event._bubbles = bubbles orelse false;
|
||||
event._cancelable = cancelable orelse false;
|
||||
self._view = view;
|
||||
|
||||
@@ -62,8 +62,8 @@ pub fn initTrusted(typ: []const u8, _opts: ?Options, frame: *Frame) !*WheelEvent
|
||||
|
||||
fn initWithTrusted(typ: []const u8, _opts: ?Options, trusted: bool, frame: *Frame) !*WheelEvent {
|
||||
const arena = try frame.getArena(.medium, "WheelEvent");
|
||||
errdefer frame.releaseArena(arena);
|
||||
const type_string = try String.init(arena, typ, .{});
|
||||
errdefer arena.release();
|
||||
const type_string = try String.init(arena.allocator(), typ, .{});
|
||||
|
||||
const opts = _opts orelse Options{};
|
||||
|
||||
|
||||
@@ -213,9 +213,9 @@ pub fn pushEntry(
|
||||
const id = self._next_entry_id;
|
||||
self._next_entry_id += 1;
|
||||
|
||||
const id_str = try std.fmt.allocPrint(arena, "{d}", .{id});
|
||||
const id_str = try std.fmt.allocPrint(arena.allocator(), "{d}", .{id});
|
||||
|
||||
const entry = try Factory.chainedWithAllocator(arena, .{
|
||||
const entry = try Factory.chainedWithAllocator(arena.allocator(), .{
|
||||
EventTarget{ ._type = undefined },
|
||||
NavigationHistoryEntry{
|
||||
._proto = undefined,
|
||||
@@ -229,7 +229,7 @@ pub fn pushEntry(
|
||||
|
||||
// we don't always have a current entry...
|
||||
const previous = if (self._entries.items.len > 0) self.getCurrentEntry() else null;
|
||||
try self._entries.append(arena, entry);
|
||||
try self._entries.append(arena.allocator(), entry);
|
||||
self._index = index;
|
||||
|
||||
if (previous != null and should_dispatch) {
|
||||
@@ -260,9 +260,9 @@ pub fn replaceEntry(
|
||||
|
||||
const id = self._next_entry_id;
|
||||
self._next_entry_id += 1;
|
||||
const id_str = try std.fmt.allocPrint(arena, "{d}", .{id});
|
||||
const id_str = try std.fmt.allocPrint(arena.allocator(), "{d}", .{id});
|
||||
|
||||
const entry = try Factory.chainedWithAllocator(arena, .{
|
||||
const entry = try Factory.chainedWithAllocator(arena.allocator(), .{
|
||||
EventTarget{ ._type = undefined },
|
||||
NavigationHistoryEntry{
|
||||
._proto = undefined,
|
||||
@@ -320,7 +320,7 @@ pub fn navigateInner(
|
||||
const committed = local.createPromiseResolver();
|
||||
const finished = local.createPromiseResolver();
|
||||
|
||||
var new_url = try URL.resolve(arena, frame.url, url, .{});
|
||||
var new_url = try URL.resolve(arena.allocator(), frame.url, url, .{});
|
||||
const is_same_document = URL.eqlDocument(new_url, frame.url);
|
||||
|
||||
// In case of navigation to the same document, we force an url duplication.
|
||||
@@ -406,7 +406,7 @@ pub fn navigateInner(
|
||||
pub fn navigate(self: *Navigation, _url: [:0]const u8, _opts: ?NavigateOptions, frame: *Frame) !NavigationReturn {
|
||||
const arena = frame._session.arena;
|
||||
const opts = _opts orelse NavigateOptions{};
|
||||
const json = if (opts.state) |state| state.toJson(arena) catch return error.DataClone else null;
|
||||
const json = if (opts.state) |state| state.toJson(arena.allocator()) catch return error.DataClone else null;
|
||||
|
||||
const kind: NavigationKind = if (opts.history) |history|
|
||||
if (std.mem.eql(u8, "replace", history)) .{ .replace = json } else .{ .push = json }
|
||||
@@ -469,7 +469,7 @@ pub fn updateCurrentEntry(self: *Navigation, options: UpdateCurrentEntryOptions,
|
||||
const previous = self.getCurrentEntry();
|
||||
self.getCurrentEntry()._state = .{
|
||||
.source = .navigation,
|
||||
.value = options.state.toJson(arena) catch return error.DataClone,
|
||||
.value = options.state.toJson(arena.allocator()) catch return error.DataClone,
|
||||
};
|
||||
|
||||
if (self._on_currententrychange) |cec| {
|
||||
|
||||
@@ -33,7 +33,6 @@ const MessageEvent = @import("../event/MessageEvent.zig");
|
||||
const log = lp.log;
|
||||
const String = lp.String;
|
||||
const Execution = js.Execution;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/server-sent-events.html
|
||||
@@ -44,7 +43,7 @@ pub const Proto = EventTarget;
|
||||
_rc: lp.RC = .{},
|
||||
_exec: *const Execution,
|
||||
_proto: *EventTarget,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
|
||||
_url: [:0]const u8,
|
||||
_with_credentials: bool = false,
|
||||
@@ -96,13 +95,13 @@ const Opts = struct {
|
||||
|
||||
pub fn init(url: []const u8, opts_: ?Opts, exec: *const Execution) !*EventSource {
|
||||
const arena = try exec.getArena(.medium, "EventSource");
|
||||
errdefer exec.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const resolved = URL.resolve(arena, exec.base(), url, .{ .encoding = exec.charset.* }) catch {
|
||||
const resolved = URL.resolve(arena.allocator(), exec.base(), url, .{ .encoding = exec.charset.* }) catch {
|
||||
return error.SyntaxError;
|
||||
};
|
||||
|
||||
const self = try exec._factory.eventTargetWithAllocator(arena, EventSource{
|
||||
const self = try exec._factory.eventTargetWithAllocator(arena.allocator(), EventSource{
|
||||
._exec = exec,
|
||||
._arena = arena,
|
||||
._proto = undefined,
|
||||
@@ -130,7 +129,7 @@ pub fn init(url: []const u8, opts_: ?Opts, exec: *const Execution) !*EventSource
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *EventSource, page: *Page) void {
|
||||
pub fn deinit(self: *EventSource, _: *Page) void {
|
||||
self._ready_state = .closed;
|
||||
if (self._transfer) |transfer| {
|
||||
self._transfer = null;
|
||||
@@ -147,7 +146,7 @@ pub fn deinit(self: *EventSource, page: *Page) void {
|
||||
func.release();
|
||||
}
|
||||
|
||||
page.releaseArena(self._arena);
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *EventSource, page: *Page) void {
|
||||
@@ -174,7 +173,7 @@ fn connect(self: *EventSource) !void {
|
||||
self._event_type_buf.clearRetainingCapacity();
|
||||
|
||||
self._id_buf.clearRetainingCapacity();
|
||||
try self._id_buf.appendSlice(self._arena, self._last_event_id.items);
|
||||
try self._id_buf.appendSlice(self._arena.allocator(), self._last_event_id.items);
|
||||
|
||||
var headers = try http_client.newHeaders();
|
||||
try headers.add("Accept: text/event-stream");
|
||||
@@ -344,7 +343,7 @@ fn httpHeaderDoneCallback(transfer: *Transfer) !Transfer.HeaderResult {
|
||||
defer ls.deinit();
|
||||
|
||||
const final_url = try self._arena.dupeZ(u8, transfer.req.url);
|
||||
self._event_origin = (URL.getOrigin(self._arena, final_url) catch null) orelse "";
|
||||
self._event_origin = (URL.getOrigin(self._arena.allocator(), final_url) catch null) orelse "";
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/server-sent-events.html#announce-the-connection
|
||||
self._ready_state = .open;
|
||||
@@ -463,7 +462,7 @@ fn bufferLine(self: *EventSource, bytes: []const u8) !void {
|
||||
if (self._line_buf.items.len + bytes.len > self._max_response_size) {
|
||||
return error.ResponseTooLarge;
|
||||
}
|
||||
return self._line_buf.appendSlice(self._arena, bytes);
|
||||
return self._line_buf.appendSlice(self._arena.allocator(), bytes);
|
||||
}
|
||||
|
||||
fn processLine(self: *EventSource) !void {
|
||||
@@ -501,20 +500,20 @@ fn processLine(self: *EventSource) !void {
|
||||
if (self._data_buf.items.len + add_len > self._max_response_size) {
|
||||
return error.ResponseTooLarge;
|
||||
}
|
||||
try self._data_buf.ensureUnusedCapacity(arena, add_len);
|
||||
try self._data_buf.ensureUnusedCapacity(arena.allocator(), add_len);
|
||||
self._data_buf.appendSliceAssumeCapacity(value);
|
||||
self._data_buf.appendAssumeCapacity('\n');
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, field, "event")) {
|
||||
self._event_type_buf.clearRetainingCapacity();
|
||||
try self._event_type_buf.appendSlice(arena, value);
|
||||
try self._event_type_buf.appendSlice(arena.allocator(), value);
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, field, "id")) {
|
||||
if (std.mem.indexOfScalar(u8, value, 0) == null) {
|
||||
self._id_buf.clearRetainingCapacity();
|
||||
try self._id_buf.appendSlice(arena, value);
|
||||
try self._id_buf.appendSlice(arena.allocator(), value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -529,7 +528,7 @@ fn processLine(self: *EventSource) !void {
|
||||
// An empty line completed an event block.
|
||||
fn dispatchPending(self: *EventSource) !void {
|
||||
self._last_event_id.clearRetainingCapacity();
|
||||
try self._last_event_id.appendSlice(self._arena, self._id_buf.items);
|
||||
try self._last_event_id.appendSlice(self._arena.allocator(), self._id_buf.items);
|
||||
|
||||
const data = self._data_buf.items;
|
||||
if (data.len == 0) {
|
||||
|
||||
@@ -152,7 +152,7 @@ fn httpHeaderDoneCallback(transfer: *Transfer) !Transfer.HeaderResult {
|
||||
|
||||
const arena = self._response._arena;
|
||||
if (transfer.getContentLength()) |cl| {
|
||||
try self._buf.ensureTotalCapacity(arena, cl);
|
||||
try self._buf.ensureTotalCapacity(arena.allocator(), cl);
|
||||
}
|
||||
|
||||
const res = self._response;
|
||||
@@ -183,8 +183,8 @@ fn httpHeaderDoneCallback(transfer: *Transfer) !Transfer.HeaderResult {
|
||||
|
||||
// Determine response type based on origin comparison
|
||||
const exec = self._exec;
|
||||
const requesting_origin = URL.getOrigin(arena, exec.url.*) catch null;
|
||||
const response_origin = URL.getOrigin(arena, res._url) catch null;
|
||||
const requesting_origin = URL.getOrigin(arena.allocator(), exec.url.*) catch null;
|
||||
const response_origin = URL.getOrigin(arena.allocator(), res._url) catch null;
|
||||
|
||||
if (requesting_origin) |fo| {
|
||||
if (response_origin) |ro| {
|
||||
@@ -218,7 +218,7 @@ fn httpDataCallback(transfer: *Transfer, data: []const u8) !void {
|
||||
}
|
||||
}
|
||||
|
||||
try self._buf.appendSlice(self._response._arena, data);
|
||||
try self._buf.appendSlice(self._response._arena.allocator(), data);
|
||||
}
|
||||
|
||||
fn httpDoneCallback(ctx: *anyopaque) !void {
|
||||
|
||||
@@ -40,7 +40,7 @@ const FormData = @This();
|
||||
|
||||
_rc: lp.RC,
|
||||
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_entries: std.ArrayList(Entry),
|
||||
|
||||
pub const Entry = struct {
|
||||
@@ -77,7 +77,7 @@ pub const Entry = struct {
|
||||
|
||||
pub fn init(form_: ?*Form, submitter: ?*Element, exec: *const Execution) !*FormData {
|
||||
const arena = try exec.getArena(.small, "FormData");
|
||||
errdefer exec.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const form_data = try arena.create(FormData);
|
||||
form_data.* = .{
|
||||
@@ -101,7 +101,7 @@ pub fn init(form_: ?*Form, submitter: ?*Element, exec: *const Execution) !*FormD
|
||||
form._constructing_entry_list = true;
|
||||
defer form._constructing_entry_list = false;
|
||||
|
||||
form_data._entries = try collectForm(arena, form, submitter, frame);
|
||||
form_data._entries = try collectForm(arena.allocator(), form, submitter, frame);
|
||||
|
||||
// Hold a reference on each entry's File for the FormData's lifetime; released
|
||||
// in deinit.
|
||||
@@ -126,7 +126,7 @@ pub fn init(form_: ?*Form, submitter: ?*Element, exec: *const Execution) !*FormD
|
||||
// application/x-www-form-urlencoded body back into a FormData.
|
||||
pub fn initFromUrlEncoded(bytes: []const u8, exec: *const Execution) !*FormData {
|
||||
const arena = try exec.getArena(.small, "FormData");
|
||||
errdefer exec.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const form_data = try arena.create(FormData);
|
||||
form_data.* = .{
|
||||
@@ -142,7 +142,7 @@ pub fn initFromUrlEncoded(bytes: []const u8, exec: *const Execution) !*FormData
|
||||
// body back into a FormData. `boundary` is the Content-Type boundary param.
|
||||
pub fn initFromMultipart(bytes: []const u8, boundary: []const u8, exec: *const Execution) !*FormData {
|
||||
const arena = try exec.getArena(.small, "FormData");
|
||||
errdefer exec.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const form_data = try arena.create(FormData);
|
||||
form_data.* = .{
|
||||
@@ -170,7 +170,7 @@ pub fn deinit(self: *FormData, page: *Page) void {
|
||||
}
|
||||
}
|
||||
// Frees the entry list and this FormData itself; do not touch self afterwards.
|
||||
page.releaseArena(self._arena);
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *FormData, page: *Page) void {
|
||||
@@ -238,11 +238,11 @@ pub fn append(self: *FormData, name: []const u8, value: EntryValue, filename: ?[
|
||||
// A Blob that is not a File becomes a File named "blob".
|
||||
break :blk .{ .file = try fileFrom(blob, "blob", exec.page) };
|
||||
},
|
||||
.bytes => |b| .{ .string = try String.init(self._arena, b, .{}) },
|
||||
.bytes => |b| .{ .string = try String.init(self._arena.allocator(), b, .{}) },
|
||||
};
|
||||
|
||||
try self._entries.append(self._arena, .{
|
||||
.name = try String.init(self._arena, name, .{}),
|
||||
try self._entries.append(self._arena.allocator(), .{
|
||||
.name = try String.init(self._arena.allocator(), name, .{}),
|
||||
.value = entry_value,
|
||||
});
|
||||
}
|
||||
@@ -252,9 +252,9 @@ pub fn append(self: *FormData, name: []const u8, value: EntryValue, filename: ?[
|
||||
// the entry owns that reference and deleteByName releases it.
|
||||
fn fileFrom(source: *Blob, name: []const u8, page: *Page) !*File {
|
||||
const arena = try page.getArena(source._slice.len + source._mime.len + 256, "Blob");
|
||||
errdefer page.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const file = try Factory.chainedWithAllocator(arena, .{
|
||||
const file = try Factory.chainedWithAllocator(arena.allocator(), .{
|
||||
try Blob.buildValueFromBytes(arena, source._slice, source._mime),
|
||||
File{
|
||||
._proto = undefined,
|
||||
@@ -268,9 +268,9 @@ fn fileFrom(source: *Blob, name: []const u8, page: *Page) !*File {
|
||||
}
|
||||
|
||||
pub fn appendText(self: *FormData, name: []const u8, value: []const u8) !void {
|
||||
try self._entries.append(self._arena, .{
|
||||
.name = try String.init(self._arena, name, .{}),
|
||||
.value = .{ .string = try String.init(self._arena, value, .{}) },
|
||||
try self._entries.append(self._arena.allocator(), .{
|
||||
.name = try String.init(self._arena.allocator(), name, .{}),
|
||||
.value = .{ .string = try String.init(self._arena.allocator(), value, .{}) },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -444,11 +444,11 @@ pub fn parseUrlEncoded(self: *FormData, bytes: []const u8) !void {
|
||||
}
|
||||
if (std.mem.indexOfScalar(u8, pair, '=')) |idx| {
|
||||
try self.appendText(
|
||||
try urlDecode(self._arena, pair[0..idx]),
|
||||
try urlDecode(self._arena, pair[idx + 1 ..]),
|
||||
try urlDecode(self._arena.allocator(), pair[0..idx]),
|
||||
try urlDecode(self._arena.allocator(), pair[idx + 1 ..]),
|
||||
);
|
||||
} else {
|
||||
const key = try urlDecode(self._arena, pair);
|
||||
const key = try urlDecode(self._arena.allocator(), pair);
|
||||
// Insert with empty value.
|
||||
try self.appendText(key, "");
|
||||
}
|
||||
@@ -605,7 +605,7 @@ fn parseMultipart(self: *FormData, page: *Page, bytes: []const u8, boundary: []c
|
||||
}
|
||||
|
||||
const parsed = disposition orelse return error.InvalidFormData;
|
||||
const name = try decodeMultipartName(self._arena, parsed.name orelse return error.InvalidFormData);
|
||||
const name = try decodeMultipartName(self._arena.allocator(), parsed.name orelse return error.InvalidFormData);
|
||||
|
||||
const content_end = indexOfBoundary(cursor.remaining(), boundary) orelse return error.InvalidFormData;
|
||||
const content = cursor.remaining()[0..content_end];
|
||||
@@ -619,14 +619,14 @@ fn parseMultipart(self: *FormData, page: *Page, bytes: []const u8, boundary: []c
|
||||
const file = try blob._arena.create(File);
|
||||
file.* = .{
|
||||
._proto = blob,
|
||||
._name = try blob._arena.dupe(u8, try decodeMultipartName(self._arena, filename)),
|
||||
._name = try blob._arena.dupe(u8, try decodeMultipartName(self._arena.allocator(), filename)),
|
||||
._last_modified = @intCast(lp.datetime.milliTimestamp(.real)),
|
||||
};
|
||||
blob._type = .{ .file = file };
|
||||
|
||||
file.acquireRef();
|
||||
try self._entries.append(self._arena, .{
|
||||
.name = try String.init(self._arena, name, .{}),
|
||||
try self._entries.append(self._arena.allocator(), .{
|
||||
.name = try String.init(self._arena.allocator(), name, .{}),
|
||||
.value = .{ .file = file },
|
||||
});
|
||||
} else {
|
||||
@@ -875,10 +875,12 @@ test "WebApi: FormData" {
|
||||
|
||||
test "FormData: multipart write" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
try fd.appendText("name", "John");
|
||||
@@ -904,10 +906,12 @@ test "FormData: multipart write" {
|
||||
|
||||
test "FormData: multipart escapes name CR/LF/quote" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
try fd.appendText("a\"b\r\nc", "v");
|
||||
@@ -929,10 +933,12 @@ test "FormData: multipart escapes name CR/LF/quote" {
|
||||
|
||||
test "FormData: multipart empty body" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
|
||||
@@ -947,7 +953,7 @@ test "FormData: multipart empty body" {
|
||||
|
||||
fn buildTestFile(arena: Allocator, page: *@import("../../Page.zig"), name: []const u8, mime: []const u8, body: []const u8) !*File {
|
||||
const blob_arena = try page.getArena(body.len + mime.len + 256, "Blob");
|
||||
const file = try Factory.chainedWithAllocator(blob_arena, .{
|
||||
const file = try Factory.chainedWithAllocator(blob_arena.allocator(), .{
|
||||
try Blob.buildValueFromBytes(blob_arena, body, mime),
|
||||
File{
|
||||
._proto = undefined,
|
||||
@@ -962,6 +968,8 @@ fn buildTestFile(arena: Allocator, page: *@import("../../Page.zig"), name: []con
|
||||
|
||||
test "FormData: multipart with file" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
const frame = try testing.createFrame();
|
||||
defer testing.test_session.closeAllPages();
|
||||
|
||||
@@ -970,7 +978,7 @@ test "FormData: multipart with file" {
|
||||
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
try fd.appendText("field", "value");
|
||||
@@ -1000,6 +1008,8 @@ test "FormData: multipart with file" {
|
||||
|
||||
test "FormData: multipart with empty file defaults to octet-stream" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
const frame = try testing.createFrame();
|
||||
defer testing.test_session.closeAllPages();
|
||||
|
||||
@@ -1008,7 +1018,7 @@ test "FormData: multipart with empty file defaults to octet-stream" {
|
||||
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
try fd._entries.append(allocator, .{
|
||||
@@ -1034,6 +1044,8 @@ test "FormData: multipart with empty file defaults to octet-stream" {
|
||||
|
||||
test "FormData: multipart escapes file name and filename" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
const frame = try testing.createFrame();
|
||||
defer testing.test_session.closeAllPages();
|
||||
|
||||
@@ -1042,7 +1054,7 @@ test "FormData: multipart escapes file name and filename" {
|
||||
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
try fd._entries.append(allocator, .{
|
||||
@@ -1068,6 +1080,8 @@ test "FormData: multipart escapes file name and filename" {
|
||||
|
||||
test "FormData: file entry collapses to filename in urlencode" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
const frame = try testing.createFrame();
|
||||
defer testing.test_session.closeAllPages();
|
||||
|
||||
@@ -1076,7 +1090,7 @@ test "FormData: file entry collapses to filename in urlencode" {
|
||||
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
try fd._entries.append(allocator, .{
|
||||
@@ -1091,10 +1105,12 @@ test "FormData: file entry collapses to filename in urlencode" {
|
||||
|
||||
test "FormData: multipart no_file (unselected file input)" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
try fd._entries.append(allocator, .{
|
||||
@@ -1120,10 +1136,12 @@ test "FormData: multipart no_file (unselected file input)" {
|
||||
|
||||
test "FormData: no_file entry collapses to empty in urlencode" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
try fd._entries.append(allocator, .{
|
||||
@@ -1138,10 +1156,12 @@ test "FormData: no_file entry collapses to empty in urlencode" {
|
||||
|
||||
test "FormData: plaintext write" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
try fd.appendText("name", "John");
|
||||
@@ -1164,10 +1184,12 @@ test "FormData: plaintext write" {
|
||||
|
||||
test "FormData: plaintext empty body" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
|
||||
@@ -1178,11 +1200,12 @@ test "FormData: plaintext empty body" {
|
||||
}
|
||||
|
||||
test "FormData: urlencoded parse" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
try fd.parseUrlEncoded("a=1&b=hello+world&c=%26%3D&no_value&&bad=100%zz");
|
||||
@@ -1197,11 +1220,12 @@ test "FormData: urlencoded parse" {
|
||||
}
|
||||
|
||||
test "FormData: urlencoded parse exercises the vectorized guard" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
// Values longer than any SIMD vector length, with the lone special
|
||||
@@ -1217,13 +1241,14 @@ test "FormData: urlencoded parse exercises the vectorized guard" {
|
||||
}
|
||||
|
||||
test "FormData: multipart parse" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
const frame = try testing.createFrame();
|
||||
defer testing.test_session.closeAllPages();
|
||||
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
try fd.parseMultipart(frame._page, "--BOUNDARY\r\n" ++
|
||||
@@ -1247,13 +1272,14 @@ test "FormData: multipart parse" {
|
||||
}
|
||||
|
||||
test "FormData: multipart parse with file" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
const frame = try testing.createFrame();
|
||||
defer testing.test_session.closeAllPages();
|
||||
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
try fd.parseMultipart(frame._page, "--B\r\n" ++
|
||||
@@ -1285,7 +1311,8 @@ test "FormData: multipart parse with file" {
|
||||
}
|
||||
|
||||
test "FormData: multipart parse rejects malformed bodies" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
const frame = try testing.createFrame();
|
||||
defer testing.test_session.closeAllPages();
|
||||
|
||||
@@ -1300,7 +1327,7 @@ test "FormData: multipart parse rejects malformed bodies" {
|
||||
for (cases) |case| {
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
try testing.expectError(error.InvalidFormData, fd.parseMultipart(frame._page, case, "B"));
|
||||
@@ -1309,12 +1336,14 @@ test "FormData: multipart parse rejects malformed bodies" {
|
||||
|
||||
test "FormData: multipart round-trip" {
|
||||
const allocator = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "FormData test");
|
||||
defer arena.release();
|
||||
const frame = try testing.createFrame();
|
||||
defer testing.test_session.closeAllPages();
|
||||
|
||||
var src = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
try src.appendText("username", "alice");
|
||||
@@ -1332,7 +1361,7 @@ test "FormData: multipart round-trip" {
|
||||
|
||||
var fd = FormData{
|
||||
._rc = .{},
|
||||
._arena = allocator,
|
||||
._arena = arena,
|
||||
._entries = .empty,
|
||||
};
|
||||
try fd.parseMultipart(frame._page, buf.written(), "BOUNDARY");
|
||||
|
||||
@@ -34,7 +34,6 @@ const body_init = @import("body_init.zig");
|
||||
const BodyInit = body_init.BodyInit;
|
||||
|
||||
const Execution = js.Execution;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const Request = @This();
|
||||
|
||||
@@ -43,7 +42,7 @@ _url: [:0]const u8,
|
||||
_method: http.Method,
|
||||
_headers: ?*Headers,
|
||||
_body: ?[]const u8,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_cache: Cache,
|
||||
_credentials: Credentials,
|
||||
_redirect: Redirect,
|
||||
@@ -94,10 +93,10 @@ const Cache = enum {
|
||||
|
||||
pub fn init(input: Input, opts_: ?InitOpts, exec: *const Execution) !*Request {
|
||||
const arena = try exec.getArena(.medium, "Request");
|
||||
errdefer exec.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const url = switch (input) {
|
||||
.url => |u| try URL.resolve(arena, exec.base(), u, .{ .encoding = exec.charset.* }),
|
||||
.url => |u| try URL.resolve(arena.allocator(), exec.base(), u, .{ .encoding = exec.charset.* }),
|
||||
.request => |r| try arena.dupeZ(u8, r._url),
|
||||
};
|
||||
|
||||
@@ -124,7 +123,7 @@ pub fn init(input: Input, opts_: ?InitOpts, exec: *const Execution) !*Request {
|
||||
};
|
||||
|
||||
const body = if (opts.body) |b| blk: {
|
||||
const extracted = try b.extract(arena);
|
||||
const extracted = try b.extract(arena.allocator());
|
||||
// Per Fetch §6.5 step 11, the default Content-Type only applies if
|
||||
// the user has not already set one via the headers init dict.
|
||||
if (extracted.content_type) |ct| {
|
||||
@@ -164,8 +163,8 @@ pub fn init(input: Input, opts_: ?InitOpts, exec: *const Execution) !*Request {
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Request, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *Request, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *Request, page: *Page) void {
|
||||
@@ -345,7 +344,7 @@ pub fn formData(self: *Request, exec: *const Execution) !js.Promise {
|
||||
|
||||
pub fn clone(self: *const Request, exec: *const Execution) !*Request {
|
||||
const arena = try exec.getArena(if (self._body) |b| b.len else 512, "Request.clone");
|
||||
errdefer exec.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const request = try arena.create(Request);
|
||||
request.* = .{
|
||||
|
||||
@@ -49,7 +49,7 @@ pub const Type = enum {
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_status: u16,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_headers: *Headers,
|
||||
_body: Body = .empty,
|
||||
_type: Type,
|
||||
@@ -76,7 +76,7 @@ pub const BodyInit = body_init.BodyInit;
|
||||
pub fn init(body_: ?BodyInit, opts_: ?InitOpts, exec: *const Execution) !*Response {
|
||||
const session = exec.session;
|
||||
const arena = try session.getArena(.large, "Response");
|
||||
errdefer session.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const opts = opts_ orelse InitOpts{};
|
||||
const status_text = if (opts.statusText) |st| try arena.dupe(u8, st) else "";
|
||||
@@ -87,7 +87,7 @@ pub fn init(body_: ?BodyInit, opts_: ?InitOpts, exec: *const Execution) !*Respon
|
||||
switch (b) {
|
||||
.stream => |stream| break :blk .{ .stream = stream },
|
||||
else => {
|
||||
const extracted = try b.extract(arena);
|
||||
const extracted = try b.extract(arena.allocator());
|
||||
content_type = extracted.content_type;
|
||||
break :blk .{ .bytes = extracted.bytes };
|
||||
},
|
||||
@@ -118,7 +118,7 @@ pub fn init(body_: ?BodyInit, opts_: ?InitOpts, exec: *const Execution) !*Respon
|
||||
pub fn createError(exec: *const Execution) !*Response {
|
||||
const session = exec.session;
|
||||
const arena = try session.getArena(.large, "Response.error");
|
||||
errdefer session.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const self = try arena.create(Response);
|
||||
self.* = .{
|
||||
@@ -143,9 +143,9 @@ pub fn createRedirect(url_: []const u8, status_: ?u16, exec: *const Execution) !
|
||||
|
||||
const session = exec.session;
|
||||
const arena = try session.getArena(.large, "Response.redirect");
|
||||
errdefer session.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const location = try URL.resolve(arena, exec.base(), url_, .{ .encoding = exec.charset.* });
|
||||
const location = try URL.resolve(arena.allocator(), exec.base(), url_, .{ .encoding = exec.charset.* });
|
||||
|
||||
const headers = try Headers.init(null, exec);
|
||||
try headers.set("location", location, exec);
|
||||
@@ -167,9 +167,9 @@ pub fn createRedirect(url_: []const u8, status_: ?u16, exec: *const Execution) !
|
||||
pub fn createJson(data: js.Value, opts_: ?InitOpts, exec: *const Execution) !*Response {
|
||||
const session = exec.session;
|
||||
const arena = try session.getArena(.medium, "Response.json");
|
||||
errdefer session.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const json = data.toJson(arena) catch |err| switch (err) {
|
||||
const json = data.toJson(arena.allocator()) catch |err| switch (err) {
|
||||
error.JsException => return error.TryCatchRethrow,
|
||||
else => return err,
|
||||
};
|
||||
@@ -199,12 +199,12 @@ pub fn createJson(data: js.Value, opts_: ?InitOpts, exec: *const Execution) !*Re
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Response, page: *Page) void {
|
||||
pub fn deinit(self: *Response, _: *Page) void {
|
||||
if (self._http_transfer) |resp| {
|
||||
resp.abort(error.Abort);
|
||||
self._http_transfer = null;
|
||||
}
|
||||
page.releaseArena(self._arena);
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *Response, page: *Page) void {
|
||||
@@ -509,7 +509,7 @@ pub fn clone(self: *const Response, exec: *const Execution) !*Response {
|
||||
.stream => 0,
|
||||
};
|
||||
const arena = try session.getArena(body_len + self._url.len + 256, "Response.clone");
|
||||
errdefer session.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const body: Body = switch (self._body) {
|
||||
.bytes => |b| .{ .bytes = try arena.dupe(u8, b) },
|
||||
|
||||
@@ -42,7 +42,7 @@ pub fn registerTypes() []const type {
|
||||
const URLSearchParams = @This();
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_params: KeyValueList,
|
||||
|
||||
const InitOpts = union(enum) {
|
||||
@@ -53,17 +53,17 @@ const InitOpts = union(enum) {
|
||||
|
||||
pub fn init(opts_: ?InitOpts, exec: *const Execution) !*URLSearchParams {
|
||||
const arena = try exec.getArena(.small, "URLSearchParams");
|
||||
errdefer exec.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const params: KeyValueList = blk: {
|
||||
const opts = opts_ orelse break :blk .empty;
|
||||
switch (opts) {
|
||||
.query_string => |qs| break :blk try paramsFromString(arena, qs, exec.buf),
|
||||
.form_data => |fd| break :blk try fd.toKeyValueList(arena),
|
||||
.query_string => |qs| break :blk try paramsFromString(arena.allocator(), qs, exec.buf),
|
||||
.form_data => |fd| break :blk try fd.toKeyValueList(arena.allocator()),
|
||||
.value => |js_val| {
|
||||
// Order matters here; Array is also an Object.
|
||||
if (js_val.isArray()) {
|
||||
break :blk try paramsFromArray(arena, js_val.toArray());
|
||||
break :blk try paramsFromArray(arena.allocator(), js_val.toArray());
|
||||
}
|
||||
if (js_val.isObject()) {
|
||||
// Per the URL spec, an iterable init (URLSearchParams,
|
||||
@@ -73,13 +73,13 @@ pub fn init(opts_: ?InitOpts, exec: *const Execution) !*URLSearchParams {
|
||||
// the prototype-method-leak doesn't just turn into a
|
||||
// silent empty querystring.
|
||||
if (js_val.toZig(*URLSearchParams)) |other| {
|
||||
break :blk try KeyValueList.copy(arena, other._params);
|
||||
break :blk try KeyValueList.copy(arena.allocator(), other._params);
|
||||
} else |_| {}
|
||||
// normalizer is null, so frame won't be used
|
||||
break :blk try KeyValueList.fromJsObject(arena, js_val.toObject(), null, exec.buf);
|
||||
break :blk try KeyValueList.fromJsObject(arena.allocator(), js_val.toObject(), null, exec.buf);
|
||||
}
|
||||
if (js_val.isString()) |js_str| {
|
||||
break :blk try paramsFromString(arena, try js_str.toSliceWithAlloc(arena), exec.buf);
|
||||
break :blk try paramsFromString(arena.allocator(), try js_str.toSliceWithAlloc(arena.allocator()), exec.buf);
|
||||
}
|
||||
return error.InvalidArgument;
|
||||
},
|
||||
@@ -94,8 +94,8 @@ pub fn init(opts_: ?InitOpts, exec: *const Execution) !*URLSearchParams {
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *URLSearchParams, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *URLSearchParams, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *URLSearchParams, page: *Page) void {
|
||||
@@ -107,7 +107,7 @@ pub fn acquireRef(self: *URLSearchParams) void {
|
||||
}
|
||||
|
||||
pub fn updateFromString(self: *URLSearchParams, query_string: []const u8, exec: *const Execution) !void {
|
||||
self._params = try paramsFromString(self._arena, query_string, exec.buf);
|
||||
self._params = try paramsFromString(self._arena.allocator(), query_string, exec.buf);
|
||||
}
|
||||
|
||||
pub fn getSize(self: *const URLSearchParams) usize {
|
||||
@@ -127,11 +127,11 @@ pub fn has(self: *const URLSearchParams, name: []const u8) bool {
|
||||
}
|
||||
|
||||
pub fn set(self: *URLSearchParams, name: []const u8, value: []const u8) !void {
|
||||
return self._params.set(self._arena, name, value);
|
||||
return self._params.set(self._arena.allocator(), name, value);
|
||||
}
|
||||
|
||||
pub fn append(self: *URLSearchParams, name: []const u8, value: []const u8) !void {
|
||||
return self._params.append(self._arena, name, value);
|
||||
return self._params.append(self._arena.allocator(), name, value);
|
||||
}
|
||||
|
||||
pub fn delete(self: *URLSearchParams, name: []const u8, value: ?[]const u8) void {
|
||||
|
||||
@@ -35,7 +35,6 @@ const MessageEvent = @import("../event/MessageEvent.zig");
|
||||
|
||||
const log = lp.log;
|
||||
const Execution = js.Execution;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
|
||||
const WebSocket = @This();
|
||||
@@ -45,7 +44,7 @@ pub const Proto = EventTarget;
|
||||
_rc: lp.RC = .{},
|
||||
_exec: *const Execution,
|
||||
_proto: *EventTarget,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
|
||||
// Connection state
|
||||
_ready_state: ReadyState = .connecting,
|
||||
@@ -74,7 +73,7 @@ _recv_buffer: std.ArrayList(u8) = .empty,
|
||||
_events: std.ArrayList(RecvEvent) = .empty,
|
||||
|
||||
// data is dupe'd by the _batch_arena and re-used after every delivery
|
||||
_batch_arena: ?Allocator = null,
|
||||
_batch_arena: ?*lp.Arena = null,
|
||||
_batch_bytes: usize = 0,
|
||||
|
||||
// Linked into the client's ws_dispatch_queue while events await delivery.
|
||||
@@ -153,11 +152,11 @@ pub fn init(url: []const u8, protocols: [][]const u8, exec: *const Execution) !*
|
||||
}
|
||||
|
||||
const arena = try exec.getArena(.medium, "WebSocket");
|
||||
errdefer exec.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
|
||||
const resolved_url = blk: {
|
||||
// Always UTF-8, never the document's charse
|
||||
const resolved = URL.resolve(arena, exec.base(), url, .{ .encoding = "UTF-8" }) catch |err| switch (err) {
|
||||
const resolved = URL.resolve(arena.allocator(), exec.base(), url, .{ .encoding = "UTF-8" }) catch |err| switch (err) {
|
||||
error.TypeError => return error.SyntaxError,
|
||||
else => return err,
|
||||
};
|
||||
@@ -170,10 +169,10 @@ pub fn init(url: []const u8, protocols: [][]const u8, exec: *const Execution) !*
|
||||
|
||||
// yup, this is what we're supposed to do.
|
||||
if (std.mem.eql(u8, scheme, "http:")) {
|
||||
break :blk try std.fmt.allocPrintSentinel(arena, "ws{s}", .{resolved["http".len..]}, 0);
|
||||
break :blk try std.fmt.allocPrintSentinel(arena.allocator(), "ws{s}", .{resolved["http".len..]}, 0);
|
||||
}
|
||||
if (std.mem.eql(u8, scheme, "https:")) {
|
||||
break :blk try std.fmt.allocPrintSentinel(arena, "wss{s}", .{resolved["https".len..]}, 0);
|
||||
break :blk try std.fmt.allocPrintSentinel(arena.allocator(), "wss{s}", .{resolved["https".len..]}, 0);
|
||||
}
|
||||
|
||||
return error.SyntaxError;
|
||||
@@ -181,7 +180,7 @@ pub fn init(url: []const u8, protocols: [][]const u8, exec: *const Execution) !*
|
||||
|
||||
const http_client = &exec.session.browser.http_client;
|
||||
|
||||
const self = try exec._factory.eventTargetWithAllocator(arena, WebSocket{
|
||||
const self = try exec._factory.eventTargetWithAllocator(arena.allocator(), WebSocket{
|
||||
._exec = exec,
|
||||
._conn = null,
|
||||
._arena = arena,
|
||||
@@ -193,7 +192,7 @@ pub fn init(url: []const u8, protocols: [][]const u8, exec: *const Execution) !*
|
||||
|
||||
// This ensures that if we fail to connect, we have at least 1 event slot
|
||||
// to register the close+error
|
||||
try self._events.ensureTotalCapacity(arena, 1);
|
||||
try self._events.ensureTotalCapacity(arena.allocator(), 1);
|
||||
|
||||
exec.httpOwner().addWS(self);
|
||||
|
||||
@@ -244,7 +243,7 @@ fn connect(self: *WebSocket, protocols: [][]const u8) !void {
|
||||
errdefer headers.deinit();
|
||||
|
||||
if (protocols.len > 0) {
|
||||
const header = try std.fmt.allocPrintSentinel(arena, "Sec-WebSocket-Protocol: {s}", .{try std.mem.join(arena, ", ", protocols)}, 0);
|
||||
const header = try std.fmt.allocPrintSentinel(arena.allocator(), "Sec-WebSocket-Protocol: {s}", .{try std.mem.join(arena.allocator(), ", ", protocols)}, 0);
|
||||
try headers.add(header);
|
||||
}
|
||||
|
||||
@@ -254,13 +253,13 @@ fn connect(self: *WebSocket, protocols: [][]const u8) !void {
|
||||
// protection on WS servers) reject upgrades that arrive without it.
|
||||
// Non-tuple origins (about:blank, data:) serialize to "null", like
|
||||
// Chrome sends for opaque origins.
|
||||
const origin = (try URL.getOrigin(arena, exec.url.*)) orelse "null";
|
||||
const header = try std.fmt.allocPrintSentinel(arena, "Origin: {s}", .{origin}, 0);
|
||||
const origin = (try URL.getOrigin(arena.allocator(), exec.url.*)) orelse "null";
|
||||
const header = try std.fmt.allocPrintSentinel(arena.allocator(), "Origin: {s}", .{origin}, 0);
|
||||
try headers.add(header);
|
||||
}
|
||||
|
||||
{
|
||||
var buf: std.Io.Writer.Allocating = .init(arena);
|
||||
var buf: std.Io.Writer.Allocating = .init(arena.allocator());
|
||||
try exec.session.cookie_jar.forRequest(resolved_url, &buf.writer, .{
|
||||
.is_http = true,
|
||||
.is_navigation = false,
|
||||
@@ -312,10 +311,10 @@ pub fn deinit(self: *WebSocket, page: *Page) void {
|
||||
}
|
||||
|
||||
if (self._batch_arena) |arena| {
|
||||
page.releaseArena(arena);
|
||||
arena.release();
|
||||
}
|
||||
|
||||
page.releaseArena(self._arena);
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *WebSocket, page: *Page) void {
|
||||
@@ -470,7 +469,7 @@ fn releaseTransport(self: *WebSocket) void {
|
||||
// callback return value — never tear down from here, the pump may still be
|
||||
// inside curl.
|
||||
fn bufferEvent(self: *WebSocket, event: RecvEvent) !void {
|
||||
try self._events.append(self._arena, event);
|
||||
try self._events.append(self._arena.allocator(), event);
|
||||
self.enqueueDispatch();
|
||||
}
|
||||
|
||||
@@ -518,13 +517,13 @@ fn clearEvents(self: *WebSocket) void {
|
||||
self._batch_bytes = 0;
|
||||
if (self._batch_arena) |arena| {
|
||||
self._batch_arena = null;
|
||||
self._exec.releaseArena(arena);
|
||||
arena.release();
|
||||
}
|
||||
}
|
||||
|
||||
fn queueMessage(self: *WebSocket, msg: Message) !void {
|
||||
const was_empty = self._send_queue.items.len == 0;
|
||||
try self._send_queue.append(self._arena, msg);
|
||||
try self._send_queue.append(self._arena.allocator(), msg);
|
||||
|
||||
if (was_empty) {
|
||||
// Unpause the send callback so libcurl will request data
|
||||
@@ -587,7 +586,7 @@ pub fn send(self: *WebSocket, data: SendData) !void {
|
||||
switch (data) {
|
||||
.blob => |blob| {
|
||||
const arena = try self._exec.getArena(blob._slice.len, "WebSocket.message");
|
||||
errdefer self._exec.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
try self.queueMessage(.{ .binary = .{
|
||||
.arena = arena,
|
||||
.data = try arena.dupe(u8, blob._slice),
|
||||
@@ -596,17 +595,17 @@ pub fn send(self: *WebSocket, data: SendData) !void {
|
||||
.js_val => |js_val| {
|
||||
if (js_val.isString()) |str| {
|
||||
const arena = try self._exec.getArena(str.len(), "WebSocket.message");
|
||||
errdefer self._exec.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
try self.queueMessage(.{ .text = .{
|
||||
.arena = arena,
|
||||
.data = try str.toSliceWithAlloc(arena),
|
||||
.data = try str.toSliceWithAlloc(arena.allocator()),
|
||||
} });
|
||||
} else {
|
||||
const binary = try js_val.toZig(BinaryData);
|
||||
const buffer = binary.asBuffer();
|
||||
|
||||
const arena = try self._exec.getArena(buffer.len, "WebSocket.message");
|
||||
errdefer self._exec.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
try self.queueMessage(.{ .binary = .{
|
||||
.arena = arena,
|
||||
.data = try arena.dupe(u8, buffer),
|
||||
@@ -907,10 +906,10 @@ fn _receivedDataCallback(conn: *http.Connection, data: []const u8) !void {
|
||||
if (meta.len > self._http_client.max_response_size) {
|
||||
return error.MessageTooLarge;
|
||||
}
|
||||
try self._recv_buffer.ensureTotalCapacity(self._arena, meta.len);
|
||||
try self._recv_buffer.ensureTotalCapacity(self._arena.allocator(), meta.len);
|
||||
}
|
||||
|
||||
try self._recv_buffer.appendSlice(self._arena, data);
|
||||
try self._recv_buffer.appendSlice(self._arena.allocator(), data);
|
||||
|
||||
if (meta.bytes_left > 0) {
|
||||
// still more data waiting for this frame
|
||||
@@ -1001,12 +1000,12 @@ const Message = union(enum) {
|
||||
binary: Content,
|
||||
|
||||
const Content = struct {
|
||||
arena: Allocator,
|
||||
arena: *lp.Arena,
|
||||
data: []const u8,
|
||||
};
|
||||
fn deinit(self: Message, page: *Page) void {
|
||||
fn deinit(self: Message, _: *Page) void {
|
||||
switch (self) {
|
||||
.text, .binary => |msg| page.releaseArena(msg.arena),
|
||||
.text, .binary => |msg| msg.arena.release(),
|
||||
.close => {},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ const XMLHttpRequestUpload = @import("XMLHttpRequestUpload.zig");
|
||||
|
||||
const log = lp.log;
|
||||
const Execution = js.Execution;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
|
||||
const XMLHttpRequest = @This();
|
||||
@@ -49,7 +48,7 @@ _rc: lp.RC = .{},
|
||||
_exec: *const Execution,
|
||||
_proto: *XMLHttpRequestEventTarget,
|
||||
_upload: ?*XMLHttpRequestUpload = null,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
_http_transfer: ?*Transfer = null,
|
||||
|
||||
// number of inflight requests, we can have multiple, e.g. xhr calling its own
|
||||
@@ -110,8 +109,8 @@ const ResponseType = enum {
|
||||
|
||||
pub fn init(exec: *const Execution) !*XMLHttpRequest {
|
||||
const arena = try exec.getArena(.large, "XMLHttpRequest");
|
||||
errdefer exec.releaseArena(arena);
|
||||
const self = try exec._factory.xhrEventTarget(arena, XMLHttpRequest{
|
||||
errdefer arena.release();
|
||||
const self = try exec._factory.xhrEventTarget(arena.allocator(), XMLHttpRequest{
|
||||
._exec = exec,
|
||||
._arena = arena,
|
||||
._proto = undefined,
|
||||
@@ -120,7 +119,7 @@ pub fn init(exec: *const Execution) !*XMLHttpRequest {
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *XMLHttpRequest, page: *Page) void {
|
||||
pub fn deinit(self: *XMLHttpRequest, _: *Page) void {
|
||||
if (self._http_transfer) |resp| {
|
||||
resp.abort(error.Abort);
|
||||
self._http_transfer = null;
|
||||
@@ -134,7 +133,7 @@ pub fn deinit(self: *XMLHttpRequest, page: *Page) void {
|
||||
if (self._upload) |upload| {
|
||||
upload._proto.releaseListeners();
|
||||
}
|
||||
page.releaseArena(self._arena);
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
fn releaseSelfRef(self: *XMLHttpRequest) void {
|
||||
@@ -212,7 +211,7 @@ pub fn open(self: *XMLHttpRequest, method_: []const u8, url: [:0]const u8) !void
|
||||
|
||||
const exec = self._exec;
|
||||
self._method = try parseMethod(method_);
|
||||
self._url = try URL.resolve(self._arena, exec.base(), url, .{ .encoding = exec.charset.* });
|
||||
self._url = try URL.resolve(self._arena.allocator(), exec.base(), url, .{ .encoding = exec.charset.* });
|
||||
try self.stateChanged(.opened, exec);
|
||||
}
|
||||
|
||||
@@ -242,7 +241,7 @@ pub fn send(self: *XMLHttpRequest, body_: ?BodyInit, exec_: *const Execution) !v
|
||||
|
||||
if (body_) |b| {
|
||||
if (self._method != .GET and self._method != .HEAD) {
|
||||
const extracted = try b.extract(self._arena);
|
||||
const extracted = try b.extract(self._arena.allocator());
|
||||
self._request_body = extracted.bytes;
|
||||
// Per XHR §4.7.6 "send()" step 4, the default Content-Type only
|
||||
// applies if the author hasn't already set one via
|
||||
@@ -322,7 +321,7 @@ pub fn getUpload(self: *XMLHttpRequest) !*XMLHttpRequestUpload {
|
||||
return upload;
|
||||
}
|
||||
const upload = try self._exec._factory.xhrEventTarget(
|
||||
self._arena,
|
||||
self._arena.allocator(),
|
||||
XMLHttpRequestUpload{ ._proto = undefined, ._xhr = self },
|
||||
);
|
||||
self._upload = upload;
|
||||
@@ -529,14 +528,14 @@ fn httpHeaderDoneCallback(transfer: *Transfer) !Transfer.HeaderResult {
|
||||
|
||||
var it = transfer.responseHeaderIterator();
|
||||
while (it.next()) |hdr| {
|
||||
const joined = try std.fmt.allocPrint(self._arena, "{s}: {s}", .{ hdr.name, hdr.value });
|
||||
try self._response_headers.append(self._arena, joined);
|
||||
const joined = try std.fmt.allocPrint(self._arena.allocator(), "{s}: {s}", .{ hdr.name, hdr.value });
|
||||
try self._response_headers.append(self._arena.allocator(), joined);
|
||||
}
|
||||
|
||||
self._response_status = transfer.responseStatus().?;
|
||||
if (transfer.getContentLength()) |cl| {
|
||||
self._response_len = cl;
|
||||
try self._response_data.ensureTotalCapacity(self._arena, cl);
|
||||
try self._response_data.ensureTotalCapacity(self._arena.allocator(), cl);
|
||||
}
|
||||
self._response_url = try self._arena.dupeZ(u8, transfer.req.url);
|
||||
|
||||
@@ -555,7 +554,7 @@ fn httpHeaderDoneCallback(transfer: *Transfer) !Transfer.HeaderResult {
|
||||
|
||||
fn httpDataCallback(transfer: *Transfer, data: []const u8) !void {
|
||||
const self: *XMLHttpRequest = @ptrCast(@alignCast(transfer.req.ctx));
|
||||
try self._response_data.appendSlice(self._arena, data);
|
||||
try self._response_data.appendSlice(self._arena.allocator(), data);
|
||||
|
||||
try self._proto.dispatch(.progress, .{
|
||||
.total = self._response_len orelse 0,
|
||||
|
||||
@@ -144,28 +144,30 @@ test "BodyInit: bytes pass through with text/plain" {
|
||||
|
||||
test "BodyInit: URLSearchParams emit urlencoded body + content-type" {
|
||||
defer testing.reset();
|
||||
const arena = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "body_init test");
|
||||
defer arena.release();
|
||||
|
||||
const usp = try arena.create(URLSearchParams);
|
||||
usp.* = .{ ._arena = arena, ._params = .empty };
|
||||
try usp.append("a", "1");
|
||||
try usp.append("b", "2");
|
||||
|
||||
const r = try (BodyInit{ .url_search_params = usp }).extract(arena);
|
||||
const r = try (BodyInit{ .url_search_params = usp }).extract(arena.allocator());
|
||||
try testing.expectString("a=1&b=2", r.bytes);
|
||||
try testing.expectString("application/x-www-form-urlencoded;charset=UTF-8", r.content_type.?);
|
||||
}
|
||||
|
||||
test "BodyInit: FormData emits multipart with random boundary" {
|
||||
defer testing.reset();
|
||||
const arena = testing.arena_allocator;
|
||||
const arena = try testing.test_app.arena_pool.acquire(.small, "body_init test");
|
||||
defer arena.release();
|
||||
|
||||
const fd = try arena.create(FormData);
|
||||
fd.* = .{ ._rc = .{}, ._arena = arena, ._entries = .empty };
|
||||
try fd.appendText("username", "alice");
|
||||
try fd.appendText("email", "alice@example.com");
|
||||
|
||||
const r = try (BodyInit{ .form_data = fd }).extract(arena);
|
||||
const r = try (BodyInit{ .form_data = fd }).extract(arena.allocator());
|
||||
|
||||
// Body must contain the entries' Content-Disposition lines and end with
|
||||
// the closing boundary marker.
|
||||
@@ -177,7 +179,7 @@ test "BodyInit: FormData emits multipart with random boundary" {
|
||||
try testing.expect(std.mem.indexOf(u8, r.bytes, "Content-Disposition: form-data; name=\"email\"") != null);
|
||||
try testing.expect(std.mem.indexOf(u8, r.bytes, "alice") != null);
|
||||
try testing.expect(std.mem.indexOf(u8, r.bytes, "alice@example.com") != null);
|
||||
const closer = try std.fmt.allocPrint(arena, "--{s}--\r\n", .{boundary});
|
||||
const closer = try std.fmt.allocPrint(arena.allocator(), "--{s}--\r\n", .{boundary});
|
||||
try testing.expect(std.mem.endsWith(u8, r.bytes, closer));
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const Page = @import("../../Page.zig");
|
||||
const Frame = @import("../../Frame.zig");
|
||||
@@ -27,12 +28,10 @@ const Selector = @import("Selector.zig");
|
||||
const TreeWalker = @import("../TreeWalker.zig").Full;
|
||||
const GenericIterator = @import("../collections/iterator.zig").Entry;
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const List = @This();
|
||||
|
||||
_nodes: []const *Node,
|
||||
_arena: Allocator,
|
||||
_arena: *lp.Arena,
|
||||
// For the [somewhat common] case where we just have an #id selector
|
||||
// we can avoid allocating a slice and just use this.
|
||||
_single_node: [1]*Node = undefined,
|
||||
@@ -41,8 +40,8 @@ pub const EntryIterator = GenericIterator(Iterator, null);
|
||||
pub const KeyIterator = GenericIterator(Iterator, "0");
|
||||
pub const ValueIterator = GenericIterator(Iterator, "1");
|
||||
|
||||
pub fn deinit(self: *const List, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
pub fn deinit(self: *const List, _: *Page) void {
|
||||
self._arena.release();
|
||||
}
|
||||
|
||||
pub fn collect(
|
||||
|
||||
@@ -113,10 +113,10 @@ pub const Cache = struct {
|
||||
}
|
||||
};
|
||||
|
||||
fn collectAll(arena: Allocator, selectors: []const Selector, root: *Node, frame: *Frame) !*List {
|
||||
fn collectAll(arena: *lp.Arena, selectors: []const Selector, root: *Node, frame: *Frame) !*List {
|
||||
var nodes: std.AutoArrayHashMapUnmanaged(*Node, void) = .empty;
|
||||
for (selectors) |selector| {
|
||||
try List.collect(arena, root, selector, &nodes, frame);
|
||||
try List.collect(arena.allocator(), root, selector, &nodes, frame);
|
||||
}
|
||||
|
||||
const list = try arena.create(List);
|
||||
@@ -142,7 +142,7 @@ pub fn querySelector(root: *Node, input: []const u8, frame: *Frame) !?*Node.Elem
|
||||
|
||||
pub fn querySelectorAll(root: *Node, input: []const u8, frame: *Frame) !*List {
|
||||
const arena = try frame.getArena(.small, "querySelectorAll");
|
||||
errdefer frame.releaseArena(arena);
|
||||
errdefer arena.release();
|
||||
return collectAll(arena, try cachedParse(frame._session.browser, input), root, frame);
|
||||
}
|
||||
|
||||
@@ -171,8 +171,8 @@ pub fn querySelectorAllUncached(root: *Node, input: []const u8, frame: *Frame) !
|
||||
return error.SyntaxError;
|
||||
}
|
||||
const arena = try frame.getArena(.small, "querySelectorAllUncached");
|
||||
errdefer frame.releaseArena(arena);
|
||||
return collectAll(arena, try Parser.parseList(arena, input), root, frame);
|
||||
errdefer arena.release();
|
||||
return collectAll(arena, try Parser.parseList(arena.allocator(), input), root, frame);
|
||||
}
|
||||
|
||||
pub fn matchesUncached(arena: Allocator, el: *Node.Element, input: []const u8, frame: *Frame) !bool {
|
||||
|
||||
Loaded 100 of 123 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user