mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 23:23:28 +00:00
Change NamedFunction from a generic to a normal struct.
NamedFunction is important for displaying good error messages when there's something wrong with the Zig structs we're trying to bind to JS. By making it a normal struct, it's easier and cheaper to pass wherever an @compileError might be needed.
This commit is contained in:
@@ -57,7 +57,7 @@ pub const Platform = struct {
|
||||
// The `S` parameter is arbitrary state. When we start an Executor, an instance
|
||||
// of S must be given. This instance is available to any Zig binding.
|
||||
// The `types` parameter is a tuple of Zig structures we want to bind to V8.
|
||||
pub fn Env(comptime S: type, comptime WebApis: type) type {
|
||||
pub fn Env(comptime State: type, comptime WebApis: type) type {
|
||||
const Types = @typeInfo(WebApis.Interfaces).@"struct".fields;
|
||||
|
||||
// Imagine we have a type Cat which has a getter:
|
||||
@@ -179,7 +179,6 @@ pub fn Env(comptime S: type, comptime WebApis: type) type {
|
||||
|
||||
const Self = @This();
|
||||
|
||||
const State = S;
|
||||
const TYPE_LOOKUP = TypeLookup{};
|
||||
|
||||
const Opts = struct {
|
||||
@@ -1216,7 +1215,7 @@ pub fn Env(comptime S: type, comptime WebApis: type) type {
|
||||
const template = v8.FunctionTemplate.initCallback(isolate, struct {
|
||||
fn callback(raw_info: ?*const v8.C_FunctionCallbackInfo) callconv(.c) void {
|
||||
const info = v8.FunctionCallbackInfo.initFromV8(raw_info);
|
||||
var caller = Caller(Self).init(info);
|
||||
var caller = Caller(Self, State).init(info);
|
||||
defer caller.deinit();
|
||||
|
||||
// See comment above. We generateConstructor on all types
|
||||
@@ -1233,9 +1232,9 @@ pub fn Env(comptime S: type, comptime WebApis: type) type {
|
||||
|
||||
// Safe to call now, because if Struct.constructor didn't
|
||||
// exist, the above if block would have returned.
|
||||
const named_function = NamedFunction(Struct, Struct.constructor, "constructor"){};
|
||||
caller.constructor(named_function, info) catch |err| {
|
||||
caller.handleError(named_function, err, info);
|
||||
const named_function = comptime NamedFunction.init(Struct, "constructor");
|
||||
caller.constructor(Struct, named_function, info) catch |err| {
|
||||
caller.handleError(Struct, named_function, err, info);
|
||||
};
|
||||
}
|
||||
}.callback);
|
||||
@@ -1261,12 +1260,12 @@ pub fn Env(comptime S: type, comptime WebApis: type) type {
|
||||
const function_template = v8.FunctionTemplate.initCallback(isolate, struct {
|
||||
fn callback(raw_info: ?*const v8.C_FunctionCallbackInfo) callconv(.c) void {
|
||||
const info = v8.FunctionCallbackInfo.initFromV8(raw_info);
|
||||
var caller = Caller(Self).init(info);
|
||||
var caller = Caller(Self, State).init(info);
|
||||
defer caller.deinit();
|
||||
|
||||
const named_function = NamedFunction(Struct, @field(Struct, name), name){};
|
||||
caller.method(named_function, info) catch |err| {
|
||||
caller.handleError(named_function, err, info);
|
||||
const named_function = comptime NamedFunction.init(Struct, name);
|
||||
caller.method(Struct, named_function, info) catch |err| {
|
||||
caller.handleError(Struct, named_function, err, info);
|
||||
};
|
||||
}
|
||||
}.callback);
|
||||
@@ -1303,12 +1302,12 @@ pub fn Env(comptime S: type, comptime WebApis: type) type {
|
||||
const getter_callback = struct {
|
||||
fn callback(_: ?*const v8.C_Name, raw_info: ?*const v8.C_PropertyCallbackInfo) callconv(.c) void {
|
||||
const info = v8.PropertyCallbackInfo.initFromV8(raw_info);
|
||||
var caller = Caller(Self).init(info);
|
||||
var caller = Caller(Self, State).init(info);
|
||||
defer caller.deinit();
|
||||
|
||||
const named_function = NamedFunction(Struct, getter, "get_" ++ name){};
|
||||
caller.getter(named_function, info) catch |err| {
|
||||
caller.handleError(named_function, err, info);
|
||||
const named_function = comptime NamedFunction.init(Struct, "get_" ++ name);
|
||||
caller.getter(Struct, named_function, info) catch |err| {
|
||||
caller.handleError(Struct, named_function, err, info);
|
||||
};
|
||||
}
|
||||
}.callback;
|
||||
@@ -1319,17 +1318,16 @@ pub fn Env(comptime S: type, comptime WebApis: type) type {
|
||||
return;
|
||||
}
|
||||
|
||||
const setter = @field(Struct, setter_name);
|
||||
const setter_callback = struct {
|
||||
fn callback(_: ?*const v8.C_Name, raw_value: ?*const v8.C_Value, raw_info: ?*const v8.C_PropertyCallbackInfo) callconv(.c) void {
|
||||
const info = v8.PropertyCallbackInfo.initFromV8(raw_info);
|
||||
var caller = Caller(Self).init(info);
|
||||
var caller = Caller(Self, State).init(info);
|
||||
defer caller.deinit();
|
||||
|
||||
const js_value = v8.Value{ .handle = raw_value.? };
|
||||
const named_function = NamedFunction(Struct, setter, "set_" ++ name){};
|
||||
caller.setter(named_function, js_value, info) catch |err| {
|
||||
caller.handleError(named_function, err, info);
|
||||
const named_function = comptime NamedFunction.init(Struct, "set_" ++ name);
|
||||
caller.setter(Struct, named_function, js_value, info) catch |err| {
|
||||
caller.handleError(Struct, named_function, err, info);
|
||||
};
|
||||
}
|
||||
}.callback;
|
||||
@@ -1344,12 +1342,12 @@ pub fn Env(comptime S: type, comptime WebApis: type) type {
|
||||
.getter = struct {
|
||||
fn callback(idx: u32, raw_info: ?*const v8.C_PropertyCallbackInfo) callconv(.c) void {
|
||||
const info = v8.PropertyCallbackInfo.initFromV8(raw_info);
|
||||
var caller = Caller(Self).init(info);
|
||||
var caller = Caller(Self, State).init(info);
|
||||
defer caller.deinit();
|
||||
|
||||
const named_function = NamedFunction(Struct, Struct.indexed_get, "indexed_get"){};
|
||||
caller.getIndex(named_function, idx, info) catch |err| {
|
||||
caller.handleError(named_function, err, info);
|
||||
const named_function = comptime NamedFunction.init(Struct, "indexed_get");
|
||||
caller.getIndex(Struct, named_function, idx, info) catch |err| {
|
||||
caller.handleError(Struct, named_function, err, info);
|
||||
};
|
||||
}
|
||||
}.callback,
|
||||
@@ -1373,12 +1371,12 @@ pub fn Env(comptime S: type, comptime WebApis: type) type {
|
||||
.getter = struct {
|
||||
fn callback(c_name: ?*const v8.C_Name, raw_info: ?*const v8.C_PropertyCallbackInfo) callconv(.c) void {
|
||||
const info = v8.PropertyCallbackInfo.initFromV8(raw_info);
|
||||
var caller = Caller(Self).init(info);
|
||||
var caller = Caller(Self, State).init(info);
|
||||
defer caller.deinit();
|
||||
|
||||
const named_function = NamedFunction(Struct, Struct.named_get, "named_get"){};
|
||||
caller.getNamedIndex(named_function, .{ .handle = c_name.? }, info) catch |err| {
|
||||
caller.handleError(named_function, err, info);
|
||||
const named_function = comptime NamedFunction.init(Struct, "named_get");
|
||||
caller.getNamedIndex(Struct, named_function, .{ .handle = c_name.? }, info) catch |err| {
|
||||
caller.handleError(Struct, named_function, err, info);
|
||||
};
|
||||
}
|
||||
}.callback,
|
||||
@@ -1539,7 +1537,7 @@ pub fn Env(comptime S: type, comptime WebApis: type) type {
|
||||
}
|
||||
// Reverses the mapZigInstanceToJs, making sure that our TaggedAnyOpaque
|
||||
// contains a ptr to the correct type.
|
||||
fn typeTaggedAnyOpaque(comptime named_function: anytype, comptime R: type, js_obj: v8.Object) !R {
|
||||
fn typeTaggedAnyOpaque(comptime named_function: NamedFunction, comptime R: type, js_obj: v8.Object) !R {
|
||||
const ti = @typeInfo(R);
|
||||
if (ti != .pointer) {
|
||||
@compileError(std.fmt.comptimePrint(
|
||||
@@ -1663,8 +1661,7 @@ fn isEmpty(comptime T: type) bool {
|
||||
// probably just contained in Executor, but having this specific logic, which
|
||||
// is somewhat repetitive between constructors, functions, getters, etc contained
|
||||
// here does feel like it makes it clenaer.
|
||||
fn Caller(comptime E: type) type {
|
||||
const State = E.State;
|
||||
fn Caller(comptime E: type, comptime State: type) type {
|
||||
const TYPE_LOOKUP = E.TYPE_LOOKUP;
|
||||
const TypeLookup = @TypeOf(TYPE_LOOKUP);
|
||||
|
||||
@@ -1723,13 +1720,12 @@ fn Caller(comptime E: type) type {
|
||||
scope.call_depth = call_depth;
|
||||
}
|
||||
|
||||
fn constructor(self: *Self, comptime named_function: anytype, info: v8.FunctionCallbackInfo) !void {
|
||||
const S = named_function.S;
|
||||
const args = try self.getArgs(named_function, 0, info);
|
||||
const res = @call(.auto, S.constructor, args);
|
||||
fn constructor(self: *Self, comptime Struct: type, comptime named_function: NamedFunction, info: v8.FunctionCallbackInfo) !void {
|
||||
const args = try self.getArgs(Struct, named_function, 0, info);
|
||||
const res = @call(.auto, Struct.constructor, args);
|
||||
|
||||
const ReturnType = @typeInfo(@TypeOf(S.constructor)).@"fn".return_type orelse {
|
||||
@compileError(@typeName(S) ++ " has a constructor without a return type");
|
||||
const ReturnType = @typeInfo(@TypeOf(Struct.constructor)).@"fn".return_type orelse {
|
||||
@compileError(@typeName(Struct) ++ " has a constructor without a return type");
|
||||
};
|
||||
|
||||
const this = info.getThis();
|
||||
@@ -1742,25 +1738,25 @@ fn Caller(comptime E: type) type {
|
||||
info.getReturnValue().set(this);
|
||||
}
|
||||
|
||||
fn method(self: *Self, comptime named_function: anytype, info: v8.FunctionCallbackInfo) !void {
|
||||
const S = named_function.S;
|
||||
comptime assertSelfReceiver(named_function);
|
||||
fn method(self: *Self, comptime Struct: type, comptime named_function: NamedFunction, info: v8.FunctionCallbackInfo) !void {
|
||||
const func = @field(Struct, named_function.name);
|
||||
comptime assertSelfReceiver(Struct, named_function);
|
||||
|
||||
var args = try self.getArgs(named_function, 1, info);
|
||||
const zig_instance = try E.typeTaggedAnyOpaque(named_function, *Receiver(S), info.getThis());
|
||||
var args = try self.getArgs(Struct, named_function, 1, info);
|
||||
const zig_instance = try E.typeTaggedAnyOpaque(named_function, *Receiver(Struct), info.getThis());
|
||||
|
||||
// inject 'self' as the first parameter
|
||||
@field(args, "0") = zig_instance;
|
||||
|
||||
const res = @call(.auto, named_function.func, args);
|
||||
const res = @call(.auto, func, args);
|
||||
info.getReturnValue().set(try self.zigValueToJs(res));
|
||||
}
|
||||
|
||||
fn getter(self: *Self, comptime named_function: anytype, info: v8.PropertyCallbackInfo) !void {
|
||||
const S = named_function.S;
|
||||
const Getter = @TypeOf(named_function.func);
|
||||
fn getter(self: *Self, comptime Struct: type, comptime named_function: NamedFunction, info: v8.PropertyCallbackInfo) !void {
|
||||
const func = @field(Struct, named_function.name);
|
||||
const Getter = @TypeOf(func);
|
||||
if (@typeInfo(Getter).@"fn".return_type == null) {
|
||||
@compileError(@typeName(S) ++ " has a getter without a return type: " ++ @typeName(Getter));
|
||||
@compileError(@typeName(Struct) ++ " has a getter without a return type: " ++ @typeName(Getter));
|
||||
}
|
||||
|
||||
var args: ParamterTypes(Getter) = undefined;
|
||||
@@ -1768,27 +1764,27 @@ fn Caller(comptime E: type) type {
|
||||
switch (arg_fields.len) {
|
||||
0 => {}, // getters _can_ be parameterless
|
||||
1, 2 => {
|
||||
const zig_instance = try E.typeTaggedAnyOpaque(named_function, *Receiver(S), info.getThis());
|
||||
comptime assertSelfReceiver(named_function);
|
||||
const zig_instance = try E.typeTaggedAnyOpaque(named_function, *Receiver(Struct), info.getThis());
|
||||
comptime assertSelfReceiver(Struct, named_function);
|
||||
@field(args, "0") = zig_instance;
|
||||
if (comptime arg_fields.len == 2) {
|
||||
comptime assertIsStateArg(named_function, 1);
|
||||
comptime assertIsStateArg(Struct, named_function, 1);
|
||||
@field(args, "1") = self.scope.state;
|
||||
}
|
||||
},
|
||||
else => @compileError(named_function.full_name + " has too many parmaters: " ++ @typeName(named_function.func)),
|
||||
}
|
||||
const res = @call(.auto, named_function.func, args);
|
||||
const res = @call(.auto, func, args);
|
||||
info.getReturnValue().set(try self.zigValueToJs(res));
|
||||
}
|
||||
|
||||
fn setter(self: *Self, comptime named_function: anytype, js_value: v8.Value, info: v8.PropertyCallbackInfo) !void {
|
||||
const S = named_function.S;
|
||||
comptime assertSelfReceiver(named_function);
|
||||
fn setter(self: *Self, comptime Struct: type, comptime named_function: NamedFunction, js_value: v8.Value, info: v8.PropertyCallbackInfo) !void {
|
||||
const func = @field(Struct, named_function.name);
|
||||
comptime assertSelfReceiver(Struct, named_function);
|
||||
|
||||
const zig_instance = try E.typeTaggedAnyOpaque(named_function, *Receiver(S), info.getThis());
|
||||
const zig_instance = try E.typeTaggedAnyOpaque(named_function, *Receiver(Struct), info.getThis());
|
||||
|
||||
const Setter = @TypeOf(named_function.func);
|
||||
const Setter = @TypeOf(func);
|
||||
var args: ParamterTypes(Setter) = undefined;
|
||||
const arg_fields = @typeInfo(@TypeOf(args)).@"struct".fields;
|
||||
switch (arg_fields.len) {
|
||||
@@ -1798,7 +1794,7 @@ fn Caller(comptime E: type) type {
|
||||
@field(args, "0") = zig_instance;
|
||||
@field(args, "1") = try self.jsValueToZig(named_function, arg_fields[1].type, js_value);
|
||||
if (comptime arg_fields.len == 3) {
|
||||
comptime assertIsStateArg(named_function, 2);
|
||||
comptime assertIsStateArg(Struct, named_function, 2);
|
||||
@field(args, "2") = self.scope.state;
|
||||
}
|
||||
},
|
||||
@@ -1807,16 +1803,16 @@ fn Caller(comptime E: type) type {
|
||||
|
||||
if (@typeInfo(Setter).@"fn".return_type) |return_type| {
|
||||
if (@typeInfo(return_type) == .error_union) {
|
||||
_ = try @call(.auto, named_function.func, args);
|
||||
_ = try @call(.auto, func, args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ = @call(.auto, named_function.func, args);
|
||||
_ = @call(.auto, func, args);
|
||||
}
|
||||
|
||||
fn getIndex(self: *Self, comptime named_function: anytype, idx: u32, info: v8.PropertyCallbackInfo) !void {
|
||||
const S = named_function.S;
|
||||
const IndexedGet = @TypeOf(named_function.func);
|
||||
fn getIndex(self: *Self, comptime Struct: type, comptime named_function: NamedFunction, idx: u32, info: v8.PropertyCallbackInfo) !void {
|
||||
const func = @field(Struct, named_function.name);
|
||||
const IndexedGet = @TypeOf(func);
|
||||
if (@typeInfo(IndexedGet).@"fn".return_type == null) {
|
||||
@compileError(named_function.full_name ++ " must have a return type");
|
||||
}
|
||||
@@ -1828,20 +1824,20 @@ fn Caller(comptime E: type) type {
|
||||
switch (arg_fields.len) {
|
||||
0, 1, 2 => @compileError(named_function.full_name ++ " must take at least a u32 and *bool parameter"),
|
||||
3, 4 => {
|
||||
const zig_instance = try E.typeTaggedAnyOpaque(named_function, *Receiver(S), info.getThis());
|
||||
comptime assertSelfReceiver(named_function);
|
||||
const zig_instance = try E.typeTaggedAnyOpaque(named_function, *Receiver(Struct), info.getThis());
|
||||
comptime assertSelfReceiver(Struct, named_function);
|
||||
@field(args, "0") = zig_instance;
|
||||
@field(args, "1") = idx;
|
||||
@field(args, "2") = &has_value;
|
||||
if (comptime arg_fields.len == 4) {
|
||||
comptime assertIsStateArg(named_function, 3);
|
||||
comptime assertIsStateArg(Struct, named_function, 3);
|
||||
@field(args, "3") = self.scope.state;
|
||||
}
|
||||
},
|
||||
else => @compileError(named_function.full_name ++ " has too many parmaters"),
|
||||
}
|
||||
|
||||
const res = @call(.auto, S.indexed_get, args);
|
||||
const res = @call(.auto, func, args);
|
||||
if (has_value == false) {
|
||||
// for an indexed parameter, say nodes[10000], we should return
|
||||
// undefined, not null, if the index is out of rante
|
||||
@@ -1851,9 +1847,9 @@ fn Caller(comptime E: type) type {
|
||||
}
|
||||
}
|
||||
|
||||
fn getNamedIndex(self: *Self, comptime named_function: anytype, name: v8.Name, info: v8.PropertyCallbackInfo) !void {
|
||||
const S = named_function.S;
|
||||
const NamedGet = @TypeOf(named_function.func);
|
||||
fn getNamedIndex(self: *Self, comptime Struct: type, comptime named_function: NamedFunction, name: v8.Name, info: v8.PropertyCallbackInfo) !void {
|
||||
const func = @field(Struct, named_function.name);
|
||||
const NamedGet = @TypeOf(func);
|
||||
if (@typeInfo(NamedGet).@"fn".return_type == null) {
|
||||
@compileError(named_function.full_name ++ " must have a return type");
|
||||
}
|
||||
@@ -1864,20 +1860,20 @@ fn Caller(comptime E: type) type {
|
||||
switch (arg_fields.len) {
|
||||
0, 1, 2 => @compileError(named_function.full_name ++ " must take at least a u32 and *bool parameter"),
|
||||
3, 4 => {
|
||||
const zig_instance = try E.typeTaggedAnyOpaque(named_function, *Receiver(S), info.getThis());
|
||||
comptime assertSelfReceiver(named_function);
|
||||
const zig_instance = try E.typeTaggedAnyOpaque(named_function, *Receiver(Struct), info.getThis());
|
||||
comptime assertSelfReceiver(Struct, named_function);
|
||||
@field(args, "0") = zig_instance;
|
||||
@field(args, "1") = try self.nameToString(name);
|
||||
@field(args, "2") = &has_value;
|
||||
if (comptime arg_fields.len == 4) {
|
||||
comptime assertIsStateArg(named_function, 3);
|
||||
comptime assertIsStateArg(Struct, named_function, 3);
|
||||
@field(args, "3") = self.scope.state;
|
||||
}
|
||||
},
|
||||
else => @compileError(named_function.full_name ++ " has too many parmaters"),
|
||||
}
|
||||
|
||||
const res = @call(.auto, S.named_get, args);
|
||||
const res = @call(.auto, func, args);
|
||||
if (has_value == false) {
|
||||
// for an indexed parameter, say nodes[10000], we should return
|
||||
// undefined, not null, if the index is out of rante
|
||||
@@ -1891,12 +1887,13 @@ fn Caller(comptime E: type) type {
|
||||
return valueToString(self.call_arena, .{ .handle = name.handle }, self.isolate, self.context);
|
||||
}
|
||||
|
||||
fn assertSelfReceiver(comptime named_function: anytype) void {
|
||||
const params = @typeInfo(@TypeOf(named_function.func)).@"fn".params;
|
||||
fn assertSelfReceiver(comptime Struct: type, comptime named_function: NamedFunction) void {
|
||||
const func = @field(Struct, named_function.name);
|
||||
const params = @typeInfo(@TypeOf(func)).@"fn".params;
|
||||
if (params.len == 0) {
|
||||
@compileError(named_function.full_name ++ " must have a self parameter");
|
||||
}
|
||||
const R = Receiver(named_function.S);
|
||||
const R = Receiver(Struct);
|
||||
|
||||
const first_param = params[0].type.?;
|
||||
if (first_param != *R and first_param != *const R) {
|
||||
@@ -1904,8 +1901,9 @@ fn Caller(comptime E: type) type {
|
||||
}
|
||||
}
|
||||
|
||||
fn assertIsStateArg(comptime named_function: anytype, index: comptime_int) void {
|
||||
const F = @TypeOf(named_function.func);
|
||||
fn assertIsStateArg(comptime Struct: type, comptime named_function: NamedFunction, index: comptime_int) void {
|
||||
const func = @field(Struct, named_function.name);
|
||||
const F = @TypeOf(func);
|
||||
const params = @typeInfo(F).@"fn".params;
|
||||
|
||||
const param = params[index].type.?;
|
||||
@@ -1914,13 +1912,14 @@ fn Caller(comptime E: type) type {
|
||||
}
|
||||
}
|
||||
|
||||
fn handleError(self: *Self, comptime named_function: anytype, err: anyerror, info: anytype) void {
|
||||
fn handleError(self: *Self, comptime Struct: type, comptime named_function: NamedFunction, err: anyerror, info: anytype) void {
|
||||
const isolate = self.isolate;
|
||||
var js_err: ?v8.Value = switch (err) {
|
||||
error.InvalidArgument => createTypeException(isolate, "invalid argument"),
|
||||
error.OutOfMemory => createException(isolate, "out of memory"),
|
||||
else => blk: {
|
||||
const return_type = @typeInfo(@TypeOf(named_function.func)).@"fn".return_type orelse {
|
||||
const func = @field(Struct, named_function.name);
|
||||
const return_type = @typeInfo(@TypeOf(func)).@"fn".return_type orelse {
|
||||
// void return type;
|
||||
break :blk null;
|
||||
};
|
||||
@@ -1935,7 +1934,7 @@ fn Caller(comptime E: type) type {
|
||||
|
||||
const function_error_set = @typeInfo(return_type).error_union.error_set;
|
||||
|
||||
const Exception = comptime getCustomException(named_function.S) orelse break :blk null;
|
||||
const Exception = comptime getCustomException(Struct) orelse break :blk null;
|
||||
if (function_error_set == Exception or isErrorSetException(Exception, err)) {
|
||||
const custom_exception = Exception.init(self.call_arena, err, named_function.js_name) catch |init_err| {
|
||||
switch (init_err) {
|
||||
@@ -2004,8 +2003,8 @@ fn Caller(comptime E: type) type {
|
||||
// Finally, if the JS function is called with _more_ parameters and
|
||||
// the last parameter in Zig is an array, we'll try to slurp the additional
|
||||
// parameters into the array.
|
||||
fn getArgs(self: *const Self, comptime named_function: anytype, comptime offset: usize, info: anytype) !ParamterTypes(@TypeOf(named_function.func)) {
|
||||
const F = @TypeOf(named_function.func);
|
||||
fn getArgs(self: *const Self, comptime Struct: type, comptime named_function: NamedFunction, comptime offset: usize, info: anytype) !ParamterTypes(@TypeOf(@field(Struct, named_function.name))) {
|
||||
const F = @TypeOf(@field(Struct, named_function.name));
|
||||
var args: ParamterTypes(F) = undefined;
|
||||
|
||||
const params = @typeInfo(F).@"fn".params[offset..];
|
||||
@@ -2111,7 +2110,7 @@ fn Caller(comptime E: type) type {
|
||||
return args;
|
||||
}
|
||||
|
||||
fn jsValueToZig(self: *const Self, comptime named_function: anytype, comptime T: type, js_value: v8.Value) !T {
|
||||
fn jsValueToZig(self: *const Self, comptime named_function: NamedFunction, comptime T: type, js_value: v8.Value) !T {
|
||||
switch (@typeInfo(T)) {
|
||||
.optional => |o| {
|
||||
if (js_value.isNullOrUndefined()) {
|
||||
@@ -2329,7 +2328,7 @@ fn Caller(comptime E: type) type {
|
||||
|
||||
// Extracted so that it can be used in both jsValueToZig and in
|
||||
// probeJsValueToZig. Avoids having to duplicate this logic when probing.
|
||||
fn jsValueToStruct(self: *const Self, comptime named_function: anytype, comptime T: type, js_value: v8.Value) !?T {
|
||||
fn jsValueToStruct(self: *const Self, comptime named_function: NamedFunction, comptime T: type, js_value: v8.Value) !?T {
|
||||
if (@hasDecl(T, "_CALLBACK_ID_KLUDGE")) {
|
||||
if (!js_value.isFunction()) {
|
||||
return error.InvalidArgument;
|
||||
@@ -2416,7 +2415,7 @@ fn Caller(comptime E: type) type {
|
||||
invalid: void,
|
||||
};
|
||||
}
|
||||
fn probeJsValueToZig(self: *const Self, comptime named_function: anytype, comptime T: type, js_value: v8.Value) !ProbeResult(T) {
|
||||
fn probeJsValueToZig(self: *const Self, comptime named_function: NamedFunction, comptime T: type, js_value: v8.Value) !ProbeResult(T) {
|
||||
switch (@typeInfo(T)) {
|
||||
.optional => |o| {
|
||||
if (js_value.isNullOrUndefined()) {
|
||||
@@ -2843,27 +2842,28 @@ const ErrorModuleLoader = struct {
|
||||
// pub fn meow(self: *OtherImpl) void { ... }
|
||||
// }
|
||||
// In which case, as we see above, the receiver is derived from the Self declaration
|
||||
fn Receiver(comptime S: type) type {
|
||||
return if (@hasDecl(S, "Self")) S.Self else S;
|
||||
fn Receiver(comptime Struct: type) type {
|
||||
return if (@hasDecl(Struct, "Self")) Struct.Self else Struct;
|
||||
}
|
||||
|
||||
// We want the function name, or more precisely, the "Struct.function" for
|
||||
// displaying helpful @compileError.
|
||||
// However, there's no way to get the name from a std.Builtin.Fn,
|
||||
// so we capture it early and mostly pass around this NamedFunction instance
|
||||
// whenever we're trying to bind a function/getter/setter/etc so that we always
|
||||
// have the main data (struct + function) along with the meta data for displaying
|
||||
// better errors.
|
||||
fn NamedFunction(comptime S: type, comptime function: anytype, comptime name: []const u8) type {
|
||||
const full_name = @typeName(S) ++ "." ++ name;
|
||||
const js_name = if (name[0] == '_') name[1..] else name;
|
||||
return struct {
|
||||
S: type = S,
|
||||
full_name: []const u8 = full_name,
|
||||
func: @TypeOf(function) = function,
|
||||
js_name: []const u8 = js_name,
|
||||
// However, there's no way to get the name from a std.Builtin.Fn, so we create
|
||||
// a NamedFunction as part of our binding, and pass it around incase we need
|
||||
// to display an error
|
||||
const NamedFunction = struct {
|
||||
name: []const u8,
|
||||
js_name: []const u8,
|
||||
full_name: []const u8,
|
||||
|
||||
fn init(comptime Struct: type, comptime name: []const u8) NamedFunction {
|
||||
return .{
|
||||
.name = name,
|
||||
.js_name = if (name[0] == '_') name[1..] else name,
|
||||
.full_name = @typeName(Struct) ++ "." ++ name,
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// This is called from V8. Whenever the v8 inspector has to describe a value
|
||||
// it'll call this function to gets its [optional] subtype - which, from V8's
|
||||
|
||||
Reference in New Issue
Block a user