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
44 changes: 44 additions & 0 deletions src/Config.zig
Original file line number Diff line number Diff line change
Expand Up @@ -217,13 +217,22 @@ pub const DumpFormat = enum {
semantic_tree_text,
};

pub const WaitUntil = enum {
load,
domcontentloaded,
networkidle,
fixed,
};

pub const Fetch = struct {
url: [:0]const u8,
dump_mode: ?DumpFormat = null,
common: Common = .{},
with_base: bool = false,
with_frames: bool = false,
strip: dump.Opts.Strip = .{},
wait_ms: u32 = 5000,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add the help text for these in the fetch section of the printUsageAndExit function?

wait_until: WaitUntil = .load,
};

pub const Common = struct {
Expand Down Expand Up @@ -387,6 +396,13 @@ pub fn printUsageAndExit(self: *const Config, success: bool) void {
\\
\\--with_frames Includes the contents of iframes. Defaults to false.
\\
\\--wait_ms Wait time in milliseconds.
\\ Defaults to 5000.
\\
\\--wait_until Wait until the specified event.
\\ Supported events: load, domcontentloaded, networkidle, fixed.
\\ Defaults to 'load'.
\\
++ common_options ++
\\
\\serve command
Expand Down Expand Up @@ -619,8 +635,34 @@ fn parseFetchArgs(
var url: ?[:0]const u8 = null;
var common: Common = .{};
var strip: dump.Opts.Strip = .{};
var wait_ms: u32 = 5000;
var wait_until: WaitUntil = .load;

while (args.next()) |opt| {
if (std.mem.eql(u8, "--wait_ms", opt)) {
const str = args.next() orelse {
log.fatal(.app, "missing argument value", .{ .arg = "--wait_ms" });
return error.InvalidArgument;
};
wait_ms = std.fmt.parseInt(u32, str, 10) catch |err| {
log.fatal(.app, "invalid argument value", .{ .arg = "--wait_ms", .err = err });
return error.InvalidArgument;
};
continue;
}

if (std.mem.eql(u8, "--wait_until", opt)) {
const str = args.next() orelse {
log.fatal(.app, "missing argument value", .{ .arg = "--wait_until" });
return error.InvalidArgument;
};
wait_until = std.meta.stringToEnum(WaitUntil, str) orelse {
log.fatal(.app, "invalid argument value", .{ .arg = "--wait_until", .val = str });
return error.InvalidArgument;
};
continue;
}

if (std.mem.eql(u8, "--dump", opt)) {
var peek_args = args.*;
if (peek_args.next()) |next_arg| {
Expand Down Expand Up @@ -709,6 +751,8 @@ fn parseFetchArgs(
.common = common,
.with_base = with_base,
.with_frames = with_frames,
.wait_ms = wait_ms,
.wait_until = wait_until,
};
}

Expand Down
49 changes: 28 additions & 21 deletions src/browser/Session.zig
Original file line number Diff line number Diff line change
Expand Up @@ -319,10 +319,11 @@ fn findPageBy(page: *Page, comptime field: []const u8, id: u32) ?*Page {
return null;
}

pub fn wait(self: *Session, wait_ms: u32) WaitResult {
var page = &(self.page orelse return .no_page);
pub fn wait(self: *Session, wait_ms: u32, wait_until: lp.Config.WaitUntil) WaitResult {
while (true) {
const wait_result = self._wait(page, wait_ms) catch |err| {
if (self.page == null) return .no_page;
const page = &self.page.?;
const wait_result = self._wait(page, wait_ms, wait_until) catch |err| {
switch (err) {
error.JsError => {}, // already logged (with hopefully more context)
else => log.err(.browser, "session wait", .{
Expand All @@ -339,14 +340,13 @@ pub fn wait(self: *Session, wait_ms: u32) WaitResult {
return .done;
}
self.processQueuedNavigation() catch return .done;
page = &self.page.?; // might have changed
},
else => |result| return result,
}
}
}

fn _wait(self: *Session, page: *Page, wait_ms: u32) !WaitResult {
fn _wait(self: *Session, page: *Page, wait_ms: u32, wait_until: lp.Config.WaitUntil) !WaitResult {
var timer = try std.time.Timer.start();
var ms_remaining = wait_ms;

Expand All @@ -372,7 +372,9 @@ fn _wait(self: *Session, page: *Page, wait_ms: u32) !WaitResult {
// There's no JS to run, and no reason to run the scheduler.
if (http_client.active == 0 and exit_when_done) {
// haven't started navigating, I guess.
return .done;
if (wait_until != .fixed) {
return .done;
}
}
// Either we have active http connections, or we're in CDP
// mode with an extra socket. Either way, we're waiting
Expand Down Expand Up @@ -423,37 +425,42 @@ fn _wait(self: *Session, page: *Page, wait_ms: u32) !WaitResult {
std.debug.assert(http_client.intercepted == 0);
}

var ms = blk: {
// if (wait_ms - ms_remaining < 100) {
// if (comptime builtin.is_test) {
// return .done;
// }
// // Look, we want to exit ASAP, but we don't want
// // to exit so fast that we've run none of the
// // background jobs.
// break :blk 50;
// }
const is_event_done = switch (wait_until) {
.fixed => false,
.domcontentloaded => (page._load_state == .load or page._load_state == .complete),
.load => (page._load_state == .complete),
.networkidle => (page._notified_network_idle == .done),
};

var ms = blk: {
if (browser.hasBackgroundTasks()) {
// _we_ have nothing to run, but v8 is working on
// background tasks. We'll wait for them.
browser.waitForBackgroundTasks();
break :blk 20;
}

break :blk browser.msToNextMacrotask() orelse return .done;
const next_task = browser.msToNextMacrotask();
if (next_task == null and is_event_done) {
return .done;
}
break :blk next_task orelse 20;
};

if (ms > ms_remaining) {
if (is_event_done) {
return .done;
}
// Same as above, except we have a scheduled task,
// it just happens to be too far into the future
// compared to how long we were told to wait.
if (!browser.hasBackgroundTasks()) {
return .done;
if (is_event_done) return .done;
} else {
// _we_ have nothing to run, but v8 is working on
// background tasks. We'll wait for them.
browser.waitForBackgroundTasks();
}
// _we_ have nothing to run, but v8 is working on
// background tasks. We'll wait for them.
browser.waitForBackgroundTasks();
ms = 20;
}

Expand Down
2 changes: 1 addition & 1 deletion src/cdp/cdp.zig
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ pub fn CDPT(comptime TypeProvider: type) type {
// timeouts (or http events) which are ready to be processed.
pub fn pageWait(self: *Self, ms: u32) Session.WaitResult {
const session = &(self.browser.session orelse return .no_page);
return session.wait(ms);
return session.wait(ms, .load);
}

// Called from above, in processMessage which handles client messages
Expand Down
2 changes: 1 addition & 1 deletion src/cdp/domains/lp.zig
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ test "cdp.lp: action tools" {
const page = try bc.session.createPage();
const url = "http://localhost:9582/src/browser/tests/mcp_actions.html";
try page.navigate(url, .{ .reason = .address_bar, .kind = .{ .push = null } });
_ = bc.session.wait(5000);
_ = bc.session.wait(5000, .load);

// Test Click
const btn = page.document.getElementById("btn", page).?.asNode();
Expand Down
2 changes: 1 addition & 1 deletion src/cdp/testing.zig
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ const TestContext = struct {
0,
);
try page.navigate(full_url, .{});
_ = bc.session.wait(2000);
_ = bc.session.wait(2000, .load);
}
return bc;
}
Expand Down
3 changes: 2 additions & 1 deletion src/lightpanda.zig
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const IS_DEBUG = @import("builtin").mode == .Debug;

pub const FetchOpts = struct {
wait_ms: u32 = 5000,
wait_until: Config.WaitUntil = .load,
dump: dump.Opts,
dump_mode: ?Config.DumpFormat = null,
writer: ?*std.Io.Writer = null,
Expand Down Expand Up @@ -107,7 +108,7 @@ pub fn fetch(app: *App, url: [:0]const u8, opts: FetchOpts) !void {
.reason = .address_bar,
.kind = .{ .push = null },
});
_ = session.wait(opts.wait_ms);
_ = session.wait(opts.wait_ms, opts.wait_until);

const writer = opts.writer orelse return;
if (opts.dump_mode) |mode| {
Expand Down
3 changes: 2 additions & 1 deletion src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ fn run(allocator: Allocator, main_arena: Allocator) !void {
log.debug(.app, "startup", .{ .mode = "fetch", .dump_mode = opts.dump_mode, .url = url, .snapshot = app.snapshot.fromEmbedded() });

var fetch_opts = lp.FetchOpts{
.wait_ms = 5000,
.wait_ms = opts.wait_ms,
.wait_until = opts.wait_until,
.dump_mode = opts.dump_mode,
.dump = .{
.strip = opts.strip,
Expand Down
2 changes: 1 addition & 1 deletion src/main_legacy_test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ pub fn run(allocator: Allocator, file: []const u8, session: *lp.Session) !void {
defer try_catch.deinit();

try page.navigate(url, .{});
_ = session.wait(2000);
_ = session.wait(2000, .load);

ls.local.eval("testing.assertOk()", "testing.assertOk()") catch |err| {
const caught = try_catch.caughtOrError(allocator, err);
Expand Down
4 changes: 2 additions & 2 deletions src/mcp/tools.zig
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ fn performGoto(server: *Server, url: [:0]const u8, id: std.json.Value) !void {
return error.NavigationFailed;
};

_ = server.session.wait(5000);
_ = server.session.wait(5000, .load);
}

const testing = @import("../testing.zig");
Expand Down Expand Up @@ -603,7 +603,7 @@ test "MCP - Actions: click, fill, scroll" {
const page = try server.session.createPage();
const url = "http://localhost:9582/src/browser/tests/mcp_actions.html";
try page.navigate(url, .{ .reason = .address_bar, .kind = .{ .push = null } });
_ = server.session.wait(5000);
_ = server.session.wait(5000, .load);

// Test Click
const btn = page.document.getElementById("btn", page).?.asNode();
Expand Down
4 changes: 2 additions & 2 deletions src/testing.zig
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ fn runWebApiTest(test_file: [:0]const u8) !void {
defer try_catch.deinit();

try page.navigate(url, .{});
_ = test_session.wait(2000);
_ = test_session.wait(2000, .load);

test_browser.runMicrotasks();

Expand All @@ -439,7 +439,7 @@ pub fn pageTest(comptime test_file: []const u8) !*Page {
);

try page.navigate(url, .{});
_ = test_session.wait(2000);
_ = test_session.wait(2000, .load);
return page;
}

Expand Down
Loading