mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-02-04 14:33:47 +00:00
pass IdleDeadline to idle callback
This commit is contained in:
@@ -607,6 +607,7 @@ pub const JsApis = flattenTypes(&.{
|
|||||||
@import("../webapi/IntersectionObserver.zig"),
|
@import("../webapi/IntersectionObserver.zig"),
|
||||||
@import("../webapi/CustomElementRegistry.zig"),
|
@import("../webapi/CustomElementRegistry.zig"),
|
||||||
@import("../webapi/ResizeObserver.zig"),
|
@import("../webapi/ResizeObserver.zig"),
|
||||||
|
@import("../webapi/IdleDeadline.zig"),
|
||||||
@import("../webapi/Blob.zig"),
|
@import("../webapi/Blob.zig"),
|
||||||
@import("../webapi/File.zig"),
|
@import("../webapi/File.zig"),
|
||||||
@import("../webapi/Screen.zig"),
|
@import("../webapi/Screen.zig"),
|
||||||
|
|||||||
51
src/browser/webapi/IdleDeadline.zig
Normal file
51
src/browser/webapi/IdleDeadline.zig
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// Copyright (C) 2023-2025 Lightpanda (Selecy SAS)
|
||||||
|
//
|
||||||
|
// Francis Bouvier <francis@lightpanda.io>
|
||||||
|
// Pierre Tachoire <pierre@lightpanda.io>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const IdleDeadline = @This();
|
||||||
|
|
||||||
|
pub fn init() IdleDeadline {
|
||||||
|
return .{};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getDidTimeout(_: *const IdleDeadline) bool {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn timeRemaining(_: *const IdleDeadline) f64 {
|
||||||
|
// Return a fixed 50ms.
|
||||||
|
// This allows idle callbacks to perform work without complex
|
||||||
|
// timing infrastructure.
|
||||||
|
return 50.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const JsApi = struct {
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
|
pub const bridge = js.Bridge(IdleDeadline);
|
||||||
|
|
||||||
|
pub const Meta = struct {
|
||||||
|
pub const name = "IdleDeadline";
|
||||||
|
pub const prototype_chain = bridge.prototypeChain();
|
||||||
|
pub var class_id: bridge.ClassId = undefined;
|
||||||
|
pub const empty_with_no_proto = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const timeRemaining = bridge.function(IdleDeadline.timeRemaining, .{});
|
||||||
|
pub const didTimeout = bridge.accessor(IdleDeadline.getDidTimeout, null, .{});
|
||||||
|
};
|
||||||
@@ -223,7 +223,7 @@ pub fn requestAnimationFrame(self: *Window, cb: js.Function, page: *Page) !u32 {
|
|||||||
.repeat = false,
|
.repeat = false,
|
||||||
.params = &.{},
|
.params = &.{},
|
||||||
.low_priority = false,
|
.low_priority = false,
|
||||||
.animation_frame = true,
|
.mode = .animation_frame,
|
||||||
.name = "window.requestAnimationFrame",
|
.name = "window.requestAnimationFrame",
|
||||||
}, page);
|
}, page);
|
||||||
}
|
}
|
||||||
@@ -258,6 +258,7 @@ const RequestIdleCallbackOpts = struct {
|
|||||||
pub fn requestIdleCallback(self: *Window, cb: js.Function, opts_: ?RequestIdleCallbackOpts, page: *Page) !u32 {
|
pub fn requestIdleCallback(self: *Window, cb: js.Function, opts_: ?RequestIdleCallbackOpts, page: *Page) !u32 {
|
||||||
const opts = opts_ orelse RequestIdleCallbackOpts{};
|
const opts = opts_ orelse RequestIdleCallbackOpts{};
|
||||||
return self.scheduleCallback(cb, opts.timeout orelse 50, .{
|
return self.scheduleCallback(cb, opts.timeout orelse 50, .{
|
||||||
|
.mode = .idle,
|
||||||
.repeat = false,
|
.repeat = false,
|
||||||
.params = &.{},
|
.params = &.{},
|
||||||
.low_priority = true,
|
.low_priority = true,
|
||||||
@@ -364,6 +365,7 @@ const ScheduleOpts = struct {
|
|||||||
name: []const u8,
|
name: []const u8,
|
||||||
low_priority: bool = false,
|
low_priority: bool = false,
|
||||||
animation_frame: bool = false,
|
animation_frame: bool = false,
|
||||||
|
mode: ScheduleCallback.Mode = .normal,
|
||||||
};
|
};
|
||||||
fn scheduleCallback(self: *Window, cb: js.Function, delay_ms: u32, opts: ScheduleOpts, page: *Page) !u32 {
|
fn scheduleCallback(self: *Window, cb: js.Function, delay_ms: u32, opts: ScheduleOpts, page: *Page) !u32 {
|
||||||
if (self._timers.count() > 512) {
|
if (self._timers.count() > 512) {
|
||||||
@@ -393,10 +395,10 @@ fn scheduleCallback(self: *Window, cb: js.Function, delay_ms: u32, opts: Schedul
|
|||||||
const callback = try page._factory.create(ScheduleCallback{
|
const callback = try page._factory.create(ScheduleCallback{
|
||||||
.cb = cb,
|
.cb = cb,
|
||||||
.page = page,
|
.page = page,
|
||||||
|
.mode = opts.mode,
|
||||||
.name = opts.name,
|
.name = opts.name,
|
||||||
.timer_id = timer_id,
|
.timer_id = timer_id,
|
||||||
.params = persisted_params,
|
.params = persisted_params,
|
||||||
.animation_frame = opts.animation_frame,
|
|
||||||
.repeat_ms = if (opts.repeat) if (delay_ms == 0) 1 else delay_ms else null,
|
.repeat_ms = if (opts.repeat) if (delay_ms == 0) 1 else delay_ms else null,
|
||||||
});
|
});
|
||||||
gop.value_ptr.* = callback;
|
gop.value_ptr.* = callback;
|
||||||
@@ -428,7 +430,13 @@ const ScheduleCallback = struct {
|
|||||||
|
|
||||||
removed: bool = false,
|
removed: bool = false,
|
||||||
|
|
||||||
animation_frame: bool = false,
|
mode: Mode,
|
||||||
|
|
||||||
|
const Mode = enum {
|
||||||
|
idle,
|
||||||
|
normal,
|
||||||
|
animation_frame,
|
||||||
|
};
|
||||||
|
|
||||||
fn deinit(self: *ScheduleCallback) void {
|
fn deinit(self: *ScheduleCallback) void {
|
||||||
self.page._factory.destroy(self);
|
self.page._factory.destroy(self);
|
||||||
@@ -443,16 +451,23 @@ const ScheduleCallback = struct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.animation_frame) {
|
switch (self.mode) {
|
||||||
|
.idle => {
|
||||||
|
const IdleDeadline = @import("IdleDeadline.zig");
|
||||||
|
self.cb.call(void, .{IdleDeadline{}}) catch |err| {
|
||||||
|
log.warn(.js, "window.idleCallback", .{ .name = self.name, .err = err });
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.animation_frame => {
|
||||||
self.cb.call(void, .{page.window._performance.now()}) catch |err| {
|
self.cb.call(void, .{page.window._performance.now()}) catch |err| {
|
||||||
// a non-JS error
|
|
||||||
log.warn(.js, "window.RAF", .{ .name = self.name, .err = err });
|
log.warn(.js, "window.RAF", .{ .name = self.name, .err = err });
|
||||||
};
|
};
|
||||||
} else {
|
},
|
||||||
|
.normal => {
|
||||||
self.cb.call(void, .{self.params}) catch |err| {
|
self.cb.call(void, .{self.params}) catch |err| {
|
||||||
// a non-JS error
|
|
||||||
log.warn(.js, "window.timer", .{ .name = self.name, .err = err });
|
log.warn(.js, "window.timer", .{ .name = self.name, .err = err });
|
||||||
};
|
};
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.repeat_ms) |ms| {
|
if (self.repeat_ms) |ms| {
|
||||||
|
|||||||
Reference in New Issue
Block a user