@@ -1876,7 +1876,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
18761876 defer caller .deinit ();
18771877
18781878 const named_function = comptime NamedFunction .init (Struct , "get_" ++ name );
1879- caller .getter (Struct , named_function , info ) catch | err | {
1879+ caller .method (Struct , named_function , info ) catch | err | {
18801880 caller .handleError (Struct , named_function , err , info );
18811881 };
18821882 }
@@ -1891,13 +1891,13 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
18911891 const setter_callback = v8 .FunctionTemplate .initCallback (isolate , struct {
18921892 fn callback (raw_info : ? * const v8.C_FunctionCallbackInfo ) callconv (.c ) void {
18931893 const info = v8 .FunctionCallbackInfo .initFromV8 (raw_info );
1894+ std .debug .assert (info .length () == 1 );
1895+
18941896 var caller = Caller (Self , State ).init (info );
18951897 defer caller .deinit ();
18961898
1897- std .debug .assert (info .length () == 1 );
1898- const js_value = info .getArg (0 );
18991899 const named_function = comptime NamedFunction .init (Struct , "set_" ++ name );
1900- caller .setter (Struct , named_function , js_value , info ) catch | err | {
1900+ caller .method (Struct , named_function , info ) catch | err | {
19011901 caller .handleError (Struct , named_function , err , info );
19021902 };
19031903 }
@@ -2424,66 +2424,6 @@ fn Caller(comptime E: type, comptime State: type) type {
24242424 info .getReturnValue ().set (try js_context .zigValueToJs (res ));
24252425 }
24262426
2427- fn getter (self : * Self , comptime Struct : type , comptime named_function : NamedFunction , info : v8.FunctionCallbackInfo ) ! void {
2428- const js_context = self .js_context ;
2429- const func = @field (Struct , named_function .name );
2430- const Getter = @TypeOf (func );
2431- if (@typeInfo (Getter ).@"fn" .return_type == null ) {
2432- @compileError (@typeName (Struct ) ++ " has a getter without a return type: " ++ @typeName (Getter ));
2433- }
2434-
2435- var args : ParamterTypes (Getter ) = undefined ;
2436- const arg_fields = @typeInfo (@TypeOf (args )).@"struct" .fields ;
2437- switch (arg_fields .len ) {
2438- 0 = > {}, // getters _can_ be parameterless
2439- 1 , 2 = > {
2440- const zig_instance = try E .typeTaggedAnyOpaque (named_function , * Receiver (Struct ), info .getThis ());
2441- comptime assertSelfReceiver (Struct , named_function );
2442- @field (args , "0" ) = zig_instance ;
2443- if (comptime arg_fields .len == 2 ) {
2444- comptime assertIsStateArg (Struct , named_function , 1 );
2445- @field (args , "1" ) = js_context .state ;
2446- }
2447- },
2448- else = > @compileError (named_function .full_name + " has too many parmaters: " ++ @typeName (named_function .func )),
2449- }
2450- const res = @call (.auto , func , args );
2451- info .getReturnValue ().set (try js_context .zigValueToJs (res ));
2452- }
2453-
2454- fn setter (self : * Self , comptime Struct : type , comptime named_function : NamedFunction , js_value : v8.Value , info : v8.FunctionCallbackInfo ) ! void {
2455- const js_context = self .js_context ;
2456- const func = @field (Struct , named_function .name );
2457- comptime assertSelfReceiver (Struct , named_function );
2458-
2459- const zig_instance = try E .typeTaggedAnyOpaque (named_function , * Receiver (Struct ), info .getThis ());
2460-
2461- const Setter = @TypeOf (func );
2462- var args : ParamterTypes (Setter ) = undefined ;
2463- const arg_fields = @typeInfo (@TypeOf (args )).@"struct" .fields ;
2464- switch (arg_fields .len ) {
2465- 0 = > unreachable , // assertSelfReceiver make sure of this
2466- 1 = > @compileError (named_function .full_name ++ " only has 1 parameter" ),
2467- 2 , 3 = > {
2468- @field (args , "0" ) = zig_instance ;
2469- @field (args , "1" ) = try js_context .jsValueToZig (named_function , arg_fields [1 ].type , js_value );
2470- if (comptime arg_fields .len == 3 ) {
2471- comptime assertIsStateArg (Struct , named_function , 2 );
2472- @field (args , "2" ) = js_context .state ;
2473- }
2474- },
2475- else = > @compileError (named_function .full_name ++ " setter with more than 3 parameters, why?" ),
2476- }
2477-
2478- if (@typeInfo (Setter ).@"fn" .return_type ) | return_type | {
2479- if (@typeInfo (return_type ) == .error_union ) {
2480- _ = try @call (.auto , func , args );
2481- return ;
2482- }
2483- }
2484- _ = @call (.auto , func , args );
2485- }
2486-
24872427 fn getIndex (self : * Self , comptime Struct : type , comptime named_function : NamedFunction , idx : u32 , info : v8.PropertyCallbackInfo ) ! u8 {
24882428 const js_context = self .js_context ;
24892429 const func = @field (Struct , named_function .name );
@@ -2596,13 +2536,7 @@ fn Caller(comptime E: type, comptime State: type) type {
25962536
25972537 if (comptime builtin .mode == .Debug and @hasDecl (@TypeOf (info ), "length" )) {
25982538 if (log .enabled (.js , .warn )) {
2599- const args_dump = self .serializeFunctionArgs (info ) catch "failed to serialize args" ;
2600- log .warn (.js , "function call error" , .{
2601- .name = named_function .full_name ,
2602- .err = err ,
2603- .args = args_dump ,
2604- .stack = stackForLogs (self .call_arena , isolate ) catch | err1 | @errorName (err1 ),
2605- });
2539+ logFunctionCallError (self .call_arena , self .isolate , self .v8_context , err , named_function .full_name , info );
26062540 }
26072541 }
26082542
@@ -2670,6 +2604,7 @@ fn Caller(comptime E: type, comptime State: type) type {
26702604 // Does the error we want to return belong to the custom exeception's ErrorSet
26712605 fn isErrorSetException (comptime Exception : type , err : anytype ) bool {
26722606 const Entry = std .meta .Tuple (&.{ []const u8 , void });
2607+
26732608 const error_set = @typeInfo (Exception .ErrorSet ).error_set .? ;
26742609 const entries = comptime blk : {
26752610 var kv : [error_set .len ]Entry = undefined ;
@@ -2808,28 +2743,6 @@ fn Caller(comptime E: type, comptime State: type) type {
28082743 const Const_State = if (ti == .pointer ) * const ti .pointer .child else State ;
28092744 return T == State or T == Const_State ;
28102745 }
2811-
2812- fn serializeFunctionArgs (self : * const Self , info : anytype ) ! []const u8 {
2813- const isolate = self .isolate ;
2814- const v8_context = self .v8_context ;
2815- const arena = self .call_arena ;
2816- const separator = log .separator ();
2817- const js_parameter_count = info .length ();
2818-
2819- var arr : std .ArrayListUnmanaged (u8 ) = .{};
2820- for (0.. js_parameter_count ) | i | {
2821- const js_value = info .getArg (@intCast (i ));
2822- const value_string = try valueToDetailString (arena , js_value , isolate , v8_context );
2823- const value_type = try jsStringToZig (arena , try js_value .typeOf (isolate ), isolate );
2824- try std .fmt .format (arr .writer (arena ), "{s}{d}: {s} ({s})" , .{
2825- separator ,
2826- i + 1 ,
2827- value_string ,
2828- value_type ,
2829- });
2830- }
2831- return arr .items ;
2832- }
28332746 };
28342747}
28352748
@@ -3270,6 +3183,37 @@ const NamedFunction = struct {
32703183 }
32713184};
32723185
3186+ // This is extracted to speed up compilation. When left inlined in handleError,
3187+ // this can add as much as 10 seconds of compilation time.
3188+ fn logFunctionCallError (arena : Allocator , isolate : v8.Isolate , context : v8.Context , err : anyerror , function_name : []const u8 , info : v8.FunctionCallbackInfo ) void {
3189+ const args_dump = serializeFunctionArgs (arena , isolate , context , info ) catch "failed to serialize args" ;
3190+ log .warn (.js , "function call error" , .{
3191+ .name = function_name ,
3192+ .err = err ,
3193+ .args = args_dump ,
3194+ .stack = stackForLogs (arena , isolate ) catch | err1 | @errorName (err1 ),
3195+ });
3196+ }
3197+
3198+ fn serializeFunctionArgs (arena : Allocator , isolate : v8.Isolate , context : v8.Context , info : v8.FunctionCallbackInfo ) ! []const u8 {
3199+ const separator = log .separator ();
3200+ const js_parameter_count = info .length ();
3201+
3202+ var arr : std .ArrayListUnmanaged (u8 ) = .{};
3203+ for (0.. js_parameter_count ) | i | {
3204+ const js_value = info .getArg (@intCast (i ));
3205+ const value_string = try valueToDetailString (arena , js_value , isolate , context );
3206+ const value_type = try jsStringToZig (arena , try js_value .typeOf (isolate ), isolate );
3207+ try std .fmt .format (arr .writer (arena ), "{s}{d}: {s} ({s})" , .{
3208+ separator ,
3209+ i + 1 ,
3210+ value_string ,
3211+ value_type ,
3212+ });
3213+ }
3214+ return arr .items ;
3215+ }
3216+
32733217// This is called from V8. Whenever the v8 inspector has to describe a value
32743218// it'll call this function to gets its [optional] subtype - which, from V8's
32753219// point of view, is an arbitrary string.
0 commit comments