14
14
15
15
#if ENABLE_DEBUGGER
16
16
17
+ #define STACK_FRAME_INDEX_START 1
18
+
17
19
static void js_process_breakpoints (JSDebuggerInfo * info ,
18
20
Source * source ,
19
21
SourceBreakpoint * breakpoints ,
20
22
size_t breakpointsLen );
21
23
22
24
typedef struct VariableType {
23
25
const char * type ;
26
+ const char * value ;
24
27
int64_t variablesReference ;
25
28
} VariableType ;
26
29
@@ -42,6 +45,15 @@ const char* atom_to_string(JSContext* ctx, JSAtom atom) {
42
45
return result ;
43
46
}
44
47
48
+ const char * value_to_string (JSContext * ctx , JSValue value ) {
49
+ JSValue name_value = JS_ToString (ctx , value );
50
+ const char * value_str = JS_ToCString (ctx , name_value );
51
+ const char * result = copy_string (value_str , strlen (value_str ));
52
+ JS_FreeCString (ctx , value_str );
53
+ JS_FreeValue (ctx , name_value );
54
+ return result ;
55
+ }
56
+
45
57
static uint32_t handle_client_write (void * ptr , DebuggerMessage * message ) {
46
58
JSDebuggerInfo * info = (JSDebuggerInfo * )ptr ;
47
59
// Gain access to front_message.
@@ -271,20 +283,51 @@ static void js_debugger_get_variable_type(JSContext* ctx,
271
283
JSValue var_val ) {
272
284
// 0 means not expandible
273
285
uint32_t reference = 0 ;
274
- if (JS_IsString (var_val ))
286
+ if (JS_IsString (var_val )) {
275
287
variable_type -> type = "string" ;
276
- else if (JS_IsInteger (var_val ))
288
+ const char * s = value_to_string (ctx , var_val );
289
+ char * buffer = js_malloc (ctx , sizeof (char ) * (strlen (s ) + 3 ));
290
+ sprintf (buffer , "\"%s\"" , s );
291
+ variable_type -> value = buffer ;
292
+ js_free (ctx , (void * )s );
293
+ }
294
+ else if (JS_IsInteger (var_val )) {
277
295
variable_type -> type = "integer" ;
278
- else if (JS_IsNumber (var_val ) || JS_IsBigFloat (var_val ))
296
+ variable_type -> value = to_json_string (ctx , var_val );
297
+ }
298
+ else if (JS_IsNumber (var_val ) || JS_IsBigFloat (var_val )) {
279
299
variable_type -> type = "float" ;
280
- else if (JS_IsBool (var_val ))
300
+ variable_type -> value = to_json_string (ctx , var_val );
301
+ }
302
+ else if (JS_IsBool (var_val )) {
281
303
variable_type -> type = "boolean" ;
282
- else if (JS_IsNull (var_val ))
304
+ variable_type -> value = to_json_string (ctx , var_val );
305
+ }
306
+ else if (JS_IsNull (var_val )) {
283
307
variable_type -> type = "null" ;
284
- else if (JS_IsUndefined (var_val ))
308
+ variable_type -> value = "null" ;
309
+ }
310
+ else if (JS_IsUndefined (var_val )) {
285
311
variable_type -> type = "undefined" ;
312
+ variable_type -> value = "undefined" ;
313
+ }
286
314
else if (JS_IsObject (var_val )) {
287
315
variable_type -> type = "object" ;
316
+ if (JS_IsFunction (ctx , var_val )) {
317
+ const char * func_name = get_func_name (ctx , var_val );
318
+ char buffer [64 ];
319
+ sprintf (buffer , "ƒ %s ()" , func_name );
320
+ variable_type -> value = copy_string (buffer , strlen (buffer ));
321
+ JS_FreeCString (ctx , func_name );
322
+ } else {
323
+ JSValue object_proto = JS_GetPrototype (ctx , var_val );
324
+ JSValue constructor_func = JS_GetPropertyStr (ctx , object_proto , "constructor" );
325
+ char buffer [64 ];
326
+ sprintf (buffer , "%s" , get_func_name (ctx , constructor_func ));
327
+ variable_type -> value = copy_string (buffer , strlen (buffer ));
328
+ JS_FreeValue (ctx , object_proto );
329
+ JS_FreeValue (ctx , constructor_func );
330
+ }
288
331
289
332
JSObject * p = JS_VALUE_GET_OBJ (var_val );
290
333
// todo: xor the the two dwords to get a better hash?
@@ -302,34 +345,6 @@ static void js_debugger_get_variable_type(JSContext* ctx,
302
345
variable_type -> variablesReference = reference ;
303
346
}
304
347
305
- //static void js_debugger_get_value(JSContext* ctx, JSValue var_val, JSValue var, const char* value_property) {
306
- // // do not toString on Arrays, since that makes a giant string of all the elements.
307
- // // todo: typed arrays?
308
- // if (JS_IsArray(ctx, var_val)) {
309
- // JSValue length = JS_GetPropertyStr(ctx, var_val, "length");
310
- // uint32_t len;
311
- // JS_ToUint32(ctx, &len, length);
312
- // JS_FreeValue(ctx, length);
313
- // char lenBuf[64];
314
- // sprintf(lenBuf, "Array (%d)", len);
315
- // JS_SetPropertyStr(ctx, var, value_property, JS_NewString(ctx, lenBuf));
316
- // JS_SetPropertyStr(ctx, var, "indexedVariables", JS_NewInt32(ctx, len));
317
- // } else {
318
- // JS_SetPropertyStr(ctx, var, value_property, JS_ToString(ctx, var_val));
319
- // }
320
- //}
321
-
322
- //static JSValue js_debugger_get_variable(JSContext* ctx,
323
- // struct DebuggerSuspendedState* state,
324
- // JSValue var_name,
325
- // JSValue var_val) {
326
- //// JSValue var = JS_NewObject(ctx);
327
- //// JS_SetPropertyStr(ctx, var, "name", var_name);
328
- //// js_debugger_get_value(ctx, var_val, var, "value");
329
- //// js_debugger_get_variable_type(ctx, state, var, var_val);
330
- // return var;
331
- //}
332
-
333
348
static int js_debugger_get_frame (JSContext * ctx , JSValue args ) {
334
349
JSValue reference_property = JS_GetPropertyStr (ctx , args , "frameId" );
335
350
int frame ;
@@ -460,7 +475,7 @@ static void process_request(JSDebuggerInfo* info, struct DebuggerSuspendedState*
460
475
// then it must be a frame locals, frame closures, or the global
461
476
if (JS_IsUndefined (variable )) {
462
477
skip_proto = 1 ;
463
- int64_t frame = (reference >> 2 ) - 1 ;
478
+ int64_t frame = (reference >> 2 ) - STACK_FRAME_INDEX_START ;
464
479
int64_t scope = reference % 4 ;
465
480
466
481
assert (frame < js_debugger_stack_depth (ctx ));
@@ -506,7 +521,7 @@ static void process_request(JSDebuggerInfo* info, struct DebuggerSuspendedState*
506
521
variables [i ].name = copy_string (name_buf , strlen (name_buf ));
507
522
variables [i ].type = variable_type .type ;
508
523
variables [i ].variablesReference = variable_type .variablesReference ;
509
- variables [i ].value = to_json_string ( ctx , value ) ;
524
+ variables [i ].value = variable_type . value ;
510
525
511
526
assert (variables [i ].name != NULL );
512
527
assert (variables [i ].value != NULL );
@@ -517,6 +532,12 @@ static void process_request(JSDebuggerInfo* info, struct DebuggerSuspendedState*
517
532
518
533
unfiltered :
519
534
if (!JS_GetOwnPropertyNames (ctx , & tab_atom , & tab_atom_count , variable , JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK )) {
535
+ if (tab_atom_count == 0 ) {
536
+ variables = NULL ;
537
+ variableLen = 0 ;
538
+ goto done ;
539
+ }
540
+
520
541
int offset = 0 ;
521
542
variables = js_malloc (ctx , sizeof (Variable ) * (tab_atom_count + (skip_proto ? 0 : 1 )));
522
543
@@ -528,8 +549,8 @@ static void process_request(JSDebuggerInfo* info, struct DebuggerSuspendedState*
528
549
int i = offset ++ ;
529
550
init_variable (& variables [i ]);
530
551
variables [i ].name = "[[Prototype]]" ;
531
- variables [i ].value = to_json_string ( ctx , proto ) ;
532
- variables [i ].type = variable_type .type ;
552
+ variables [i ].value = variable_type . type ;
553
+ variables [i ].type = variable_type .value ;
533
554
variables [i ].variablesReference = variable_type .variablesReference ;
534
555
assert (variables [i ].name != NULL );
535
556
assert (variables [i ].value != NULL );
@@ -546,7 +567,7 @@ static void process_request(JSDebuggerInfo* info, struct DebuggerSuspendedState*
546
567
variables [i + offset ].name = atom_to_string (ctx , tab_atom [i ].atom );
547
568
variables [i + offset ].type = variable_type .type ;
548
569
variables [i + offset ].variablesReference = variable_type .variablesReference ;
549
- variables [i + offset ].value = to_json_string ( ctx , value ) ;
570
+ variables [i + offset ].value = variable_type . value ;
550
571
assert (variables [i + offset ].name != NULL );
551
572
assert (variables [i + offset ].value != NULL );
552
573
JS_FreeValue (ctx , value );
@@ -863,7 +884,7 @@ void js_debugger_build_backtrace(JSContext* ctx, const uint8_t* cur_pc, StackTra
863
884
864
885
init_stackframe (& stack_frames [id ]);
865
886
866
- stack_frames [id ].id = id + 1 ;
887
+ stack_frames [id ].id = id + STACK_FRAME_INDEX_START ;
867
888
func_name_str = get_func_name (ctx , sf -> cur_func );
868
889
if (!func_name_str || func_name_str [0 ] == '\0' ) {
869
890
stack_frames [id ].name = "<anonymous>" ;
0 commit comments