Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions src/browser/html/History.zig
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub fn set_scrollRestoration(self: *History, mode: ScrollRestorationMode) void {
}

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

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

pub fn _replaceState(_: *const History, state: js.Object, _: ?[]const u8, _url: ?[]const u8, page: *Page) !void {
const arena = page.session.arena;

const entry = page.session.navigation.currentEntry();
const json = try state.toJson(arena);
const url = if (_url) |u| try arena.dupe(u8, u) else try arena.dupe(u8, page.url.raw);

entry.state = json;
entry.url = url;
const json = try state.toJson(arena);
_ = try page.session.navigation.replaceEntry(url, .{ .source = .history, .value = json }, page, true);
}

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

if (entry.url) |url| {
if (try page.isSameOrigin(url)) {
PopStateEvent.dispatch(entry.state, page);
PopStateEvent.dispatch(entry.state.value, page);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/browser/html/location.zig
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub const Location = struct {
break :blk try std.fmt.allocPrint(page.arena, "#{s}", .{hash});
};

return page.navigateFromWebAPI(normalized_hash, .{ .reason = .script }, .replace);
return page.navigateFromWebAPI(normalized_hash, .{ .reason = .script }, .{ .replace = null });
}

pub fn get_protocol(self: *Location) []const u8 {
Expand Down Expand Up @@ -96,7 +96,7 @@ pub const Location = struct {
}

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

pub fn _reload(_: *const Location, page: *Page) !void {
Expand Down
55 changes: 43 additions & 12 deletions src/browser/navigation/Navigation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const Navigation = @This();
const NavigationKind = @import("root.zig").NavigationKind;
const NavigationHistoryEntry = @import("root.zig").NavigationHistoryEntry;
const NavigationTransition = @import("root.zig").NavigationTransition;
const NavigationState = @import("root.zig").NavigationState;
const NavigationCurrentEntryChangeEvent = @import("root.zig").NavigationCurrentEntryChangeEvent;

const NavigationEventTarget = @import("NavigationEventTarget.zig");
Expand Down Expand Up @@ -110,10 +111,10 @@ pub fn _forward(self: *Navigation, page: *Page) !NavigationReturn {
pub fn updateEntries(self: *Navigation, url: []const u8, kind: NavigationKind, page: *Page, dispatch: bool) !void {
switch (kind) {
.replace => {
_ = try self.replaceEntry(url, null, page, dispatch);
_ = try self.replaceEntry(url, .{ .source = .navigation, .value = null }, page, dispatch);
},
.push => |state| {
_ = try self.pushEntry(url, state, page, dispatch);
_ = try self.pushEntry(url, .{ .source = .navigation, .value = state }, page, dispatch);
},
.traverse => |index| {
self.index = index;
Expand All @@ -132,7 +133,13 @@ pub fn processNavigation(self: *Navigation, page: *Page) !void {

/// Pushes an entry into the Navigation stack WITHOUT actually navigating to it.
/// For that, use `navigate`.
pub fn pushEntry(self: *Navigation, _url: []const u8, state: ?[]const u8, page: *Page, dispatch: bool) !*NavigationHistoryEntry {
pub fn pushEntry(
self: *Navigation,
_url: []const u8,
state: NavigationState,
page: *Page,
dispatch: bool,
) !*NavigationHistoryEntry {
const arena = page.session.arena;

const url = try arena.dupe(u8, _url);
Expand Down Expand Up @@ -160,18 +167,24 @@ pub fn pushEntry(self: *Navigation, _url: []const u8, state: ?[]const u8, page:
// we don't always have a current entry...
const previous = if (self.entries.items.len > 0) self.currentEntry() else null;
try self.entries.append(arena, entry);
self.index = index;

if (previous) |prev| {
if (dispatch) {
NavigationCurrentEntryChangeEvent.dispatch(self, prev, .push);
}
}

self.index = index;

return entry;
}

pub fn replaceEntry(self: *Navigation, _url: []const u8, state: ?[]const u8, page: *Page, dispatch: bool) !*NavigationHistoryEntry {
pub fn replaceEntry(
self: *Navigation,
_url: []const u8,
state: NavigationState,
page: *Page,
dispatch: bool,
) !*NavigationHistoryEntry {
const arena = page.session.arena;
const url = try arena.dupe(u8, _url);

Expand All @@ -184,7 +197,7 @@ pub fn replaceEntry(self: *Navigation, _url: []const u8, state: ?[]const u8, pag
const entry = try arena.create(NavigationHistoryEntry);
entry.* = NavigationHistoryEntry{
.id = id_str,
.key = id_str,
.key = previous.key,
.url = url,
.state = state,
};
Expand Down Expand Up @@ -242,7 +255,20 @@ pub fn navigate(
// todo: Fire navigate event
try finished.resolve({});

_ = try self.pushEntry(url, state, page, true);
_ = try self.pushEntry(url, .{ .source = .navigation, .value = state }, page, true);
} else {
try page.navigateFromWebAPI(url, .{ .reason = .navigation }, kind);
}
},
.replace => |state| {
if (is_same_document) {
page.url = new_url;

try committed.resolve({});
// todo: Fire navigate event
try finished.resolve({});

_ = try self.replaceEntry(url, .{ .source = .navigation, .value = state }, page, true);
} else {
try page.navigateFromWebAPI(url, .{ .reason = .navigation }, kind);
}
Expand All @@ -263,7 +289,6 @@ pub fn navigate(
.reload => {
try page.navigateFromWebAPI(url, .{ .reason = .navigation }, kind);
},
else => unreachable,
}

return .{
Expand All @@ -275,7 +300,13 @@ pub fn navigate(
pub fn _navigate(self: *Navigation, _url: []const u8, _opts: ?NavigateOptions, page: *Page) !NavigationReturn {
const opts = _opts orelse NavigateOptions{};
const json = if (opts.state) |state| state.toJson(page.session.arena) catch return error.DataClone else null;
return try self.navigate(_url, .{ .push = json }, page);

const kind: NavigationKind = switch (opts.history) {
.replace => .{ .replace = json },
.push, .auto => .{ .push = json },
};

return try self.navigate(_url, kind, page);
}

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

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

const previous = self.currentEntry();
self.currentEntry().state = options.state.toJson(arena) catch return error.DataClone;
self.currentEntry().state = .{ .source = .navigation, .value = options.state.toJson(arena) catch return error.DataClone };
NavigationCurrentEntryChangeEvent.dispatch(self, previous, null);
}
23 changes: 16 additions & 7 deletions src/browser/navigation/root.zig
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,16 @@ pub const NavigationType = enum {

pub const NavigationKind = union(NavigationType) {
push: ?[]const u8,
replace,
replace: ?[]const u8,
traverse: usize,
reload,
};

pub const NavigationState = struct {
source: enum { history, navigation },
value: ?[]const u8,
};

// https://developer.mozilla.org/en-US/docs/Web/API/NavigationHistoryEntry
pub const NavigationHistoryEntry = struct {
pub const prototype = *EventTarget;
Expand All @@ -64,7 +69,7 @@ pub const NavigationHistoryEntry = struct {
id: []const u8,
key: []const u8,
url: ?[]const u8,
state: ?[]const u8,
state: NavigationState,

pub fn get_id(self: *const NavigationHistoryEntry) []const u8 {
return self.id;
Expand Down Expand Up @@ -95,12 +100,16 @@ pub const NavigationHistoryEntry = struct {
return self.url;
}

pub fn _getState(self: *const NavigationHistoryEntry, page: *Page) !?js.Value {
if (self.state) |state| {
return try js.Value.fromJson(page.js, state);
} else {
return null;
pub const StateReturn = union(enum) { value: ?js.Value, undefined: void };

pub fn _getState(self: *const NavigationHistoryEntry, page: *Page) !StateReturn {
if (self.state.source == .navigation) {
if (self.state.value) |value| {
return .{ .value = try js.Value.fromJson(page.js, value) };
}
}

return .undefined;
}
};

Expand Down