From ac85341cab9301d4260fd8246862976e1dcf0292 Mon Sep 17 00:00:00 2001 From: Muki Kiboigo Date: Mon, 8 Dec 2025 05:16:48 -0800 Subject: [PATCH] add NavigationKind to navigate --- src/browser/Page.zig | 7 +++-- src/browser/Session.zig | 6 +++- src/browser/webapi/Location.zig | 2 +- src/browser/webapi/navigation/Navigation.zig | 29 ++++++++++++-------- src/cdp/domains/page.zig | 2 +- src/cdp/domains/target.zig | 8 ++++-- src/cdp/testing.zig | 4 +-- src/lightpanda.zig | 2 +- src/main_legacy_test.zig | 2 +- src/main_wpt.zig | 2 +- src/testing.zig | 4 +-- 11 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/browser/Page.zig b/src/browser/Page.zig index 75b64413..0fd2c750 100644 --- a/src/browser/Page.zig +++ b/src/browser/Page.zig @@ -58,6 +58,7 @@ const IntersectionObserver = @import("webapi/IntersectionObserver.zig"); const CustomElementDefinition = @import("webapi/CustomElementDefinition.zig"); const storage = @import("webapi/storage/storage.zig"); const PageTransitionEvent = @import("webapi/event/PageTransitionEvent.zig"); +const NavigationKind = @import("webapi/navigation/root.zig").NavigationKind; const timestamp = @import("../datetime.zig").timestamp; const milliTimestamp = @import("../datetime.zig").milliTimestamp; @@ -270,7 +271,7 @@ fn registerBackgroundTasks(self: *Page) !void { }.runMessageLoop, 250, .{ .name = "page.messageLoop" }); } -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, kind: NavigationKind) !void { const session = self._session; const resolved_url = try URL.resolve( @@ -292,7 +293,7 @@ pub fn navigate(self: *Page, request_url: [:0]const u8, opts: NavigateOpts) !voi self.window._location = try Location.init(self.url, self); self.document._location = self.window._location; - try session.navigation.updateEntries("", .{ .push = null }, self, true); + try session.navigation.updateEntries(resolved_url, kind, self, true); return; } } @@ -353,6 +354,8 @@ pub fn navigate(self: *Page, request_url: [:0]const u8, opts: NavigateOpts) !voi .timestamp = timestamp(.monotonic), }); + session.navigation._current_navigation_kind = kind; + http_client.request(.{ .ctx = self, .url = self.url, diff --git a/src/browser/Session.zig b/src/browser/Session.zig index 5f25ae85..3c599c39 100644 --- a/src/browser/Session.zig +++ b/src/browser/Session.zig @@ -191,7 +191,11 @@ fn processQueuedNavigation(self: *Session) !bool { return err; }; - page.navigate(qn.url, qn.opts) catch |err| { + page.navigate( + qn.url, + qn.opts, + self.navigation._current_navigation_kind orelse .{ .push = null }, + ) catch |err| { log.err(.browser, "queued navigation error", .{ .err = err, .url = qn.url }); return err; }; diff --git a/src/browser/webapi/Location.zig b/src/browser/webapi/Location.zig index 205d1732..c2c2b1a8 100644 --- a/src/browser/webapi/Location.zig +++ b/src/browser/webapi/Location.zig @@ -81,7 +81,7 @@ pub fn setHash(_: *const Location, hash: []const u8, page: *Page) !void { }; const duped_hash = try page.arena.dupeZ(u8, normalized_hash); - return page.navigate(duped_hash, .{ .reason = .script }); + return page.navigate(duped_hash, .{ .reason = .script }, .{ .replace = null }); } pub fn toString(self: *const Location, page: *const Page) ![:0]const u8 { diff --git a/src/browser/webapi/navigation/Navigation.zig b/src/browser/webapi/navigation/Navigation.zig index e19e8b03..2f2b284f 100644 --- a/src/browser/webapi/navigation/Navigation.zig +++ b/src/browser/webapi/navigation/Navigation.zig @@ -92,7 +92,6 @@ pub fn back(self: *Navigation, page: *Page) !NavigationReturn { const new_index = self._index - 1; const next_entry = self._entries.items[new_index]; - self._index = new_index; return self.navigateInner(next_entry._url, .{ .traverse = new_index }, page); } @@ -108,7 +107,6 @@ pub fn forward(self: *Navigation, page: *Page) !NavigationReturn { const new_index = self._index + 1; const next_entry = self._entries.items[new_index]; - self._index = new_index; return self.navigateInner(next_entry._url, .{ .traverse = new_index }, page); } @@ -132,7 +130,10 @@ pub fn updateEntries(self: *Navigation, url: [:0]const u8, kind: NavigationKind, // This is only really safe to run in the `pageDoneCallback` where we can guarantee that the URL and NavigationKind are correct. pub fn processNavigation(self: *Navigation, page: *Page) !void { const url = page.url; + const kind: NavigationKind = self._current_navigation_kind orelse .{ .push = null }; + defer self._current_navigation_kind = null; + try self.updateEntries(url, kind, page, false); } @@ -247,9 +248,11 @@ pub fn navigateInner( const committed = try page.js.createPromiseResolver(.page); const finished = try page.js.createPromiseResolver(.page); - const new_url = try URL.resolve(arena, url, page.url, .{}); + const new_url = try URL.resolve(arena, page.url, url, .{}); const is_same_document = URL.eqlDocument(new_url, page.url); + const previous = self.getCurrentEntry(); + switch (kind) { .push => |state| { if (is_same_document) { @@ -261,8 +264,7 @@ pub fn navigateInner( _ = try self.pushEntry(url, .{ .source = .navigation, .value = state }, page, true); } else { - // try page.navigate(url, .{ .reason = .navigation }, kind); - try page.navigate(url, .{ .reason = .navigation }); + try page.navigate(url, .{ .reason = .navigation }, kind); } }, .replace => |state| { @@ -275,8 +277,7 @@ pub fn navigateInner( _ = try self.replaceEntry(url, .{ .source = .navigation, .value = state }, page, true); } else { - // try page.navigate(url, .{ .reason = .navigation }, kind); - try page.navigate(url, .{ .reason = .navigation }); + try page.navigate(url, .{ .reason = .navigation }, kind); } }, .traverse => |index| { @@ -289,16 +290,22 @@ pub fn navigateInner( // todo: Fire navigate event finished.resolve("navigation traverse", {}); } else { - // try page.navigate(url, .{ .reason = .navigation }, kind); - try page.navigate(url, .{ .reason = .navigation }); + try page.navigate(url, .{ .reason = .navigation }, kind); } }, .reload => { - // try page.navigate(url, .{ .reason = .navigation }, kind); - try page.navigate(url, .{ .reason = .navigation }); + try page.navigate(url, .{ .reason = .navigation }, kind); }, } + // If we haven't navigated off, let us fire off an a currententrychange. + const event = try NavigationCurrentEntryChangeEvent.init( + "currententrychange", + .{ .from = previous, .navigationType = @tagName(kind) }, + page, + ); + try self._proto.dispatch(.{ .currententrychange = event }, page); + return .{ .committed = committed.promise(), .finished = finished.promise(), diff --git a/src/cdp/domains/page.zig b/src/cdp/domains/page.zig index bc961fe1..c27d3de7 100644 --- a/src/cdp/domains/page.zig +++ b/src/cdp/domains/page.zig @@ -183,7 +183,7 @@ fn navigate(cmd: anytype) !void { try page.navigate(params.url, .{ .reason = .address_bar, .cdp_id = cmd.input.id, - }); + }, .{ .push = null }); } pub fn pageNavigate(arena: Allocator, bc: anytype, event: *const Notification.PageNavigate) !void { diff --git a/src/cdp/domains/target.zig b/src/cdp/domains/target.zig index b59285af..d6f672e2 100644 --- a/src/cdp/domains/target.zig +++ b/src/cdp/domains/target.zig @@ -179,9 +179,11 @@ fn createTarget(cmd: anytype) !void { try doAttachtoTarget(cmd, target_id); } - try page.navigate(params.url, .{ - .reason = .address_bar, - }); + try page.navigate( + params.url, + .{ .reason = .address_bar }, + .{ .push = null }, + ); try cmd.sendResult(.{ .targetId = target_id, diff --git a/src/cdp/testing.zig b/src/cdp/testing.zig index 8d459a9f..b575d4f6 100644 --- a/src/cdp/testing.zig +++ b/src/cdp/testing.zig @@ -127,10 +127,10 @@ const TestContext = struct { const full_url = try std.fmt.allocPrintSentinel( self.arena.allocator(), "http://127.0.0.1:9582/src/browser/tests/{s}", - .{ url }, + .{url}, 0, ); - try page.navigate(full_url, .{}); + try page.navigate(full_url, .{}, .{ .push = null }); bc.session.fetchWait(2000); } return bc; diff --git a/src/lightpanda.zig b/src/lightpanda.zig index c7e714b1..55ec5df7 100644 --- a/src/lightpanda.zig +++ b/src/lightpanda.zig @@ -60,7 +60,7 @@ pub fn fetch(app: *App, url: [:0]const u8, opts: FetchOpts) !void { // } // } - _ = try page.navigate(url, .{}); + _ = try page.navigate(url, .{}, .{ .push = null }); _ = session.fetchWait(opts.wait_ms); const writer = opts.writer orelse return; diff --git a/src/main_legacy_test.zig b/src/main_legacy_test.zig index 0c409c35..5b1cf862 100644 --- a/src/main_legacy_test.zig +++ b/src/main_legacy_test.zig @@ -85,7 +85,7 @@ pub fn run(allocator: Allocator, file: []const u8, session: *lp.Session) !void { try_catch.init(js_context); defer try_catch.deinit(); - try page.navigate(url, .{}); + try page.navigate(url, .{}, .{ .push = null }); session.fetchWait(2000); page._session.browser.runMicrotasks(); diff --git a/src/main_wpt.zig b/src/main_wpt.zig index ff512e40..5e334a22 100644 --- a/src/main_wpt.zig +++ b/src/main_wpt.zig @@ -114,7 +114,7 @@ fn run( defer session.removePage(); const url = try std.fmt.allocPrintSentinel(arena, "http://localhost:9582/{s}", .{test_file}, 0); - try page.navigate(url, .{}); + try page.navigate(url, .{}, .{ .push = null }); _ = page.wait(2000); diff --git a/src/testing.zig b/src/testing.zig index 452ce812..f3c1aeac 100644 --- a/src/testing.zig +++ b/src/testing.zig @@ -403,7 +403,7 @@ fn runWebApiTest(test_file: [:0]const u8) !void { try_catch.init(js_context); defer try_catch.deinit(); - try page.navigate(url, .{}); + try page.navigate(url, .{}, .{ .push = null }); test_session.fetchWait(2000); page._session.browser.runMicrotasks(); @@ -428,7 +428,7 @@ pub fn pageTest(comptime test_file: []const u8) !*Page { 0, ); - try page.navigate(url, .{}); + try page.navigate(url, .{}, .{ .push = null }); test_session.fetchWait(2000); return page; }