Skip to content

Commit e8b74e1

Browse files
Merge pull request #219 from lightpanda-io/callback-this
callback: add a this argument
2 parents 9c46a62 + 7d80552 commit e8b74e1

File tree

2 files changed

+38
-13
lines changed

2 files changed

+38
-13
lines changed

src/engines/v8/callback.zig

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const NativeContext = internal.NativeContext;
1010
const JSObjectID = @import("v8.zig").JSObjectID;
1111
const setNativeType = @import("generate.zig").setNativeType;
1212
const CallbackInfo = @import("generate.zig").CallbackInfo;
13+
const getV8Object = @import("generate.zig").getV8Object;
1314

1415
// TODO: Make this JS engine agnostic
1516
// by providing a common interface
@@ -21,17 +22,11 @@ pub const Arg = struct {
2122
// foo: bool = false,
2223
};
2324

24-
// TODO: set the correct "this" on Func object
25-
// see https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#the_this_problem
26-
// should we use:
27-
// - the context globals?
28-
// - null?
29-
// - the calling function (info.getThis)?
30-
3125
pub const FuncSync = struct {
3226
js_func: v8.Function,
3327
js_args: []v8.Value,
3428
isolate: v8.Isolate,
29+
thisArg: ?v8.Object = null,
3530

3631
pub fn init(
3732
alloc: std.mem.Allocator,
@@ -86,15 +81,23 @@ pub const FuncSync = struct {
8681
};
8782
}
8883

84+
pub fn setThisArg(self: *Func, nat_obj_ptr: anytype) !void {
85+
self.thisArg = try getV8Object(
86+
self.nat_ctx,
87+
nat_obj_ptr,
88+
) orelse return error.V8ObjectNotFound;
89+
}
90+
8991
pub fn call(self: FuncSync, alloc: std.mem.Allocator) anyerror!void {
9092

9193
// retrieve context
9294
// NOTE: match the Func.call implementation
9395
const ctx = self.isolate.getCurrentContext();
9496

95-
// retrieve JS this from persistent handle
96-
// TODO: see correct "this" comment above
97-
const this = ctx.getGlobal();
97+
// Callbacks are typically called with a this value of undefined.
98+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#callbacks
99+
// TODO use undefined this instead of global.
100+
const this = self.thisArg orelse ctx.getGlobal();
98101

99102
// execute function
100103
_ = self.js_func.call(ctx, this, self.js_args);
@@ -123,6 +126,8 @@ pub const Func = struct {
123126
nat_ctx: *NativeContext,
124127
isolate: v8.Isolate,
125128

129+
thisArg: ?v8.Object = null,
130+
126131
pub fn init(
127132
alloc: std.mem.Allocator,
128133
nat_ctx: *NativeContext,
@@ -183,6 +188,13 @@ pub const Func = struct {
183188
};
184189
}
185190

191+
pub fn setThisArg(self: *Func, nat_obj_ptr: anytype) !void {
192+
self.thisArg = try getV8Object(
193+
self.nat_ctx,
194+
nat_obj_ptr,
195+
) orelse return error.V8ObjectNotFound;
196+
}
197+
186198
pub fn deinit(self: Func, alloc: std.mem.Allocator) void {
187199

188200
// cleanup persistent references in v8
@@ -256,9 +268,10 @@ pub const Func = struct {
256268
}
257269
// else -> no arguments
258270

259-
// retrieve JS "this" from persistent handle
260-
// TODO: see correct "this" comment above
261-
const this = js_ctx.getGlobal();
271+
// Callbacks are typically called with a this value of undefined.
272+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#callbacks
273+
// TODO use undefined this instead of global.
274+
const this = self.thisArg orelse js_ctx.getGlobal();
262275

263276
// execute function
264277
const result = js_func.call(js_ctx, this, args);

src/engines/v8/generate.zig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,18 @@ inline fn initJSObject(
504504
return tpl.getInstanceTemplate().initInstance(js_ctx);
505505
}
506506

507+
// getV8Object returns the existing v8.Object corresponding to the given native
508+
// pointer from the native context.
509+
pub fn getV8Object(nat_ctx: *NativeContext, nat_obj_ptr: anytype) !?v8.Object {
510+
// ensure Native object is a pointer
511+
if (comptime !refl.isPointer(@TypeOf(nat_obj_ptr))) return error.NotAPointer;
512+
513+
const nat_obj_ref = @intFromPtr(nat_obj_ptr);
514+
const js_obj_ref = nat_ctx.js_objs.get(nat_obj_ref) orelse return null;
515+
const js_obj_handle = @as(*v8.C_Object, @ptrFromInt(js_obj_ref));
516+
return v8.Object{ .handle = js_obj_handle };
517+
}
518+
507519
pub fn setNativeObject(
508520
alloc: std.mem.Allocator,
509521
nat_ctx: *NativeContext,

0 commit comments

Comments
 (0)