Skip to content

Commit e312186

Browse files
committed
feat: optimize variable preview.
1 parent f51e56e commit e312186

File tree

1 file changed

+61
-40
lines changed

1 file changed

+61
-40
lines changed

bridge/third_party/quickjs/src/core/debugger.c

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,16 @@
1414

1515
#if ENABLE_DEBUGGER
1616

17+
#define STACK_FRAME_INDEX_START 1
18+
1719
static void js_process_breakpoints(JSDebuggerInfo* info,
1820
Source* source,
1921
SourceBreakpoint* breakpoints,
2022
size_t breakpointsLen);
2123

2224
typedef struct VariableType {
2325
const char* type;
26+
const char* value;
2427
int64_t variablesReference;
2528
} VariableType;
2629

@@ -42,6 +45,15 @@ const char* atom_to_string(JSContext* ctx, JSAtom atom) {
4245
return result;
4346
}
4447

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+
4557
static uint32_t handle_client_write(void* ptr, DebuggerMessage* message) {
4658
JSDebuggerInfo* info = (JSDebuggerInfo*)ptr;
4759
// Gain access to front_message.
@@ -271,20 +283,51 @@ static void js_debugger_get_variable_type(JSContext* ctx,
271283
JSValue var_val) {
272284
// 0 means not expandible
273285
uint32_t reference = 0;
274-
if (JS_IsString(var_val))
286+
if (JS_IsString(var_val)) {
275287
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)) {
277295
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)) {
279299
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)) {
281303
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)) {
283307
variable_type->type = "null";
284-
else if (JS_IsUndefined(var_val))
308+
variable_type->value = "null";
309+
}
310+
else if (JS_IsUndefined(var_val)) {
285311
variable_type->type = "undefined";
312+
variable_type->value = "undefined";
313+
}
286314
else if (JS_IsObject(var_val)) {
287315
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+
}
288331

289332
JSObject* p = JS_VALUE_GET_OBJ(var_val);
290333
// todo: xor the the two dwords to get a better hash?
@@ -302,34 +345,6 @@ static void js_debugger_get_variable_type(JSContext* ctx,
302345
variable_type->variablesReference = reference;
303346
}
304347

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-
333348
static int js_debugger_get_frame(JSContext* ctx, JSValue args) {
334349
JSValue reference_property = JS_GetPropertyStr(ctx, args, "frameId");
335350
int frame;
@@ -460,7 +475,7 @@ static void process_request(JSDebuggerInfo* info, struct DebuggerSuspendedState*
460475
// then it must be a frame locals, frame closures, or the global
461476
if (JS_IsUndefined(variable)) {
462477
skip_proto = 1;
463-
int64_t frame = (reference >> 2) - 1;
478+
int64_t frame = (reference >> 2) - STACK_FRAME_INDEX_START;
464479
int64_t scope = reference % 4;
465480

466481
assert(frame < js_debugger_stack_depth(ctx));
@@ -506,7 +521,7 @@ static void process_request(JSDebuggerInfo* info, struct DebuggerSuspendedState*
506521
variables[i].name = copy_string(name_buf, strlen(name_buf));
507522
variables[i].type = variable_type.type;
508523
variables[i].variablesReference = variable_type.variablesReference;
509-
variables[i].value = to_json_string(ctx, value);
524+
variables[i].value = variable_type.value;
510525

511526
assert(variables[i].name != NULL);
512527
assert(variables[i].value != NULL);
@@ -517,6 +532,12 @@ static void process_request(JSDebuggerInfo* info, struct DebuggerSuspendedState*
517532

518533
unfiltered:
519534
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+
520541
int offset = 0;
521542
variables = js_malloc(ctx, sizeof(Variable) * (tab_atom_count + (skip_proto ? 0 : 1)));
522543

@@ -528,8 +549,8 @@ static void process_request(JSDebuggerInfo* info, struct DebuggerSuspendedState*
528549
int i = offset++;
529550
init_variable(&variables[i]);
530551
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;
533554
variables[i].variablesReference = variable_type.variablesReference;
534555
assert(variables[i].name != NULL);
535556
assert(variables[i].value != NULL);
@@ -546,7 +567,7 @@ static void process_request(JSDebuggerInfo* info, struct DebuggerSuspendedState*
546567
variables[i + offset].name = atom_to_string(ctx, tab_atom[i].atom);
547568
variables[i + offset].type = variable_type.type;
548569
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;
550571
assert(variables[i + offset].name != NULL);
551572
assert(variables[i + offset].value != NULL);
552573
JS_FreeValue(ctx, value);
@@ -863,7 +884,7 @@ void js_debugger_build_backtrace(JSContext* ctx, const uint8_t* cur_pc, StackTra
863884

864885
init_stackframe(&stack_frames[id]);
865886

866-
stack_frames[id].id = id + 1;
887+
stack_frames[id].id = id + STACK_FRAME_INDEX_START;
867888
func_name_str = get_func_name(ctx, sf->cur_func);
868889
if (!func_name_str || func_name_str[0] == '\0') {
869890
stack_frames[id].name = "<anonymous>";

0 commit comments

Comments
 (0)