Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions api-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,142 @@ static void get_uint8array(void)
JS_FreeRuntime(rt);
}

static struct {
int call_count;
int last_line;
int last_col;
char last_filename[256];
char last_funcname[256];
int stack_depth;
int max_local_count;
int abort_at; /* abort (return -1) on this call, 0 = never */
} trace_state;

static int debug_trace_cb(JSContext *ctx,
JSAtom filename,
JSAtom funcname,
int line,
int col,
void *opaque)
{
trace_state.call_count++;
trace_state.last_line = line;
trace_state.last_col = col;
/* Convert while the atom is still valid (within callback lifetime).
Embedders who only need to compare against known breakpoint atoms
can skip this conversion entirely. */
const char *fn = JS_AtomToCString(ctx, filename);
if (fn) {
snprintf(trace_state.last_filename, sizeof(trace_state.last_filename),
"%s", fn);
JS_FreeCString(ctx, fn);
}
const char *fnn = JS_AtomToCString(ctx, funcname);
if (fnn) {
snprintf(trace_state.last_funcname, sizeof(trace_state.last_funcname),
"%s", fnn);
JS_FreeCString(ctx, fnn);
}
trace_state.stack_depth = JS_GetStackDepth(ctx);
int count = 0;
JSDebugLocalVar *vars = NULL;
assert(JS_GetLocalVariablesAtLevel(ctx, 0, &vars, &count) == 0);
if (count > trace_state.max_local_count)
trace_state.max_local_count = count;
if (vars)
JS_FreeLocalVariables(ctx, vars, count);
if (trace_state.abort_at > 0 &&
trace_state.call_count >= trace_state.abort_at)
return -1;
return 0;
}

static void debug_trace(void)
{
JSRuntime *rt = JS_NewRuntime();
JSContext *ctx = JS_NewContext(rt);

memset(&trace_state, 0, sizeof(trace_state));
{
JSValue ret = eval(ctx, "1+2");
assert(!JS_IsException(ret));
JS_FreeValue(ctx, ret);
assert(trace_state.call_count == 0);
}

JS_SetDebugTraceHandler(ctx, debug_trace_cb, NULL);
memset(&trace_state, 0, sizeof(trace_state));
{
JSValue ret = eval(ctx, "var x = 1; x + 2");
assert(!JS_IsException(ret));
JS_FreeValue(ctx, ret);
assert(trace_state.call_count > 0);
assert(!strcmp(trace_state.last_filename, "<input>"));
}

{
JSDebugLocalVar *vars = NULL;
int count = -1;
assert(JS_GetLocalVariablesAtLevel(ctx, 0, &vars, &count) == 0);
assert(vars == NULL);
assert(count == 0);
}

memset(&trace_state, 0, sizeof(trace_state));
{
static const char code[] =
"function outer() {\n"
" function inner() {\n"
" return 42;\n"
" }\n"
" return inner();\n"
"}\n"
"outer();\n";
JSValue ret = eval(ctx, code);
assert(!JS_IsException(ret));
JS_FreeValue(ctx, ret);
assert(trace_state.call_count > 0);
assert(trace_state.stack_depth >= 1);
}

memset(&trace_state, 0, sizeof(trace_state));
{
static const char code[] =
"function f(a, b) {\n"
" var c = a + b;\n"
" return c;\n"
"}\n"
"f(10, 20);\n";
JSValue ret = eval(ctx, code);
assert(!JS_IsException(ret));
JS_FreeValue(ctx, ret);
assert(trace_state.call_count > 0);
assert(trace_state.max_local_count >= 2);
}

memset(&trace_state, 0, sizeof(trace_state));
trace_state.abort_at = 1;
{
JSValue ret = eval(ctx, "1+2; 3+4");
assert(JS_IsException(ret));
JS_FreeValue(ctx, ret);
JSValue exc = JS_GetException(ctx);
JS_FreeValue(ctx, exc);
}

JS_SetDebugTraceHandler(ctx, NULL, NULL);
memset(&trace_state, 0, sizeof(trace_state));
{
JSValue ret = eval(ctx, "1+2");
assert(!JS_IsException(ret));
JS_FreeValue(ctx, ret);
assert(trace_state.call_count == 0);
}

JS_FreeContext(ctx);
JS_FreeRuntime(rt);
}

static void new_symbol(void)
{
JSRuntime *rt = new_runtime();
Expand Down Expand Up @@ -1089,6 +1225,7 @@ int main(void)
slice_string_tocstring();
immutable_array_buffer();
get_uint8array();
debug_trace();
new_symbol();
return 0;
}
2 changes: 2 additions & 0 deletions quickjs-opcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,8 @@ DEF( is_null, 1, 1, 1, none)
DEF(typeof_is_undefined, 1, 1, 1, none)
DEF( typeof_is_function, 1, 1, 1, none)

DEF( debug, 1, 0, 0, none)

#undef DEF
#undef def
#endif /* DEF */
Loading