Merge pull request #715 from lightpanda-io/location_change

Implement location.reload(), location.assign() and location setter
This commit is contained in:
Karl Seguin
2025-05-31 07:23:36 +08:00
committed by GitHub
4 changed files with 34 additions and 26 deletions

View File

@@ -174,6 +174,10 @@ pub const HTMLDocument = struct {
return try parser.documentHTMLGetLocation(Location, self); return try parser.documentHTMLGetLocation(Location, self);
} }
pub fn set_location(_: *const parser.DocumentHTML, url: []const u8, page: *Page) !void {
return page.navigateFromWebAPI(url);
}
pub fn get_designMode(_: *parser.DocumentHTML) []const u8 { pub fn get_designMode(_: *parser.DocumentHTML) []const u8 {
return "off"; return "off";
} }

View File

@@ -69,18 +69,17 @@ pub const Location = struct {
return ""; return "";
} }
// TODO pub fn _assign(_: *const Location, url: []const u8, page: *Page) !void {
pub fn _assign(_: *Location, url: []const u8) !void { return page.navigateFromWebAPI(url);
_ = url;
} }
// TODO pub fn _replace(_: *const Location, url: []const u8, page: *Page) !void {
pub fn _replace(_: *Location, url: []const u8) !void { return page.navigateFromWebAPI(url);
_ = url;
} }
// TODO pub fn _reload(_: *const Location, page: *Page) !void {
pub fn _reload(_: *Location) !void {} return page.navigateFromWebAPI(page.url.raw);
}
pub fn _toString(self: *Location, page: *Page) ![]const u8 { pub fn _toString(self: *Location, page: *Page) ![]const u8 {
return try self.get_href(page); return try self.get_href(page);

View File

@@ -100,6 +100,10 @@ pub const Window = struct {
return &self.location; return &self.location;
} }
pub fn set_location(_: *const Window, url: []const u8, page: *Page) !void {
return page.navigateFromWebAPI(url);
}
pub fn get_console(self: *Window) *Console { pub fn get_console(self: *Window) *Console {
return &self.console; return &self.console;
} }

View File

@@ -550,23 +550,25 @@ pub const Page = struct {
.a => { .a => {
const element: *parser.Element = @ptrCast(node); const element: *parser.Element = @ptrCast(node);
const href = (try parser.elementGetAttribute(element, "href")) orelse return; const href = (try parser.elementGetAttribute(element, "href")) orelse return;
try self.navigateFromWebAPI(href);
// We cannot navigate immediately as navigating will delete the DOM tree, which holds this event's node.
// As such we schedule the function to be called as soon as possible.
// NOTE Using the page.arena assumes that the scheduling loop does use this object after invoking the callback
// If that changes we may want to consider storing DelayedNavigation in the session instead.
const arena = self.arena;
const navi = try arena.create(DelayedNavigation);
navi.* = .{
.session = self.session,
.href = try arena.dupe(u8, href),
};
_ = try self.loop.timeout(0, &navi.navigate_node);
}, },
else => {}, else => {},
} }
} }
// As such we schedule the function to be called as soon as possible.
// The page.arena is safe to use here, but the transfer_arena exists
// specifically for this type of lifetime.
pub fn navigateFromWebAPI(self: *Page, url: []const u8) !void {
const arena = self.session.transfer_arena;
const navi = try arena.create(DelayedNavigation);
navi.* = .{
.session = self.session,
.url = try arena.dupe(u8, url),
};
_ = try self.loop.timeout(0, &navi.navigate_node);
}
pub fn getOrCreateNodeWrapper(self: *Page, comptime T: type, node: *parser.Node) !*T { pub fn getOrCreateNodeWrapper(self: *Page, comptime T: type, node: *parser.Node) !*T {
if (self.getNodeWrapper(T, node)) |wrap| { if (self.getNodeWrapper(T, node)) |wrap| {
return wrap; return wrap;
@@ -588,16 +590,15 @@ pub const Page = struct {
}; };
const DelayedNavigation = struct { const DelayedNavigation = struct {
navigate_node: Loop.CallbackNode = .{ .func = DelayedNavigation.delay_navigate }, url: []const u8,
session: *Session, session: *Session,
href: []const u8, navigate_node: Loop.CallbackNode = .{ .func = delayNavigate },
fn delay_navigate(node: *Loop.CallbackNode, repeat_delay: *?u63) void { fn delayNavigate(node: *Loop.CallbackNode, repeat_delay: *?u63) void {
_ = repeat_delay; _ = repeat_delay;
const self: *DelayedNavigation = @fieldParentPtr("navigate_node", node); const self: *DelayedNavigation = @fieldParentPtr("navigate_node", node);
self.session.pageNavigate(self.href) catch |err| { self.session.pageNavigate(self.url) catch |err| {
// TODO: should we trigger a specific event here? log.err(.page, "delayed navigation error", .{ .err = err, .url = self.url });
log.err(.page, "delayed navigation error", .{ .err = err });
}; };
} }
}; };