Skip to content

Commit 58215a4

Browse files
committed
Implement location.reload(), location.assign() and location setter
I'm not sure that _any_ location instance should be able to change the page URL. But you can't create a new location (i.e. new Location() isn't valid), and the only two ways I know of are via `window.location` and `document.location` both of which _should_ alter the location of the window/document.
1 parent bddb3f0 commit 58215a4

File tree

4 files changed

+34
-26
lines changed

4 files changed

+34
-26
lines changed

src/browser/html/document.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@ pub const HTMLDocument = struct {
174174
return try parser.documentHTMLGetLocation(Location, self);
175175
}
176176

177+
pub fn set_location(_: *const parser.DocumentHTML, url: []const u8, page: *Page) !void {
178+
return page.navigateFromWebAPI(url);
179+
}
180+
177181
pub fn get_designMode(_: *parser.DocumentHTML) []const u8 {
178182
return "off";
179183
}

src/browser/html/location.zig

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,17 @@ pub const Location = struct {
6969
return "";
7070
}
7171

72-
// TODO
73-
pub fn _assign(_: *Location, url: []const u8) !void {
74-
_ = url;
72+
pub fn _assign(_: *const Location, url: []const u8, page: *Page) !void {
73+
return page.navigateFromWebAPI(url);
7574
}
7675

77-
// TODO
78-
pub fn _replace(_: *Location, url: []const u8) !void {
79-
_ = url;
76+
pub fn _replace(_: *const Location, url: []const u8, page: *Page) !void {
77+
return page.navigateFromWebAPI(url);
8078
}
8179

82-
// TODO
83-
pub fn _reload(_: *Location) !void {}
80+
pub fn _reload(_: *const Location, page: *Page) !void {
81+
return page.navigateFromWebAPI(page.url.raw);
82+
}
8483

8584
pub fn _toString(self: *Location, page: *Page) ![]const u8 {
8685
return try self.get_href(page);

src/browser/html/window.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ pub const Window = struct {
100100
return &self.location;
101101
}
102102

103+
pub fn set_location(_: *const Window, url: []const u8, page: *Page) !void {
104+
return page.navigateFromWebAPI(url);
105+
}
106+
103107
pub fn get_console(self: *Window) *Console {
104108
return &self.console;
105109
}

src/browser/page.zig

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -541,23 +541,25 @@ pub const Page = struct {
541541
.a => {
542542
const element: *parser.Element = @ptrCast(node);
543543
const href = (try parser.elementGetAttribute(element, "href")) orelse return;
544-
545-
// We cannot navigate immediately as navigating will delete the DOM tree, which holds this event's node.
546-
// As such we schedule the function to be called as soon as possible.
547-
// NOTE Using the page.arena assumes that the scheduling loop does use this object after invoking the callback
548-
// If that changes we may want to consider storing DelayedNavigation in the session instead.
549-
const arena = self.arena;
550-
const navi = try arena.create(DelayedNavigation);
551-
navi.* = .{
552-
.session = self.session,
553-
.href = try arena.dupe(u8, href),
554-
};
555-
_ = try self.loop.timeout(0, &navi.navigate_node);
544+
try self.navigateFromWebAPI(href);
556545
},
557546
else => {},
558547
}
559548
}
560549

550+
// As such we schedule the function to be called as soon as possible.
551+
// The page.arena is safe to use here, but the transfer_arena exists
552+
// specifically for this type of lifetime.
553+
pub fn navigateFromWebAPI(self: *Page, url: []const u8) !void {
554+
const arena = self.session.transfer_arena;
555+
const navi = try arena.create(DelayedNavigation);
556+
navi.* = .{
557+
.session = self.session,
558+
.url = try arena.dupe(u8, url),
559+
};
560+
_ = try self.loop.timeout(0, &navi.navigate_node);
561+
}
562+
561563
pub fn getOrCreateNodeWrapper(self: *Page, comptime T: type, node: *parser.Node) !*T {
562564
if (try self.getNodeWrapper(T, node)) |wrap| {
563565
return wrap;
@@ -579,16 +581,15 @@ pub const Page = struct {
579581
};
580582

581583
const DelayedNavigation = struct {
582-
navigate_node: Loop.CallbackNode = .{ .func = DelayedNavigation.delay_navigate },
584+
url: []const u8,
583585
session: *Session,
584-
href: []const u8,
586+
navigate_node: Loop.CallbackNode = .{ .func = delayNavigate },
585587

586-
fn delay_navigate(node: *Loop.CallbackNode, repeat_delay: *?u63) void {
588+
fn delayNavigate(node: *Loop.CallbackNode, repeat_delay: *?u63) void {
587589
_ = repeat_delay;
588590
const self: *DelayedNavigation = @fieldParentPtr("navigate_node", node);
589-
self.session.pageNavigate(self.href) catch |err| {
590-
// TODO: should we trigger a specific event here?
591-
log.err(.page, "delayed navigation error", .{ .err = err });
591+
self.session.pageNavigate(self.url) catch |err| {
592+
log.err(.page, "delayed navigation error", .{ .err = err, .url = self.url });
592593
};
593594
}
594595
};

0 commit comments

Comments
 (0)