have our js.Context directly hold a js handle

This commit is contained in:
Karl Seguin
2025-12-31 19:13:13 +08:00
parent 363b95bdef
commit 701de08e8a
13 changed files with 97 additions and 73 deletions

View File

@@ -33,7 +33,7 @@ pub fn get(self: Array, index: u32) !js.Value {
const ctx = self.ctx; const ctx = self.ctx;
const idx = js.Integer.init(ctx.isolate.handle, index); const idx = js.Integer.init(ctx.isolate.handle, index);
const handle = v8.c.v8__Object__Get(@ptrCast(self.handle), ctx.v8_context.handle, idx.handle) orelse { const handle = v8.c.v8__Object__Get(@ptrCast(self.handle), ctx.handle, idx.handle) orelse {
return error.JsException; return error.JsException;
}; };

View File

@@ -38,7 +38,6 @@ const CALL_ARENA_RETAIN = 1024 * 16;
// here does feel like it makes it cleaner. // here does feel like it makes it cleaner.
const Caller = @This(); const Caller = @This();
context: *Context, context: *Context,
v8_context: v8.Context,
isolate: js.Isolate, isolate: js.Isolate,
call_arena: Allocator, call_arena: Allocator,
@@ -55,7 +54,6 @@ pub fn init(info: anytype) Caller {
return .{ return .{
.context = context, .context = context,
.isolate = isolate, .isolate = isolate,
.v8_context = v8_context,
.call_arena = context.call_arena, .call_arena = context.call_arena,
}; };
} }
@@ -120,7 +118,8 @@ pub fn _constructor(self: *Caller, func: anytype, info: v8.FunctionCallbackInfo)
// from new object. (this happens when we're upgrading an CustomElement) // from new object. (this happens when we're upgrading an CustomElement)
if (this.handle != new_this.handle) { if (this.handle != new_this.handle) {
const new_prototype = new_this.getPrototype(); const new_prototype = new_this.getPrototype();
_ = this.setPrototype(self.context.v8_context, new_prototype.castTo(v8.Object)); const v8_context = v8.Context{ .handle = self.context.handle };
_ = this.setPrototype(v8_context, new_prototype.castTo(v8.Object));
} }
info.getReturnValue().set(this); info.getReturnValue().set(this);

View File

@@ -45,7 +45,7 @@ id: usize,
page: *Page, page: *Page,
isolate: js.Isolate, isolate: js.Isolate,
// This context is a persistent object. The persistent needs to be recovered and reset. // This context is a persistent object. The persistent needs to be recovered and reset.
v8_context: v8.Context, handle: *const v8.c.Context,
handle_scope: ?js.HandleScope, handle_scope: ?js.HandleScope,
cpu_profiler: ?v8.CpuProfiler = null, cpu_profiler: ?v8.CpuProfiler = null,
@@ -124,18 +124,22 @@ const ModuleEntry = struct {
}; };
pub fn fromC(c_context: *const v8.C_Context) *Context { pub fn fromC(c_context: *const v8.C_Context) *Context {
const v8_context = v8.Context{ .handle = c_context }; const data = v8.c.v8__Context__GetEmbedderData(c_context, 1).?;
return @ptrFromInt(v8_context.getEmbedderData(1).castTo(v8.BigInt).getUint64()); const big_int = v8.BigInt{ .handle = @ptrCast(data) };
return @ptrFromInt(big_int.getUint64());
} }
pub fn fromIsolate(isolate: js.Isolate) *Context { pub fn fromIsolate(isolate: js.Isolate) *Context {
const v8_context = v8.c.v8__Isolate__GetCurrentContext(isolate.handle).?; const v8_context = v8.c.v8__Isolate__GetCurrentContext(isolate.handle).?;
const ctx = v8.Context{ .handle = v8_context }; const data = v8.c.v8__Context__GetEmbedderData(v8_context, 1).?;
return @ptrFromInt(ctx.getEmbedderData(1).castTo(v8.BigInt).getUint64()); const big_int = v8.BigInt{ .handle = @ptrCast(data) };
return @ptrFromInt(big_int.getUint64());
} }
pub fn setupGlobal(self: *Context) !void { pub fn setupGlobal(self: *Context) !void {
_ = try self.mapZigInstanceToJs(self.v8_context.getGlobal(), self.page.window); const global = v8.c.v8__Context__Global(self.handle).?;
const v8_obj = v8.Object{ .handle = global };
_ = try self.mapZigInstanceToJs(v8_obj, self.page.window);
} }
pub fn deinit(self: *Context) void { pub fn deinit(self: *Context) void {
@@ -190,9 +194,10 @@ pub fn deinit(self: *Context) void {
if (self.handle_scope) |*scope| { if (self.handle_scope) |*scope| {
scope.deinit(); scope.deinit();
self.v8_context.exit(); v8.c.v8__Context__Exit(self.handle);
} }
var presistent_context = v8.Persistent(v8.Context).recoverCast(self.v8_context); const v8_context = v8.Context{ .handle = self.handle };
var presistent_context = v8.Persistent(v8.Context).recoverCast(v8_context);
presistent_context.deinit(); presistent_context.deinit();
} }
@@ -202,7 +207,7 @@ pub fn eval(self: *Context, src: []const u8, name: ?[]const u8) !void {
} }
pub fn exec(self: *Context, src: []const u8, name: ?[]const u8) !js.Value { pub fn exec(self: *Context, src: []const u8, name: ?[]const u8) !js.Value {
const v8_context = self.v8_context; const v8_context = v8.Context{ .handle = self.handle };
const v8_isolate = v8.Isolate{ .handle = self.isolate.handle }; const v8_isolate = v8.Isolate{ .handle = self.isolate.handle };
const scr = try compileScript(v8_isolate, v8_context, src, name); const scr = try compileScript(v8_isolate, v8_context, src, name);
@@ -251,7 +256,7 @@ pub fn module(self: *Context, comptime want_result: bool, src: []const u8, url:
try self.postCompileModule(mod, owned_url); try self.postCompileModule(mod, owned_url);
const v8_context = self.v8_context; const v8_context = v8.Context{ .handle = self.handle };
if (try mod.instantiate(v8_context, resolveModuleCallback) == false) { if (try mod.instantiate(v8_context, resolveModuleCallback) == false) {
return error.ModuleInstantiationError; return error.ModuleInstantiationError;
} }
@@ -311,7 +316,7 @@ pub fn stringToFunction(self: *Context, str: []const u8) !js.Function {
} }
const full = try std.fmt.allocPrintSentinel(self.call_arena, "(function(e) {{ {s}{s} }})", .{ normalized, extra }, 0); const full = try std.fmt.allocPrintSentinel(self.call_arena, "(function(e) {{ {s}{s} }})", .{ normalized, extra }, 0);
const v8_context = self.v8_context; const v8_context = v8.Context{ .handle = self.handle };
const v8_isolate = v8.Isolate{ .handle = self.isolate.handle }; const v8_isolate = v8.Isolate{ .handle = self.isolate.handle };
const script = try compileScript(v8_isolate, v8_context, full, null); const script = try compileScript(v8_isolate, v8_context, full, null);
const js_value = script.run(v8_context) catch { const js_value = script.run(v8_context) catch {
@@ -329,7 +334,7 @@ pub fn stringToFunction(self: *Context, str: []const u8) !js.Function {
fn postCompileModule(self: *Context, mod: v8.Module, url: [:0]const u8) !void { fn postCompileModule(self: *Context, mod: v8.Module, url: [:0]const u8) !void {
try self.module_identifier.putNoClobber(self.arena, mod.getIdentityHash(), url); try self.module_identifier.putNoClobber(self.arena, mod.getIdentityHash(), url);
const v8_context = self.v8_context; const v8_context = v8.Context{ .handle = self.handle };
// Non-async modules are blocking. We can download them in parallel, but // Non-async modules are blocking. We can download them in parallel, but
// they need to be processed serially. So we want to get the list of // they need to be processed serially. So we want to get the list of
@@ -411,7 +416,7 @@ pub fn zigValueToJs(self: *Context, value: anytype, comptime opts: Caller.CallOp
return js_value; return js_value;
} }
const v8_context = self.v8_context; const v8_context = v8.Context{ .handle = self.handle };
const T = @TypeOf(value); const T = @TypeOf(value);
switch (@typeInfo(T)) { switch (@typeInfo(T)) {
.void, .bool, .int, .comptime_int, .float, .comptime_float, .@"enum", .null => { .void, .bool, .int, .comptime_int, .float, .comptime_float, .@"enum", .null => {
@@ -574,7 +579,7 @@ pub fn zigValueToJs(self: *Context, value: anytype, comptime opts: Caller.CallOp
// 5 - Update our identity_map (so that, if we return this same instance again, // 5 - Update our identity_map (so that, if we return this same instance again,
// we can just grab it from the identity_map) // we can just grab it from the identity_map)
pub fn mapZigInstanceToJs(self: *Context, js_obj_: ?v8.Object, value: anytype) !PersistentObject { pub fn mapZigInstanceToJs(self: *Context, js_obj_: ?v8.Object, value: anytype) !PersistentObject {
const v8_context = self.v8_context; const v8_context = v8.Context{ .handle = self.handle };
const arena = self.arena; const arena = self.arena;
const T = @TypeOf(value); const T = @TypeOf(value);
@@ -646,6 +651,7 @@ pub fn mapZigInstanceToJs(self: *Context, js_obj_: ?v8.Object, value: anytype) !
pub fn jsValueToZig(self: *Context, comptime T: type, js_value: v8.Value) !T { pub fn jsValueToZig(self: *Context, comptime T: type, js_value: v8.Value) !T {
const v8_isolate = v8.Isolate{ .handle = self.isolate.handle }; const v8_isolate = v8.Isolate{ .handle = self.isolate.handle };
const v8_context = v8.Context{ .handle = self.handle };
switch (@typeInfo(T)) { switch (@typeInfo(T)) {
.optional => |o| { .optional => |o| {
// If type type is a ?js.Value or a ?js.Object, then we want to pass // If type type is a ?js.Value or a ?js.Object, then we want to pass
@@ -683,11 +689,11 @@ pub fn jsValueToZig(self: *Context, comptime T: type, js_value: v8.Value) !T {
return try self.jsValueToZig(o.child, js_value); return try self.jsValueToZig(o.child, js_value);
}, },
.float => |f| switch (f.bits) { .float => |f| switch (f.bits) {
0...32 => return js_value.toF32(self.v8_context), 0...32 => return js_value.toF32(v8_context),
33...64 => return js_value.toF64(self.v8_context), 33...64 => return js_value.toF64(v8_context),
else => {}, else => {},
}, },
.int => return jsIntToZig(T, js_value, self.v8_context), .int => return jsIntToZig(T, js_value, v8_context),
.bool => return js_value.toBool(v8_isolate), .bool => return js_value.toBool(v8_isolate),
.pointer => |ptr| switch (ptr.size) { .pointer => |ptr| switch (ptr.size) {
.one => { .one => {
@@ -720,8 +726,6 @@ pub fn jsValueToZig(self: *Context, comptime T: type, js_value: v8.Value) !T {
if (!js_value.isArray()) { if (!js_value.isArray()) {
return error.InvalidArgument; return error.InvalidArgument;
} }
const v8_context = self.v8_context;
const js_arr = js_value.castTo(v8.Array); const js_arr = js_value.castTo(v8.Array);
const js_obj = js_arr.castTo(v8.Object); const js_obj = js_arr.castTo(v8.Object);
@@ -797,7 +801,7 @@ pub fn jsValueToZig(self: *Context, comptime T: type, js_value: v8.Value) !T {
return std.meta.stringToEnum(T, try self.valueToString(js_value, .{})) orelse return error.InvalidArgument; return std.meta.stringToEnum(T, try self.valueToString(js_value, .{})) orelse return error.InvalidArgument;
} }
switch (@typeInfo(e.tag_type)) { switch (@typeInfo(e.tag_type)) {
.int => return std.meta.intToEnum(T, try jsIntToZig(e.tag_type, js_value, self.v8_context)), .int => return std.meta.intToEnum(T, try jsIntToZig(e.tag_type, js_value, v8_context)),
else => @compileError("unsupported enum parameter type: " ++ @typeName(T)), else => @compileError("unsupported enum parameter type: " ++ @typeName(T)),
} }
}, },
@@ -851,7 +855,7 @@ fn jsValueToStruct(self: *Context, comptime T: type, js_value: v8.Value) !?T {
} }
const js_obj = js_value.castTo(v8.Object); const js_obj = js_value.castTo(v8.Object);
const v8_context = self.v8_context; const v8_context = v8.Context{ .handle = self.handle };
const isolate = self.isolate; const isolate = self.isolate;
const v8_isolate = v8.Isolate{ .handle = isolate.handle }; const v8_isolate = v8.Isolate{ .handle = isolate.handle };
@@ -1022,7 +1026,8 @@ pub fn valueToString(self: *const Context, js_val: v8.Value, opts: valueToString
const js_sym_desc = js_sym.getDescription(v8_isolate); const js_sym_desc = js_sym.getDescription(v8_isolate);
return self.valueToString(js_sym_desc, .{}); return self.valueToString(js_sym_desc, .{});
} }
const str = try js_val.toString(self.v8_context); const v8_context = v8.Context{ .handle = self.handle };
const str = try js_val.toString(v8_context);
return self.jsStringToZig(str, .{ .allocator = allocator }); return self.jsStringToZig(str, .{ .allocator = allocator });
} }
@@ -1034,7 +1039,8 @@ pub fn valueToStringZ(self: *const Context, js_val: v8.Value, opts: valueToStrin
const js_sym_desc = js_sym.getDescription(v8_isolate); const js_sym_desc = js_sym.getDescription(v8_isolate);
return self.valueToStringZ(js_sym_desc, .{}); return self.valueToStringZ(js_sym_desc, .{});
} }
const str = try js_val.toString(self.v8_context); const v8_context = v8.Context{ .handle = self.handle };
const str = try js_val.toString(v8_context);
return self.jsStringToZigZ(str, .{ .allocator = allocator }); return self.jsStringToZigZ(str, .{ .allocator = allocator });
} }
@@ -1114,7 +1120,7 @@ fn _debugValue(self: *const Context, js_val: v8.Value, seen: *std.AutoHashMapUnm
gop.value_ptr.* = {}; gop.value_ptr.* = {};
} }
const v8_context = self.v8_context; const v8_context = v8.Context{ .handle = self.handle };
const names_arr = js_obj.getOwnPropertyNames(v8_context); const names_arr = js_obj.getOwnPropertyNames(v8_context);
const names_obj = names_arr.castTo(v8.Object); const names_obj = names_arr.castTo(v8.Object);
const len = names_arr.length(); const len = names_arr.length();
@@ -1183,7 +1189,7 @@ pub fn stackTrace(self: *const Context) !?[]const u8 {
// == Promise Helpers == // == Promise Helpers ==
pub fn rejectPromise(self: *Context, value: anytype) !js.Promise { pub fn rejectPromise(self: *Context, value: anytype) !js.Promise {
const ctx = self.v8_context; const ctx = v8.Context{ .handle = self.handle };
var resolver = v8.PromiseResolver.init(ctx); var resolver = v8.PromiseResolver.init(ctx);
const js_value = try self.zigValueToJs(value, .{}); const js_value = try self.zigValueToJs(value, .{});
if (resolver.reject(ctx, js_value) == null) { if (resolver.reject(ctx, js_value) == null) {
@@ -1194,7 +1200,7 @@ pub fn rejectPromise(self: *Context, value: anytype) !js.Promise {
} }
pub fn resolvePromise(self: *Context, value: anytype) !js.Promise { pub fn resolvePromise(self: *Context, value: anytype) !js.Promise {
const ctx = self.v8_context; const ctx = v8.Context{ .handle = self.handle };
const js_value = try self.zigValueToJs(value, .{}); const js_value = try self.zigValueToJs(value, .{});
var resolver = v8.PromiseResolver.init(ctx); var resolver = v8.PromiseResolver.init(ctx);
@@ -1224,7 +1230,8 @@ fn PromiseResolverType(comptime lifetime: PromiseResolverLifetime) type {
return error{OutOfMemory}!js.PersistentPromiseResolver; return error{OutOfMemory}!js.PersistentPromiseResolver;
} }
pub fn createPromiseResolver(self: *Context, comptime lifetime: PromiseResolverLifetime) PromiseResolverType(lifetime) { pub fn createPromiseResolver(self: *Context, comptime lifetime: PromiseResolverLifetime) PromiseResolverType(lifetime) {
const resolver = v8.PromiseResolver.init(self.v8_context); const v8_context = v8.Context{ .handle = self.handle };
const resolver = v8.PromiseResolver.init(v8_context);
if (comptime lifetime == .none) { if (comptime lifetime == .none) {
return .{ .context = self, .resolver = resolver }; return .{ .context = self, .resolver = resolver };
} }
@@ -1324,7 +1331,8 @@ pub fn metaObjectCallback(c_context: ?*v8.C_Context, c_module: ?*v8.C_Module, c_
const v8_isolate = v8.Isolate{ .handle = self.isolate.handle }; const v8_isolate = v8.Isolate{ .handle = self.isolate.handle };
const js_key = v8.String.initUtf8(v8_isolate, "url"); const js_key = v8.String.initUtf8(v8_isolate, "url");
const js_value = try self.zigValueToJs(url, .{}); const js_value = try self.zigValueToJs(url, .{});
const res = meta.defineOwnProperty(self.v8_context, js_key.toName(), js_value, 0) orelse false; const v8_context = v8.Context{ .handle = self.handle };
const res = meta.defineOwnProperty(v8_context, js_key.toName(), js_value, 0) orelse false;
if (!res) { if (!res) {
log.err(.js, "import meta", .{ .err = error.FailedToSet }); log.err(.js, "import meta", .{ .err = error.FailedToSet });
} }
@@ -1384,7 +1392,8 @@ fn _dynamicModuleCallback(self: *Context, specifier: [:0]const u8, referrer: []c
return gop.value_ptr.resolver_promise.?.castToPromise(); return gop.value_ptr.resolver_promise.?.castToPromise();
} }
const persistent_resolver = v8.Persistent(v8.PromiseResolver).init(v8_isolate, v8.PromiseResolver.init(self.v8_context)); const v8_context = v8.Context{ .handle = self.handle };
const persistent_resolver = v8.Persistent(v8.PromiseResolver).init(v8_isolate, v8.PromiseResolver.init(v8_context));
try self.persisted_promise_resolvers.append(self.arena, persistent_resolver); try self.persisted_promise_resolvers.append(self.arena, persistent_resolver);
var resolver = persistent_resolver.castToPromiseResolver(); var resolver = persistent_resolver.castToPromiseResolver();
@@ -1417,7 +1426,7 @@ fn _dynamicModuleCallback(self: *Context, specifier: [:0]const u8, referrer: []c
// Next, we need to actually load it. // Next, we need to actually load it.
self.script_manager.?.getAsyncImport(specifier, dynamicModuleSourceCallback, state, referrer) catch |err| { self.script_manager.?.getAsyncImport(specifier, dynamicModuleSourceCallback, state, referrer) catch |err| {
const error_msg = v8.String.initUtf8(v8_isolate, @errorName(err)); const error_msg = v8.String.initUtf8(v8_isolate, @errorName(err));
_ = resolver.reject(self.v8_context, error_msg.toValue()); _ = resolver.reject(v8_context, error_msg.toValue());
}; };
// For now, we're done. but this will be continued in // For now, we're done. but this will be continued in
@@ -1444,17 +1453,17 @@ fn _dynamicModuleCallback(self: *Context, specifier: [:0]const u8, referrer: []c
if (status == .kEvaluated or status == .kEvaluating) { if (status == .kEvaluated or status == .kEvaluating) {
// Module was already evaluated (shouldn't normally happen, but handle it). // Module was already evaluated (shouldn't normally happen, but handle it).
// Create a pre-resolved promise with the module namespace. // Create a pre-resolved promise with the module namespace.
const persisted_module_resolver = v8.Persistent(v8.PromiseResolver).init(v8_isolate, v8.PromiseResolver.init(self.v8_context)); const persisted_module_resolver = v8.Persistent(v8.PromiseResolver).init(v8_isolate, v8.PromiseResolver.init(v8_context));
try self.persisted_promise_resolvers.append(self.arena, persisted_module_resolver); try self.persisted_promise_resolvers.append(self.arena, persisted_module_resolver);
var module_resolver = persisted_module_resolver.castToPromiseResolver(); var module_resolver = persisted_module_resolver.castToPromiseResolver();
_ = module_resolver.resolve(self.v8_context, mod.getModuleNamespace()); _ = module_resolver.resolve(v8_context, mod.getModuleNamespace());
gop.value_ptr.module_promise = PersistentPromise.init(v8_isolate, module_resolver.getPromise()); gop.value_ptr.module_promise = PersistentPromise.init(v8_isolate, module_resolver.getPromise());
} else { } else {
// the module was loaded, but not evaluated, we _have_ to evaluate it now // the module was loaded, but not evaluated, we _have_ to evaluate it now
const evaluated = mod.evaluate(self.v8_context) catch { const evaluated = mod.evaluate(v8_context) catch {
std.debug.assert(status == .kErrored); std.debug.assert(status == .kErrored);
const error_msg = v8.String.initUtf8(v8_isolate, "Module evaluation failed"); const error_msg = v8.String.initUtf8(v8_isolate, "Module evaluation failed");
_ = resolver.reject(self.v8_context, error_msg.toValue()); _ = resolver.reject(v8_context, error_msg.toValue());
return promise; return promise;
}; };
std.debug.assert(evaluated.isPromise()); std.debug.assert(evaluated.isPromise());
@@ -1480,7 +1489,8 @@ fn dynamicModuleSourceCallback(ctx: *anyopaque, module_source_: anyerror!ScriptM
var ms = module_source_ catch |err| { var ms = module_source_ catch |err| {
const v8_isolate = v8.Isolate{ .handle = self.isolate.handle }; const v8_isolate = v8.Isolate{ .handle = self.isolate.handle };
const error_msg = v8.String.initUtf8(v8_isolate, @errorName(err)); const error_msg = v8.String.initUtf8(v8_isolate, @errorName(err));
_ = state.resolver.castToPromiseResolver().reject(self.v8_context, error_msg.toValue()); const v8_context = v8.Context{ .handle = self.handle };
_ = state.resolver.castToPromiseResolver().reject(v8_context, error_msg.toValue());
return; return;
}; };
@@ -1500,8 +1510,9 @@ fn dynamicModuleSourceCallback(ctx: *anyopaque, module_source_: anyerror!ScriptM
.line = try_catch.sourceLineNumber() orelse 0, .line = try_catch.sourceLineNumber() orelse 0,
}); });
const v8_isolate = v8.Isolate{ .handle = self.isolate.handle }; const v8_isolate = v8.Isolate{ .handle = self.isolate.handle };
const v8_context = v8.Context{ .handle = self.handle };
const error_msg = v8.String.initUtf8(v8_isolate, ex); const error_msg = v8.String.initUtf8(v8_isolate, ex);
_ = state.resolver.castToPromiseResolver().reject(self.v8_context, error_msg.toValue()); _ = state.resolver.castToPromiseResolver().reject(v8_context, error_msg.toValue());
return; return;
}; };
}; };
@@ -1511,7 +1522,7 @@ fn dynamicModuleSourceCallback(ctx: *anyopaque, module_source_: anyerror!ScriptM
fn resolveDynamicModule(self: *Context, state: *DynamicModuleResolveState, module_entry: ModuleEntry) void { fn resolveDynamicModule(self: *Context, state: *DynamicModuleResolveState, module_entry: ModuleEntry) void {
defer self.runMicrotasks(); defer self.runMicrotasks();
const ctx = self.v8_context; const ctx = v8.Context{ .handle = self.handle };
const isolate = self.isolate; const isolate = self.isolate;
const v8_isolate = v8.Isolate{ .handle = isolate.handle }; const v8_isolate = v8.Isolate{ .handle = isolate.handle };
const external = v8.External.init(v8_isolate, @ptrCast(state)); const external = v8.External.init(v8_isolate, @ptrCast(state));
@@ -1549,7 +1560,8 @@ fn resolveDynamicModule(self: *Context, state: *DynamicModuleResolveState, modul
defer caller.context.runMicrotasks(); defer caller.context.runMicrotasks();
const namespace = s.module.?.getModuleNamespace(); const namespace = s.module.?.getModuleNamespace();
_ = s.resolver.castToPromiseResolver().resolve(caller.context.v8_context, namespace); const v8_context = v8.Context{ .handle = caller.context.handle };
_ = s.resolver.castToPromiseResolver().resolve(v8_context, namespace);
} }
}.callback, external); }.callback, external);
@@ -1564,7 +1576,8 @@ fn resolveDynamicModule(self: *Context, state: *DynamicModuleResolveState, modul
return; return;
} }
defer caller.context.runMicrotasks(); defer caller.context.runMicrotasks();
_ = s.resolver.castToPromiseResolver().reject(caller.context.v8_context, info.getData()); const v8_context = v8.Context{ .handle = caller.context.handle };
_ = s.resolver.castToPromiseResolver().reject(v8_context, info.getData());
} }
}.callback, external); }.callback, external);
@@ -1810,7 +1823,7 @@ fn probeJsValueToZig(self: *Context, comptime T: type, js_value: v8.Value) !Prob
// We settle for just probing the first value. Ok, actually // We settle for just probing the first value. Ok, actually
// not tricky in this case either. // not tricky in this case either.
const v8_context = self.v8_context; const v8_context = v8.Context{ .handle = self.handle };
const js_obj = js_arr.castTo(v8.Object); const js_obj = js_arr.castTo(v8.Object);
switch (try self.probeJsValueToZig(ptr.child, try js_obj.getAtIndex(v8_context, 0))) { switch (try self.probeJsValueToZig(ptr.child, try js_obj.getAtIndex(v8_context, 0))) {
.value, .ok => return .{ .ok = {} }, .value, .ok => return .{ .ok = {} },
@@ -1839,7 +1852,7 @@ fn probeJsValueToZig(self: *Context, comptime T: type, js_value: v8.Value) !Prob
return .{ .ok = {} }; return .{ .ok = {} };
} }
} else if (js_value.isString() and arr.child == u8) { } else if (js_value.isString() and arr.child == u8) {
const str = try js_value.toString(self.v8_context); const str = try js_value.toString(self.handle);
if (str.lenUtf8(self.isolate) == arr.len) { if (str.lenUtf8(self.isolate) == arr.len) {
return .{ .ok = {} }; return .{ .ok = {} };
} }

View File

@@ -117,7 +117,7 @@ pub fn createContext(self: *ExecutionWorld, page: *Page, enter: bool) !*Context
.page = page, .page = page,
.id = context_id, .id = context_id,
.isolate = isolate, .isolate = isolate,
.v8_context = v8_context, .handle = v8_context.handle,
.templates = env.templates, .templates = env.templates,
.handle_scope = handle_scope, .handle_scope = handle_scope,
.script_manager = &page._script_manager, .script_manager = &page._script_manager,

View File

@@ -59,7 +59,7 @@ pub fn newInstance(self: *const Function, result: *Result) !js.Object {
// This creates a new instance using this Function as a constructor. // This creates a new instance using this Function as a constructor.
// const c_args = @as(?[*]const ?*c.Value, @ptrCast(&.{})); // const c_args = @as(?[*]const ?*c.Value, @ptrCast(&.{}));
const handle = v8.c.v8__Function__NewInstance(self.handle, ctx.v8_context.handle, 0, null) orelse { const handle = v8.c.v8__Function__NewInstance(self.handle, ctx.handle, 0, null) orelse {
if (try_catch.hasCaught()) { if (try_catch.hasCaught()) {
const allocator = ctx.call_arena; const allocator = ctx.call_arena;
result.stack = try_catch.stack(allocator) catch null; result.stack = try_catch.stack(allocator) catch null;
@@ -155,7 +155,7 @@ pub fn callWithThis(self: *const Function, comptime T: type, this: anytype, args
}; };
const c_args = @as(?[*]const ?*v8.c.Value, @ptrCast(js_args.ptr)); const c_args = @as(?[*]const ?*v8.c.Value, @ptrCast(js_args.ptr));
const handle = v8.c.v8__Function__Call(self.handle, ctx.v8_context.handle, js_this.handle, @as(c_int, @intCast(js_args.len)), c_args) orelse { const handle = v8.c.v8__Function__Call(self.handle, ctx.handle, js_this.handle, @as(c_int, @intCast(js_args.len)), c_args) orelse {
// std.debug.print("CB ERR: {s}\n", .{self.src() catch "???"}); // std.debug.print("CB ERR: {s}\n", .{self.src() catch "???"});
return error.JSExecCallback; return error.JSExecCallback;
}; };
@@ -167,7 +167,7 @@ pub fn callWithThis(self: *const Function, comptime T: type, this: anytype, args
} }
fn getThis(self: *const Function) js.Object { fn getThis(self: *const Function) js.Object {
const handle = self.this orelse self.ctx.v8_context.getGlobal().handle; const handle = if (self.this) |t| t else v8.c.v8__Context__Global(self.ctx.handle).?;
return .{ return .{
.ctx = self.ctx, .ctx = self.ctx,
.handle = handle, .handle = handle,
@@ -182,7 +182,7 @@ pub fn getPropertyValue(self: *const Function, name: []const u8) !?js.Value {
const ctx = self.ctx; const ctx = self.ctx;
const v8_isolate = v8.Isolate{ .handle = ctx.isolate.handle }; const v8_isolate = v8.Isolate{ .handle = ctx.isolate.handle };
const key = v8.String.initUtf8(v8_isolate, name); const key = v8.String.initUtf8(v8_isolate, name);
const handle = v8.c.v8__Object__Get(self.handle, ctx.v8_context.handle, key.handle) orelse { const handle = v8.c.v8__Object__Get(self.handle, ctx.handle, key.handle) orelse {
return error.JsException; return error.JsException;
}; };

View File

@@ -21,12 +21,12 @@ const v8 = js.v8;
const HandleScope = @This(); const HandleScope = @This();
inner: v8.c.HandleScope, handle: v8.c.HandleScope,
pub fn init(self: *HandleScope, isolate: js.Isolate) void { pub fn init(self: *HandleScope, isolate: js.Isolate) void {
v8.c.v8__HandleScope__CONSTRUCT(&self.inner, isolate.handle); v8.c.v8__HandleScope__CONSTRUCT(&self.handle, isolate.handle);
} }
pub fn deinit(self: *HandleScope) void { pub fn deinit(self: *HandleScope) void {
v8.c.v8__HandleScope__DESTRUCT(&self.inner); v8.c.v8__HandleScope__DESTRUCT(&self.handle);
} }

View File

@@ -153,7 +153,7 @@ pub fn contextCreated(
auxData_ptr, auxData_ptr,
auxData_len, auxData_len,
CONTEST_GROUP_ID, CONTEST_GROUP_ID,
context.v8_context.handle, context.handle,
); );
} }
@@ -174,7 +174,7 @@ pub fn getRemoteObject(
const generate_preview = false; const generate_preview = false;
return self.session.wrapObject( return self.session.wrapObject(
context.isolate.handle, context.isolate.handle,
context.v8_context.handle, context.handle,
js_value.handle, js_value.handle,
group, group,
generate_preview, generate_preview,

View File

@@ -58,7 +58,7 @@ pub fn set(self: Object, key: []const u8, value: anytype, opts: SetOpts) error{
const js_value = try ctx.zigValueToJs(value, .{}); const js_value = try ctx.zigValueToJs(value, .{});
var out: v8.c.MaybeBool = undefined; var out: v8.c.MaybeBool = undefined;
v8.c.v8__Object__DefineOwnProperty(self.handle, ctx.v8_context.handle, @ptrCast(js_key), js_value.handle, @bitCast(opts), &out); v8.c.v8__Object__DefineOwnProperty(self.handle, ctx.handle, @ptrCast(js_key), js_value.handle, @bitCast(opts), &out);
const res = if (out.has_value) out.value else false; const res = if (out.has_value) out.value else false;
if (!res) { if (!res) {
@@ -69,7 +69,7 @@ pub fn set(self: Object, key: []const u8, value: anytype, opts: SetOpts) error{
pub fn get(self: Object, key: []const u8) !js.Value { pub fn get(self: Object, key: []const u8) !js.Value {
const ctx = self.ctx; const ctx = self.ctx;
const js_key = v8.c.v8__String__NewFromUtf8(ctx.isolate.handle, key.ptr, v8.c.kNormal, @intCast(key.len)).?; const js_key = v8.c.v8__String__NewFromUtf8(ctx.isolate.handle, key.ptr, v8.c.kNormal, @intCast(key.len)).?;
const js_val_handle = v8.c.v8__Object__Get(self.handle, ctx.v8_context.handle, js_key) orelse return error.JsException; const js_val_handle = v8.c.v8__Object__Get(self.handle, ctx.handle, js_key) orelse return error.JsException;
const js_val = v8.Value{ .handle = js_val_handle }; const js_val = v8.Value{ .handle = js_val_handle };
return ctx.createValue(js_val); return ctx.createValue(js_val);
} }
@@ -89,7 +89,7 @@ pub fn format(self: Object, writer: *std.Io.Writer) !void {
} }
pub fn toJson(self: Object, allocator: Allocator) ![]u8 { pub fn toJson(self: Object, allocator: Allocator) ![]u8 {
const json_str_handle = v8.c.v8__JSON__Stringify(self.ctx.v8_context.handle, @ptrCast(self.handle), null) orelse return error.JsException; const json_str_handle = v8.c.v8__JSON__Stringify(self.ctx.handle, @ptrCast(self.handle), null) orelse return error.JsException;
const json_string = v8.String{ .handle = json_str_handle }; const json_string = v8.String{ .handle = json_str_handle };
return self.ctx.jsStringToZig(json_string, .{ .allocator = allocator }); return self.ctx.jsStringToZig(json_string, .{ .allocator = allocator });
} }
@@ -113,7 +113,7 @@ pub fn getFunction(self: Object, name: []const u8) !?js.Function {
const ctx = self.ctx; const ctx = self.ctx;
const js_name = v8.c.v8__String__NewFromUtf8(ctx.isolate.handle, name.ptr, v8.c.kNormal, @intCast(name.len)).?; const js_name = v8.c.v8__String__NewFromUtf8(ctx.isolate.handle, name.ptr, v8.c.kNormal, @intCast(name.len)).?;
const js_val_handle = v8.c.v8__Object__Get(self.handle, ctx.v8_context.handle, js_name) orelse return error.JsException; const js_val_handle = v8.c.v8__Object__Get(self.handle, ctx.handle, js_name) orelse return error.JsException;
const js_value = v8.Value{ .handle = js_val_handle }; const js_value = v8.Value{ .handle = js_val_handle };
if (!js_value.isFunction()) { if (!js_value.isFunction()) {
@@ -134,7 +134,7 @@ pub fn isNullOrUndefined(self: Object) bool {
pub fn nameIterator(self: Object) NameIterator { pub fn nameIterator(self: Object) NameIterator {
const ctx = self.ctx; const ctx = self.ctx;
const handle = v8.c.v8__Object__GetPropertyNames(self.handle, ctx.v8_context.handle).?; const handle = v8.c.v8__Object__GetPropertyNames(self.handle, ctx.handle).?;
const count = v8.c.v8__Array__Length(handle); const count = v8.c.v8__Array__Length(handle);
return .{ return .{
@@ -162,7 +162,7 @@ pub const NameIterator = struct {
} }
self.idx += 1; self.idx += 1;
const js_val_handle = v8.c.v8__Object__GetIndex(@ptrCast(self.handle), self.ctx.v8_context.handle, idx) orelse return error.JsException; const js_val_handle = v8.c.v8__Object__GetIndex(@ptrCast(self.handle), self.ctx.handle, idx) orelse return error.JsException;
const js_val = v8.Value{ .handle = js_val_handle }; const js_val = v8.Value{ .handle = js_val_handle };
return try self.ctx.valueToString(js_val, .{}); return try self.ctx.valueToString(js_val, .{});
} }

View File

@@ -46,7 +46,7 @@ pub fn exception(self: TryCatch, allocator: Allocator) !?[]const u8 {
// the caller needs to deinit the string returned // the caller needs to deinit the string returned
pub fn stack(self: TryCatch, allocator: Allocator) !?[]const u8 { pub fn stack(self: TryCatch, allocator: Allocator) !?[]const u8 {
const ctx = self.ctx; const ctx = self.ctx;
const s_value = v8.c.v8__TryCatch__StackTrace(&self.handle, ctx.v8_context.handle) orelse return null; const s_value = v8.c.v8__TryCatch__StackTrace(&self.handle, ctx.handle) orelse return null;
const s = v8.Value{ .handle = s_value }; const s = v8.Value{ .handle = s_value };
return try ctx.valueToString(s, .{ .allocator = allocator }); return try ctx.valueToString(s, .{ .allocator = allocator });
} }
@@ -55,7 +55,7 @@ pub fn stack(self: TryCatch, allocator: Allocator) !?[]const u8 {
pub fn sourceLine(self: TryCatch, allocator: Allocator) !?[]const u8 { pub fn sourceLine(self: TryCatch, allocator: Allocator) !?[]const u8 {
const ctx = self.ctx; const ctx = self.ctx;
const msg = v8.c.v8__TryCatch__Message(&self.handle) orelse return null; const msg = v8.c.v8__TryCatch__Message(&self.handle) orelse return null;
const sl = v8.c.v8__Message__GetSourceLine(msg, ctx.v8_context.handle) orelse return null; const sl = v8.c.v8__Message__GetSourceLine(msg, ctx.handle) orelse return null;
const sl_string = v8.String{ .handle = sl }; const sl_string = v8.String{ .handle = sl };
return try ctx.jsStringToZig(sl_string, .{ .allocator = allocator }); return try ctx.jsStringToZig(sl_string, .{ .allocator = allocator });
} }
@@ -63,7 +63,7 @@ pub fn sourceLine(self: TryCatch, allocator: Allocator) !?[]const u8 {
pub fn sourceLineNumber(self: TryCatch) ?u32 { pub fn sourceLineNumber(self: TryCatch) ?u32 {
const ctx = self.ctx; const ctx = self.ctx;
const msg = v8.c.v8__TryCatch__Message(&self.handle) orelse return null; const msg = v8.c.v8__TryCatch__Message(&self.handle) orelse return null;
const line = v8.c.v8__Message__GetLineNumber(msg, ctx.v8_context.handle); const line = v8.c.v8__Message__GetLineNumber(msg, ctx.handle);
if (line < 0) { if (line < 0) {
return null; return null;
} }

View File

@@ -69,7 +69,7 @@ fn _toString(self: Value, comptime null_terminate: bool, opts: js.String.ToZigOp
return _toString(.{ .handle = @ptrCast(sym_handle), .ctx = ctx }, null_terminate, opts); return _toString(.{ .handle = @ptrCast(sym_handle), .ctx = ctx }, null_terminate, opts);
} }
const str_handle = v8.c.v8__Value__ToString(self.handle, ctx.v8_context.handle) orelse { const str_handle = v8.c.v8__Value__ToString(self.handle, ctx.handle) orelse {
return error.JsException; return error.JsException;
}; };
@@ -87,7 +87,8 @@ pub fn toBool(self: Value) bool {
pub fn fromJson(ctx: *js.Context, json: []const u8) !Value { pub fn fromJson(ctx: *js.Context, json: []const u8) !Value {
const v8_isolate = v8.Isolate{ .handle = ctx.isolate.handle }; const v8_isolate = v8.Isolate{ .handle = ctx.isolate.handle };
const json_string = v8.String.initUtf8(v8_isolate, json); const json_string = v8.String.initUtf8(v8_isolate, json);
const value = try v8.Json.parse(ctx.v8_context, json_string); const v8_context = v8.Context{ .handle = ctx.handle };
const value = try v8.Json.parse(v8_context, json_string);
return .{ .ctx = ctx, .handle = value.handle }; return .{ .ctx = ctx, .handle = value.handle };
} }

View File

@@ -89,7 +89,8 @@ pub const PromiseResolver = struct {
const context = self.context; const context = self.context;
const js_value = try context.zigValueToJs(value, .{}); const js_value = try context.zigValueToJs(value, .{});
if (self.resolver.resolve(context.v8_context, js_value) == null) { const v8_context = v8.Context{ .handle = context.handle };
if (self.resolver.resolve(v8_context, js_value) == null) {
return error.FailedToResolvePromise; return error.FailedToResolvePromise;
} }
self.context.runMicrotasks(); self.context.runMicrotasks();
@@ -104,7 +105,8 @@ pub const PromiseResolver = struct {
const context = self.context; const context = self.context;
const js_value = try context.zigValueToJs(value); const js_value = try context.zigValueToJs(value);
if (self.resolver.reject(context.v8_context, js_value) == null) { const v8_context = v8.Context{ .handle = context.handle };
if (self.resolver.reject(v8_context, js_value) == null) {
return error.FailedToRejectPromise; return error.FailedToRejectPromise;
} }
self.context.runMicrotasks(); self.context.runMicrotasks();
@@ -133,7 +135,8 @@ pub const PersistentPromiseResolver = struct {
const js_value = try context.zigValueToJs(value, .{}); const js_value = try context.zigValueToJs(value, .{});
defer context.runMicrotasks(); defer context.runMicrotasks();
if (self.resolver.castToPromiseResolver().resolve(context.v8_context, js_value) == null) { const v8_context = v8.Context{ .handle = context.handle };
if (self.resolver.castToPromiseResolver().resolve(v8_context, js_value) == null) {
return error.FailedToResolvePromise; return error.FailedToResolvePromise;
} }
} }
@@ -147,10 +150,11 @@ pub const PersistentPromiseResolver = struct {
fn _reject(self: PersistentPromiseResolver, value: anytype) !void { fn _reject(self: PersistentPromiseResolver, value: anytype) !void {
const context = self.context; const context = self.context;
const js_value = try context.zigValueToJs(value, .{}); const js_value = try context.zigValueToJs(value, .{});
const v8_context = v8.Context{ .handle = context.handle };
defer context.runMicrotasks(); defer context.runMicrotasks();
// resolver.reject will return null if the promise isn't pending // resolver.reject will return null if the promise isn't pending
if (self.resolver.castToPromiseResolver().reject(context.v8_context, js_value) == null) { if (self.resolver.castToPromiseResolver().reject(v8_context, js_value) == null) {
return error.FailedToRejectPromise; return error.FailedToRejectPromise;
} }
} }

View File

@@ -23,6 +23,8 @@ const DOMNode = @import("../../browser/webapi/Node.zig");
const Selector = @import("../../browser/webapi/selector/Selector.zig"); const Selector = @import("../../browser/webapi/selector/Selector.zig");
const dump = @import("../../browser/dump.zig"); const dump = @import("../../browser/dump.zig");
const js = @import("../../browser/js/js.zig");
const v8 = js.v8;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
@@ -273,10 +275,12 @@ fn resolveNode(cmd: anytype) !void {
var js_context = page.js; var js_context = page.js;
if (params.executionContextId) |context_id| { if (params.executionContextId) |context_id| {
if (js_context.v8_context.debugContextId() != context_id) { const v8_context = v8.Context{ .handle = js_context.handle };
if (v8_context.debugContextId() != context_id) {
for (bc.isolated_worlds.items) |*isolated_world| { for (bc.isolated_worlds.items) |*isolated_world| {
js_context = &(isolated_world.executor.context orelse return error.ContextNotFound); js_context = &(isolated_world.executor.context orelse return error.ContextNotFound);
if (js_context.v8_context.debugContextId() == context_id) { const isolated_v8_context = v8.Context{ .handle = js_context.handle };
if (isolated_v8_context.debugContextId() == context_id) {
break; break;
} }
} else return error.ContextNotFound; } else return error.ContextNotFound;

View File

@@ -21,6 +21,8 @@ const Page = @import("../../browser/Page.zig");
const timestampF = @import("../../datetime.zig").timestamp; const timestampF = @import("../../datetime.zig").timestamp;
const Notification = @import("../../Notification.zig"); const Notification = @import("../../Notification.zig");
const log = @import("../../log.zig"); const log = @import("../../log.zig");
const js = @import("../../browser/js/js.zig");
const v8 = js.v8;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
@@ -194,7 +196,8 @@ fn createIsolatedWorld(cmd: anytype) !void {
const aux_data = try std.fmt.allocPrint(cmd.arena, "{{\"isDefault\":false,\"type\":\"isolated\",\"frameId\":\"{s}\"}}", .{params.frameId}); const aux_data = try std.fmt.allocPrint(cmd.arena, "{{\"isDefault\":false,\"type\":\"isolated\",\"frameId\":\"{s}\"}}", .{params.frameId});
bc.inspector.contextCreated(js_context, world.name, "", aux_data, false); bc.inspector.contextCreated(js_context, world.name, "", aux_data, false);
return cmd.sendResult(.{ .executionContextId = js_context.v8_context.debugContextId() }, .{}); const v8_context = v8.Context{ .handle = js_context.handle };
return cmd.sendResult(.{ .executionContextId = v8_context.debugContextId() }, .{});
} }
fn navigate(cmd: anytype) !void { fn navigate(cmd: anytype) !void {