Skip to content

Commit 29967fd

Browse files
committed
delay navigate on click
1 parent bd65e40 commit 29967fd

File tree

1 file changed

+24
-1
lines changed

1 file changed

+24
-1
lines changed

src/browser/browser.zig

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,12 +706,35 @@ pub const Page = struct {
706706
.a => {
707707
const element: *parser.Element = @ptrCast(node);
708708
const href = (try parser.elementGetAttribute(element, "href")) orelse return;
709-
return self.session.pageNavigate(href);
709+
710+
// We cannot navigate immediately as navigating will delete the DOM tree, which holds this event's node.
711+
// As such we schedule the function to be called as soon as possible.
712+
// NOTE Using the page.arena assumes that the scheduling loop does use this object after invoking the callback
713+
// If that changes we may want to consider storing DelayedNavigation in the session instead.
714+
const arena = self.arena;
715+
const navi = try arena.create(DelayedNavigation);
716+
navi.* = .{
717+
.session = self.session,
718+
.href = try arena.dupe(u8, href),
719+
};
720+
_ = try self.state.loop.timeout(0, &navi.navigate_node);
710721
},
711722
else => {},
712723
}
713724
}
714725

726+
const DelayedNavigation = struct {
727+
navigate_node: Loop.CallbackNode = .{ .func = DelayedNavigation.delay_navigate },
728+
session: *Session,
729+
href: []const u8,
730+
731+
fn delay_navigate(node: *Loop.CallbackNode, repeat_delay: *?u63) void {
732+
_ = repeat_delay;
733+
const self: *DelayedNavigation = @fieldParentPtr("navigate_node", node);
734+
self.session.pageNavigate(self.href) catch unreachable;
735+
}
736+
};
737+
715738
const Script = struct {
716739
element: *parser.Element,
717740
kind: Kind,

0 commit comments

Comments
 (0)