Skip to content

Commit

Permalink
Merge pull request #225 from lightpanda-io/callback-result
Browse files Browse the repository at this point in the history
callback: add a func.trycall and callback.Result
  • Loading branch information
krichprollsch committed May 22, 2024
2 parents 700a41a + 96fdcd4 commit d4a2eae
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 8 deletions.
1 change: 1 addition & 0 deletions src/api.zig
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub const JSObjectID = Engine.JSObjectID;
pub const Callback = Engine.Callback;
pub const CallbackSync = Engine.CallbackSync;
pub const CallbackArg = Engine.CallbackArg;
pub const CallbackResult = Engine.CallbackResult;

pub const TryCatch = Engine.TryCatch;
pub const VM = Engine.VM;
Expand Down
85 changes: 81 additions & 4 deletions src/engines/v8/callback.zig
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const setNativeType = @import("generate.zig").setNativeType;
const CallbackInfo = @import("generate.zig").CallbackInfo;
const getV8Object = @import("generate.zig").getV8Object;

const valueToUtf8 = @import("types_primitives.zig").valueToUtf8;

// TODO: Make this JS engine agnostic
// by providing a common interface

Expand All @@ -36,6 +38,41 @@ pub const Arg = struct {
// foo: bool = false,
};

pub const Result = struct {
alloc: std.mem.Allocator,
success: bool = false,
result: ?[]const u8 = null,
stack: ?[]const u8 = null,

pub fn init(alloc: std.mem.Allocator) Result {
return .{ .alloc = alloc };
}

pub fn deinit(self: Result) void {
if (self.result) |res| self.alloc.free(res);
if (self.stack) |stack| self.alloc.free(stack);
}

pub fn setError(
self: *Result,
isolate: v8.Isolate,
js_ctx: v8.Context,
try_catch: v8.TryCatch,
) !void {
self.success = false;

// exception
if (try_catch.getException()) |except| {
self.result = try valueToUtf8(self.alloc, except, isolate, js_ctx);
}

// stack
if (try_catch.getStackTrace(js_ctx)) |stack| {
self.stack = try valueToUtf8(self.alloc, stack, isolate, js_ctx);
}
}
};

pub const FuncSync = struct {
js_func: v8.Function,
js_args: []v8.Value,
Expand Down Expand Up @@ -102,6 +139,28 @@ pub const FuncSync = struct {
) orelse return error.V8ObjectNotFound;
}

// call the function with a try catch to catch errors an report in res.
pub fn trycall(self: FuncSync, alloc: std.mem.Allocator, res: *Result) anyerror!void {
// JS try cache
var try_catch: v8.TryCatch = undefined;
try_catch.init(self.isolate);
defer try_catch.deinit();

self.call(alloc) catch |e| {
res.success = false;
if (try_catch.hasCaught()) {
// retrieve context
// NOTE: match the Func.call implementation
const ctx = self.isolate.getCurrentContext();
try res.setError(self.isolate, ctx, try_catch);
}

return e;
};

res.success = true;
}

pub fn call(self: FuncSync, alloc: std.mem.Allocator) anyerror!void {

// retrieve context
Expand Down Expand Up @@ -228,11 +287,29 @@ pub const Func = struct {
return self._id.get();
}

pub fn call(
self: Func,
nat_args: anytype,
) anyerror!void {
// call the function with a try catch to catch errors an report in res.
pub fn trycall(self: Func, nat_args: anytype, res: *Result) anyerror!void {
// JS try cache
var try_catch: v8.TryCatch = undefined;
try_catch.init(self.isolate);
defer try_catch.deinit();

self.call(nat_args) catch |e| {
res.success = false;
if (try_catch.hasCaught()) {
// retrieve context
// NOTE: match the Func.call implementation
const ctx = self.isolate.getCurrentContext();
try res.setError(self.isolate, ctx, try_catch);
}

return e;
};

res.success = true;
}

pub fn call(self: Func, nat_args: anytype) anyerror!void {
// ensure Native args and JS args are not both provided
const info = @typeInfo(@TypeOf(nat_args));
if (comptime info != .Null) {
Expand Down
1 change: 1 addition & 0 deletions src/engines/v8/v8.zig
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const public = @import("../../api.zig");
pub const Callback = @import("callback.zig").Func;
pub const CallbackSync = @import("callback.zig").FuncSync;
pub const CallbackArg = @import("callback.zig").Arg;
pub const CallbackResult = @import("callback.zig").Result;

pub const LoadFnType = @import("generate.zig").LoadFnType;
pub const loadFn = @import("generate.zig").loadFn;
Expand Down
20 changes: 18 additions & 2 deletions src/interfaces.zig
Original file line number Diff line number Diff line change
Expand Up @@ -157,22 +157,38 @@ pub fn TryCatch(comptime T: type, comptime env: type) void {
) callconv(.Inline) anyerror!?[]const u8);
}

pub fn Callback(comptime T: type) void {
pub fn Callback(comptime T: type, comptime Res_T: type) void {

// id()
assertDecl(T, "id", fn (T: T) usize);

// call()
assertDecl(T, "call", fn (T: T, nat_args: anytype) anyerror!void);

// trycall()
assertDecl(T, "trycall", fn (T: T, nat_args: anytype, res: *Res_T) anyerror!void);
}

pub fn CallbackSync(comptime T: type) void {
pub fn CallbackSync(comptime T: type, comptime Res_T: type) void {
// call()
assertDecl(T, "call", fn (T: T, alloc: std.mem.Allocator) anyerror!void);

// trycall()
assertDecl(T, "trycall", fn (T: T, alloc: std.mem.Allocator, res: *Res_T) anyerror!void);
}

pub fn CallbackArg(comptime _: type) void {}

pub fn CallbackResult(comptime T: type) void {
// init()
assertDecl(T, "init", fn (alloc: std.mem.Allocator) T);

// deinit()
assertDecl(T, "deinit", fn (self: T) void);

// TODO: how to get the result?
}

// Utils
// -----

Expand Down
5 changes: 3 additions & 2 deletions src/private_api.zig
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ fn checkInterfaces(engine: anytype) void {
// public api
interfaces.API(engine.API, engine.LoadFnType);

interfaces.Callback(engine.Callback);
interfaces.CallbackSync(engine.CallbackSync);
interfaces.CallbackResult(engine.CallbackResult);
interfaces.Callback(engine.Callback, engine.CallbackResult);
interfaces.CallbackSync(engine.CallbackSync, engine.CallbackResult);
interfaces.CallbackArg(engine.CallbackArg);

interfaces.JSResult(engine.JSResult);
Expand Down

0 comments on commit d4a2eae

Please sign in to comment.