mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-09-15 07:19:20 -04:00
tools: add waitUntil option to goto
Optional param on the goto tool (load | domcontentloaded | networkalmostidle | networkidle), default unchanged (load). Threaded through performGoto, startGoto and the script runtime's pending-goto driver, which previously hard-coded .load. Closes half of #3138.
This commit is contained in:
1 parent
e143533987
commit
cd8ff37882
2 files changed
+17
-8
No files matched your search
+14
-7
@@ -329,7 +329,8 @@ pub const Tool = enum {
|
||||
\\ "type": "object",
|
||||
\\ "properties": {
|
||||
\\ "url": { "type": "string", "description": "The URL to navigate to, must be a valid URL." },
|
||||
\\ "timeout": { "type": "integer", "description": "Optional timeout in milliseconds. Defaults to 10000." }
|
||||
\\ "timeout": { "type": "integer", "description": "Optional timeout in milliseconds. Defaults to 10000." },
|
||||
\\ "waitUntil": { "type": "string", "enum": ["load", "domcontentloaded", "networkalmostidle", "networkidle"], "description": "Event that completes the navigation. Defaults to 'load'. Prefer 'domcontentloaded' followed by waitForSelector on pages whose late scripts (ads) hold 'load' back." }
|
||||
\\ },
|
||||
\\ "required": ["url"]
|
||||
\\}
|
||||
@@ -758,6 +759,7 @@ pub const ToolResult = struct {
|
||||
pub const GotoParams = struct {
|
||||
url: [:0]const u8,
|
||||
timeout: ?u32 = null,
|
||||
waitUntil: ?lp.Config.WaitUntil = null,
|
||||
};
|
||||
|
||||
pub const UrlParams = struct {
|
||||
@@ -936,7 +938,7 @@ const schema_walker_suffix = ")";
|
||||
|
||||
fn execGoto(arena: std.mem.Allocator, session: *lp.Session, registry: *CDPNode.Registry, arguments: ?std.json.Value) ToolError![]const u8 {
|
||||
const args = try parseArgs(GotoParams, arena, arguments);
|
||||
return switch (try performGoto(session, registry, args.url, args.timeout)) {
|
||||
return switch (try performGoto(session, registry, args.url, args.timeout, args.waitUntil)) {
|
||||
.completed => "Navigated successfully.",
|
||||
.timeout => "Navigation started but the page did not finish loading before the timeout.",
|
||||
};
|
||||
@@ -988,7 +990,7 @@ fn execSearch(arena: std.mem.Allocator, session: *lp.Session, registry: *CDPNode
|
||||
.{encoded},
|
||||
0,
|
||||
) catch return ToolError.OutOfMemory;
|
||||
_ = try performGoto(session, registry, ddg_url, args.timeout);
|
||||
_ = try performGoto(session, registry, ddg_url, args.timeout, null);
|
||||
const ddg_frame = try requireFrame(session);
|
||||
return .{ .text = try renderFrameMarkdown(arena, ddg_frame) };
|
||||
}
|
||||
@@ -1921,7 +1923,7 @@ fn ensurePage(session: *lp.Session, registry: *CDPNode.Registry, url: ?[:0]const
|
||||
if (session.currentFrame()) |frame| {
|
||||
if (std.mem.eql(u8, frame.url, u)) return frame;
|
||||
}
|
||||
_ = try performGoto(session, registry, u, timeout);
|
||||
_ = try performGoto(session, registry, u, timeout, null);
|
||||
}
|
||||
return session.currentFrame() orelse ToolError.FrameNotLoaded;
|
||||
}
|
||||
@@ -1937,6 +1939,7 @@ const default_nav_timeout_ms: u32 = 10000;
|
||||
pub const StartedGoto = struct {
|
||||
frame_id: u32,
|
||||
timeout_ms: u32,
|
||||
until: lp.Config.WaitUntil,
|
||||
};
|
||||
|
||||
/// Open a fresh top-level page and start its navigation. The frame is non-null
|
||||
@@ -1971,10 +1974,14 @@ pub fn startGoto(
|
||||
}
|
||||
}
|
||||
const page = try openPage(session, args.url);
|
||||
return .{ .frame_id = page.frame_id, .timeout_ms = args.timeout orelse default_nav_timeout_ms };
|
||||
return .{
|
||||
.frame_id = page.frame_id,
|
||||
.timeout_ms = args.timeout orelse default_nav_timeout_ms,
|
||||
.until = args.waitUntil orelse default_nav_wait,
|
||||
};
|
||||
}
|
||||
|
||||
fn performGoto(session: *lp.Session, registry: *CDPNode.Registry, url: [:0]const u8, timeout: ?u32) ToolError!lp.Session.Runner.WaitResult {
|
||||
fn performGoto(session: *lp.Session, registry: *CDPNode.Registry, url: [:0]const u8, timeout: ?u32, wait_until: ?lp.Config.WaitUntil) ToolError!lp.Session.Runner.WaitResult {
|
||||
if (session.primaryPage()) |old_page| {
|
||||
registry.reset();
|
||||
old_page.close();
|
||||
@@ -1982,7 +1989,7 @@ fn performGoto(session: *lp.Session, registry: *CDPNode.Registry, url: [:0]const
|
||||
const page = try openPage(session, url);
|
||||
|
||||
var runner = session.runner(.{});
|
||||
const condition = lp.Session.Runner.WaitCondition{ .frame_id = page.frame_id, .until = default_nav_wait };
|
||||
const condition = lp.Session.Runner.WaitCondition{ .frame_id = page.frame_id, .until = wait_until orelse default_nav_wait };
|
||||
var conditions = [_]lp.Session.Runner.WaitCondition{condition};
|
||||
const result = runner.waitResult(timeout orelse default_nav_timeout_ms, &conditions) catch |err| {
|
||||
return if (err == error.Cancelled) ToolError.Cancelled else ToolError.NavigationFailed;
|
||||
|
||||
@@ -74,6 +74,7 @@ const PendingGoto = struct {
|
||||
receiver: v8.Global,
|
||||
/// `run_timer` reading (ms) past which the navigation is abandoned.
|
||||
deadline_ms: u64,
|
||||
until: lp.Config.WaitUntil,
|
||||
|
||||
fn reset(self: *PendingGoto) void {
|
||||
v8.v8__Global__Reset(&self.resolver);
|
||||
@@ -513,6 +514,7 @@ fn invokeGoto(
|
||||
.resolver = undefined,
|
||||
.receiver = undefined,
|
||||
.deadline_ms = @as(u64, @intCast(self.run_timer.untilNow(lp.io, .boot).toMilliseconds())) + started.timeout_ms,
|
||||
.until = started.until,
|
||||
};
|
||||
v8.v8__Global__New(self.env.isolate.handle, resolver, &pending.resolver);
|
||||
v8.v8__Global__New(self.env.isolate.handle, this, &pending.receiver);
|
||||
@@ -551,7 +553,7 @@ fn driveAsync(self: *Runtime, context: *const v8.Context, try_catch: *const v8.T
|
||||
break;
|
||||
};
|
||||
for (self.pending_gotos.items, conditions) |pending, *condition| {
|
||||
condition.* = .{ .frame_id = pending.frame_id, .until = .load };
|
||||
condition.* = .{ .frame_id = pending.frame_id, .until = pending.until };
|
||||
}
|
||||
|
||||
// Browser-side tick: run under the browser's isolate, exit before the
|
||||
|
||||
Reference in new issue
Block a user