mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-22 04:34:44 +00:00
Merge pull request #1651 from lightpanda-io/more_pump_message_loop
Run the MessageLoop [a lot] more.
This commit is contained in:
2
.github/actions/install/action.yml
vendored
2
.github/actions/install/action.yml
vendored
@@ -13,7 +13,7 @@ inputs:
|
|||||||
zig-v8:
|
zig-v8:
|
||||||
description: 'zig v8 version to install'
|
description: 'zig v8 version to install'
|
||||||
required: false
|
required: false
|
||||||
default: 'v0.3.0'
|
default: 'v0.3.1'
|
||||||
v8:
|
v8:
|
||||||
description: 'v8 version to install'
|
description: 'v8 version to install'
|
||||||
required: false
|
required: false
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ FROM debian:stable-slim
|
|||||||
ARG MINISIG=0.12
|
ARG MINISIG=0.12
|
||||||
ARG ZIG_MINISIG=RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U
|
ARG ZIG_MINISIG=RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U
|
||||||
ARG V8=14.0.365.4
|
ARG V8=14.0.365.4
|
||||||
ARG ZIG_V8=v0.3.0
|
ARG ZIG_V8=v0.3.1
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
|
|
||||||
RUN apt-get update -yq && \
|
RUN apt-get update -yq && \
|
||||||
|
|||||||
@@ -6,8 +6,9 @@
|
|||||||
.minimum_zig_version = "0.15.2",
|
.minimum_zig_version = "0.15.2",
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.v8 = .{
|
.v8 = .{
|
||||||
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/refs/tags/v0.3.0.tar.gz",
|
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/refs/tags/v0.3.1.tar.gz",
|
||||||
.hash = "v8-0.0.0-xddH69R6BADRXsnhjA8wNnfKfLQACF1I7CSTZvsMAvp8",
|
.hash = "v8-0.0.0-xddH64J7BAC81mkf6G9RbEJxS-W3TIRl5iFnShwbqCqy",
|
||||||
|
|
||||||
},
|
},
|
||||||
//.v8 = .{ .path = "../zig-v8-fork" },
|
//.v8 = .{ .path = "../zig-v8-fork" },
|
||||||
.@"boringssl-zig" = .{
|
.@"boringssl-zig" = .{
|
||||||
|
|||||||
@@ -92,10 +92,24 @@ pub fn runMicrotasks(self: *Browser) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn runMacrotasks(self: *Browser) !?u64 {
|
pub fn runMacrotasks(self: *Browser) !?u64 {
|
||||||
return try self.env.runMacrotasks();
|
const env = &self.env;
|
||||||
|
|
||||||
|
const time_to_next = try self.env.runMacrotasks();
|
||||||
|
env.pumpMessageLoop();
|
||||||
|
|
||||||
|
// either of the above could have queued more microtasks
|
||||||
|
env.runMicrotasks();
|
||||||
|
|
||||||
|
return time_to_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn runMessageLoop(self: *const Browser) void {
|
pub fn hasBackgroundTasks(self: *Browser) bool {
|
||||||
self.env.pumpMessageLoop();
|
return self.env.hasBackgroundTasks();
|
||||||
|
}
|
||||||
|
pub fn waitForBackgroundTasks(self: *Browser) void {
|
||||||
|
self.env.waitForBackgroundTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn runIdleTasks(self: *const Browser) void {
|
||||||
self.env.runIdleTasks();
|
self.env.runIdleTasks();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -314,12 +314,12 @@ pub fn init(self: *Page, id: u32, session: *Session, parent: ?*Page) !void {
|
|||||||
if (comptime builtin.is_test == false) {
|
if (comptime builtin.is_test == false) {
|
||||||
// HTML test runner manually calls these as necessary
|
// HTML test runner manually calls these as necessary
|
||||||
try self.js.scheduler.add(session.browser, struct {
|
try self.js.scheduler.add(session.browser, struct {
|
||||||
fn runMessageLoop(ctx: *anyopaque) !?u32 {
|
fn runIdleTasks(ctx: *anyopaque) !?u32 {
|
||||||
const b: *@import("Browser.zig") = @ptrCast(@alignCast(ctx));
|
const b: *@import("Browser.zig") = @ptrCast(@alignCast(ctx));
|
||||||
b.runMessageLoop();
|
b.runIdleTasks();
|
||||||
return 250;
|
return 200;
|
||||||
}
|
}
|
||||||
}.runMessageLoop, 250, .{ .name = "page.messageLoop" });
|
}.runIdleTasks, 200, .{ .name = "page.runIdleTasks", .low_priority = true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -873,8 +873,7 @@ pub const Script = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defer {
|
defer {
|
||||||
// We should run microtasks even if script execution fails.
|
local.runMacrotasks(); // also runs microtasks
|
||||||
local.runMicrotasks();
|
|
||||||
_ = page.js.scheduler.run() catch |err| {
|
_ = page.js.scheduler.run() catch |err| {
|
||||||
log.err(.page, "scheduler", .{ .err = err });
|
log.err(.page, "scheduler", .{ .err = err });
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ fn _wait(self: *Session, page: *Page, wait_ms: u32) !WaitResult {
|
|||||||
std.debug.assert(http_client.intercepted == 0);
|
std.debug.assert(http_client.intercepted == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ms = ms_to_next_task orelse blk: {
|
const ms: u64 = ms_to_next_task orelse blk: {
|
||||||
if (wait_ms - ms_remaining < 100) {
|
if (wait_ms - ms_remaining < 100) {
|
||||||
if (comptime builtin.is_test) {
|
if (comptime builtin.is_test) {
|
||||||
return .done;
|
return .done;
|
||||||
@@ -268,6 +268,14 @@ fn _wait(self: *Session, page: *Page, wait_ms: u32) !WaitResult {
|
|||||||
// background jobs.
|
// background jobs.
|
||||||
break :blk 50;
|
break :blk 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
// No http transfers, no cdp extra socket, no
|
// No http transfers, no cdp extra socket, no
|
||||||
// scheduled tasks, we're done.
|
// scheduled tasks, we're done.
|
||||||
return .done;
|
return .done;
|
||||||
@@ -293,8 +301,14 @@ fn _wait(self: *Session, page: *Page, wait_ms: u32) !WaitResult {
|
|||||||
// an cdp_socket registered with the http client).
|
// an cdp_socket registered with the http client).
|
||||||
// We should continue to run lowPriority tasks, so we
|
// We should continue to run lowPriority tasks, so we
|
||||||
// minimize how long we'll poll for network I/O.
|
// minimize how long we'll poll for network I/O.
|
||||||
const ms_to_wait = @min(200, @min(ms_remaining, ms_to_next_task orelse 200));
|
var ms_to_wait = @min(200, ms_to_next_task orelse 200);
|
||||||
if (try http_client.tick(ms_to_wait) == .cdp_socket) {
|
if (ms_to_wait > 10 and browser.hasBackgroundTasks()) {
|
||||||
|
// if we have background tasks, we don't want to wait too
|
||||||
|
// long for a message from the client. We want to go back
|
||||||
|
// to the top of the loop and run macrotasks.
|
||||||
|
ms_to_wait = 10;
|
||||||
|
}
|
||||||
|
if (try http_client.tick(@min(ms_remaining, ms_to_wait)) == .cdp_socket) {
|
||||||
// data on a socket we aren't handling, return to caller
|
// data on a socket we aren't handling, return to caller
|
||||||
return .cdp_socket;
|
return .cdp_socket;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ pub fn deinit(self: *Context) void {
|
|||||||
env.isolate.notifyContextDisposed();
|
env.isolate.notifyContextDisposed();
|
||||||
// There can be other tasks associated with this context that we need to
|
// There can be other tasks associated with this context that we need to
|
||||||
// purge while the context is still alive.
|
// purge while the context is still alive.
|
||||||
env.pumpMessageLoop();
|
_ = env.pumpMessageLoop();
|
||||||
v8.v8__MicrotaskQueue__DELETE(self.microtask_queue);
|
v8.v8__MicrotaskQueue__DELETE(self.microtask_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -397,10 +397,23 @@ pub fn pumpMessageLoop(self: *const Env) void {
|
|||||||
|
|
||||||
const isolate = self.isolate.handle;
|
const isolate = self.isolate.handle;
|
||||||
const platform = self.platform.handle;
|
const platform = self.platform.handle;
|
||||||
while (v8.v8__Platform__PumpMessageLoop(platform, isolate, false)) {
|
while (v8.v8__Platform__PumpMessageLoop(platform, isolate, false)) {}
|
||||||
if (comptime IS_DEBUG) {
|
}
|
||||||
log.debug(.browser, "pumpMessageLoop", .{});
|
|
||||||
}
|
pub fn hasBackgroundTasks(self: *const Env) bool {
|
||||||
|
return v8.v8__Isolate__HasPendingBackgroundTasks(self.isolate.handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn waitForBackgroundTasks(self: *Env) void {
|
||||||
|
var hs: v8.HandleScope = undefined;
|
||||||
|
v8.v8__HandleScope__CONSTRUCT(&hs, self.isolate.handle);
|
||||||
|
defer v8.v8__HandleScope__DESTRUCT(&hs);
|
||||||
|
|
||||||
|
const isolate = self.isolate.handle;
|
||||||
|
const platform = self.platform.handle;
|
||||||
|
while (v8.v8__Isolate__HasPendingBackgroundTasks(isolate)) {
|
||||||
|
_ = v8.v8__Platform__PumpMessageLoop(platform, isolate, true);
|
||||||
|
self.runMicrotasks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,12 @@ pub fn createTypedArray(self: *const Local, comptime array_type: js.ArrayType, s
|
|||||||
return .init(self, size);
|
return .init(self, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn runMacrotasks(self: *const Local) void {
|
||||||
|
const env = self.ctx.env;
|
||||||
|
env.pumpMessageLoop();
|
||||||
|
env.runMicrotasks(); // macrotasks can cause microtasks to queue
|
||||||
|
}
|
||||||
|
|
||||||
pub fn runMicrotasks(self: *const Local) void {
|
pub fn runMicrotasks(self: *const Local) void {
|
||||||
self.ctx.env.runMicrotasks();
|
self.ctx.env.runMicrotasks();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -436,17 +436,18 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *Self) void {
|
||||||
const browser = &self.cdp.browser;
|
const browser = &self.cdp.browser;
|
||||||
|
const env = &browser.env;
|
||||||
|
|
||||||
// Drain microtasks makes sure we don't have inspector's callback
|
// Drain microtasks makes sure we don't have inspector's callback
|
||||||
// in progress before deinit.
|
// in progress before deinit.
|
||||||
browser.env.runMicrotasks();
|
env.runMicrotasks();
|
||||||
|
|
||||||
// resetContextGroup detach the inspector from all contexts.
|
// resetContextGroup detach the inspector from all contexts.
|
||||||
// It append async tasks, so we make sure we run the message loop
|
// It append async tasks, so we make sure we run the message loop
|
||||||
// before deinit it.
|
// before deinit it.
|
||||||
browser.env.inspector.?.resetContextGroup();
|
env.inspector.?.resetContextGroup();
|
||||||
browser.runMessageLoop();
|
_ = env.pumpMessageLoop();
|
||||||
browser.env.inspector.?.stopSession();
|
env.inspector.?.stopSession();
|
||||||
|
|
||||||
// abort all intercepted requests before closing the sesion/page
|
// abort all intercepted requests before closing the sesion/page
|
||||||
// since some of these might callback into the page/scriptmanager
|
// since some of these might callback into the page/scriptmanager
|
||||||
|
|||||||
Reference in New Issue
Block a user