Skip to content

Commit a19d1de

Browse files
committed
add NavigationActivation
1 parent ab369bd commit a19d1de

File tree

5 files changed

+90
-29
lines changed

5 files changed

+90
-29
lines changed

src/browser/Page.zig

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ fn pageDoneCallback(ctx: *anyopaque) !void {
530530
self.clearTransferArena();
531531

532532
//We need to handle different navigation types differently.
533-
try self._session.navigation.processNavigation(self);
533+
try self._session.navigation.commitNavigation(self);
534534

535535
defer if (comptime IS_DEBUG) {
536536
log.debug(.page, "page.load.complete", .{ .url = self.url });
@@ -567,9 +567,6 @@ fn pageDoneCallback(ctx: *anyopaque) !void {
567567
},
568568
else => unreachable,
569569
}
570-
// We need to handle different navigation types differently.
571-
// @ZIGDOM
572-
// try self._session.navigation.processNavigation(self);
573570
}
574571

575572
fn pageErrorCallback(ctx: *anyopaque, err: anyerror) void {

src/browser/js/bridge.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,4 +605,5 @@ pub const JsApis = flattenTypes(&.{
605605
@import("../webapi/navigation/Navigation.zig"),
606606
@import("../webapi/navigation/NavigationEventTarget.zig"),
607607
@import("../webapi/navigation/NavigationHistoryEntry.zig"),
608+
@import("../webapi/navigation/NavigationActivation.zig"),
608609
});

src/browser/webapi/navigation/Navigation.zig

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@ const EventTarget = @import("../EventTarget.zig");
2929
const Navigation = @This();
3030

3131
const NavigationKind = @import("root.zig").NavigationKind;
32-
const NavigationHistoryEntry = @import("NavigationHistoryEntry.zig");
32+
const NavigationActivation = @import("NavigationActivation.zig");
3333
const NavigationTransition = @import("root.zig").NavigationTransition;
3434
const NavigationState = @import("root.zig").NavigationState;
3535

36+
const NavigationHistoryEntry = @import("NavigationHistoryEntry.zig");
3637
const NavigationCurrentEntryChangeEvent = @import("../event/NavigationCurrentEntryChangeEvent.zig");
3738
const NavigationEventTarget = @import("NavigationEventTarget.zig");
3839

@@ -44,6 +45,7 @@ _index: usize = 0,
4445
// Need to be stable pointers, because Events can reference entries.
4546
_entries: std.ArrayList(*NavigationHistoryEntry) = .empty,
4647
_next_entry_id: usize = 0,
48+
_activation: ?NavigationActivation = null,
4749

4850
pub fn init(arena: std.mem.Allocator) Navigation {
4951
return Navigation{ ._arena = arena };
@@ -63,6 +65,10 @@ pub fn onNewPage(self: *Navigation, page: *Page) !void {
6365
);
6466
}
6567

68+
pub fn getActivation(self: *const Navigation) ?NavigationActivation {
69+
return self._activation;
70+
}
71+
6672
pub fn getCanGoBack(self: *const Navigation) bool {
6773
return self._index > 0;
6874
}
@@ -71,12 +77,18 @@ pub fn getCanGoForward(self: *const Navigation) bool {
7177
return self._entries.items.len > self._index + 1;
7278
}
7379

80+
pub fn getCurrentEntryOrNull(self: *Navigation) ?*NavigationHistoryEntry {
81+
if (self._entries.items.len > self._index) {
82+
return self._entries.items[self._index];
83+
} else return null;
84+
}
85+
7486
pub fn getCurrentEntry(self: *Navigation) *NavigationHistoryEntry {
7587
// This should never fail. An entry should always be created before
7688
// we run the scripts on the page we are loading.
7789
std.debug.assert(self._entries.items.len > 0);
7890

79-
return self._entries.items[self._index];
91+
return self.getCurrentEntryOrNull().?;
8092
}
8193

8294
pub fn getTransition(_: *const Navigation) ?NavigationTransition {
@@ -117,8 +129,8 @@ pub fn forward(self: *Navigation, page: *Page) !NavigationReturn {
117129

118130
pub fn updateEntries(self: *Navigation, url: [:0]const u8, kind: NavigationKind, page: *Page, dispatch: bool) !void {
119131
switch (kind) {
120-
.replace => {
121-
_ = try self.replaceEntry(url, .{ .source = .navigation, .value = null }, page, dispatch);
132+
.replace => |state| {
133+
_ = try self.replaceEntry(url, .{ .source = .navigation, .value = state }, page, dispatch);
122134
},
123135
.push => |state| {
124136
_ = try self.pushEntry(url, .{ .source = .navigation, .value = state }, page, dispatch);
@@ -131,14 +143,23 @@ pub fn updateEntries(self: *Navigation, url: [:0]const u8, kind: NavigationKind,
131143
}
132144

133145
// This is for after true navigation processing, where we need to ensure that our entries are up to date.
134-
// This is only really safe to run in the `pageDoneCallback` where we can guarantee that the URL and NavigationKind are correct.
135-
pub fn processNavigation(self: *Navigation, page: *Page) !void {
146+
//
147+
// This is only really safe to run in the `pageDoneCallback`
148+
// where we can guarantee that the URL and NavigationKind are correct.
149+
pub fn commitNavigation(self: *Navigation, page: *Page) !void {
136150
const url = page.url;
137151

138152
const kind: NavigationKind = self._current_navigation_kind orelse .{ .push = null };
139153
defer self._current_navigation_kind = null;
140154

155+
const from_entry = self.getCurrentEntryOrNull();
141156
try self.updateEntries(url, kind, page, false);
157+
158+
self._activation = NavigationActivation{
159+
._from = from_entry,
160+
._entry = self.getCurrentEntry(),
161+
._type = kind.toNavigationType(),
162+
};
142163
}
143164

144165
/// Pushes an entry into the Navigation stack WITHOUT actually navigating to it.
@@ -401,6 +422,7 @@ pub const JsApi = struct {
401422
pub var class_id: bridge.ClassId = undefined;
402423
};
403424

425+
pub const activation = bridge.accessor(Navigation.getActivation, null, .{});
404426
pub const canGoBack = bridge.accessor(Navigation.getCanGoBack, null, .{});
405427
pub const canGoForward = bridge.accessor(Navigation.getCanGoForward, null, .{});
406428
pub const currentEntry = bridge.accessor(Navigation.getCurrentEntry, null, .{});
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright (C) 2023-2025 Lightpanda (Selecy SAS)
2+
//
3+
// Francis Bouvier <[email protected]>
4+
// Pierre Tachoire <[email protected]>
5+
//
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU Affero General Public License as
8+
// published by the Free Software Foundation, either version 3 of the
9+
// License, or (at your option) any later version.
10+
//
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU Affero General Public License for more details.
15+
//
16+
// You should have received a copy of the GNU Affero General Public License
17+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
19+
const std = @import("std");
20+
const js = @import("../../js/js.zig");
21+
22+
const NavigationType = @import("root.zig").NavigationType;
23+
const NavigationHistoryEntry = @import("NavigationHistoryEntry.zig");
24+
25+
// https://developer.mozilla.org/en-US/docs/Web/API/NavigationActivation
26+
const NavigationActivation = @This();
27+
28+
_entry: *NavigationHistoryEntry,
29+
_from: ?*NavigationHistoryEntry = null,
30+
_type: NavigationType,
31+
32+
pub fn getEntry(self: *const NavigationActivation) *NavigationHistoryEntry {
33+
return self._entry;
34+
}
35+
36+
pub fn getFrom(self: *const NavigationActivation) ?*NavigationHistoryEntry {
37+
return self._from;
38+
}
39+
40+
pub fn getNavigationType(self: *const NavigationActivation) []const u8 {
41+
return @tagName(self._type);
42+
}
43+
44+
pub const JsApi = struct {
45+
pub const bridge = js.Bridge(NavigationActivation);
46+
47+
pub const Meta = struct {
48+
pub const name = "NavigationActivation";
49+
pub const prototype_chain = bridge.prototypeChain();
50+
pub var class_id: bridge.ClassId = undefined;
51+
};
52+
53+
pub const entry = bridge.accessor(NavigationActivation.getEntry, null, .{});
54+
pub const from = bridge.accessor(NavigationActivation.getFrom, null, .{});
55+
pub const navigationType = bridge.accessor(NavigationActivation.getNavigationType, null, .{});
56+
};

src/browser/webapi/navigation/root.zig

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,32 +38,17 @@ pub const NavigationKind = union(NavigationType) {
3838
replace: ?[]const u8,
3939
traverse: usize,
4040
reload,
41+
42+
pub fn toNavigationType(self: NavigationKind) NavigationType {
43+
return std.meta.activeTag(self);
44+
}
4145
};
4246

4347
pub const NavigationState = struct {
4448
source: enum { history, navigation },
4549
value: ?[]const u8,
4650
};
4751

48-
// https://developer.mozilla.org/en-US/docs/Web/API/NavigationActivation
49-
pub const NavigationActivation = struct {
50-
entry: NavigationHistoryEntry,
51-
from: ?NavigationHistoryEntry = null,
52-
type: NavigationType,
53-
54-
pub fn get_entry(self: *const NavigationActivation) NavigationHistoryEntry {
55-
return self.entry;
56-
}
57-
58-
pub fn get_from(self: *const NavigationActivation) ?NavigationHistoryEntry {
59-
return self.from;
60-
}
61-
62-
pub fn get_navigationType(self: *const NavigationActivation) NavigationType {
63-
return self.type;
64-
}
65-
};
66-
6752
// https://developer.mozilla.org/en-US/docs/Web/API/NavigationTransition
6853
pub const NavigationTransition = struct {
6954
finished: js.Promise,

0 commit comments

Comments
 (0)