diff --git a/src/browser/js/Caller.zig b/src/browser/js/Caller.zig index 5f34a5b9..509adef0 100644 --- a/src/browser/js/Caller.zig +++ b/src/browser/js/Caller.zig @@ -60,6 +60,11 @@ fn initWithContext(self: *Caller, ctx: *Context, v8_context: *const v8.Context) ctx.local = &self.local; } +pub fn initFromHandle(self: *Caller, handle: ?*const v8.FunctionCallbackInfo) void { + const isolate = v8.v8__FunctionCallbackInfo__GetIsolate(handle).?; + self.init(isolate); +} + pub fn deinit(self: *Caller) void { const ctx = self.local.ctx; const call_depth = ctx.call_depth - 1; @@ -441,6 +446,11 @@ pub const FunctionCallbackInfo = struct { return .{ .local = local, .handle = v8.v8__FunctionCallbackInfo__INDEX(self.handle, @intCast(index)).? }; } + pub fn getData(self: FunctionCallbackInfo) ?*anyopaque { + const data = v8.v8__FunctionCallbackInfo__Data(self.handle) orelse return null; + return v8.v8__External__Value(@ptrCast(data)); + } + pub fn getThis(self: FunctionCallbackInfo) *const v8.Object { return v8.v8__FunctionCallbackInfo__This(self.handle).?; } diff --git a/src/browser/js/Context.zig b/src/browser/js/Context.zig index 6b2e724a..ba160058 100644 --- a/src/browser/js/Context.zig +++ b/src/browser/js/Context.zig @@ -539,15 +539,6 @@ fn postCompileModule(self: *Context, mod: js.Module, url: [:0]const u8, local: * } } -fn newFunctionWithData(local: *const js.Local, comptime callback: *const fn (?*const v8.FunctionCallbackInfo) callconv(.c) void, data: *anyopaque) js.Function { - const external = local.isolate.createExternal(data); - const handle = v8.v8__Function__New__DEFAULT2(local.handle, callback, @ptrCast(external)).?; - return .{ - .local = local, - .handle = handle, - }; -} - // == Callbacks == // Callback from V8, asking us to load a module. The "specifier" is // the src of the module to load. @@ -866,15 +857,14 @@ fn resolveDynamicModule(self: *Context, state: *DynamicModuleResolveState, modul // last value of the module. But, for module loading, we need to // resolve to the module's namespace. - const then_callback = newFunctionWithData(local, struct { + const then_callback = local.newFunctionWithData(struct { pub fn callback(callback_handle: ?*const v8.FunctionCallbackInfo) callconv(.c) void { - const isolate = v8.v8__FunctionCallbackInfo__GetIsolate(callback_handle).?; var c: Caller = undefined; - c.init(isolate); + c.initFromHandle(callback_handle); defer c.deinit(); - const info_data = v8.v8__FunctionCallbackInfo__Data(callback_handle).?; - const s: *DynamicModuleResolveState = @ptrCast(@alignCast(v8.v8__External__Value(@ptrCast(info_data)))); + const info = Caller.FunctionCallbackInfo{ .handle = callback_handle.? }; + const s: *DynamicModuleResolveState = @ptrCast(@alignCast(info.getData() orelse return)); if (s.context_id != c.local.ctx.id) { // The microtask is tied to the isolate, not the context @@ -891,19 +881,17 @@ fn resolveDynamicModule(self: *Context, state: *DynamicModuleResolveState, modul } }.callback, @ptrCast(state)); - const catch_callback = newFunctionWithData(local, struct { + const catch_callback = local.newFunctionWithData(struct { pub fn callback(callback_handle: ?*const v8.FunctionCallbackInfo) callconv(.c) void { - const isolate = v8.v8__FunctionCallbackInfo__GetIsolate(callback_handle).?; var c: Caller = undefined; - c.init(isolate); + c.initFromHandle(callback_handle); defer c.deinit(); - const info_data = v8.v8__FunctionCallbackInfo__Data(callback_handle).?; - const s: *DynamicModuleResolveState = @ptrCast(@alignCast(v8.v8__External__Value(@ptrCast(info_data)))); + const info = Caller.FunctionCallbackInfo{ .handle = callback_handle.? }; + const s: *DynamicModuleResolveState = @ptrCast(@alignCast(info.getData() orelse return)); const l = &c.local; - const ctx = l.ctx; - if (s.context_id != ctx.id) { + if (s.context_id != l.ctx.id) { return; } diff --git a/src/browser/js/Local.zig b/src/browser/js/Local.zig index 5ff6917d..65e577e9 100644 --- a/src/browser/js/Local.zig +++ b/src/browser/js/Local.zig @@ -82,6 +82,16 @@ pub fn createTypedArray(self: *const Local, comptime array_type: js.ArrayType, s return .init(self, size); } +pub fn newFunctionWithData( + self: *const Local, + comptime callback: *const fn (?*const v8.FunctionCallbackInfo) callconv(.c) void, + data: *anyopaque, +) js.Function { + const external = self.isolate.createExternal(data); + const handle = v8.v8__Function__New__DEFAULT2(self.handle, callback, @ptrCast(external)).?; + return .{ .local = self, .handle = handle }; +} + pub fn runMacrotasks(self: *const Local) void { const env = self.ctx.env; env.pumpMessageLoop(); diff --git a/src/browser/webapi/streams/ReadableStream.zig b/src/browser/webapi/streams/ReadableStream.zig index eba03a9e..a2033878 100644 --- a/src/browser/webapi/streams/ReadableStream.zig +++ b/src/browser/webapi/streams/ReadableStream.zig @@ -20,7 +20,6 @@ const std = @import("std"); const log = @import("../../../log.zig"); const js = @import("../../js/js.zig"); -const v8 = js.v8; const Page = @import("../../Page.zig"); const ReadableStreamDefaultReader = @import("ReadableStreamDefaultReader.zig"); @@ -310,22 +309,21 @@ const PipeState = struct { const read_promise = try state.reader.read(state.page); // Create JS callback functions for .then() and .catch() - const then_fn = newFunctionWithData(local, &onReadFulfilled, state); - const catch_fn = newFunctionWithData(local, &onReadRejected, state); + const then_fn = local.newFunctionWithData(&onReadFulfilled, state); + const catch_fn = local.newFunctionWithData(&onReadRejected, state); _ = read_promise.thenAndCatch(then_fn, catch_fn) catch { state.finish(local); }; } - fn onReadFulfilled(callback_handle: ?*const v8.FunctionCallbackInfo) callconv(.c) void { - const isolate = v8.v8__FunctionCallbackInfo__GetIsolate(callback_handle).?; + fn onReadFulfilled(callback_handle: ?*const js.v8.FunctionCallbackInfo) callconv(.c) void { var c: js.Caller = undefined; - c.init(isolate); + c.initFromHandle(callback_handle); defer c.deinit(); - const info_data = v8.v8__FunctionCallbackInfo__Data(callback_handle).?; - const state: *PipeState = @ptrCast(@alignCast(v8.v8__External__Value(@ptrCast(info_data)))); + const info = js.Caller.FunctionCallbackInfo{ .handle = callback_handle.? }; + const state: *PipeState = @ptrCast(@alignCast(info.getData() orelse return)); if (state.context_id != c.local.ctx.id) return; @@ -333,10 +331,7 @@ const PipeState = struct { defer l.runMicrotasks(); // Get the read result argument {done, value} - const result_val = js.Value{ - .local = l, - .handle = v8.v8__FunctionCallbackInfo__INDEX(callback_handle, 0) orelse return, - }; + const result_val = info.getArg(0, l); if (!result_val.isObject()) { state.finish(l); @@ -374,14 +369,13 @@ const PipeState = struct { }; } - fn onReadRejected(callback_handle: ?*const v8.FunctionCallbackInfo) callconv(.c) void { - const isolate = v8.v8__FunctionCallbackInfo__GetIsolate(callback_handle).?; + fn onReadRejected(callback_handle: ?*const js.v8.FunctionCallbackInfo) callconv(.c) void { var c: js.Caller = undefined; - c.init(isolate); + c.initFromHandle(callback_handle); defer c.deinit(); - const info_data = v8.v8__FunctionCallbackInfo__Data(callback_handle).?; - const state: *PipeState = @ptrCast(@alignCast(v8.v8__External__Value(@ptrCast(info_data)))); + const info = js.Caller.FunctionCallbackInfo{ .handle = callback_handle.? }; + const state: *PipeState = @ptrCast(@alignCast(info.getData() orelse return)); if (state.context_id != c.local.ctx.id) return; @@ -404,19 +398,6 @@ const PipeState = struct { local.toLocal(r).resolve("pipe finished", {}); } } - - fn newFunctionWithData( - local: *const js.Local, - comptime callback: *const fn (?*const v8.FunctionCallbackInfo) callconv(.c) void, - data: *anyopaque, - ) js.Function { - const external = local.isolate.createExternal(data); - const handle = v8.v8__Function__New__DEFAULT2(local.handle, callback, @ptrCast(external)).?; - return .{ - .local = local, - .handle = handle, - }; - } }; const Cancel = struct {