spread new implementation

This commit is contained in:
Halil Durak
2026-02-02 13:36:24 +03:00
parent 12fe119d6b
commit a4595f58b8
4 changed files with 72 additions and 55 deletions

View File

@@ -379,13 +379,18 @@ fn registerBackgroundTasks(self: *Page) !void {
const Browser = @import("Browser.zig");
try self.scheduler.add(self._session.browser, struct {
fn runMessageLoop(ctx: *anyopaque) !?u32 {
const b: *Browser = @ptrCast(@alignCast(ctx));
b.runMessageLoop();
return 250;
return self.scheduler.after(
.{ .name = "runMessageLoop", .priority = .high },
Browser,
self._session.browser,
250,
struct {
fn runMessageLoop(_: *Scheduler, browser: *Browser) !Scheduler.AfterAction {
browser.runMessageLoop();
return .repeat(250);
}
}.runMessageLoop, 250, .{ .name = "page.messageLoop" });
}.runMessageLoop,
);
}
pub fn getTitle(self: *Page) !?[]const u8 {
@@ -1262,25 +1267,22 @@ pub fn notifyPerformanceObservers(self: *Page, entry: *Performance.Entry) !void
}
self._performance_delivery_scheduled = true;
return self.scheduler.add(
return self.scheduler.once(
.{ .priority = .low },
Page,
self,
struct {
fn run(_page: *anyopaque) anyerror!?u32 {
const page: *Page = @ptrCast(@alignCast(_page));
fn run(_: *Scheduler, page: *Page) !void {
page._performance_delivery_scheduled = false;
// Dispatch performance observer events.
// Dispatch performance observers.
for (page._performance_observers.items) |observer| {
if (observer.hasRecords()) {
try observer.dispatch(page);
}
}
return null;
}
}.run,
0,
.{ .low_priority = true },
);
}

View File

@@ -21,6 +21,7 @@ const js = @import("../js/js.zig");
const log = @import("../../log.zig");
const Page = @import("../Page.zig");
const Scheduler = @import("../Scheduler.zig");
const Event = @import("Event.zig");
const EventTarget = @import("EventTarget.zig");
@@ -99,9 +100,17 @@ pub fn createTimeout(delay: u32, page: *Page) !*AbortSignal {
.signal = try init(page),
};
try page.scheduler.add(callback, TimeoutCallback.run, delay, .{
.name = "AbortSignal.timeout",
});
//try page.scheduler.add(callback, TimeoutCallback.run, delay, .{
// .name = "AbortSignal.timeout",
//});
try page.scheduler.after(
.{ .name = "AbortSignal.timeout", .priority = .high },
TimeoutCallback,
callback,
delay,
TimeoutCallback.run,
);
return callback.signal;
}
@@ -134,8 +143,7 @@ const TimeoutCallback = struct {
page: *Page,
signal: *AbortSignal,
fn run(ctx: *anyopaque) !?u32 {
const self: *TimeoutCallback = @ptrCast(@alignCast(ctx));
fn run(_: *Scheduler, self: *TimeoutCallback) !Scheduler.AfterAction {
var ls: js.Local.Scope = undefined;
self.page.js.localScope(&ls);
defer ls.deinit();
@@ -143,7 +151,8 @@ const TimeoutCallback = struct {
self.signal.abort(.{ .string = "TimeoutError" }, &ls.local, self.page) catch |err| {
log.warn(.app, "abort signal timeout", .{ .err = err });
};
return null;
return .dont_repeat;
}
};

View File

@@ -21,6 +21,7 @@ const js = @import("../js/js.zig");
const log = @import("../../log.zig");
const Page = @import("../Page.zig");
const Scheduler = @import("../Scheduler.zig");
const EventTarget = @import("EventTarget.zig");
const MessageEvent = @import("event/MessageEvent.zig");
@@ -65,10 +66,12 @@ pub fn postMessage(self: *MessagePort, message: js.Value.Global, page: *Page) !v
.message = message,
});
try page.scheduler.add(callback, PostMessageCallback.run, 0, .{
.name = "MessagePort.postMessage",
.low_priority = false,
});
try page.scheduler.once(
.{ .name = "MessagePort.postMessage", .priority = .high },
PostMessageCallback,
callback,
PostMessageCallback.run,
);
}
pub fn start(self: *MessagePort) void {
@@ -113,13 +116,12 @@ const PostMessageCallback = struct {
self.page._factory.destroy(self);
}
fn run(ctx: *anyopaque) !?u32 {
const self: *PostMessageCallback = @ptrCast(@alignCast(ctx));
fn run(_: *Scheduler, self: *PostMessageCallback) !void {
defer self.deinit();
const page = self.page;
if (self.port._closed) {
return null;
return;
}
const event = MessageEvent.initTrusted("message", .{
@@ -128,7 +130,7 @@ const PostMessageCallback = struct {
.source = null,
}, page) catch |err| {
log.err(.dom, "MessagePort.postMessage", .{ .err = err });
return null;
return;
};
var ls: js.Local.Scope = undefined;
@@ -143,8 +145,6 @@ const PostMessageCallback = struct {
) catch |err| {
log.err(.dom, "MessagePort.postMessage", .{ .err = err });
};
return null;
}
};

View File

@@ -22,6 +22,7 @@ const builtin = @import("builtin");
const log = @import("../../log.zig");
const Page = @import("../Page.zig");
const Scheduler = @import("../Scheduler.zig");
const Console = @import("Console.zig");
const History = @import("History.zig");
const Navigation = @import("navigation/Navigation.zig");
@@ -366,11 +367,19 @@ pub fn postMessage(self: *Window, message: js.Value.Global, target_origin: ?[]co
.message = message,
.origin = try arena.dupe(u8, origin),
};
try page.scheduler.add(callback, PostMessageCallback.run, 0, .{
.name = "postMessage",
.low_priority = false,
.finalizer = PostMessageCallback.cancelled,
});
//try page.scheduler.add(callback, PostMessageCallback.run, 0, .{
// .name = "postMessage",
// .low_priority = false,
// .finalizer = PostMessageCallback.cancelled,
//});
return page.scheduler.once(
.{ .name = "postMessage", .priority = .high },
PostMessageCallback,
callback,
PostMessageCallback.run,
);
}
pub fn btoa(_: *const Window, input: []const u8, page: *Page) ![]const u8 {
@@ -447,16 +456,17 @@ pub fn scrollTo(self: *Window, opts: ScrollToOpts, y: ?i32, page: *Page) !void {
// We dispatch scroll event asynchronously after 10ms. So we can throttle
// them.
try page.scheduler.add(
try page.scheduler.once(
.{ .priority = .low },
Page,
page,
struct {
fn dispatch(_page: *anyopaque) anyerror!?u32 {
const p: *Page = @ptrCast(@alignCast(_page));
fn dispatch(_: *Scheduler, p: *Page) !void {
const pos = &p.window._scroll_pos;
// If the state isn't scroll, we can ignore safely to throttle
// the events.
if (pos.state != .scroll) {
return null;
return;
}
const event = try Event.initTrusted("scroll", .{ .bubbles = true }, p);
@@ -464,38 +474,37 @@ pub fn scrollTo(self: *Window, opts: ScrollToOpts, y: ?i32, page: *Page) !void {
pos.state = .end;
return null;
return;
}
}.dispatch,
10,
.{ .low_priority = true },
);
// We dispatch scrollend event asynchronously after 20ms.
try page.scheduler.add(
try page.scheduler.after(
.{ .priority = .low },
Page,
page,
20,
struct {
fn dispatch(_page: *anyopaque) anyerror!?u32 {
const p: *Page = @ptrCast(@alignCast(_page));
fn dispatch(_: *Scheduler, p: *Page) !Scheduler.AfterAction {
const pos = &p.window._scroll_pos;
// Dispatch only if the state is .end.
// If a scroll is pending, retry in 10ms.
// If the state is .end, the event has been dispatched, so
// ignore safely.
switch (pos.state) {
.scroll => return 10,
.scroll => return .repeat(10),
.end => {},
.done => return null,
.done => return .dont_repeat,
}
const event = try Event.initTrusted("scrollend", .{ .bubbles = true }, p);
try p._event_manager.dispatch(p.document.asEventTarget(), event);
pos.state = .done;
return null;
return .dont_repeat;
}
}.dispatch,
20,
.{ .low_priority = true },
);
}
@@ -656,8 +665,7 @@ const PostMessageCallback = struct {
self.page.releaseArena(self.arena);
}
fn run(ctx: *anyopaque) !?u32 {
const self: *PostMessageCallback = @ptrCast(@alignCast(ctx));
fn run(_: *Scheduler, self: *PostMessageCallback) !void {
defer self.deinit();
const page = self.page;
@@ -673,8 +681,6 @@ const PostMessageCallback = struct {
const event = message_event.asEvent();
try page._event_manager.dispatch(window.asEventTarget(), event);
return null;
}
};