mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-22 04:34:44 +00:00
Merge pull request #1522 from lightpanda-io/remove_page_reset
Some checks failed
e2e-test / zig build release (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
e2e-test / cdp-and-hyperfine-bench (push) Has been cancelled
e2e-test / perf-fmt (push) Has been cancelled
e2e-test / browser fetch (push) Has been cancelled
zig-test / zig test using v8 in debug mode (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
Some checks failed
e2e-test / zig build release (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
e2e-test / cdp-and-hyperfine-bench (push) Has been cancelled
e2e-test / perf-fmt (push) Has been cancelled
e2e-test / browser fetch (push) Has been cancelled
zig-test / zig test using v8 in debug mode (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
Remove Page.reset
This commit is contained in:
@@ -66,13 +66,13 @@ lookup: std.HashMapUnmanaged(
|
|||||||
dispatch_depth: usize,
|
dispatch_depth: usize,
|
||||||
deferred_removals: std.ArrayList(struct { list: *std.DoublyLinkedList, listener: *Listener }),
|
deferred_removals: std.ArrayList(struct { list: *std.DoublyLinkedList, listener: *Listener }),
|
||||||
|
|
||||||
pub fn init(page: *Page) EventManager {
|
pub fn init(arena: Allocator, page: *Page) EventManager {
|
||||||
return .{
|
return .{
|
||||||
.page = page,
|
.page = page,
|
||||||
.lookup = .{},
|
.lookup = .{},
|
||||||
.arena = page.arena,
|
.arena = arena,
|
||||||
.list_pool = std.heap.MemoryPool(std.DoublyLinkedList).init(page.arena),
|
.list_pool = .init(arena),
|
||||||
.listener_pool = std.heap.MemoryPool(Listener).init(page.arena),
|
.listener_pool = .init(arena),
|
||||||
.dispatch_depth = 0,
|
.dispatch_depth = 0,
|
||||||
.deferred_removals = .{},
|
.deferred_removals = .{},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ const IS_DEBUG = builtin.mode == .Debug;
|
|||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
const Factory = @This();
|
const Factory = @This();
|
||||||
|
|
||||||
_page: *Page,
|
_page: *Page,
|
||||||
|
_arena: Allocator,
|
||||||
_slab: SlabAllocator,
|
_slab: SlabAllocator,
|
||||||
|
|
||||||
fn PrototypeChain(comptime types: []const type) type {
|
fn PrototypeChain(comptime types: []const type) type {
|
||||||
@@ -149,10 +151,11 @@ fn AutoPrototypeChain(comptime types: []const type) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(page: *Page) Factory {
|
pub fn init(arena: Allocator, page: *Page) Factory {
|
||||||
return .{
|
return .{
|
||||||
._page = page,
|
._page = page,
|
||||||
._slab = SlabAllocator.init(page.arena, 128),
|
._arena = arena,
|
||||||
|
._slab = SlabAllocator.init(arena, 128),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,7 +332,7 @@ pub fn svgElement(self: *Factory, tag_name: []const u8, child: anytype) !*@TypeO
|
|||||||
chain.setMiddle(2, Element.Type);
|
chain.setMiddle(2, Element.Type);
|
||||||
|
|
||||||
// will never allocate, can't fail
|
// will never allocate, can't fail
|
||||||
const tag_name_str = String.init(self._page.arena, tag_name, .{}) catch unreachable;
|
const tag_name_str = String.init(self._arena, tag_name, .{}) catch unreachable;
|
||||||
|
|
||||||
// Manually set Element.Svg with the tag_name
|
// Manually set Element.Svg with the tag_name
|
||||||
chain.set(3, .{
|
chain.set(3, .{
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ _session: *Session,
|
|||||||
|
|
||||||
_event_manager: EventManager,
|
_event_manager: EventManager,
|
||||||
|
|
||||||
_parse_mode: enum { document, fragment, document_write },
|
_parse_mode: enum { document, fragment, document_write } = .document,
|
||||||
|
|
||||||
// See Attribute.List for what this is. TL;DR: proper DOM Attribute Nodes are
|
// See Attribute.List for what this is. TL;DR: proper DOM Attribute Nodes are
|
||||||
// fat yet rarely needed. We only create them on-demand, but still need proper
|
// fat yet rarely needed. We only create them on-demand, but still need proper
|
||||||
@@ -91,21 +91,21 @@ _parse_mode: enum { document, fragment, document_write },
|
|||||||
// a look here. We don't store this in the Element or Attribute.List.Entry
|
// a look here. We don't store this in the Element or Attribute.List.Entry
|
||||||
// because that would require additional space per element / Attribute.List.Entry
|
// because that would require additional space per element / Attribute.List.Entry
|
||||||
// even thoug we'll create very few (if any) actual *Attributes.
|
// even thoug we'll create very few (if any) actual *Attributes.
|
||||||
_attribute_lookup: std.AutoHashMapUnmanaged(usize, *Element.Attribute),
|
_attribute_lookup: std.AutoHashMapUnmanaged(usize, *Element.Attribute) = .empty,
|
||||||
|
|
||||||
// Same as _atlribute_lookup, but instead of individual attributes, this is for
|
// Same as _atlribute_lookup, but instead of individual attributes, this is for
|
||||||
// the return of elements.attributes.
|
// the return of elements.attributes.
|
||||||
_attribute_named_node_map_lookup: std.AutoHashMapUnmanaged(usize, *Element.Attribute.NamedNodeMap),
|
_attribute_named_node_map_lookup: std.AutoHashMapUnmanaged(usize, *Element.Attribute.NamedNodeMap) = .empty,
|
||||||
|
|
||||||
// Lazily-created style, classList, and dataset objects. Only stored for elements
|
// Lazily-created style, classList, and dataset objects. Only stored for elements
|
||||||
// that actually access these features via JavaScript, saving 24 bytes per element.
|
// that actually access these features via JavaScript, saving 24 bytes per element.
|
||||||
_element_styles: Element.StyleLookup = .{},
|
_element_styles: Element.StyleLookup = .empty,
|
||||||
_element_datasets: Element.DatasetLookup = .{},
|
_element_datasets: Element.DatasetLookup = .empty,
|
||||||
_element_class_lists: Element.ClassListLookup = .{},
|
_element_class_lists: Element.ClassListLookup = .empty,
|
||||||
_element_rel_lists: Element.RelListLookup = .{},
|
_element_rel_lists: Element.RelListLookup = .empty,
|
||||||
_element_shadow_roots: Element.ShadowRootLookup = .{},
|
_element_shadow_roots: Element.ShadowRootLookup = .empty,
|
||||||
_node_owner_documents: Node.OwnerDocumentLookup = .{},
|
_node_owner_documents: Node.OwnerDocumentLookup = .empty,
|
||||||
_element_assigned_slots: Element.AssignedSlotLookup = .{},
|
_element_assigned_slots: Element.AssignedSlotLookup = .empty,
|
||||||
|
|
||||||
/// Lazily-created inline event listeners (or listeners provided as attributes).
|
/// Lazily-created inline event listeners (or listeners provided as attributes).
|
||||||
/// Avoids bloating all elements with extra function fields for rare usage.
|
/// Avoids bloating all elements with extra function fields for rare usage.
|
||||||
@@ -125,7 +125,7 @@ _element_assigned_slots: Element.AssignedSlotLookup = .{},
|
|||||||
/// ```js
|
/// ```js
|
||||||
/// img.setAttribute("onload", "(() => { ... })()");
|
/// img.setAttribute("onload", "(() => { ... })()");
|
||||||
/// ```
|
/// ```
|
||||||
_element_attr_listeners: GlobalEventHandlersLookup = .{},
|
_element_attr_listeners: GlobalEventHandlersLookup = .empty,
|
||||||
|
|
||||||
/// `load` events that'll be fired before window's `load` event.
|
/// `load` events that'll be fired before window's `load` event.
|
||||||
/// A call to `documentIsComplete` (which calls `_documentIsComplete`) resets it.
|
/// A call to `documentIsComplete` (which calls `_documentIsComplete`) resets it.
|
||||||
@@ -167,9 +167,9 @@ _undefined_custom_elements: std.ArrayList(*Element.Html.Custom) = .{},
|
|||||||
// for heap allocations and managing WebAPI objects
|
// for heap allocations and managing WebAPI objects
|
||||||
_factory: Factory,
|
_factory: Factory,
|
||||||
|
|
||||||
_load_state: LoadState,
|
_load_state: LoadState = .waiting,
|
||||||
|
|
||||||
_parse_state: ParseState,
|
_parse_state: ParseState = .pre,
|
||||||
|
|
||||||
_notified_network_idle: IdleNotification = .init,
|
_notified_network_idle: IdleNotification = .init,
|
||||||
_notified_network_almost_idle: IdleNotification = .init,
|
_notified_network_almost_idle: IdleNotification = .init,
|
||||||
@@ -179,19 +179,19 @@ _notified_network_almost_idle: IdleNotification = .init,
|
|||||||
_queued_navigation: ?QueuedNavigation = null,
|
_queued_navigation: ?QueuedNavigation = null,
|
||||||
|
|
||||||
// The URL of the current page
|
// The URL of the current page
|
||||||
url: [:0]const u8,
|
url: [:0]const u8 = "about:blank",
|
||||||
|
|
||||||
// The base url specifies the base URL used to resolve the relative urls.
|
// The base url specifies the base URL used to resolve the relative urls.
|
||||||
// It is set by a <base> tag.
|
// It is set by a <base> tag.
|
||||||
// If null the url must be used.
|
// If null the url must be used.
|
||||||
base_url: ?[:0]const u8,
|
base_url: ?[:0]const u8 = null,
|
||||||
|
|
||||||
// referer header cache.
|
// referer header cache.
|
||||||
referer_header: ?[:0]const u8,
|
referer_header: ?[:0]const u8 = null,
|
||||||
|
|
||||||
// Arbitrary buffer. Need to temporarily lowercase a value? Use this. No lifetime
|
// Arbitrary buffer. Need to temporarily lowercase a value? Use this. No lifetime
|
||||||
// guarantee - it's valid until someone else uses it.
|
// guarantee - it's valid until someone else uses it.
|
||||||
buf: [BUF_SIZE]u8,
|
buf: [BUF_SIZE]u8 = undefined,
|
||||||
|
|
||||||
// access to the JavaScript engine
|
// access to the JavaScript engine
|
||||||
js: *JS.Context,
|
js: *JS.Context,
|
||||||
@@ -209,13 +209,13 @@ arena_pool: *ArenaPool,
|
|||||||
_arena_pool_leak_track: (if (IS_DEBUG) std.AutoHashMapUnmanaged(usize, struct {
|
_arena_pool_leak_track: (if (IS_DEBUG) std.AutoHashMapUnmanaged(usize, struct {
|
||||||
owner: []const u8,
|
owner: []const u8,
|
||||||
count: usize,
|
count: usize,
|
||||||
}) else void),
|
}) else void) = if (IS_DEBUG) .empty else {},
|
||||||
|
|
||||||
window: *Window,
|
window: *Window,
|
||||||
document: *Document,
|
document: *Document,
|
||||||
|
|
||||||
// DOM version used to invalidate cached state of "live" collections
|
// DOM version used to invalidate cached state of "live" collections
|
||||||
version: usize,
|
version: usize = 0,
|
||||||
|
|
||||||
_req_id: ?usize = null,
|
_req_id: ?usize = null,
|
||||||
_navigated_options: ?NavigatedOpts = null,
|
_navigated_options: ?NavigatedOpts = null,
|
||||||
@@ -224,19 +224,59 @@ pub fn init(self: *Page, session: *Session) !void {
|
|||||||
if (comptime IS_DEBUG) {
|
if (comptime IS_DEBUG) {
|
||||||
log.debug(.page, "page.init", .{});
|
log.debug(.page, "page.init", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
const browser = session.browser;
|
const browser = session.browser;
|
||||||
self._session = session;
|
const page_arena = browser.page_arena.allocator();
|
||||||
|
errdefer _ = browser.page_arena.reset(.free_all);
|
||||||
|
|
||||||
self.arena_pool = browser.arena_pool;
|
var factory = Factory.init(page_arena, self);
|
||||||
self.arena = browser.page_arena.allocator();
|
|
||||||
self.call_arena = browser.call_arena.allocator();
|
|
||||||
|
|
||||||
if (comptime IS_DEBUG) {
|
const document = (try factory.document(Node.Document.HTMLDocument{
|
||||||
self._arena_pool_leak_track = .empty;
|
._proto = undefined,
|
||||||
|
})).asDocument();
|
||||||
|
|
||||||
|
self.* = .{
|
||||||
|
.js = undefined,
|
||||||
|
.arena = page_arena,
|
||||||
|
.document = document,
|
||||||
|
.window = undefined,
|
||||||
|
.arena_pool = browser.arena_pool,
|
||||||
|
.call_arena = browser.call_arena.allocator(),
|
||||||
|
._session = session,
|
||||||
|
._factory = factory,
|
||||||
|
._script_manager = undefined,
|
||||||
|
._event_manager = EventManager.init(page_arena, self),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.window = try factory.eventTarget(Window{
|
||||||
|
._proto = undefined,
|
||||||
|
._document = self.document,
|
||||||
|
._location = &default_location,
|
||||||
|
._performance = Performance.init(),
|
||||||
|
._screen = try factory.eventTarget(Screen{
|
||||||
|
._proto = undefined,
|
||||||
|
._orientation = null,
|
||||||
|
}),
|
||||||
|
._visual_viewport = try factory.eventTarget(VisualViewport{
|
||||||
|
._proto = undefined,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
self._script_manager = ScriptManager.init(browser.allocator, browser.http_client, self);
|
||||||
|
errdefer self._script_manager.deinit();
|
||||||
|
|
||||||
|
self.js = try browser.env.createContext(self, true);
|
||||||
|
errdefer self.js.deinit();
|
||||||
|
|
||||||
|
if (comptime builtin.is_test == false) {
|
||||||
|
// HTML test runner manually calls these as necessary
|
||||||
|
try self.js.scheduler.add(session.browser, struct {
|
||||||
|
fn runMessageLoop(ctx: *anyopaque) !?u32 {
|
||||||
|
const b: *@import("Browser.zig") = @ptrCast(@alignCast(ctx));
|
||||||
|
b.runMessageLoop();
|
||||||
|
return 250;
|
||||||
|
}
|
||||||
|
}.runMessageLoop, 250, .{ .name = "page.messageLoop" });
|
||||||
}
|
}
|
||||||
|
|
||||||
try self.reset(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Page) void {
|
pub fn deinit(self: *Page) void {
|
||||||
@@ -267,130 +307,10 @@ pub fn deinit(self: *Page) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset(self: *Page, comptime initializing: bool) !void {
|
|
||||||
const browser = self._session.browser;
|
|
||||||
|
|
||||||
if (comptime initializing == false) {
|
|
||||||
browser.env.destroyContext(self.js);
|
|
||||||
|
|
||||||
// We force a garbage collection between page navigations to keep v8
|
|
||||||
// memory usage as low as possible.
|
|
||||||
browser.env.memoryPressureNotification(.moderate);
|
|
||||||
self._script_manager.shutdown = true;
|
|
||||||
browser.http_client.abort();
|
|
||||||
self._script_manager.deinit();
|
|
||||||
|
|
||||||
// destroying the context, and aborting the http_client can both cause
|
|
||||||
// resources to be freed. We need to check for a leak after we've finished
|
|
||||||
// all of our cleanup.
|
|
||||||
if (comptime IS_DEBUG) {
|
|
||||||
var it = self._arena_pool_leak_track.valueIterator();
|
|
||||||
while (it.next()) |value_ptr| {
|
|
||||||
if (value_ptr.count > 0) {
|
|
||||||
log.err(.bug, "ArenaPool Leak", .{ .owner = value_ptr.owner });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self._arena_pool_leak_track = .empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = browser.page_arena.reset(.{ .retain_with_limit = 1 * 1024 * 1024 });
|
|
||||||
}
|
|
||||||
|
|
||||||
self._factory = Factory.init(self);
|
|
||||||
|
|
||||||
self.version = 0;
|
|
||||||
self.url = "about:blank";
|
|
||||||
self.base_url = null;
|
|
||||||
self.referer_header = null;
|
|
||||||
|
|
||||||
self.document = (try self._factory.document(Node.Document.HTMLDocument{ ._proto = undefined })).asDocument();
|
|
||||||
|
|
||||||
const storage_bucket = try self._factory.create(storage.Bucket{});
|
|
||||||
const screen = try Screen.init(self);
|
|
||||||
const visual_viewport = try VisualViewport.init(self);
|
|
||||||
self.window = try self._factory.eventTarget(Window{
|
|
||||||
._document = self.document,
|
|
||||||
._storage_bucket = storage_bucket,
|
|
||||||
._performance = Performance.init(),
|
|
||||||
._proto = undefined,
|
|
||||||
._location = &default_location,
|
|
||||||
._screen = screen,
|
|
||||||
._visual_viewport = visual_viewport,
|
|
||||||
});
|
|
||||||
self.window._document = self.document;
|
|
||||||
self.window._location = &default_location;
|
|
||||||
|
|
||||||
self._parse_state = .pre;
|
|
||||||
self._load_state = .waiting;
|
|
||||||
self._queued_navigation = null;
|
|
||||||
self._parse_mode = .document;
|
|
||||||
self._attribute_lookup = .empty;
|
|
||||||
self._attribute_named_node_map_lookup = .empty;
|
|
||||||
self._event_manager = EventManager.init(self);
|
|
||||||
|
|
||||||
self._script_manager = ScriptManager.init(self);
|
|
||||||
errdefer self._script_manager.deinit();
|
|
||||||
|
|
||||||
self.js = try browser.env.createContext(self, true);
|
|
||||||
errdefer self.js.deinit();
|
|
||||||
|
|
||||||
self._element_styles = .{};
|
|
||||||
self._element_datasets = .{};
|
|
||||||
self._element_class_lists = .{};
|
|
||||||
self._element_rel_lists = .{};
|
|
||||||
self._element_shadow_roots = .{};
|
|
||||||
self._node_owner_documents = .{};
|
|
||||||
self._element_assigned_slots = .{};
|
|
||||||
|
|
||||||
self._element_attr_listeners = .{};
|
|
||||||
|
|
||||||
self._to_load = .{};
|
|
||||||
|
|
||||||
self._notified_network_idle = .init;
|
|
||||||
self._notified_network_almost_idle = .init;
|
|
||||||
|
|
||||||
self._performance_observers = .{};
|
|
||||||
self._mutation_observers = .{};
|
|
||||||
self._mutation_delivery_scheduled = false;
|
|
||||||
self._mutation_delivery_depth = 0;
|
|
||||||
self._intersection_observers = .{};
|
|
||||||
self._intersection_check_scheduled = false;
|
|
||||||
self._intersection_delivery_scheduled = false;
|
|
||||||
self._slots_pending_slotchange = .{};
|
|
||||||
self._slotchange_delivery_scheduled = false;
|
|
||||||
self._customized_builtin_definitions = .{};
|
|
||||||
self._customized_builtin_connected_callback_invoked = .{};
|
|
||||||
self._customized_builtin_disconnected_callback_invoked = .{};
|
|
||||||
self._undefined_custom_elements = .{};
|
|
||||||
|
|
||||||
if (comptime IS_DEBUG) {
|
|
||||||
self._arena_pool_leak_track = .{};
|
|
||||||
}
|
|
||||||
|
|
||||||
try self.registerBackgroundTasks();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn base(self: *const Page) [:0]const u8 {
|
pub fn base(self: *const Page) [:0]const u8 {
|
||||||
return self.base_url orelse self.url;
|
return self.base_url orelse self.url;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn registerBackgroundTasks(self: *Page) !void {
|
|
||||||
if (comptime builtin.is_test) {
|
|
||||||
// HTML test runner manually calls these as necessary
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Browser = @import("Browser.zig");
|
|
||||||
|
|
||||||
try self.js.scheduler.add(self._session.browser, struct {
|
|
||||||
fn runMessageLoop(ctx: *anyopaque) !?u32 {
|
|
||||||
const b: *Browser = @ptrCast(@alignCast(ctx));
|
|
||||||
b.runMessageLoop();
|
|
||||||
return 250;
|
|
||||||
}
|
|
||||||
}.runMessageLoop, 250, .{ .name = "page.messageLoop" });
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getTitle(self: *Page) !?[]const u8 {
|
pub fn getTitle(self: *Page) !?[]const u8 {
|
||||||
if (self.window._document.is(Document.HTMLDocument)) |html_doc| {
|
if (self.window._document.is(Document.HTMLDocument)) |html_doc| {
|
||||||
return try html_doc.getTitle(self);
|
return try html_doc.getTitle(self);
|
||||||
@@ -461,12 +381,8 @@ pub fn isSameOrigin(self: *const Page, url: [:0]const u8) !bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn navigate(self: *Page, request_url: [:0]const u8, opts: NavigateOpts) !void {
|
pub fn navigate(self: *Page, request_url: [:0]const u8, opts: NavigateOpts) !void {
|
||||||
|
lp.assert(self._load_state == .waiting, "page.renavigate", .{});
|
||||||
const session = self._session;
|
const session = self._session;
|
||||||
if (self._parse_state != .pre or self._load_state != .waiting) {
|
|
||||||
// it's possible for navigate to be called multiple times on the
|
|
||||||
// same page (via CDP). We want to reset the page between each call.
|
|
||||||
try self.reset(false);
|
|
||||||
}
|
|
||||||
self._load_state = .parsing;
|
self._load_state = .parsing;
|
||||||
|
|
||||||
const req_id = self._session.browser.http_client.nextReqId();
|
const req_id = self._session.browser.http_client.nextReqId();
|
||||||
|
|||||||
@@ -83,10 +83,7 @@ imported_modules: std.StringHashMapUnmanaged(ImportedModule),
|
|||||||
// importmap contains resolved urls.
|
// importmap contains resolved urls.
|
||||||
importmap: std.StringHashMapUnmanaged([:0]const u8),
|
importmap: std.StringHashMapUnmanaged([:0]const u8),
|
||||||
|
|
||||||
pub fn init(page: *Page) ScriptManager {
|
pub fn init(allocator: Allocator, http_client: *Http.Client, page: *Page) ScriptManager {
|
||||||
// page isn't fully initialized, we can setup our reference, but that's it.
|
|
||||||
const browser = page._session.browser;
|
|
||||||
const allocator = browser.allocator;
|
|
||||||
return .{
|
return .{
|
||||||
.page = page,
|
.page = page,
|
||||||
.async_scripts = .{},
|
.async_scripts = .{},
|
||||||
@@ -96,7 +93,7 @@ pub fn init(page: *Page) ScriptManager {
|
|||||||
.is_evaluating = false,
|
.is_evaluating = false,
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.imported_modules = .empty,
|
.imported_modules = .empty,
|
||||||
.client = browser.http_client,
|
.client = http_client,
|
||||||
.static_scripts_done = false,
|
.static_scripts_done = false,
|
||||||
.buffer_pool = BufferPool.init(allocator, 5),
|
.buffer_pool = BufferPool.init(allocator, 5),
|
||||||
.script_pool = std.heap.MemoryPool(Script).init(allocator),
|
.script_pool = std.heap.MemoryPool(Script).init(allocator),
|
||||||
|
|||||||
@@ -127,6 +127,23 @@ pub fn removePage(self: *Session) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn replacePage(self: *Session) !*Page {
|
||||||
|
if (comptime IS_DEBUG) {
|
||||||
|
log.debug(.browser, "replace page", .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
lp.assert(self.page != null, "Session.replacePage null page", .{});
|
||||||
|
self.page.?.deinit();
|
||||||
|
|
||||||
|
_ = self.browser.page_arena.reset(.{ .retain_with_limit = 1 * 1024 * 1024 });
|
||||||
|
self.browser.env.memoryPressureNotification(.moderate);
|
||||||
|
|
||||||
|
self.page = @as(Page, undefined);
|
||||||
|
const page = &self.page.?;
|
||||||
|
try Page.init(page, self);
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn currentPage(self: *Session) ?*Page {
|
pub fn currentPage(self: *Session) ?*Page {
|
||||||
return &(self.page orelse return null);
|
return &(self.page orelse return null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,13 +32,6 @@ const Screen = @This();
|
|||||||
_proto: *EventTarget,
|
_proto: *EventTarget,
|
||||||
_orientation: ?*Orientation = null,
|
_orientation: ?*Orientation = null,
|
||||||
|
|
||||||
pub fn init(page: *Page) !*Screen {
|
|
||||||
return page._factory.eventTarget(Screen{
|
|
||||||
._proto = undefined,
|
|
||||||
._orientation = null,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn asEventTarget(self: *Screen) *EventTarget {
|
pub fn asEventTarget(self: *Screen) *EventTarget {
|
||||||
return self._proto;
|
return self._proto;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,6 @@ const VisualViewport = @This();
|
|||||||
|
|
||||||
_proto: *EventTarget,
|
_proto: *EventTarget,
|
||||||
|
|
||||||
pub fn init(page: *Page) !*VisualViewport {
|
|
||||||
return page._factory.eventTarget(VisualViewport{
|
|
||||||
._proto = undefined,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn asEventTarget(self: *VisualViewport) *EventTarget {
|
pub fn asEventTarget(self: *VisualViewport) *EventTarget {
|
||||||
return self._proto;
|
return self._proto;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ _navigator: Navigator = .init,
|
|||||||
_screen: *Screen,
|
_screen: *Screen,
|
||||||
_visual_viewport: *VisualViewport,
|
_visual_viewport: *VisualViewport,
|
||||||
_performance: Performance,
|
_performance: Performance,
|
||||||
_storage_bucket: *storage.Bucket,
|
_storage_bucket: storage.Bucket = .{},
|
||||||
_on_load: ?js.Function.Global = null,
|
_on_load: ?js.Function.Global = null,
|
||||||
_on_pageshow: ?js.Function.Global = null,
|
_on_pageshow: ?js.Function.Global = null,
|
||||||
_on_popstate: ?js.Function.Global = null,
|
_on_popstate: ?js.Function.Global = null,
|
||||||
@@ -128,11 +128,11 @@ pub fn getPerformance(self: *Window) *Performance {
|
|||||||
return &self._performance;
|
return &self._performance;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getLocalStorage(self: *const Window) *storage.Lookup {
|
pub fn getLocalStorage(self: *Window) *storage.Lookup {
|
||||||
return &self._storage_bucket.local;
|
return &self._storage_bucket.local;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getSessionStorage(self: *const Window) *storage.Lookup {
|
pub fn getSessionStorage(self: *Window) *storage.Lookup {
|
||||||
return &self._storage_bucket.session;
|
return &self._storage_bucket.session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -213,7 +213,12 @@ fn navigate(cmd: anytype) !void {
|
|||||||
return error.SessionIdNotLoaded;
|
return error.SessionIdNotLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
var page = bc.session.currentPage() orelse return error.PageNotLoaded;
|
const session = bc.session;
|
||||||
|
var page = session.currentPage() orelse return error.PageNotLoaded;
|
||||||
|
|
||||||
|
if (page._load_state != .waiting) {
|
||||||
|
page = try session.replacePage();
|
||||||
|
}
|
||||||
|
|
||||||
try page.navigate(params.url, .{
|
try page.navigate(params.url, .{
|
||||||
.reason = .address_bar,
|
.reason = .address_bar,
|
||||||
|
|||||||
Reference in New Issue
Block a user