mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-07-31 17:55:59 -04:00
pr feedback: Run background tasks, push wait errors to caller
This fixes two bugs introduced in the previous PR. First, in non-CDP mode, when there's nothing to do except v8 background tasks, we wait for those background tasks. Second, the various wait helpers (e.g. waitForFrame) now return the first error of any WaitCondition.
This commit is contained in:
@@ -67,11 +67,14 @@ pub fn waitForFrame(self: *Runner, frame_id: u32, timeout_ms: u32, opts: WaitFor
|
||||
const condition = WaitCondition{ .frame_id = frame_id, .until = opts.until };
|
||||
var conditions = [_]WaitCondition{condition};
|
||||
_ = try self._wait(false, timeout_ms, &conditions);
|
||||
try firstConditionError(&conditions);
|
||||
}
|
||||
|
||||
pub fn waitForFrameCDP(self: *Runner, frame_id: u32, timeout_ms: u32, until: lp.Config.WaitUntil) !void {
|
||||
const condition = WaitCondition{ .frame_id = frame_id, .until = until };
|
||||
var conditions = [_]WaitCondition{condition};
|
||||
// Unlike waitForFrame, we deliberately don't surface a per-frame error here.
|
||||
// The frame we're waiting on can legitimately disappear mid-wait.
|
||||
_ = try self._wait(true, timeout_ms, &conditions);
|
||||
}
|
||||
|
||||
@@ -97,6 +100,7 @@ pub fn waitForAll(self: *Runner, timeout_ms: u32, opts: WaitForFrameOpts) !void
|
||||
}
|
||||
}
|
||||
_ = try self._wait(false, timeout_ms, conditions);
|
||||
try firstConditionError(conditions);
|
||||
}
|
||||
|
||||
pub fn wait(self: *Runner, timeout_ms: u32, conditions: []WaitCondition) !void {
|
||||
@@ -191,7 +195,9 @@ pub const TickResult = union(enum) {
|
||||
pub fn tickForFrame(self: *Runner, frame_id: u32, timeout_ms: u32, opts: WaitForFrameOpts) !TickResult {
|
||||
const condition = WaitCondition{ .frame_id = frame_id, .until = opts.until };
|
||||
var conditions = [_]WaitCondition{condition};
|
||||
return self.tick(timeout_ms, &conditions);
|
||||
const result = try self.tick(timeout_ms, &conditions);
|
||||
try firstConditionError(&conditions);
|
||||
return result;
|
||||
}
|
||||
pub fn tick(self: *Runner, timeout_ms: u32, conditions: []WaitCondition) !TickResult {
|
||||
return self._tick(false, timeout_ms, conditions);
|
||||
@@ -216,14 +222,23 @@ fn _tick(self: *Runner, comptime is_cdp: bool, timeout_ms: u32, conditions: []Wa
|
||||
const total_http_activity = http_active + http_next_tick + http_client.interception_layer.intercepted;
|
||||
const total_network_activity = total_http_activity + http_client.ws_active;
|
||||
|
||||
const ms_to_next_microtask = browser.msToNextMacrotask();
|
||||
const is_done = ms_to_next_microtask == null and total_network_activity == 0 and http_client.queue.first == null and http_client.ready_queue.first == null;
|
||||
const ms_to_next_macrotask = browser.msToNextMacrotask();
|
||||
const network_idle = total_network_activity == 0 and http_client.queue.first == null and http_client.ready_queue.first == null;
|
||||
const is_done = ms_to_next_macrotask == null and network_idle;
|
||||
|
||||
// _we_ have nothing to run, but v8 is working on background tasks. We'll
|
||||
// wait for them. Don't do this for CDP, since new CDP messages can always
|
||||
// come in at any time.
|
||||
if ((comptime is_cdp) == false and network_idle and browser.hasBackgroundTasks()) {
|
||||
browser.waitForBackgroundTasks();
|
||||
return .{ .ok = 0 };
|
||||
}
|
||||
|
||||
var want_http_tick = false;
|
||||
|
||||
for (conditions) |*condition| {
|
||||
if (condition.status != .pending) {
|
||||
// this condition is at a termianl state
|
||||
// this condition is at a terminal state
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -279,7 +294,7 @@ fn _tick(self: *Runner, comptime is_cdp: bool, timeout_ms: u32, conditions: []Wa
|
||||
}
|
||||
|
||||
if ((comptime is_cdp) or want_http_tick) {
|
||||
var ms_to_wait = @min(timeout_ms, ms_to_next_microtask orelse 200);
|
||||
var ms_to_wait = @min(timeout_ms, ms_to_next_macrotask orelse 200);
|
||||
if (browser.hasBackgroundTasks()) {
|
||||
// background work will queue more to do soon — don't block long
|
||||
// for a client message; loop back and run macrotasks instead.
|
||||
@@ -407,6 +422,15 @@ pub fn waitForScript(self: *Runner, frame_id: u32, src: [:0]const u8, timeout_ms
|
||||
}
|
||||
}
|
||||
|
||||
fn firstConditionError(conditions: []const WaitCondition) !void {
|
||||
for (conditions) |condition| {
|
||||
switch (condition.status) {
|
||||
.err => |err| return err,
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const testing = @import("../testing.zig");
|
||||
test "Runner: waitForSelector timeout" {
|
||||
const page = try testing.pageTest("runner/runner1.html", .{});
|
||||
|
||||
Reference in New Issue
Block a user