mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-02-04 06:23:45 +00:00
Make Global Function explicit.
This is the first in a series of changes to make globals explicit. The ultimate goal of having explicit Globals is to move away from the global HandleScope and to explicit HandleScopes. Currently, we treat globals and locals interchangeably. In fact, for Global -> Local, we just ptrCast. This works because we have 1 global HandleScope, which effectively disables V8's GC and thus nothing ever gets moved. If we're going to introduce explicit HandleScopes, then we need to first have correct Globals. Specifically, when we want to act on the global, we need to get the local value, and that will eventually mean making sure there's a HandleScope. While adding explicit globals, we're keeping the global HandleScope so that we can minimize the change. So, given that we still have the global HandleScope the change is largely two things: 1 - js.Function.persit() returns a js.Function.Global. Types that persist global functions must be updated to js.Function.Global. 2 - To turn js.Function.Global -> js.Function, we need to call .local() on it. The bridge has been updated to support js.Function.Global for both input and output parameters. Thus, window.setOnLoad can now directly take a js.Function.Global, and window.getOnLoad can directly return that js.Function.Global.
This commit is contained in:
@@ -5,11 +5,11 @@
|
||||
.fingerprint = 0xda130f3af836cea0, // Changing this has security and trust implications.
|
||||
.minimum_zig_version = "0.15.2",
|
||||
.dependencies = .{
|
||||
.v8 = .{
|
||||
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/5b0555e6b6154f957f9d7002ecb8005cc5a41b7a.tar.gz",
|
||||
.hash = "v8-0.0.0-xddH6xUqBABofwwIBsof3cD3c2FstBvm7_VzoughX1Km",
|
||||
},
|
||||
//.v8 = .{ .path = "../zig-v8-fork" },
|
||||
//.v8 = .{
|
||||
// .url = "https://github.com/lightpanda-io/zig-v8-fork/archive/5b0555e6b6154f957f9d7002ecb8005cc5a41b7a.tar.gz",
|
||||
// .hash = "v8-0.0.0-xddH6xUqBABofwwIBsof3cD3c2FstBvm7_VzoughX1Km",
|
||||
//},
|
||||
.v8 = .{ .path = "../zig-v8-fork" },
|
||||
.@"boringssl-zig" = .{
|
||||
.url = "git+https://github.com/Syndica/boringssl-zig.git#c53df00d06b02b755ad88bbf4d1202ed9687b096",
|
||||
.hash = "boringssl-0.1.0-VtJeWehMAAA4RNnwRnzEvKcS9rjsR1QVRw1uJrwXxmVK",
|
||||
|
||||
@@ -102,7 +102,7 @@ pub fn register(self: *EventManager, target: *EventTarget, typ: []const u8, call
|
||||
}
|
||||
|
||||
const func = switch (callback) {
|
||||
.function => |f| Function{ .value = f },
|
||||
.function => |f| Function{ .value = try f.persist() },
|
||||
.object => |o| Function{ .object = o },
|
||||
};
|
||||
|
||||
@@ -368,7 +368,7 @@ fn dispatchPhase(self: *EventManager, list: *std.DoublyLinkedList, current_targe
|
||||
}
|
||||
|
||||
switch (listener.function) {
|
||||
.value => |value| try value.callWithThis(void, current_target, .{event}),
|
||||
.value => |value| try value.local().callWithThis(void, current_target, .{event}),
|
||||
.string => |string| {
|
||||
const str = try page.call_arena.dupeZ(u8, string.str());
|
||||
try self.page.js.eval(str, null);
|
||||
@@ -443,13 +443,13 @@ const Listener = struct {
|
||||
};
|
||||
|
||||
const Function = union(enum) {
|
||||
value: js.Function,
|
||||
value: js.Function.Global,
|
||||
string: String,
|
||||
object: js.Object,
|
||||
|
||||
fn eqlFunction(self: Function, func: js.Function) bool {
|
||||
return switch (self) {
|
||||
.value => |v| return v.id() == func.id(),
|
||||
.value => |v| v.isEqual(func),
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -562,18 +562,20 @@ fn _documentIsComplete(self: *Page) !void {
|
||||
// this event is weird, it's dispatched directly on the window, but
|
||||
// with the document as the target
|
||||
event._target = self.document.asEventTarget();
|
||||
const on_load = if (self.window._on_load) |*g| g.local() else null;
|
||||
try self._event_manager.dispatchWithFunction(
|
||||
self.window.asEventTarget(),
|
||||
event,
|
||||
self.window._on_load,
|
||||
on_load,
|
||||
.{ .inject_target = false, .context = "page load" },
|
||||
);
|
||||
|
||||
const pageshow_event = try PageTransitionEvent.initTrusted("pageshow", .{}, self);
|
||||
const on_pageshow = if (self.window._on_pageshow) |*g| g.local() else null;
|
||||
try self._event_manager.dispatchWithFunction(
|
||||
self.window.asEventTarget(),
|
||||
pageshow_event.asEvent(),
|
||||
self.window._on_pageshow,
|
||||
on_pageshow,
|
||||
.{ .context = "page show" },
|
||||
);
|
||||
}
|
||||
@@ -1997,7 +1999,7 @@ pub fn createElementNS(self: *Page, namespace: Element.Namespace, name: []const
|
||||
defer self._upgrading_element = prev_upgrading;
|
||||
|
||||
var caught: JS.TryCatch.Caught = undefined;
|
||||
_ = def.constructor.newInstance(&caught) catch |err| {
|
||||
_ = def.constructor.local().newInstance(&caught) catch |err| {
|
||||
log.warn(.js, "custom element constructor", .{ .name = name, .err = err, .caught = caught });
|
||||
return node;
|
||||
};
|
||||
|
||||
@@ -844,8 +844,9 @@ pub const Script = struct {
|
||||
self.executeCallback("error", script_element._on_error, page);
|
||||
}
|
||||
|
||||
fn executeCallback(self: *const Script, comptime typ: []const u8, cb_: ?js.Function, page: *Page) void {
|
||||
const cb = cb_ orelse return;
|
||||
fn executeCallback(self: *const Script, comptime typ: []const u8, cb_: ?js.Function.Global, page: *Page) void {
|
||||
const cb_global = cb_ orelse return;
|
||||
const cb = cb_global.local();
|
||||
|
||||
const Event = @import("webapi/Event.zig");
|
||||
const event = Event.initTrusted(typ, .{}, page) catch |err| {
|
||||
|
||||
@@ -81,7 +81,7 @@ global_values: std.ArrayList(js.Global(js.Value)) = .empty,
|
||||
global_objects: std.ArrayList(js.Global(js.Object)) = .empty,
|
||||
global_modules: std.ArrayList(js.Global(js.Module)) = .empty,
|
||||
global_promises: std.ArrayList(js.Global(js.Promise)) = .empty,
|
||||
global_functions: std.ArrayList(js.Global(js.Function)) = .empty,
|
||||
global_functions: std.ArrayList(v8.Global) = .empty,
|
||||
global_promise_resolvers: std.ArrayList(js.Global(js.PromiseResolver)) = .empty,
|
||||
|
||||
// Our module cache: normalized module specifier => module.
|
||||
@@ -154,7 +154,7 @@ pub fn deinit(self: *Context) void {
|
||||
}
|
||||
|
||||
for (self.global_functions.items) |*global| {
|
||||
global.deinit();
|
||||
v8.v8__Global__Reset(global);
|
||||
}
|
||||
|
||||
for (self.global_promises.items) |*global| {
|
||||
@@ -452,6 +452,11 @@ pub fn zigValueToJs(self: *Context, value: anytype, comptime opts: Caller.CallOp
|
||||
return .{ .ctx = self, .handle = @ptrCast(value.handle) };
|
||||
}
|
||||
|
||||
if (T == js.Function.Global) {
|
||||
// Auto-convert Global to local for bridge
|
||||
return .{ .ctx = self, .handle = @ptrCast(value.local().handle) };
|
||||
}
|
||||
|
||||
if (T == js.Object) {
|
||||
// we're returning a v8.Object
|
||||
return .{ .ctx = self, .handle = @ptrCast(value.handle) };
|
||||
@@ -778,6 +783,13 @@ fn jsValueToStruct(self: *Context, comptime T: type, js_value: js.Value) !?T {
|
||||
}
|
||||
return try self.newFunction(js_value);
|
||||
},
|
||||
js.Function.Global => {
|
||||
if (!js_value.isFunction()) {
|
||||
return null;
|
||||
}
|
||||
const func = try self.newFunction(js_value);
|
||||
return try func.persist();
|
||||
},
|
||||
// zig fmt: off
|
||||
js.TypedArray(u8), js.TypedArray(u16), js.TypedArray(u32), js.TypedArray(u64),
|
||||
js.TypedArray(i8), js.TypedArray(i16), js.TypedArray(i32), js.TypedArray(i64),
|
||||
|
||||
@@ -33,10 +33,6 @@ pub const Result = struct {
|
||||
exception: []const u8,
|
||||
};
|
||||
|
||||
pub fn id(self: *const Function) u32 {
|
||||
return @as(u32, @bitCast(v8.v8__Object__GetIdentityHash(@ptrCast(self.handle))));
|
||||
}
|
||||
|
||||
pub fn withThis(self: *const Function, value: anytype) !Function {
|
||||
const this_obj = if (@TypeOf(value) == js.Object)
|
||||
value.handle
|
||||
@@ -172,20 +168,41 @@ pub fn getPropertyValue(self: *const Function, name: []const u8) !?js.Value {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn persist(self: *const Function) !Function {
|
||||
pub fn persist(self: *const Function) !Global {
|
||||
var ctx = self.ctx;
|
||||
|
||||
const global = js.Global(Function).init(ctx.isolate.handle, self.handle);
|
||||
var global: v8.Global = undefined;
|
||||
v8.v8__Global__New(ctx.isolate.handle, self.handle, &global);
|
||||
|
||||
try ctx.global_functions.append(ctx.arena, global);
|
||||
|
||||
return .{
|
||||
.handle = global,
|
||||
.ctx = ctx,
|
||||
.this = self.this,
|
||||
.handle = global.local(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn persistWithThis(self: *const Function, value: anytype) !Function {
|
||||
var persisted = try self.persist();
|
||||
return persisted.withThis(value);
|
||||
pub fn persistWithThis(self: *const Function, value: anytype) !Global {
|
||||
const with_this = try self.withThis(value);
|
||||
return with_this.persist();
|
||||
}
|
||||
|
||||
pub const Global = struct {
|
||||
handle: v8.Global,
|
||||
ctx: *js.Context,
|
||||
|
||||
pub fn deinit(self: *Global) void {
|
||||
v8.v8__Global__Reset(&self.handle);
|
||||
}
|
||||
|
||||
pub fn local(self: *const Global) Function {
|
||||
return .{
|
||||
.ctx = self.ctx,
|
||||
.handle = @ptrCast(v8.v8__Global__Get(&self.handle, self.ctx.isolate.handle)),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isEqual(self: *const Global, other: Function) bool {
|
||||
return v8.v8__Global__IsEqual(&self.handle, other.handle);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -29,7 +29,7 @@ const AbortSignal = @This();
|
||||
_proto: *EventTarget,
|
||||
_aborted: bool = false,
|
||||
_reason: Reason = .undefined,
|
||||
_on_abort: ?js.Function = null,
|
||||
_on_abort: ?js.Function.Global = null,
|
||||
|
||||
pub fn init(page: *Page) !*AbortSignal {
|
||||
return page._factory.eventTarget(AbortSignal{
|
||||
@@ -45,16 +45,12 @@ pub fn getReason(self: *const AbortSignal) Reason {
|
||||
return self._reason;
|
||||
}
|
||||
|
||||
pub fn getOnAbort(self: *const AbortSignal) ?js.Function {
|
||||
pub fn getOnAbort(self: *const AbortSignal) ?js.Function.Global {
|
||||
return self._on_abort;
|
||||
}
|
||||
|
||||
pub fn setOnAbort(self: *AbortSignal, cb_: ?js.Function) !void {
|
||||
if (cb_) |cb| {
|
||||
self._on_abort = try cb.persistWithThis(self);
|
||||
} else {
|
||||
self._on_abort = null;
|
||||
}
|
||||
pub fn setOnAbort(self: *AbortSignal, cb: ?js.Function.Global) !void {
|
||||
self._on_abort = cb;
|
||||
}
|
||||
|
||||
pub fn asEventTarget(self: *AbortSignal) *EventTarget {
|
||||
@@ -81,10 +77,11 @@ pub fn abort(self: *AbortSignal, reason_: ?Reason, page: *Page) !void {
|
||||
|
||||
// Dispatch abort event
|
||||
const event = try Event.initTrusted("abort", .{}, page);
|
||||
const func = if (self._on_abort) |*g| g.local() else null;
|
||||
try page._event_manager.dispatchWithFunction(
|
||||
self.asEventTarget(),
|
||||
event,
|
||||
self._on_abort,
|
||||
func,
|
||||
.{ .context = "abort signal" },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ const Element = @import("Element.zig");
|
||||
const CustomElementDefinition = @This();
|
||||
|
||||
name: []const u8,
|
||||
constructor: js.Function,
|
||||
constructor: js.Function.Global,
|
||||
observed_attributes: std.StringHashMapUnmanaged(void) = .{},
|
||||
// For customized built-in elements, this is the element tag they extend (e.g., .button)
|
||||
// For autonomous custom elements, this is null
|
||||
|
||||
@@ -110,7 +110,7 @@ pub fn define(self: *CustomElementRegistry, name: []const u8, constructor: js.Fu
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(self: *CustomElementRegistry, name: []const u8) ?js.Function {
|
||||
pub fn get(self: *CustomElementRegistry, name: []const u8) ?js.Function.Global {
|
||||
const definition = self._definitions.get(name) orelse return null;
|
||||
return definition.constructor;
|
||||
}
|
||||
@@ -175,7 +175,7 @@ pub fn upgradeCustomElement(custom: *Custom, definition: *CustomElementDefinitio
|
||||
defer page._upgrading_element = prev_upgrading;
|
||||
|
||||
var caught: js.TryCatch.Caught = undefined;
|
||||
_ = definition.constructor.newInstance(&caught) catch |err| {
|
||||
_ = definition.constructor.local().newInstance(&caught) catch |err| {
|
||||
log.warn(.js, "custom element upgrade", .{ .name = definition.name, .err = err, .caught = caught });
|
||||
return error.CustomElementUpgradeFailed;
|
||||
};
|
||||
|
||||
@@ -73,7 +73,7 @@ pub fn addEventListener(self: *EventTarget, typ: []const u8, callback_: ?EventLi
|
||||
|
||||
const em_callback = switch (callback) {
|
||||
.object => |obj| EventManager.Callback{ .object = try obj.persist() },
|
||||
.function => |func| EventManager.Callback{ .function = try func.persist() },
|
||||
.function => |func| EventManager.Callback{ .function = func },
|
||||
};
|
||||
|
||||
const options = blk: {
|
||||
|
||||
@@ -81,10 +81,11 @@ fn goInner(delta: i32, page: *Page) !void {
|
||||
if (try page.isSameOrigin(url)) {
|
||||
const event = try PopStateEvent.initTrusted("popstate", .{ .state = entry._state.value }, page);
|
||||
|
||||
const func = if (page.window._on_popstate) |*g| g.local() else null;
|
||||
try page._event_manager.dispatchWithFunction(
|
||||
page.window.asEventTarget(),
|
||||
event.asEvent(),
|
||||
page.window._on_popstate,
|
||||
func,
|
||||
.{ .context = "Pop State" },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ pub fn registerTypes() []const type {
|
||||
|
||||
const IntersectionObserver = @This();
|
||||
|
||||
_callback: js.Function,
|
||||
_callback: js.Function.Global,
|
||||
_observing: std.ArrayList(*Element) = .{},
|
||||
_root: ?*Element = null,
|
||||
_root_margin: []const u8 = "0px",
|
||||
@@ -59,7 +59,7 @@ pub const ObserverInit = struct {
|
||||
};
|
||||
};
|
||||
|
||||
pub fn init(callback: js.Function, options: ?ObserverInit, page: *Page) !*IntersectionObserver {
|
||||
pub fn init(callback: js.Function.Global, options: ?ObserverInit, page: *Page) !*IntersectionObserver {
|
||||
const opts = options orelse ObserverInit{};
|
||||
const root_margin = if (opts.rootMargin) |rm| try page.arena.dupe(u8, rm) else "0px";
|
||||
|
||||
@@ -73,7 +73,7 @@ pub fn init(callback: js.Function, options: ?ObserverInit, page: *Page) !*Inters
|
||||
};
|
||||
|
||||
return page._factory.create(IntersectionObserver{
|
||||
._callback = try callback.persist(),
|
||||
._callback = callback,
|
||||
._root = opts.root,
|
||||
._root_margin = root_margin,
|
||||
._threshold = threshold,
|
||||
@@ -246,7 +246,7 @@ pub fn deliverEntries(self: *IntersectionObserver, page: *Page) !void {
|
||||
|
||||
const entries = try self.takeRecords(page);
|
||||
var caught: js.TryCatch.Caught = undefined;
|
||||
self._callback.tryCall(void, .{ entries, self }, &caught) catch |err| {
|
||||
self._callback.local().tryCall(void, .{ entries, self }, &caught) catch |err| {
|
||||
log.err(.page, "IntsctObserver.deliverEntries", .{ .err = err, .caught = caught });
|
||||
return err;
|
||||
};
|
||||
|
||||
@@ -29,8 +29,8 @@ const MessagePort = @This();
|
||||
_proto: *EventTarget,
|
||||
_enabled: bool = false,
|
||||
_closed: bool = false,
|
||||
_on_message: ?js.Function = null,
|
||||
_on_message_error: ?js.Function = null,
|
||||
_on_message: ?js.Function.Global = null,
|
||||
_on_message_error: ?js.Function.Global = null,
|
||||
_entangled_port: ?*MessagePort = null,
|
||||
|
||||
pub fn init(page: *Page) !*MessagePort {
|
||||
@@ -88,28 +88,20 @@ pub fn close(self: *MessagePort) void {
|
||||
self._entangled_port = null;
|
||||
}
|
||||
|
||||
pub fn getOnMessage(self: *const MessagePort) ?js.Function {
|
||||
pub fn getOnMessage(self: *const MessagePort) ?js.Function.Global {
|
||||
return self._on_message;
|
||||
}
|
||||
|
||||
pub fn setOnMessage(self: *MessagePort, cb_: ?js.Function) !void {
|
||||
if (cb_) |cb| {
|
||||
self._on_message = try cb.persist();
|
||||
} else {
|
||||
self._on_message = null;
|
||||
}
|
||||
pub fn setOnMessage(self: *MessagePort, cb: ?js.Function.Global) !void {
|
||||
self._on_message = cb;
|
||||
}
|
||||
|
||||
pub fn getOnMessageError(self: *const MessagePort) ?js.Function {
|
||||
pub fn getOnMessageError(self: *const MessagePort) ?js.Function.Global {
|
||||
return self._on_message_error;
|
||||
}
|
||||
|
||||
pub fn setOnMessageError(self: *MessagePort, cb_: ?js.Function) !void {
|
||||
if (cb_) |cb| {
|
||||
self._on_message_error = try cb.persist();
|
||||
} else {
|
||||
self._on_message_error = null;
|
||||
}
|
||||
pub fn setOnMessageError(self: *MessagePort, cb: ?js.Function.Global) !void {
|
||||
self._on_message_error = cb;
|
||||
}
|
||||
|
||||
const PostMessageCallback = struct {
|
||||
@@ -138,10 +130,11 @@ const PostMessageCallback = struct {
|
||||
return null;
|
||||
};
|
||||
|
||||
const func = if (self.port._on_message) |*g| g.local() else null;
|
||||
self.page._event_manager.dispatchWithFunction(
|
||||
self.port.asEventTarget(),
|
||||
event.asEvent(),
|
||||
self.port._on_message,
|
||||
func,
|
||||
.{ .context = "MessagePort message" },
|
||||
) catch |err| {
|
||||
log.err(.dom, "MessagePort.postMessage", .{ .err = err });
|
||||
|
||||
@@ -32,7 +32,7 @@ pub fn registerTypes() []const type {
|
||||
|
||||
const MutationObserver = @This();
|
||||
|
||||
_callback: js.Function,
|
||||
_callback: js.Function.Global,
|
||||
_observing: std.ArrayList(Observing) = .{},
|
||||
_pending_records: std.ArrayList(*MutationRecord) = .{},
|
||||
/// Intrusively linked to next element (see Page.zig).
|
||||
@@ -53,9 +53,9 @@ pub const ObserveOptions = struct {
|
||||
attributeFilter: ?[]const []const u8 = null,
|
||||
};
|
||||
|
||||
pub fn init(callback: js.Function, page: *Page) !*MutationObserver {
|
||||
pub fn init(callback: js.Function.Global, page: *Page) !*MutationObserver {
|
||||
return page._factory.create(MutationObserver{
|
||||
._callback = try callback.persist(),
|
||||
._callback = callback,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -249,7 +249,7 @@ pub fn deliverRecords(self: *MutationObserver, page: *Page) !void {
|
||||
// This ensures mutations triggered during the callback go into a fresh list
|
||||
const records = try self.takeRecords(page);
|
||||
var caught: js.TryCatch.Caught = undefined;
|
||||
self._callback.tryCall(void, .{ records, self }, &caught) catch |err| {
|
||||
self._callback.local().tryCall(void, .{ records, self }, &caught) catch |err| {
|
||||
log.err(.page, "MutObserver.deliverRecords", .{ .err = err, .caught = caught });
|
||||
return err;
|
||||
};
|
||||
|
||||
@@ -22,22 +22,22 @@ const Node = @import("Node.zig");
|
||||
|
||||
const NodeFilter = @This();
|
||||
|
||||
_func: ?js.Function,
|
||||
_func: ?js.Function.Global,
|
||||
_original_filter: ?FilterOpts,
|
||||
|
||||
pub const FilterOpts = union(enum) {
|
||||
function: js.Function,
|
||||
function: js.Function.Global,
|
||||
object: struct {
|
||||
pub const js_as_object = true;
|
||||
acceptNode: js.Function,
|
||||
acceptNode: js.Function.Global,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn init(opts_: ?FilterOpts) !NodeFilter {
|
||||
const opts = opts_ orelse return .{ ._func = null, ._original_filter = null };
|
||||
const func = switch (opts) {
|
||||
.function => |func| try func.persist(),
|
||||
.object => |obj| try obj.acceptNode.persist(),
|
||||
.function => |func| func,
|
||||
.object => |obj| obj.acceptNode,
|
||||
};
|
||||
return .{
|
||||
._func = func,
|
||||
@@ -67,7 +67,7 @@ pub const SHOW_NOTATION: u32 = 0x800;
|
||||
|
||||
pub fn acceptNode(self: *const NodeFilter, node: *Node) !i32 {
|
||||
const func = self._func orelse return FILTER_ACCEPT;
|
||||
return func.call(i32, .{node});
|
||||
return func.local().call(i32, .{node});
|
||||
}
|
||||
|
||||
pub fn shouldShow(node: *const Node, what_to_show: u32) bool {
|
||||
|
||||
@@ -32,7 +32,7 @@ pub fn registerTypes() []const type {
|
||||
const PerformanceObserver = @This();
|
||||
|
||||
/// Emitted when there are events with same interests.
|
||||
_callback: js.Function,
|
||||
_callback: js.Function.Global,
|
||||
/// The threshold to deliver `PerformanceEventTiming` entries.
|
||||
_duration_threshold: f64,
|
||||
/// Entry types we're looking for are encoded as bit flags.
|
||||
@@ -44,9 +44,9 @@ _entries: std.ArrayList(*Performance.Entry),
|
||||
const DefaultDurationThreshold: f64 = 104;
|
||||
|
||||
/// Creates a new PerformanceObserver object with the given observer callback.
|
||||
pub fn init(callback: js.Function, page: *Page) !*PerformanceObserver {
|
||||
pub fn init(callback: js.Function.Global, page: *Page) !*PerformanceObserver {
|
||||
return page._factory.create(PerformanceObserver{
|
||||
._callback = try callback.persist(),
|
||||
._callback = callback,
|
||||
._duration_threshold = DefaultDurationThreshold,
|
||||
._interests = 0,
|
||||
._entries = .{},
|
||||
@@ -154,7 +154,7 @@ pub inline fn hasRecords(self: *const PerformanceObserver) bool {
|
||||
pub fn dispatch(self: *PerformanceObserver, page: *Page) !void {
|
||||
const records = try self.takeRecords(page);
|
||||
var caught: js.TryCatch.Caught = undefined;
|
||||
self._callback.tryCall(void, .{ EntryList{ ._entries = records }, self }, &caught) catch |err| {
|
||||
self._callback.local().tryCall(void, .{ EntryList{ ._entries = records }, self }, &caught) catch |err| {
|
||||
log.err(.page, "PerfObserver.dispatch", .{ .err = err, .caught = caught });
|
||||
return err;
|
||||
};
|
||||
|
||||
@@ -54,11 +54,11 @@ _navigator: Navigator = .init,
|
||||
_screen: *Screen,
|
||||
_performance: Performance,
|
||||
_storage_bucket: *storage.Bucket,
|
||||
_on_load: ?js.Function = null,
|
||||
_on_pageshow: ?js.Function = null,
|
||||
_on_popstate: ?js.Function = null,
|
||||
_on_error: ?js.Function = null, // TODO: invoke on error?
|
||||
_on_unhandled_rejection: ?js.Function = null, // TODO: invoke on error
|
||||
_on_load: ?js.Function.Global = null,
|
||||
_on_pageshow: ?js.Function.Global = null,
|
||||
_on_popstate: ?js.Function.Global = null,
|
||||
_on_error: ?js.Function.Global = null, // TODO: invoke on error?
|
||||
_on_unhandled_rejection: ?js.Function.Global = null, // TODO: invoke on error
|
||||
_location: *Location,
|
||||
_timer_id: u30 = 0,
|
||||
_timers: std.AutoHashMapUnmanaged(u32, *ScheduleCallback) = .{},
|
||||
@@ -145,51 +145,51 @@ pub fn getCustomElements(self: *Window) *CustomElementRegistry {
|
||||
return &self._custom_elements;
|
||||
}
|
||||
|
||||
pub fn getOnLoad(self: *const Window) ?js.Function {
|
||||
pub fn getOnLoad(self: *const Window) ?js.Function.Global {
|
||||
return self._on_load;
|
||||
}
|
||||
|
||||
pub fn setOnLoad(self: *Window, setter: ?FunctionSetter) !void {
|
||||
self._on_load = try getFunctionFromSetter(setter);
|
||||
pub fn setOnLoad(self: *Window, setter: ?FunctionSetter) void {
|
||||
self._on_load = getFunctionFromSetter(setter);
|
||||
}
|
||||
|
||||
pub fn getOnPageShow(self: *const Window) ?js.Function {
|
||||
pub fn getOnPageShow(self: *const Window) ?js.Function.Global {
|
||||
return self._on_pageshow;
|
||||
}
|
||||
|
||||
pub fn setOnPageShow(self: *Window, setter: ?FunctionSetter) !void {
|
||||
self._on_pageshow = try getFunctionFromSetter(setter);
|
||||
pub fn setOnPageShow(self: *Window, setter: ?FunctionSetter) void {
|
||||
self._on_pageshow = getFunctionFromSetter(setter);
|
||||
}
|
||||
|
||||
pub fn getOnPopState(self: *const Window) ?js.Function {
|
||||
pub fn getOnPopState(self: *const Window) ?js.Function.Global {
|
||||
return self._on_popstate;
|
||||
}
|
||||
|
||||
pub fn setOnPopState(self: *Window, setter: ?FunctionSetter) !void {
|
||||
self._on_popstate = try getFunctionFromSetter(setter);
|
||||
pub fn setOnPopState(self: *Window, setter: ?FunctionSetter) void {
|
||||
self._on_popstate = getFunctionFromSetter(setter);
|
||||
}
|
||||
|
||||
pub fn getOnError(self: *const Window) ?js.Function {
|
||||
pub fn getOnError(self: *const Window) ?js.Function.Global {
|
||||
return self._on_error;
|
||||
}
|
||||
|
||||
pub fn setOnError(self: *Window, setter: ?FunctionSetter) !void {
|
||||
self._on_error = try getFunctionFromSetter(setter);
|
||||
pub fn setOnError(self: *Window, setter: ?FunctionSetter) void {
|
||||
self._on_error = getFunctionFromSetter(setter);
|
||||
}
|
||||
|
||||
pub fn getOnUnhandledRejection(self: *const Window) ?js.Function {
|
||||
pub fn getOnUnhandledRejection(self: *const Window) ?js.Function.Global {
|
||||
return self._on_unhandled_rejection;
|
||||
}
|
||||
|
||||
pub fn setOnUnhandledRejection(self: *Window, setter: ?FunctionSetter) !void {
|
||||
self._on_unhandled_rejection = try getFunctionFromSetter(setter);
|
||||
pub fn setOnUnhandledRejection(self: *Window, setter: ?FunctionSetter) void {
|
||||
self._on_unhandled_rejection = getFunctionFromSetter(setter);
|
||||
}
|
||||
|
||||
pub fn fetch(_: *const Window, input: Fetch.Input, options: ?Fetch.InitOpts, page: *Page) !js.Promise {
|
||||
return Fetch.init(input, options, page);
|
||||
}
|
||||
|
||||
pub fn setTimeout(self: *Window, cb: js.Function, delay_ms: ?u32, params: []js.Value, page: *Page) !u32 {
|
||||
pub fn setTimeout(self: *Window, cb: js.Function.Global, delay_ms: ?u32, params: []js.Value, page: *Page) !u32 {
|
||||
return self.scheduleCallback(cb, delay_ms orelse 0, .{
|
||||
.repeat = false,
|
||||
.params = params,
|
||||
@@ -198,7 +198,7 @@ pub fn setTimeout(self: *Window, cb: js.Function, delay_ms: ?u32, params: []js.V
|
||||
}, page);
|
||||
}
|
||||
|
||||
pub fn setInterval(self: *Window, cb: js.Function, delay_ms: ?u32, params: []js.Value, page: *Page) !u32 {
|
||||
pub fn setInterval(self: *Window, cb: js.Function.Global, delay_ms: ?u32, params: []js.Value, page: *Page) !u32 {
|
||||
return self.scheduleCallback(cb, delay_ms orelse 0, .{
|
||||
.repeat = true,
|
||||
.params = params,
|
||||
@@ -207,7 +207,7 @@ pub fn setInterval(self: *Window, cb: js.Function, delay_ms: ?u32, params: []js.
|
||||
}, page);
|
||||
}
|
||||
|
||||
pub fn setImmediate(self: *Window, cb: js.Function, params: []js.Value, page: *Page) !u32 {
|
||||
pub fn setImmediate(self: *Window, cb: js.Function.Global, params: []js.Value, page: *Page) !u32 {
|
||||
return self.scheduleCallback(cb, 0, .{
|
||||
.repeat = false,
|
||||
.params = params,
|
||||
@@ -216,7 +216,7 @@ pub fn setImmediate(self: *Window, cb: js.Function, params: []js.Value, page: *P
|
||||
}, page);
|
||||
}
|
||||
|
||||
pub fn requestAnimationFrame(self: *Window, cb: js.Function, page: *Page) !u32 {
|
||||
pub fn requestAnimationFrame(self: *Window, cb: js.Function.Global, page: *Page) !u32 {
|
||||
return self.scheduleCallback(cb, 5, .{
|
||||
.repeat = false,
|
||||
.params = &.{},
|
||||
@@ -253,7 +253,7 @@ pub fn cancelAnimationFrame(self: *Window, id: u32) void {
|
||||
const RequestIdleCallbackOpts = struct {
|
||||
timeout: ?u32 = null,
|
||||
};
|
||||
pub fn requestIdleCallback(self: *Window, cb: js.Function, opts_: ?RequestIdleCallbackOpts, page: *Page) !u32 {
|
||||
pub fn requestIdleCallback(self: *Window, cb: js.Function.Global, opts_: ?RequestIdleCallbackOpts, page: *Page) !u32 {
|
||||
const opts = opts_ orelse RequestIdleCallbackOpts{};
|
||||
return self.scheduleCallback(cb, opts.timeout orelse 50, .{
|
||||
.mode = .idle,
|
||||
@@ -471,7 +471,7 @@ const ScheduleOpts = struct {
|
||||
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.Global, delay_ms: u32, opts: ScheduleOpts, page: *Page) !u32 {
|
||||
if (self._timers.count() > 512) {
|
||||
// these are active
|
||||
return error.TooManyTimeout;
|
||||
@@ -497,7 +497,7 @@ fn scheduleCallback(self: *Window, cb: js.Function, delay_ms: u32, opts: Schedul
|
||||
errdefer _ = self._timers.remove(timer_id);
|
||||
|
||||
const callback = try page._factory.create(ScheduleCallback{
|
||||
.cb = try cb.persist(),
|
||||
.cb = cb,
|
||||
.page = page,
|
||||
.mode = opts.mode,
|
||||
.name = opts.name,
|
||||
@@ -526,7 +526,7 @@ const ScheduleCallback = struct {
|
||||
// delay, in ms, to repeat. When null, will be removed after the first time
|
||||
repeat_ms: ?u32,
|
||||
|
||||
cb: js.Function,
|
||||
cb: js.Function.Global,
|
||||
|
||||
page: *Page,
|
||||
|
||||
@@ -558,17 +558,17 @@ const ScheduleCallback = struct {
|
||||
switch (self.mode) {
|
||||
.idle => {
|
||||
const IdleDeadline = @import("IdleDeadline.zig");
|
||||
self.cb.call(void, .{IdleDeadline{}}) catch |err| {
|
||||
self.cb.local().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.local().call(void, .{page.window._performance.now()}) catch |err| {
|
||||
log.warn(.js, "window.RAF", .{ .name = self.name, .err = err });
|
||||
};
|
||||
},
|
||||
.normal => {
|
||||
self.cb.call(void, self.params) catch |err| {
|
||||
self.cb.local().call(void, self.params) catch |err| {
|
||||
log.warn(.js, "window.timer", .{ .name = self.name, .err = err });
|
||||
};
|
||||
},
|
||||
@@ -615,17 +615,17 @@ const PostMessageCallback = struct {
|
||||
};
|
||||
|
||||
const FunctionSetter = union(enum) {
|
||||
func: js.Function,
|
||||
func: js.Function.Global,
|
||||
anything: js.Value,
|
||||
};
|
||||
|
||||
// window.onload = {}; doesn't fail, but it doesn't do anything.
|
||||
// seems like setting to null is ok (though, at least on Firefix, it preserves
|
||||
// the original value, which we could do, but why?)
|
||||
fn getFunctionFromSetter(setter_: ?FunctionSetter) !?js.Function {
|
||||
fn getFunctionFromSetter(setter_: ?FunctionSetter) ?js.Function.Global {
|
||||
const setter = setter_ orelse return null;
|
||||
return switch (setter) {
|
||||
.func => |func| try func.persist(),
|
||||
.func => |func| func, // Already a Global from bridge auto-conversion
|
||||
.anything => null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -50,9 +50,10 @@ pub const Build = struct {
|
||||
pub fn complete(node: *Node, page: *Page) !void {
|
||||
const el = node.as(Element);
|
||||
const on_load = el.getAttributeSafe("onload") orelse return;
|
||||
page.window._on_load = page.js.stringToFunction(on_load) catch |err| blk: {
|
||||
if (page.js.stringToFunction(on_load)) |func| {
|
||||
page.window._on_load = try func.persist();
|
||||
} else |err| {
|
||||
log.err(.js, "body.onload", .{ .err = err, .str = on_load });
|
||||
break :blk null;
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -196,7 +196,7 @@ pub fn checkAndAttachBuiltIn(element: *Element, page: *Page) !void {
|
||||
defer page._upgrading_element = prev_upgrading;
|
||||
|
||||
var caught: js.TryCatch.Caught = undefined;
|
||||
_ = definition.constructor.newInstance(&caught) catch |err| {
|
||||
_ = definition.constructor.local().newInstance(&caught) catch |err| {
|
||||
log.warn(.js, "custom builtin ctor", .{ .name = is_value, .err = err, .caught = caught });
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -29,8 +29,8 @@ const Script = @This();
|
||||
|
||||
_proto: *HtmlElement,
|
||||
_src: []const u8 = "",
|
||||
_on_load: ?js.Function = null,
|
||||
_on_error: ?js.Function = null,
|
||||
_on_load: ?js.Function.Global = null,
|
||||
_on_error: ?js.Function.Global = null,
|
||||
_executed: bool = false,
|
||||
|
||||
pub fn asElement(self: *Script) *Element {
|
||||
@@ -74,28 +74,20 @@ pub fn setNonce(self: *Script, value: []const u8, page: *Page) !void {
|
||||
return self.asElement().setAttributeSafe("nonce", value, page);
|
||||
}
|
||||
|
||||
pub fn getOnLoad(self: *const Script) ?js.Function {
|
||||
pub fn getOnLoad(self: *const Script) ?js.Function.Global {
|
||||
return self._on_load;
|
||||
}
|
||||
|
||||
pub fn setOnLoad(self: *Script, cb_: ?js.Function) !void {
|
||||
if (cb_) |cb| {
|
||||
self._on_load = try cb.persist();
|
||||
} else {
|
||||
self._on_load = null;
|
||||
}
|
||||
pub fn setOnLoad(self: *Script, cb: ?js.Function.Global) void {
|
||||
self._on_load = cb;
|
||||
}
|
||||
|
||||
pub fn getOnError(self: *const Script) ?js.Function {
|
||||
pub fn getOnError(self: *const Script) ?js.Function.Global {
|
||||
return self._on_error;
|
||||
}
|
||||
|
||||
pub fn setOnError(self: *Script, cb_: ?js.Function) !void {
|
||||
if (cb_) |cb| {
|
||||
self._on_error = try cb.persist();
|
||||
} else {
|
||||
self._on_error = null;
|
||||
}
|
||||
pub fn setOnError(self: *Script, cb: ?js.Function.Global) void {
|
||||
self._on_error = cb;
|
||||
}
|
||||
|
||||
pub fn getNoModule(self: *const Script) bool {
|
||||
@@ -136,23 +128,19 @@ pub const Build = struct {
|
||||
self._src = element.getAttributeSafe("src") orelse "";
|
||||
|
||||
if (element.getAttributeSafe("onload")) |on_load| {
|
||||
self._on_load = blk: {
|
||||
const func = page.js.stringToFunction(on_load) catch |err| {
|
||||
log.err(.js, "script.onload", .{ .err = err, .str = on_load });
|
||||
break :blk null;
|
||||
};
|
||||
break :blk try func.persist();
|
||||
};
|
||||
if (page.js.stringToFunction(on_load)) |func| {
|
||||
self._on_load = try func.persist();
|
||||
} else |err| {
|
||||
log.err(.js, "script.onload", .{ .err = err, .str = on_load });
|
||||
}
|
||||
}
|
||||
|
||||
if (element.getAttributeSafe("onerror")) |on_error| {
|
||||
self._on_error = blk: {
|
||||
const func = page.js.stringToFunction(on_error) catch |err| {
|
||||
log.err(.js, "script.onerror", .{ .err = err, .str = on_error });
|
||||
break :blk null;
|
||||
};
|
||||
break :blk try func.persist();
|
||||
};
|
||||
if (page.js.stringToFunction(on_error)) |func| {
|
||||
self._on_error = try func.persist();
|
||||
} else |err| {
|
||||
log.err(.js, "script.onerror", .{ .err = err, .str = on_error });
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -30,8 +30,8 @@ _id: []const u8 = "",
|
||||
_start_time: f64 = 0,
|
||||
_end_time: f64 = 0,
|
||||
_pause_on_exit: bool = false,
|
||||
_on_enter: ?js.Function = null,
|
||||
_on_exit: ?js.Function = null,
|
||||
_on_enter: ?js.Function.Global = null,
|
||||
_on_exit: ?js.Function.Global = null,
|
||||
|
||||
pub const Type = union(enum) {
|
||||
vtt: *@import("VTTCue.zig"),
|
||||
@@ -73,28 +73,20 @@ pub fn setPauseOnExit(self: *TextTrackCue, value: bool) void {
|
||||
self._pause_on_exit = value;
|
||||
}
|
||||
|
||||
pub fn getOnEnter(self: *const TextTrackCue) ?js.Function {
|
||||
pub fn getOnEnter(self: *const TextTrackCue) ?js.Function.Global {
|
||||
return self._on_enter;
|
||||
}
|
||||
|
||||
pub fn setOnEnter(self: *TextTrackCue, cb_: ?js.Function) !void {
|
||||
if (cb_) |cb| {
|
||||
self._on_enter = try cb.persistWithThis(self);
|
||||
} else {
|
||||
self._on_enter = null;
|
||||
}
|
||||
pub fn setOnEnter(self: *TextTrackCue, cb: ?js.Function.Global) !void {
|
||||
self._on_enter = cb;
|
||||
}
|
||||
|
||||
pub fn getOnExit(self: *const TextTrackCue) ?js.Function {
|
||||
pub fn getOnExit(self: *const TextTrackCue) ?js.Function.Global {
|
||||
return self._on_exit;
|
||||
}
|
||||
|
||||
pub fn setOnExit(self: *TextTrackCue, cb_: ?js.Function) !void {
|
||||
if (cb_) |cb| {
|
||||
self._on_exit = try cb.persistWithThis(self);
|
||||
} else {
|
||||
self._on_exit = null;
|
||||
}
|
||||
pub fn setOnExit(self: *TextTrackCue, cb: ?js.Function.Global) !void {
|
||||
self._on_exit = cb;
|
||||
}
|
||||
|
||||
pub const JsApi = struct {
|
||||
|
||||
@@ -26,7 +26,7 @@ const NavigationCurrentEntryChangeEvent = @import("../event/NavigationCurrentEnt
|
||||
pub const NavigationEventTarget = @This();
|
||||
|
||||
_proto: *EventTarget,
|
||||
_on_currententrychange: ?js.Function = null,
|
||||
_on_currententrychange: ?js.Function.Global = null,
|
||||
|
||||
pub fn asEventTarget(self: *NavigationEventTarget) *EventTarget {
|
||||
return self._proto;
|
||||
@@ -43,15 +43,16 @@ pub fn dispatch(self: *NavigationEventTarget, event_type: DispatchType, page: *P
|
||||
};
|
||||
};
|
||||
|
||||
const func = if (@field(self, field)) |*g| g.local() else null;
|
||||
return page._event_manager.dispatchWithFunction(
|
||||
self.asEventTarget(),
|
||||
event,
|
||||
@field(self, field),
|
||||
func,
|
||||
.{ .context = "Navigation" },
|
||||
);
|
||||
}
|
||||
|
||||
pub fn getOnCurrentEntryChange(self: *NavigationEventTarget) ?js.Function {
|
||||
pub fn getOnCurrentEntryChange(self: *NavigationEventTarget) ?js.Function.Global {
|
||||
return self._on_currententrychange;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ _response_headers: std.ArrayList([]const u8) = .empty,
|
||||
_response_type: ResponseType = .text,
|
||||
|
||||
_ready_state: ReadyState = .unsent,
|
||||
_on_ready_state_change: ?js.Function = null,
|
||||
_on_ready_state_change: ?js.Function.Global = null,
|
||||
|
||||
const ReadyState = enum(u8) {
|
||||
unsent = 0,
|
||||
@@ -98,7 +98,7 @@ fn asEventTarget(self: *XMLHttpRequest) *EventTarget {
|
||||
return self._proto._proto;
|
||||
}
|
||||
|
||||
pub fn getOnReadyStateChange(self: *const XMLHttpRequest) ?js.Function {
|
||||
pub fn getOnReadyStateChange(self: *const XMLHttpRequest) ?js.Function.Global {
|
||||
return self._on_ready_state_change;
|
||||
}
|
||||
|
||||
@@ -416,10 +416,11 @@ fn stateChanged(self: *XMLHttpRequest, state: ReadyState, page: *Page) !void {
|
||||
self._ready_state = state;
|
||||
|
||||
const event = try Event.initTrusted("readystatechange", .{}, page);
|
||||
const func = if (self._on_ready_state_change) |*g| g.local() else null;
|
||||
try page._event_manager.dispatchWithFunction(
|
||||
self.asEventTarget(),
|
||||
event,
|
||||
self._on_ready_state_change,
|
||||
func,
|
||||
.{ .context = "XHR state change" },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -26,13 +26,13 @@ const XMLHttpRequestEventTarget = @This();
|
||||
|
||||
_type: Type,
|
||||
_proto: *EventTarget,
|
||||
_on_abort: ?js.Function = null,
|
||||
_on_error: ?js.Function = null,
|
||||
_on_load: ?js.Function = null,
|
||||
_on_load_end: ?js.Function = null,
|
||||
_on_load_start: ?js.Function = null,
|
||||
_on_progress: ?js.Function = null,
|
||||
_on_timeout: ?js.Function = null,
|
||||
_on_abort: ?js.Function.Global = null,
|
||||
_on_error: ?js.Function.Global = null,
|
||||
_on_load: ?js.Function.Global = null,
|
||||
_on_load_end: ?js.Function.Global = null,
|
||||
_on_load_start: ?js.Function.Global = null,
|
||||
_on_progress: ?js.Function.Global = null,
|
||||
_on_timeout: ?js.Function.Global = null,
|
||||
|
||||
pub const Type = union(enum) {
|
||||
request: *@import("XMLHttpRequest.zig"),
|
||||
@@ -63,15 +63,16 @@ pub fn dispatch(self: *XMLHttpRequestEventTarget, comptime event_type: DispatchT
|
||||
page,
|
||||
);
|
||||
|
||||
const func = if (@field(self, field)) |*g| g.local() else null;
|
||||
return page._event_manager.dispatchWithFunction(
|
||||
self.asEventTarget(),
|
||||
event.asEvent(),
|
||||
@field(self, field),
|
||||
func,
|
||||
.{ .context = "XHR " ++ typ },
|
||||
);
|
||||
}
|
||||
|
||||
pub fn getOnAbort(self: *const XMLHttpRequestEventTarget) ?js.Function {
|
||||
pub fn getOnAbort(self: *const XMLHttpRequestEventTarget) ?js.Function.Global {
|
||||
return self._on_abort;
|
||||
}
|
||||
|
||||
@@ -83,7 +84,7 @@ pub fn setOnAbort(self: *XMLHttpRequestEventTarget, cb_: ?js.Function) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getOnError(self: *const XMLHttpRequestEventTarget) ?js.Function {
|
||||
pub fn getOnError(self: *const XMLHttpRequestEventTarget) ?js.Function.Global {
|
||||
return self._on_error;
|
||||
}
|
||||
|
||||
@@ -95,7 +96,7 @@ pub fn setOnError(self: *XMLHttpRequestEventTarget, cb_: ?js.Function) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getOnLoad(self: *const XMLHttpRequestEventTarget) ?js.Function {
|
||||
pub fn getOnLoad(self: *const XMLHttpRequestEventTarget) ?js.Function.Global {
|
||||
return self._on_load;
|
||||
}
|
||||
|
||||
@@ -107,7 +108,7 @@ pub fn setOnLoad(self: *XMLHttpRequestEventTarget, cb_: ?js.Function) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getOnLoadEnd(self: *const XMLHttpRequestEventTarget) ?js.Function {
|
||||
pub fn getOnLoadEnd(self: *const XMLHttpRequestEventTarget) ?js.Function.Global {
|
||||
return self._on_load_end;
|
||||
}
|
||||
|
||||
@@ -119,7 +120,7 @@ pub fn setOnLoadEnd(self: *XMLHttpRequestEventTarget, cb_: ?js.Function) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getOnLoadStart(self: *const XMLHttpRequestEventTarget) ?js.Function {
|
||||
pub fn getOnLoadStart(self: *const XMLHttpRequestEventTarget) ?js.Function.Global {
|
||||
return self._on_load_start;
|
||||
}
|
||||
|
||||
@@ -131,7 +132,7 @@ pub fn setOnLoadStart(self: *XMLHttpRequestEventTarget, cb_: ?js.Function) !void
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getOnProgress(self: *const XMLHttpRequestEventTarget) ?js.Function {
|
||||
pub fn getOnProgress(self: *const XMLHttpRequestEventTarget) ?js.Function.Global {
|
||||
return self._on_progress;
|
||||
}
|
||||
|
||||
@@ -143,7 +144,7 @@ pub fn setOnProgress(self: *XMLHttpRequestEventTarget, cb_: ?js.Function) !void
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getOnTimeout(self: *const XMLHttpRequestEventTarget) ?js.Function {
|
||||
pub fn getOnTimeout(self: *const XMLHttpRequestEventTarget) ?js.Function.Global {
|
||||
return self._on_timeout;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,15 +43,15 @@ _state: State,
|
||||
_reader: ?*ReadableStreamDefaultReader,
|
||||
_controller: *ReadableStreamDefaultController,
|
||||
_stored_error: ?[]const u8,
|
||||
_pull_fn: ?js.Function = null,
|
||||
_pull_fn: ?js.Function.Global = null,
|
||||
_pulling: bool = false,
|
||||
_pull_again: bool = false,
|
||||
_cancel: ?Cancel = null,
|
||||
|
||||
const UnderlyingSource = struct {
|
||||
start: ?js.Function = null,
|
||||
pull: ?js.Function = null,
|
||||
cancel: ?js.Function = null,
|
||||
pull: ?js.Function.Global = null,
|
||||
cancel: ?js.Function.Global = null,
|
||||
type: ?[]const u8 = null,
|
||||
};
|
||||
|
||||
@@ -85,7 +85,7 @@ pub fn init(src_: ?UnderlyingSource, strategy_: ?QueueingStrategy, page: *Page)
|
||||
}
|
||||
|
||||
if (src.pull) |pull| {
|
||||
self._pull_fn = try pull.persist();
|
||||
self._pull_fn = pull;
|
||||
try self.callPullIfNeeded();
|
||||
}
|
||||
}
|
||||
@@ -137,12 +137,12 @@ pub fn callPullIfNeeded(self: *ReadableStream) !void {
|
||||
|
||||
self._pulling = true;
|
||||
|
||||
const pull_fn = self._pull_fn orelse return;
|
||||
const pull_fn = &(self._pull_fn orelse return);
|
||||
|
||||
// Call the pull function
|
||||
// Note: In a complete implementation, we'd handle the promise returned by pull
|
||||
// and set _pulling = false when it resolves
|
||||
try pull_fn.call(void, .{self._controller});
|
||||
try pull_fn.local().call(void, .{self._controller});
|
||||
|
||||
self._pulling = false;
|
||||
|
||||
@@ -186,11 +186,11 @@ pub fn cancel(self: *ReadableStream, reason: ?[]const u8, page: *Page) !js.Promi
|
||||
}
|
||||
|
||||
// Execute the cancel callback if provided
|
||||
if (c.callback) |cb| {
|
||||
if (c.callback) |*cb| {
|
||||
if (reason) |r| {
|
||||
try cb.call(void, .{r});
|
||||
try cb.local().call(void, .{r});
|
||||
} else {
|
||||
try cb.call(void, .{});
|
||||
try cb.local().call(void, .{});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ pub fn cancel(self: *ReadableStream, reason: ?[]const u8, page: *Page) !js.Promi
|
||||
}
|
||||
|
||||
const Cancel = struct {
|
||||
callback: ?js.Function = null,
|
||||
callback: ?js.Function.Global = null,
|
||||
reason: ?[]const u8 = null,
|
||||
resolver: ?js.PromiseResolver = null,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user