Skip to content

Commit 2b44092

Browse files
authored
Merge pull request #1215 from lightpanda-io/misc-navigation-changes
Assorted Navigation Changes/Fixes
2 parents 21464df + 4fc09ec commit 2b44092

File tree

4 files changed

+66
-29
lines changed

4 files changed

+66
-29
lines changed

src/browser/html/History.zig

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ pub fn set_scrollRestoration(self: *History, mode: ScrollRestorationMode) void {
4848
}
4949

5050
pub fn get_state(_: *History, page: *Page) !?js.Value {
51-
if (page.session.navigation.currentEntry().state) |state| {
51+
if (page.session.navigation.currentEntry().state.value) |state| {
5252
const value = try js.Value.fromJson(page.js, state);
5353
return value;
5454
} else {
@@ -61,18 +61,15 @@ pub fn _pushState(_: *const History, state: js.Object, _: ?[]const u8, _url: ?[]
6161
const url = if (_url) |u| try arena.dupe(u8, u) else try arena.dupe(u8, page.url.raw);
6262

6363
const json = state.toJson(arena) catch return error.DataClone;
64-
_ = try page.session.navigation.pushEntry(url, json, page, true);
64+
_ = try page.session.navigation.pushEntry(url, .{ .source = .history, .value = json }, page, true);
6565
}
6666

6767
pub fn _replaceState(_: *const History, state: js.Object, _: ?[]const u8, _url: ?[]const u8, page: *Page) !void {
6868
const arena = page.session.arena;
69-
70-
const entry = page.session.navigation.currentEntry();
71-
const json = try state.toJson(arena);
7269
const url = if (_url) |u| try arena.dupe(u8, u) else try arena.dupe(u8, page.url.raw);
7370

74-
entry.state = json;
75-
entry.url = url;
71+
const json = try state.toJson(arena);
72+
_ = try page.session.navigation.replaceEntry(url, .{ .source = .history, .value = json }, page, true);
7673
}
7774

7875
pub fn go(_: *const History, delta: i32, page: *Page) !void {
@@ -89,7 +86,7 @@ pub fn go(_: *const History, delta: i32, page: *Page) !void {
8986

9087
if (entry.url) |url| {
9188
if (try page.isSameOrigin(url)) {
92-
PopStateEvent.dispatch(entry.state, page);
89+
PopStateEvent.dispatch(entry.state.value, page);
9390
}
9491
}
9592

src/browser/html/location.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub const Location = struct {
5656
break :blk try std.fmt.allocPrint(page.arena, "#{s}", .{hash});
5757
};
5858

59-
return page.navigateFromWebAPI(normalized_hash, .{ .reason = .script }, .replace);
59+
return page.navigateFromWebAPI(normalized_hash, .{ .reason = .script }, .{ .replace = null });
6060
}
6161

6262
pub fn get_protocol(self: *Location) []const u8 {
@@ -96,7 +96,7 @@ pub const Location = struct {
9696
}
9797

9898
pub fn _replace(_: *const Location, url: []const u8, page: *Page) !void {
99-
return page.navigateFromWebAPI(url, .{ .reason = .script }, .replace);
99+
return page.navigateFromWebAPI(url, .{ .reason = .script }, .{ .replace = null });
100100
}
101101

102102
pub fn _reload(_: *const Location, page: *Page) !void {

src/browser/navigation/Navigation.zig

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const Navigation = @This();
3535
const NavigationKind = @import("root.zig").NavigationKind;
3636
const NavigationHistoryEntry = @import("root.zig").NavigationHistoryEntry;
3737
const NavigationTransition = @import("root.zig").NavigationTransition;
38+
const NavigationState = @import("root.zig").NavigationState;
3839
const NavigationCurrentEntryChangeEvent = @import("root.zig").NavigationCurrentEntryChangeEvent;
3940

4041
const NavigationEventTarget = @import("NavigationEventTarget.zig");
@@ -110,10 +111,10 @@ pub fn _forward(self: *Navigation, page: *Page) !NavigationReturn {
110111
pub fn updateEntries(self: *Navigation, url: []const u8, kind: NavigationKind, page: *Page, dispatch: bool) !void {
111112
switch (kind) {
112113
.replace => {
113-
_ = try self.replaceEntry(url, null, page, dispatch);
114+
_ = try self.replaceEntry(url, .{ .source = .navigation, .value = null }, page, dispatch);
114115
},
115116
.push => |state| {
116-
_ = try self.pushEntry(url, state, page, dispatch);
117+
_ = try self.pushEntry(url, .{ .source = .navigation, .value = state }, page, dispatch);
117118
},
118119
.traverse => |index| {
119120
self.index = index;
@@ -132,7 +133,13 @@ pub fn processNavigation(self: *Navigation, page: *Page) !void {
132133

133134
/// Pushes an entry into the Navigation stack WITHOUT actually navigating to it.
134135
/// For that, use `navigate`.
135-
pub fn pushEntry(self: *Navigation, _url: []const u8, state: ?[]const u8, page: *Page, dispatch: bool) !*NavigationHistoryEntry {
136+
pub fn pushEntry(
137+
self: *Navigation,
138+
_url: []const u8,
139+
state: NavigationState,
140+
page: *Page,
141+
dispatch: bool,
142+
) !*NavigationHistoryEntry {
136143
const arena = page.session.arena;
137144

138145
const url = try arena.dupe(u8, _url);
@@ -160,18 +167,24 @@ pub fn pushEntry(self: *Navigation, _url: []const u8, state: ?[]const u8, page:
160167
// we don't always have a current entry...
161168
const previous = if (self.entries.items.len > 0) self.currentEntry() else null;
162169
try self.entries.append(arena, entry);
170+
self.index = index;
171+
163172
if (previous) |prev| {
164173
if (dispatch) {
165174
NavigationCurrentEntryChangeEvent.dispatch(self, prev, .push);
166175
}
167176
}
168177

169-
self.index = index;
170-
171178
return entry;
172179
}
173180

174-
pub fn replaceEntry(self: *Navigation, _url: []const u8, state: ?[]const u8, page: *Page, dispatch: bool) !*NavigationHistoryEntry {
181+
pub fn replaceEntry(
182+
self: *Navigation,
183+
_url: []const u8,
184+
state: NavigationState,
185+
page: *Page,
186+
dispatch: bool,
187+
) !*NavigationHistoryEntry {
175188
const arena = page.session.arena;
176189
const url = try arena.dupe(u8, _url);
177190

@@ -184,7 +197,7 @@ pub fn replaceEntry(self: *Navigation, _url: []const u8, state: ?[]const u8, pag
184197
const entry = try arena.create(NavigationHistoryEntry);
185198
entry.* = NavigationHistoryEntry{
186199
.id = id_str,
187-
.key = id_str,
200+
.key = previous.key,
188201
.url = url,
189202
.state = state,
190203
};
@@ -242,7 +255,20 @@ pub fn navigate(
242255
// todo: Fire navigate event
243256
try finished.resolve({});
244257

245-
_ = try self.pushEntry(url, state, page, true);
258+
_ = try self.pushEntry(url, .{ .source = .navigation, .value = state }, page, true);
259+
} else {
260+
try page.navigateFromWebAPI(url, .{ .reason = .navigation }, kind);
261+
}
262+
},
263+
.replace => |state| {
264+
if (is_same_document) {
265+
page.url = new_url;
266+
267+
try committed.resolve({});
268+
// todo: Fire navigate event
269+
try finished.resolve({});
270+
271+
_ = try self.replaceEntry(url, .{ .source = .navigation, .value = state }, page, true);
246272
} else {
247273
try page.navigateFromWebAPI(url, .{ .reason = .navigation }, kind);
248274
}
@@ -263,7 +289,6 @@ pub fn navigate(
263289
.reload => {
264290
try page.navigateFromWebAPI(url, .{ .reason = .navigation }, kind);
265291
},
266-
else => unreachable,
267292
}
268293

269294
return .{
@@ -275,7 +300,13 @@ pub fn navigate(
275300
pub fn _navigate(self: *Navigation, _url: []const u8, _opts: ?NavigateOptions, page: *Page) !NavigationReturn {
276301
const opts = _opts orelse NavigateOptions{};
277302
const json = if (opts.state) |state| state.toJson(page.session.arena) catch return error.DataClone else null;
278-
return try self.navigate(_url, .{ .push = json }, page);
303+
304+
const kind: NavigationKind = switch (opts.history) {
305+
.replace => .{ .replace = json },
306+
.push, .auto => .{ .push = json },
307+
};
308+
309+
return try self.navigate(_url, kind, page);
279310
}
280311

281312
pub const ReloadOptions = struct {
@@ -290,7 +321,7 @@ pub fn _reload(self: *Navigation, _opts: ?ReloadOptions, page: *Page) !Navigatio
290321
const entry = self.currentEntry();
291322
if (opts.state) |state| {
292323
const previous = entry;
293-
entry.state = state.toJson(arena) catch return error.DataClone;
324+
entry.state = .{ .source = .navigation, .value = state.toJson(arena) catch return error.DataClone };
294325
NavigationCurrentEntryChangeEvent.dispatch(self, previous, .reload);
295326
}
296327

@@ -323,6 +354,6 @@ pub fn _updateCurrentEntry(self: *Navigation, options: UpdateCurrentEntryOptions
323354
const arena = page.session.arena;
324355

325356
const previous = self.currentEntry();
326-
self.currentEntry().state = options.state.toJson(arena) catch return error.DataClone;
357+
self.currentEntry().state = .{ .source = .navigation, .value = options.state.toJson(arena) catch return error.DataClone };
327358
NavigationCurrentEntryChangeEvent.dispatch(self, previous, null);
328359
}

src/browser/navigation/root.zig

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,16 @@ pub const NavigationType = enum {
5151

5252
pub const NavigationKind = union(NavigationType) {
5353
push: ?[]const u8,
54-
replace,
54+
replace: ?[]const u8,
5555
traverse: usize,
5656
reload,
5757
};
5858

59+
pub const NavigationState = struct {
60+
source: enum { history, navigation },
61+
value: ?[]const u8,
62+
};
63+
5964
// https://developer.mozilla.org/en-US/docs/Web/API/NavigationHistoryEntry
6065
pub const NavigationHistoryEntry = struct {
6166
pub const prototype = *EventTarget;
@@ -64,7 +69,7 @@ pub const NavigationHistoryEntry = struct {
6469
id: []const u8,
6570
key: []const u8,
6671
url: ?[]const u8,
67-
state: ?[]const u8,
72+
state: NavigationState,
6873

6974
pub fn get_id(self: *const NavigationHistoryEntry) []const u8 {
7075
return self.id;
@@ -95,12 +100,16 @@ pub const NavigationHistoryEntry = struct {
95100
return self.url;
96101
}
97102

98-
pub fn _getState(self: *const NavigationHistoryEntry, page: *Page) !?js.Value {
99-
if (self.state) |state| {
100-
return try js.Value.fromJson(page.js, state);
101-
} else {
102-
return null;
103+
pub const StateReturn = union(enum) { value: ?js.Value, undefined: void };
104+
105+
pub fn _getState(self: *const NavigationHistoryEntry, page: *Page) !StateReturn {
106+
if (self.state.source == .navigation) {
107+
if (self.state.value) |value| {
108+
return .{ .value = try js.Value.fromJson(page.js, value) };
109+
}
103110
}
111+
112+
return .undefined;
104113
}
105114
};
106115

0 commit comments

Comments
 (0)