Make js.Object and js.Value have explicit global

See: bb06900b6f84abaccc7ecfd386af1a9dc0029c50 for details on this change.
This commit is contained in:
Karl Seguin
2026-01-14 17:30:29 +08:00
parent 728b2b7089
commit c7dbb6792d
18 changed files with 141 additions and 89 deletions

View File

@@ -103,7 +103,7 @@ pub fn register(self: *EventManager, target: *EventTarget, typ: []const u8, call
const func = switch (callback) { const func = switch (callback) {
.function => |f| Function{ .value = try f.persist() }, .function => |f| Function{ .value = try f.persist() },
.object => |o| Function{ .object = o }, .object => |o| Function{ .object = try o.persist() },
}; };
const listener = try self.listener_pool.create(); const listener = try self.listener_pool.create();
@@ -373,7 +373,8 @@ fn dispatchPhase(self: *EventManager, list: *std.DoublyLinkedList, current_targe
const str = try page.call_arena.dupeZ(u8, string.str()); const str = try page.call_arena.dupeZ(u8, string.str());
try self.page.js.eval(str, null); try self.page.js.eval(str, null);
}, },
.object => |obj| { .object => |*obj_global| {
const obj = obj_global.local();
if (try obj.getFunction("handleEvent")) |handleEvent| { if (try obj.getFunction("handleEvent")) |handleEvent| {
try handleEvent.callWithThis(void, obj, .{event}); try handleEvent.callWithThis(void, obj, .{event});
} }
@@ -445,7 +446,7 @@ const Listener = struct {
const Function = union(enum) { const Function = union(enum) {
value: js.Function.Global, value: js.Function.Global,
string: String, string: String,
object: js.Object, object: js.Object.Global,
fn eqlFunction(self: Function, func: js.Function) bool { fn eqlFunction(self: Function, func: js.Function) bool {
return switch (self) { return switch (self) {
@@ -456,7 +457,7 @@ const Function = union(enum) {
fn eqlObject(self: Function, obj: js.Object) bool { fn eqlObject(self: Function, obj: js.Object) bool {
return switch (self) { return switch (self) {
.object => |o| return o.getId() == obj.getId(), .object => |o| return o.isEqual(obj),
else => false, else => false,
}; };
} }

View File

@@ -77,8 +77,8 @@ identity_map: std.AutoHashMapUnmanaged(usize, js.Global(js.Object)) = .empty,
// the @intFromPtr(js_obj.handle). But v8 can re-use address. Without // the @intFromPtr(js_obj.handle). But v8 can re-use address. Without
// a reliable way to know if an object has already been persisted, // a reliable way to know if an object has already been persisted,
// we now simply persist every time persist() is called. // we now simply persist every time persist() is called.
global_values: std.ArrayList(js.Global(js.Value)) = .empty, global_values: std.ArrayList(v8.Global) = .empty,
global_objects: std.ArrayList(js.Global(js.Object)) = .empty, global_objects: std.ArrayList(v8.Global) = .empty,
global_modules: std.ArrayList(js.Global(js.Module)) = .empty, global_modules: std.ArrayList(js.Global(js.Module)) = .empty,
global_promises: std.ArrayList(js.Global(js.Promise)) = .empty, global_promises: std.ArrayList(js.Global(js.Promise)) = .empty,
global_functions: std.ArrayList(v8.Global) = .empty, global_functions: std.ArrayList(v8.Global) = .empty,
@@ -142,11 +142,11 @@ pub fn deinit(self: *Context) void {
} }
for (self.global_values.items) |*global| { for (self.global_values.items) |*global| {
global.deinit(); v8.v8__Global__Reset(global);
} }
for (self.global_objects.items) |*global| { for (self.global_objects.items) |*global| {
global.deinit(); v8.v8__Global__Reset(global);
} }
for (self.global_modules.items) |*global| { for (self.global_modules.items) |*global| {
@@ -462,6 +462,16 @@ pub fn zigValueToJs(self: *Context, value: anytype, comptime opts: Caller.CallOp
return .{ .ctx = self, .handle = @ptrCast(value.handle) }; return .{ .ctx = self, .handle = @ptrCast(value.handle) };
} }
if (T == js.Object.Global) {
// Auto-convert Global to local for bridge
return .{ .ctx = self, .handle = @ptrCast(value.local().handle) };
}
if (T == js.Value.Global) {
// Auto-convert Global to local for bridge
return .{ .ctx = self, .handle = @ptrCast(value.local().handle) };
}
if (T == js.Value) { if (T == js.Value) {
return value; return value;
} }
@@ -818,6 +828,19 @@ fn jsValueToStruct(self: *Context, comptime T: type, js_value: js.Value) !?T {
.handle = @ptrCast(js_value.handle), .handle = @ptrCast(js_value.handle),
}; };
}, },
js.Object.Global => {
if (!js_value.isObject()) {
return null;
}
const obj = js.Object{
.ctx = self,
.handle = @ptrCast(js_value.handle),
};
return try obj.persist();
},
js.Value.Global => {
return try js_value.persist();
},
else => { else => {
if (!js_value.isObject()) { if (!js_value.isObject()) {
return null; return null;

View File

@@ -103,15 +103,17 @@ pub fn format(self: Object, writer: *std.Io.Writer) !void {
return writer.writeAll(str); return writer.writeAll(str);
} }
pub fn persist(self: Object) !Object { pub fn persist(self: Object) !Global {
var ctx = self.ctx; var ctx = self.ctx;
const global = js.Global(Object).init(ctx.isolate.handle, self.handle); var global: v8.Global = undefined;
v8.v8__Global__New(ctx.isolate.handle, self.handle, &global);
try ctx.global_objects.append(ctx.arena, global); try ctx.global_objects.append(ctx.arena, global);
return .{ return .{
.handle = global,
.ctx = ctx, .ctx = ctx,
.handle = global.local(),
}; };
} }
@@ -176,6 +178,26 @@ pub fn toZig(self: Object, comptime T: type) !T {
return self.ctx.jsValueToZig(T, js_value); return self.ctx.jsValueToZig(T, js_value);
} }
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) Object {
return .{
.ctx = self.ctx,
.handle = @ptrCast(v8.v8__Global__Get(&self.handle, self.ctx.isolate.handle)),
};
}
pub fn isEqual(self: *const Global, other: Object) bool {
return v8.v8__Global__IsEqual(&self.handle, other.handle);
}
};
pub const NameIterator = struct { pub const NameIterator = struct {
count: u32, count: u32,
idx: u32 = 0, idx: u32 = 0,

View File

@@ -243,15 +243,17 @@ pub fn fromJson(ctx: *js.Context, json: []const u8) !Value {
return .{ .ctx = ctx, .handle = value.handle }; return .{ .ctx = ctx, .handle = value.handle };
} }
pub fn persist(self: Value) !Value { pub fn persist(self: Value) !Global {
var ctx = self.ctx; var ctx = self.ctx;
const global = js.Global(Value).init(ctx.isolate.handle, self.handle); var global: v8.Global = undefined;
v8.v8__Global__New(ctx.isolate.handle, self.handle, &global);
try ctx.global_values.append(ctx.arena, global); try ctx.global_values.append(ctx.arena, global);
return .{ return .{
.handle = global,
.ctx = ctx, .ctx = ctx,
.handle = global.local(),
}; };
} }
@@ -298,3 +300,23 @@ pub fn format(self: Value, writer: *std.Io.Writer) !void {
const str = self.toString(.{}) catch return error.WriteFailed; const str = self.toString(.{}) catch return error.WriteFailed;
return writer.writeAll(str); return writer.writeAll(str);
} }
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) Value {
return .{
.ctx = self.ctx,
.handle = @ptrCast(v8.v8__Global__Get(&self.handle, self.ctx.isolate.handle)),
};
}
pub fn isEqual(self: *const Global, other: Value) bool {
return v8.v8__Global__IsEqual(&self.handle, other.handle);
}
};

View File

@@ -37,8 +37,8 @@ pub fn getSignal(self: *const AbortController) *AbortSignal {
return self._signal; return self._signal;
} }
pub fn abort(self: *AbortController, reason_: ?js.Object, page: *Page) !void { pub fn abort(self: *AbortController, reason_: ?js.Value.Global, page: *Page) !void {
try self._signal.abort(if (reason_) |r| .{ .js_obj = r } else null, page); try self._signal.abort(if (reason_) |r| .{ .js_val = r } else null, page);
} }
pub const JsApi = struct { pub const JsApi = struct {

View File

@@ -67,7 +67,7 @@ pub fn abort(self: *AbortSignal, reason_: ?Reason, page: *Page) !void {
// Store the abort reason (default to a simple string if none provided) // Store the abort reason (default to a simple string if none provided)
if (reason_) |reason| { if (reason_) |reason| {
switch (reason) { switch (reason) {
.js_obj => |js_obj| self._reason = .{ .js_obj = try js_obj.persist() }, .js_val => |js_val| self._reason = .{ .js_val = js_val },
.string => |str| self._reason = .{ .string = try page.dupeString(str) }, .string => |str| self._reason = .{ .string = try page.dupeString(str) },
.undefined => self._reason = reason, .undefined => self._reason = reason,
} }
@@ -87,9 +87,9 @@ pub fn abort(self: *AbortSignal, reason_: ?Reason, page: *Page) !void {
} }
// Static method to create an already-aborted signal // Static method to create an already-aborted signal
pub fn createAborted(reason_: ?js.Object, page: *Page) !*AbortSignal { pub fn createAborted(reason_: ?js.Value.Global, page: *Page) !*AbortSignal {
const signal = try init(page); const signal = try init(page);
try signal.abort(if (reason_) |r| .{ .js_obj = r } else null, page); try signal.abort(if (reason_) |r| .{ .js_val = r } else null, page);
return signal; return signal;
} }
@@ -115,7 +115,7 @@ pub fn throwIfAborted(self: *const AbortSignal, page: *Page) !ThrowIfAborted {
if (self._aborted) { if (self._aborted) {
const exception = switch (self._reason) { const exception = switch (self._reason) {
.string => |str| page.js.throw(str), .string => |str| page.js.throw(str),
.js_obj => |js_obj| page.js.throw(try js_obj.toString()), .js_val => |js_val| page.js.throw(try js_val.local().toString(.{ .allocator = page.call_arena })),
.undefined => page.js.throw("AbortError"), .undefined => page.js.throw("AbortError"),
}; };
return .{ .exception = exception }; return .{ .exception = exception };
@@ -124,7 +124,7 @@ pub fn throwIfAborted(self: *const AbortSignal, page: *Page) !ThrowIfAborted {
} }
const Reason = union(enum) { const Reason = union(enum) {
js_obj: js.Object, js_val: js.Value.Global,
string: []const u8, string: []const u8,
undefined: void, undefined: void,
}; };

View File

@@ -54,7 +54,7 @@ _active_element: ?*Element = null,
_style_sheets: ?*StyleSheetList = null, _style_sheets: ?*StyleSheetList = null,
_write_insertion_point: ?*Node = null, _write_insertion_point: ?*Node = null,
_script_created_parser: ?Parser.Streaming = null, _script_created_parser: ?Parser.Streaming = null,
_adopted_style_sheets: ?js.Object = null, _adopted_style_sheets: ?js.Object.Global = null,
pub const Type = union(enum) { pub const Type = union(enum) {
generic, generic,
@@ -766,7 +766,7 @@ pub fn getChildElementCount(self: *Document) u32 {
return i; return i;
} }
pub fn getAdoptedStyleSheets(self: *Document, page: *Page) !js.Object { pub fn getAdoptedStyleSheets(self: *Document, page: *Page) !js.Object.Global {
if (self._adopted_style_sheets) |ass| { if (self._adopted_style_sheets) |ass| {
return ass; return ass;
} }

View File

@@ -72,7 +72,7 @@ pub fn addEventListener(self: *EventTarget, typ: []const u8, callback_: ?EventLi
const callback = callback_ orelse return; const callback = callback_ orelse return;
const em_callback = switch (callback) { const em_callback = switch (callback) {
.object => |obj| EventManager.Callback{ .object = try obj.persist() }, .object => |obj| EventManager.Callback{ .object = obj },
.function => |func| EventManager.Callback{ .function = func }, .function => |func| EventManager.Callback{ .function = func },
}; };
@@ -106,7 +106,7 @@ pub fn removeEventListener(self: *EventTarget, typ: []const u8, callback_: ?Even
const em_callback = switch (callback) { const em_callback = switch (callback) {
.function => |func| EventManager.Callback{ .function = func }, .function => |func| EventManager.Callback{ .function = func },
.object => |obj| EventManager.Callback{ .object = try obj.persist() }, .object => |obj| EventManager.Callback{ .object = obj },
}; };
const use_capture = blk: { const use_capture = blk: {

View File

@@ -48,7 +48,7 @@ pub fn entangle(port1: *MessagePort, port2: *MessagePort) void {
port2._entangled_port = port1; port2._entangled_port = port1;
} }
pub fn postMessage(self: *MessagePort, message: js.Value, page: *Page) !void { pub fn postMessage(self: *MessagePort, message: js.Value.Global, page: *Page) !void {
if (self._closed) { if (self._closed) {
return; return;
} }
@@ -62,7 +62,7 @@ pub fn postMessage(self: *MessagePort, message: js.Value, page: *Page) !void {
const callback = try page._factory.create(PostMessageCallback{ const callback = try page._factory.create(PostMessageCallback{
.page = page, .page = page,
.port = other, .port = other,
.message = try message.persist(), .message = message,
}); });
try page.scheduler.add(callback, PostMessageCallback.run, 0, .{ try page.scheduler.add(callback, PostMessageCallback.run, 0, .{
@@ -106,7 +106,7 @@ pub fn setOnMessageError(self: *MessagePort, cb: ?js.Function.Global) !void {
const PostMessageCallback = struct { const PostMessageCallback = struct {
port: *MessagePort, port: *MessagePort,
message: js.Value, message: js.Value.Global,
page: *Page, page: *Page,
fn deinit(self: *PostMessageCallback) void { fn deinit(self: *PostMessageCallback) void {

View File

@@ -314,7 +314,7 @@ pub const Entry = struct {
pub const Mark = struct { pub const Mark = struct {
_proto: *Entry, _proto: *Entry,
_detail: ?js.Value, _detail: ?js.Value.Global,
const Options = struct { const Options = struct {
detail: ?js.Value = null, detail: ?js.Value = null,
@@ -344,7 +344,8 @@ pub const Mark = struct {
return m; return m;
} }
pub fn getDetail(self: *const Mark) ?js.Value {
pub fn getDetail(self: *const Mark) ?js.Value.Global {
return self._detail; return self._detail;
} }
@@ -362,7 +363,7 @@ pub const Mark = struct {
pub const Measure = struct { pub const Measure = struct {
_proto: *Entry, _proto: *Entry,
_detail: ?js.Object, _detail: ?js.Object.Global,
const Options = struct { const Options = struct {
detail: ?js.Object = null, detail: ?js.Object = null,
@@ -405,7 +406,7 @@ pub const Measure = struct {
return m; return m;
} }
pub fn getDetail(self: *const Measure) ?js.Object { pub fn getDetail(self: *const Measure) ?js.Object.Global {
return self._detail; return self._detail;
} }

View File

@@ -189,7 +189,7 @@ pub fn fetch(_: *const Window, input: Fetch.Input, options: ?Fetch.InitOpts, pag
return Fetch.init(input, options, page); return Fetch.init(input, options, page);
} }
pub fn setTimeout(self: *Window, cb: js.Function.Global, delay_ms: ?u32, params: []js.Value, page: *Page) !u32 { pub fn setTimeout(self: *Window, cb: js.Function.Global, delay_ms: ?u32, params: []js.Value.Global, page: *Page) !u32 {
return self.scheduleCallback(cb, delay_ms orelse 0, .{ return self.scheduleCallback(cb, delay_ms orelse 0, .{
.repeat = false, .repeat = false,
.params = params, .params = params,
@@ -198,7 +198,7 @@ pub fn setTimeout(self: *Window, cb: js.Function.Global, delay_ms: ?u32, params:
}, page); }, page);
} }
pub fn setInterval(self: *Window, cb: js.Function.Global, delay_ms: ?u32, params: []js.Value, page: *Page) !u32 { pub fn setInterval(self: *Window, cb: js.Function.Global, delay_ms: ?u32, params: []js.Value.Global, page: *Page) !u32 {
return self.scheduleCallback(cb, delay_ms orelse 0, .{ return self.scheduleCallback(cb, delay_ms orelse 0, .{
.repeat = true, .repeat = true,
.params = params, .params = params,
@@ -207,7 +207,7 @@ pub fn setInterval(self: *Window, cb: js.Function.Global, delay_ms: ?u32, params
}, page); }, page);
} }
pub fn setImmediate(self: *Window, cb: js.Function.Global, params: []js.Value, page: *Page) !u32 { pub fn setImmediate(self: *Window, cb: js.Function.Global, params: []js.Value.Global, page: *Page) !u32 {
return self.scheduleCallback(cb, 0, .{ return self.scheduleCallback(cb, 0, .{
.repeat = false, .repeat = false,
.params = params, .params = params,
@@ -269,10 +269,10 @@ pub fn cancelIdleCallback(self: *Window, id: u32) void {
sc.removed = true; sc.removed = true;
} }
pub fn reportError(self: *Window, err: js.Value, page: *Page) !void { pub fn reportError(self: *Window, err: js.Value.Global, page: *Page) !void {
const error_event = try ErrorEvent.initTrusted("error", .{ const error_event = try ErrorEvent.initTrusted("error", .{
.@"error" = err, .@"error" = err,
.message = err.toString(.{}) catch "Unknown error", .message = err.local().toString(.{}) catch "Unknown error",
.bubbles = false, .bubbles = false,
.cancelable = true, .cancelable = true,
}, page); }, page);
@@ -316,7 +316,7 @@ pub fn getIsSecureContext(_: *const Window) bool {
return false; return false;
} }
pub fn postMessage(self: *Window, message: js.Value, target_origin: ?[]const u8, page: *Page) !void { pub fn postMessage(self: *Window, message: js.Value.Global, target_origin: ?[]const u8, page: *Page) !void {
// For now, we ignore targetOrigin checking and just dispatch the message // For now, we ignore targetOrigin checking and just dispatch the message
// In a full implementation, we would validate the origin // In a full implementation, we would validate the origin
_ = target_origin; _ = target_origin;
@@ -325,7 +325,7 @@ pub fn postMessage(self: *Window, message: js.Value, target_origin: ?[]const u8,
const origin = try self._location.getOrigin(page); const origin = try self._location.getOrigin(page);
const callback = try page._factory.create(PostMessageCallback{ const callback = try page._factory.create(PostMessageCallback{
.window = self, .window = self,
.message = try message.persist(), .message = message,
.origin = try page.arena.dupe(u8, origin), .origin = try page.arena.dupe(u8, origin),
.page = page, .page = page,
}); });
@@ -465,7 +465,7 @@ pub fn scrollTo(self: *Window, opts: ScrollToOpts, y: ?i32, page: *Page) !void {
const ScheduleOpts = struct { const ScheduleOpts = struct {
repeat: bool, repeat: bool,
params: []js.Value, params: []js.Value.Global,
name: []const u8, name: []const u8,
low_priority: bool = false, low_priority: bool = false,
animation_frame: bool = false, animation_frame: bool = false,
@@ -481,12 +481,9 @@ fn scheduleCallback(self: *Window, cb: js.Function.Global, delay_ms: u32, opts:
self._timer_id = timer_id; self._timer_id = timer_id;
const params = opts.params; const params = opts.params;
var persisted_params: []js.Value = &.{}; var persisted_params: []js.Value.Global = &.{};
if (params.len > 0) { if (params.len > 0) {
persisted_params = try page.arena.alloc(js.Value, params.len); persisted_params = try page.arena.dupe(js.Value.Global, params);
for (params, persisted_params) |a, *ca| {
ca.* = try a.persist();
}
} }
const gop = try self._timers.getOrPut(page.arena, timer_id); const gop = try self._timers.getOrPut(page.arena, timer_id);
@@ -530,7 +527,7 @@ const ScheduleCallback = struct {
page: *Page, page: *Page,
params: []const js.Value, params: []const js.Value.Global,
removed: bool = false, removed: bool = false,
@@ -587,7 +584,7 @@ const ScheduleCallback = struct {
const PostMessageCallback = struct { const PostMessageCallback = struct {
window: *Window, window: *Window,
message: js.Value, message: js.Value.Global,
origin: []const u8, origin: []const u8,
page: *Page, page: *Page,

View File

@@ -21,8 +21,8 @@ const Page = @import("../../Page.zig");
const Animation = @This(); const Animation = @This();
_effect: ?js.Object = null, _effect: ?js.Object.Global = null,
_timeline: ?js.Object = null, _timeline: ?js.Object.Global = null,
_ready_resolver: ?js.PromiseResolver = null, _ready_resolver: ?js.PromiseResolver = null,
_finished_resolver: ?js.PromiseResolver = null, _finished_resolver: ?js.PromiseResolver = null,
@@ -62,28 +62,20 @@ pub fn getReady(self: *Animation, page: *Page) !js.Promise {
return self._ready_resolver.?.promise(); return self._ready_resolver.?.promise();
} }
pub fn getEffect(self: *const Animation) ?js.Object { pub fn getEffect(self: *const Animation) ?js.Object.Global {
return self._effect; return self._effect;
} }
pub fn setEffect(self: *Animation, effect: ?js.Object) !void { pub fn setEffect(self: *Animation, effect: ?js.Object.Global) !void {
if (effect) |e| { self._effect = effect;
self._effect = try e.persist();
} else {
self._effect = null;
}
} }
pub fn getTimeline(self: *const Animation) ?js.Object { pub fn getTimeline(self: *const Animation) ?js.Object.Global {
return self._timeline; return self._timeline;
} }
pub fn setTimeline(self: *Animation, timeline: ?js.Object) !void { pub fn setTimeline(self: *Animation, timeline: ?js.Object.Global) !void {
if (timeline) |t| { self._timeline = timeline;
self._timeline = try t.persist();
} else {
self._timeline = null;
}
} }
pub const JsApi = struct { pub const JsApi = struct {

View File

@@ -27,11 +27,11 @@ const Allocator = std.mem.Allocator;
const CustomEvent = @This(); const CustomEvent = @This();
_proto: *Event, _proto: *Event,
_detail: ?js.Value = null,
_arena: Allocator, _arena: Allocator,
_detail: ?js.Value.Global = null,
const CustomEventOptions = struct { const CustomEventOptions = struct {
detail: ?js.Value = null, detail: ?js.Value.Global = null,
}; };
const Options = Event.inheritOptions(CustomEvent, CustomEventOptions); const Options = Event.inheritOptions(CustomEvent, CustomEventOptions);
@@ -45,7 +45,7 @@ pub fn init(typ: []const u8, opts_: ?Options, page: *Page) !*CustomEvent {
CustomEvent{ CustomEvent{
._arena = arena, ._arena = arena,
._proto = undefined, ._proto = undefined,
._detail = if (opts.detail) |detail| try detail.persist() else null, ._detail = opts.detail,
}, },
); );
@@ -58,7 +58,7 @@ pub fn initCustomEvent(
event_string: []const u8, event_string: []const u8,
bubbles: ?bool, bubbles: ?bool,
cancelable: ?bool, cancelable: ?bool,
detail_: ?js.Value, detail_: ?js.Value.Global,
page: *Page, page: *Page,
) !void { ) !void {
// This function can only be called after the constructor has called. // This function can only be called after the constructor has called.
@@ -67,16 +67,14 @@ pub fn initCustomEvent(
self._proto._bubbles = bubbles orelse false; self._proto._bubbles = bubbles orelse false;
self._proto._cancelable = cancelable orelse false; self._proto._cancelable = cancelable orelse false;
// Detail is stored separately. // Detail is stored separately.
if (detail_) |detail| { self._detail = detail_;
self._detail = try detail.persist();
}
} }
pub fn asEvent(self: *CustomEvent) *Event { pub fn asEvent(self: *CustomEvent) *Event {
return self._proto; return self._proto;
} }
pub fn getDetail(self: *const CustomEvent) ?js.Value { pub fn getDetail(self: *const CustomEvent) ?js.Value.Global {
return self._detail; return self._detail;
} }

View File

@@ -30,7 +30,7 @@ _message: []const u8 = "",
_filename: []const u8 = "", _filename: []const u8 = "",
_line_number: u32 = 0, _line_number: u32 = 0,
_column_number: u32 = 0, _column_number: u32 = 0,
_error: ?js.Value = null, _error: ?js.Value.Global = null,
_arena: Allocator, _arena: Allocator,
pub const ErrorEventOptions = struct { pub const ErrorEventOptions = struct {
@@ -38,7 +38,7 @@ pub const ErrorEventOptions = struct {
filename: ?[]const u8 = null, filename: ?[]const u8 = null,
lineno: u32 = 0, lineno: u32 = 0,
colno: u32 = 0, colno: u32 = 0,
@"error": ?js.Value = null, @"error": ?js.Value.Global = null,
}; };
const Options = Event.inheritOptions(ErrorEvent, ErrorEventOptions); const Options = Event.inheritOptions(ErrorEvent, ErrorEventOptions);
@@ -64,7 +64,7 @@ fn initWithTrusted(typ: []const u8, opts_: ?Options, trusted: bool, page: *Page)
._filename = if (opts.filename) |str| try arena.dupe(u8, str) else "", ._filename = if (opts.filename) |str| try arena.dupe(u8, str) else "",
._line_number = opts.lineno, ._line_number = opts.lineno,
._column_number = opts.colno, ._column_number = opts.colno,
._error = if (opts.@"error") |err| try err.persist() else null, ._error = opts.@"error",
}, },
); );
@@ -92,7 +92,7 @@ pub fn getColumnNumber(self: *const ErrorEvent) u32 {
return self._column_number; return self._column_number;
} }
pub fn getError(self: *const ErrorEvent) ?js.Value { pub fn getError(self: *const ErrorEvent) ?js.Value.Global {
return self._error; return self._error;
} }

View File

@@ -25,12 +25,12 @@ const Window = @import("../Window.zig");
const MessageEvent = @This(); const MessageEvent = @This();
_proto: *Event, _proto: *Event,
_data: ?js.Value = null, _data: ?js.Value.Global = null,
_origin: []const u8 = "", _origin: []const u8 = "",
_source: ?*Window = null, _source: ?*Window = null,
const MessageEventOptions = struct { const MessageEventOptions = struct {
data: ?js.Value = null, data: ?js.Value.Global = null,
origin: ?[]const u8 = null, origin: ?[]const u8 = null,
source: ?*Window = null, source: ?*Window = null,
}; };
@@ -52,7 +52,7 @@ fn initWithTrusted(typ: []const u8, opts_: ?Options, trusted: bool, page: *Page)
typ, typ,
MessageEvent{ MessageEvent{
._proto = undefined, ._proto = undefined,
._data = if (opts.data) |d| try d.persist() else null, ._data = opts.data,
._origin = if (opts.origin) |str| try page.arena.dupe(u8, str) else "", ._origin = if (opts.origin) |str| try page.arena.dupe(u8, str) else "",
._source = opts.source, ._source = opts.source,
}, },
@@ -66,7 +66,7 @@ pub fn asEvent(self: *MessageEvent) *Event {
return self._proto; return self._proto;
} }
pub fn getData(self: *const MessageEvent) ?js.Value { pub fn getData(self: *const MessageEvent) ?js.Value.Global {
return self._data; return self._data;
} }

View File

@@ -26,7 +26,7 @@ const VTTCue = @This();
_proto: *TextTrackCue, _proto: *TextTrackCue,
_text: []const u8 = "", _text: []const u8 = "",
_region: ?js.Object = null, _region: ?js.Object.Global = null,
_vertical: []const u8 = "", _vertical: []const u8 = "",
_snap_to_lines: bool = true, _snap_to_lines: bool = true,
_line: ?f64 = null, // null represents "auto" _line: ?f64 = null, // null represents "auto"
@@ -65,16 +65,12 @@ pub fn setText(self: *VTTCue, value: []const u8, page: *Page) !void {
self._text = try page.dupeString(value); self._text = try page.dupeString(value);
} }
pub fn getRegion(self: *const VTTCue) ?js.Object { pub fn getRegion(self: *const VTTCue) ?js.Object.Global {
return self._region; return self._region;
} }
pub fn setRegion(self: *VTTCue, value: ?js.Object) !void { pub fn setRegion(self: *VTTCue, value: ?js.Object.Global) !void {
if (value) |v| { self._region = value;
self._region = try v.persist();
} else {
self._region = null;
}
} }
pub fn getVertical(self: *const VTTCue) []const u8 { pub fn getVertical(self: *const VTTCue) []const u8 {

View File

@@ -67,7 +67,7 @@ const ReadyState = enum(u8) {
const Response = union(ResponseType) { const Response = union(ResponseType) {
text: []const u8, text: []const u8,
json: js.Value, json: js.Value.Global,
document: *Node.Document, document: *Node.Document,
}; };

View File

@@ -80,7 +80,7 @@ pub fn init(src_: ?UnderlyingSource, strategy_: ?QueueingStrategy, page: *Page)
if (src.cancel) |callback| { if (src.cancel) |callback| {
self._cancel = .{ self._cancel = .{
.callback = try callback.persist(), .callback = callback,
}; };
} }