Merge branch 'pretty_mcode' into mcode_streamline

This commit is contained in:
2026-02-12 18:48:17 -06:00
27 changed files with 26070 additions and 20218 deletions

View File

@@ -60,18 +60,6 @@ JS_BOOL JS_IsFunction (JSValue v) {
return JS_IsGCObject(v) && objhdr_type(*chase(v)) == OBJ_FUNCTION;
}
JS_BOOL JS_IsCode (JSValue v) {
return JS_IsGCObject(v) && objhdr_type(*chase(v)) == OBJ_CODE;
}
JS_BOOL JS_IsForwarded (JSValue v) {
return JS_IsGCObject(v) && objhdr_type(*chase(v)) == OBJ_FORWARD;
}
JS_BOOL JS_IsFrame (JSValue v) {
return JS_IsGCObject(v) && objhdr_type(*chase(v)) == OBJ_FRAME;
}
JS_BOOL JS_IsBlob (JSValue v) {
return JS_IsGCObject(v) && objhdr_type(*chase(v)) == OBJ_BLOB;
}
@@ -1058,7 +1046,7 @@ JSValue gc_copy_value (JSContext *ctx, JSValue v, uint8_t *from_base, uint8_t *f
continue;
}
if (type != OBJ_ARRAY && type != OBJ_TEXT && type != OBJ_RECORD && type != OBJ_FUNCTION && type != OBJ_BLOB && type != OBJ_CODE && type != OBJ_FRAME) {
if (type != OBJ_ARRAY && type != OBJ_TEXT && type != OBJ_RECORD && type != OBJ_FUNCTION && type != OBJ_BLOB && type != OBJ_FRAME) {
fprintf (stderr, "gc_copy_value: invalid object type %d at %p (hdr=0x%llx)\n", type, ptr, (unsigned long long)hdr);
fprintf (stderr, " This may be an interior pointer or corrupt root\n");
fflush (stderr);
@@ -1150,9 +1138,6 @@ void gc_scan_object (JSContext *ctx, void *ptr, uint8_t *from_base, uint8_t *fro
case OBJ_BLOB:
/* No internal references to scan */
break;
case OBJ_CODE:
/* Dead code: old bytecode objects no longer created */
break;
case OBJ_FRAME: {
/* JSFrame - scan function, caller, and slots */
JSFrame *frame = (JSFrame *)ptr;
@@ -1173,14 +1158,6 @@ void gc_scan_object (JSContext *ctx, void *ptr, uint8_t *from_base, uint8_t *fro
}
}
/* gc_scan_parser_cpool - no-op now that the old compiler is removed.
current_parse_fd is always NULL without cell_js.c. */
void gc_scan_parser_cpool (JSContext *ctx, uint8_t *from_base, uint8_t *from_end,
uint8_t *to_base, uint8_t **to_free, uint8_t *to_end) {
(void)ctx; (void)from_base; (void)from_end;
(void)to_base; (void)to_free; (void)to_end;
}
/* Cheney copying GC - collect garbage and compact live objects
allow_grow: if true, grow heap when recovery is poor
alloc_size: the allocation that triggered GC — used to size the new block */
@@ -1282,11 +1259,6 @@ int ctx_gc (JSContext *ctx, int allow_grow, size_t alloc_size) {
ref->val = gc_copy_value (ctx, ref->val, from_base, from_end, to_base, &to_free, to_end);
}
/* Scan parser's cpool (if parsing is in progress) */
if (ctx->current_parse_fd) {
gc_scan_parser_cpool (ctx, from_base, from_end, to_base, &to_free, to_end);
}
/* Cheney scan: scan copied objects to find more references */
uint8_t *scan = to_base;
#ifdef DUMP_GC_DETAIL
@@ -1530,14 +1502,6 @@ void JS_FreeContext (JSContext *ctx) {
JSRuntime *rt = ctx->rt;
int i;
#ifdef DUMP_MEM
{
JSMemoryUsage stats;
JS_ComputeMemoryUsage (rt, &stats);
JS_DumpMemoryUsage (stdout, &stats, rt);
}
#endif
for (i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {
}
for (i = 0; i < ctx->class_count; i++) {
@@ -2295,18 +2259,6 @@ JSValue JS_NewObject (JSContext *ctx) {
}
// TODO: needs reworked
int js_method_set_properties (JSContext *ctx, JSValue func_obj, JSValue name, int flags, JSValue home_obj) {
(void)ctx;
(void)flags;
(void)home_obj;
if (!JS_IsFunction (func_obj)) return -1;
JSFunction *f = JS_VALUE_GET_FUNCTION (func_obj);
/* name is now JSValue text */
if (JS_IsText (name)) { f->name = name; }
return 0;
}
/* Note: at least 'length' arguments will be readable in 'argv' */
static JSValue JS_NewCFunction3 (JSContext *ctx, JSCFunction *func, const char *name, int length, JSCFunctionEnum cproto, int magic) {
JSValue func_obj;
@@ -2454,7 +2406,7 @@ static int js_intrinsic_array_set (JSContext *ctx, JSValue *arr_ptr, word_t idx,
return 0;
}
/* Allocate intrinsic function (JS_TAG_FUNCTION) */
/* Allocate a new function object */
JSValue js_new_function (JSContext *ctx, JSFunctionKind kind) {
JSFunction *func = js_mallocz (ctx, sizeof (JSFunction));
if (!func) return JS_EXCEPTION;
@@ -2462,25 +2414,9 @@ JSValue js_new_function (JSContext *ctx, JSFunctionKind kind) {
func->kind = kind;
func->name = JS_NULL;
func->length = 0;
/* Initialize closure fields for bytecode functions */
if (kind == JS_FUNC_KIND_BYTECODE) {
func->u.func.outer_frame = JS_NULL;
func->u.func.env_record = JS_NULL;
}
return JS_MKPTR (func);
}
/* Get pointer to an upvalue in outer scope frame chain.
depth=0 is current frame, depth=1 is immediate outer, etc.
Returns NULL if depth exceeds the frame chain.
frame_val is a JSValue containing a JSFrame pointer. */
void JS_ComputeMemoryUsage (JSRuntime *rt, JSMemoryUsage *s) {
}
void JS_DumpMemoryUsage (FILE *fp, const JSMemoryUsage *s, JSRuntime *rt) {
}
/* WARNING: obj is freed */
JSValue JS_Throw (JSContext *ctx, JSValue obj) {
ctx->current_exception = obj;
@@ -2494,66 +2430,10 @@ JSValue JS_GetException (JSContext *ctx) {
return val;
}
JS_BOOL
JS_HasException (JSContext *ctx) {
JS_BOOL JS_HasException (JSContext *ctx) {
return !JS_IsNull (ctx->current_exception);
}
/* get_line_col — compute line and column from a byte offset */
int get_line_col (int *pcol_num, const uint8_t *buf, size_t len) {
int line_num, col_num, c;
size_t i;
line_num = 0;
col_num = 0;
for (i = 0; i < len; i++) {
c = buf[i];
if (c == '\n') {
line_num++;
col_num = 0;
} else if (c < 0x80 || c >= 0xc0) {
col_num++;
}
}
*pcol_num = col_num;
return line_num;
}
int get_line_col_cached (GetLineColCache *s, int *pcol_num, const uint8_t *ptr) {
int line_num, col_num;
if (ptr >= s->ptr) {
line_num = get_line_col (&col_num, s->ptr, ptr - s->ptr);
if (line_num == 0) {
s->col_num += col_num;
} else {
s->line_num += line_num;
s->col_num = col_num;
}
} else {
line_num = get_line_col (&col_num, ptr, s->ptr - ptr);
if (line_num == 0) {
s->col_num -= col_num;
} else {
const uint8_t *p;
s->line_num -= line_num;
/* find the absolute column position */
col_num = 0;
for (p = ptr - 1; p >= s->buf_start; p--) {
if (*p == '\n') {
break;
} else if (*p < 0x80 || *p >= 0xc0) {
col_num++;
}
}
s->col_num = col_num;
}
}
s->ptr = ptr;
*pcol_num = s->col_num;
return s->line_num;
}
/* in order to avoid executing arbitrary code during the stack trace
generation, we only look at simple 'name' properties containing a
string. */
@@ -3141,39 +3021,6 @@ int JS_DeletePropertyKey (JSContext *ctx, JSValue obj, JSValue key) {
Note: makes assumption about the bit pattern of the flags
*/
/* return TRUE if 'obj' has a non empty 'name' string */
static BOOL js_object_has_name (JSContext *ctx, JSValue obj) {
if (JS_VALUE_GET_TAG (obj) != JS_TAG_PTR) return FALSE;
JSRecord *rec = (JSRecord *)JS_VALUE_GET_OBJ (obj);
JSValue name_key = MIST_TryNewImmediateASCII ("name", 4);
int slot = rec_find_slot (rec, name_key);
if (slot <= 0) return FALSE;
JSValue val = rec->slots[slot].val;
if (!JS_IsText (val)) return TRUE; /* has name but it's not a string = truthy */
return (js_string_value_len (val) != 0);
}
int JS_DefineObjectName (JSContext *ctx, JSValue obj, JSValue name) {
if (!JS_IsNull (name) && JS_IsGCObject (obj)
&& !js_object_has_name (ctx, obj)) {
JSValue name_key = MIST_TryNewImmediateASCII ("name", 4);
if (JS_SetPropertyInternal (ctx, obj, name_key, name)
< 0)
return -1;
}
return 0;
}
int JS_DefineObjectNameComputed (JSContext *ctx, JSValue obj, JSValue str) {
if (JS_IsGCObject (obj) && !js_object_has_name (ctx, obj)) {
JSValue name_key = MIST_TryNewImmediateASCII ("name", 4);
if (JS_SetPropertyInternal (ctx, obj, name_key, str)
< 0)
return -1;
}
return 0;
}
int JS_DeleteProperty (JSContext *ctx, JSValue obj, JSValue prop) {
JSRecord *rec;
int slot;
@@ -4084,9 +3931,6 @@ __maybe_unused void JS_DumpGCObject (JSRuntime *rt,
JS_DumpObject (rt, (JSRecord *)p);
} else {
switch (objhdr_type (*p)) {
case OBJ_CODE:
printf ("[function bytecode]");
break;
case OBJ_ARRAY:
printf ("[array]");
break;
@@ -4152,73 +3996,10 @@ BOOL JS_StrictEq (JSContext *ctx, JSValue op1, JSValue op2) {
return js_strict_eq (ctx, op1, op2);
}
__exception int js_operator_delete (JSContext *ctx, JSValue *sp) {
JSValue op1, op2;
int ret;
op1 = sp[-2];
op2 = sp[-1];
ret = JS_DeletePropertyKey (ctx, op1, op2);
if (unlikely (ret < 0)) return -1;
sp[-2] = JS_NewBool (ctx, ret);
return 0;
}
/* XXX: not 100% compatible, but mozilla seems to use a similar
implementation to ensure that caller in non strict mode does not
throw (ES5 compatibility) */
static JSValue js_throw_type_error (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
return JS_ThrowTypeError (ctx, "invalid property access");
}
__exception int JS_CopyDataProperties (JSContext *ctx, JSValue target, JSValue source, JSValue excluded, BOOL setprop) {
JSValue keys, key, val;
uint32_t i, key_count;
int ret;
if (JS_VALUE_GET_TAG (source) != JS_TAG_PTR) return 0;
/* Get all string keys from source */
keys = JS_GetOwnPropertyNames (ctx, source);
if (JS_IsException (keys)) return -1;
if (js_get_length32 (ctx, &key_count, keys)) {
return -1;
}
for (i = 0; i < key_count; i++) {
key = JS_GetPropertyNumber (ctx, keys, i);
if (JS_IsException (key)) goto exception;
/* Check if key is excluded */
if (JS_VALUE_GET_TAG (excluded) == JS_TAG_PTR) {
/* Check if key exists in excluded object */
JSValue test = JS_GetProperty (ctx, excluded, key);
if (!JS_IsNull (test) && !JS_IsException (test)) {
continue;
}
}
/* Get property value from source */
val = JS_GetProperty (ctx, source, key);
if (JS_IsException (val)) {
goto exception;
}
/* Set property on target */
ret = JS_SetProperty (ctx, target, key, val);
if (ret < 0) goto exception;
}
return 0;
exception:
return -1;
}
JSValue js_call_c_function (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv) {
JSCFunctionType func;
JSFunction *f;
@@ -4361,12 +4142,6 @@ JSValue JS_Call (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, J
/*******************************************************************/
/* runtime functions & objects */
int check_function (JSContext *ctx, JSValue obj) {
if (likely (JS_IsFunction (obj))) return 0;
JS_ThrowTypeError (ctx, "not a function");
return -1;
}
int check_exception_free (JSContext *ctx, JSValue obj) {
return JS_IsException (obj);
}
@@ -4463,7 +4238,7 @@ __exception int js_get_length32 (JSContext *ctx, uint32_t *pres, JSValue obj) {
return 0;
}
if (tag == JS_TAG_FUNCTION) {
if (JS_IsFunction (obj)) {
JSFunction *fn = JS_VALUE_GET_FUNCTION (obj);
*pres = fn->length;
return 0;
@@ -6562,22 +6337,13 @@ static JSValue js_cell_text (JSContext *ctx, JSValue this_val, int argc, JSValue
/* Handle function - return source or native stub */
if (JS_IsFunction (arg)) {
JSFunction *fn = JS_VALUE_GET_FUNCTION (arg);
if (fn->kind == JS_FUNC_KIND_BYTECODE) {
JSFunctionBytecode *b = fn->u.func.function_bytecode;
if (b->has_debug && b->debug.source)
return JS_NewStringLen (ctx, b->debug.source, b->debug.source_len);
}
const char *pref = "function ";
const char *suff = "() {\n [native code]\n}";
const char *name = "";
const char *name_cstr = NULL;
if (fn->kind == JS_FUNC_KIND_BYTECODE) {
JSFunctionBytecode *fb = fn->u.func.function_bytecode;
name_cstr = JS_ToCString (ctx, fb->func_name);
if (name_cstr) name = name_cstr;
} else if (!JS_IsNull (fn->name)) {
if (!JS_IsNull (fn->name)) {
name_cstr = JS_ToCString (ctx, fn->name);
if (name_cstr) name = name_cstr;
}
@@ -7627,259 +7393,6 @@ static JSValue js_stacktrace (JSContext *ctx, JSValue this_val, int argc, JSValu
return JS_NULL;
}
/* dump_bytecode_opcodes and JS_DumpFunctionBytecode removed — old stack VM deleted */
#if 0 /* dead code — old bytecode dump */
static void dump_bytecode_opcodes_DEAD (JSContext *ctx, JSFunctionBytecode *b) {
const uint8_t *tab = b->byte_code_buf;
int len = b->byte_code_len;
const JSValue *cpool = b->cpool;
uint32_t cpool_count = b->cpool_count;
const JSVarDef *vars = b->vardefs ? b->vardefs + b->arg_count : NULL;
int var_count = b->var_count;
int pos = 0;
while (pos < len) {
int op = tab[pos];
if (op >= OP_COUNT) {
printf (" %5d: <invalid opcode 0x%02x>\n", pos, op);
pos++;
continue;
}
const JSOpCode *oi = &short_opcode_info (op);
int size = oi->size;
if (pos + size > len) {
printf (" %5d: <truncated opcode 0x%02x>\n", pos, op);
break;
}
printf (" %5d: %s", pos, dump_opcode_names[op]);
pos++;
switch (oi->fmt) {
case OP_FMT_none_int:
printf (" %d", op - OP_push_0);
break;
case OP_FMT_npopx:
printf (" %d", op - OP_call0);
break;
case OP_FMT_u8:
printf (" %u", get_u8 (tab + pos));
break;
case OP_FMT_i8:
printf (" %d", get_i8 (tab + pos));
break;
case OP_FMT_u16:
case OP_FMT_npop:
printf (" %u", get_u16 (tab + pos));
break;
case OP_FMT_npop_u16:
printf (" %u,%u", get_u16 (tab + pos), get_u16 (tab + pos + 2));
break;
case OP_FMT_i16:
printf (" %d", get_i16 (tab + pos));
break;
case OP_FMT_i32:
printf (" %d", get_i32 (tab + pos));
break;
case OP_FMT_u32:
printf (" %u", get_u32 (tab + pos));
break;
case OP_FMT_label8:
printf (" ->%d", pos + get_i8 (tab + pos));
break;
case OP_FMT_label16:
printf (" ->%d", pos + get_i16 (tab + pos));
break;
case OP_FMT_label:
printf (" ->%u", pos + get_u32 (tab + pos));
break;
case OP_FMT_label_u16:
printf (" ->%u,%u", pos + get_u32 (tab + pos), get_u16 (tab + pos + 4));
break;
case OP_FMT_const8: {
uint32_t idx = get_u8 (tab + pos);
printf (" [%u]", idx);
if (idx < cpool_count) {
printf (": ");
JS_PrintValue (ctx, js_dump_value_write, stdout, cpool[idx], NULL);
}
break;
}
case OP_FMT_const: {
uint32_t idx = get_u32 (tab + pos);
printf (" [%u]", idx);
if (idx < cpool_count) {
printf (": ");
JS_PrintValue (ctx, js_dump_value_write, stdout, cpool[idx], NULL);
}
break;
}
case OP_FMT_key: {
uint32_t idx = get_u32 (tab + pos);
printf (" [%u]", idx);
if (idx < cpool_count) {
printf (": ");
JS_PrintValue (ctx, js_dump_value_write, stdout, cpool[idx], NULL);
}
break;
}
case OP_FMT_key_u8: {
uint32_t idx = get_u32 (tab + pos);
printf (" [%u],%d", idx, get_u8 (tab + pos + 4));
if (idx < cpool_count) {
printf (": ");
JS_PrintValue (ctx, js_dump_value_write, stdout, cpool[idx], NULL);
}
break;
}
case OP_FMT_key_u16: {
uint32_t idx = get_u32 (tab + pos);
printf (" [%u],%d", idx, get_u16 (tab + pos + 4));
if (idx < cpool_count) {
printf (": ");
JS_PrintValue (ctx, js_dump_value_write, stdout, cpool[idx], NULL);
}
break;
}
case OP_FMT_none_loc:
printf (" loc%d", (op - OP_get_loc0) % 4);
break;
case OP_FMT_loc8: {
int idx = get_u8 (tab + pos);
printf (" loc%d", idx);
if (vars && idx < var_count) {
char buf[KEY_GET_STR_BUF_SIZE];
printf (": %s", JS_KeyGetStr (ctx, buf, sizeof(buf), vars[idx].var_name));
}
break;
}
case OP_FMT_loc: {
int idx = get_u16 (tab + pos);
printf (" loc%d", idx);
if (vars && idx < var_count) {
char buf[KEY_GET_STR_BUF_SIZE];
printf (": %s", JS_KeyGetStr (ctx, buf, sizeof(buf), vars[idx].var_name));
}
break;
}
case OP_FMT_none_arg:
printf (" arg%d", (op - OP_get_arg0) % 4);
break;
case OP_FMT_arg:
printf (" arg%d", get_u16 (tab + pos));
break;
default:
break;
}
printf ("\n");
pos += size - 1; /* -1 because we already incremented pos after reading opcode */
}
}
void JS_DumpFunctionBytecode (JSContext *ctx, JSValue func_val) {
JSFunctionBytecode *b = NULL;
if (!JS_IsPtr (func_val)) {
printf ("JS_DumpFunctionBytecode: not a pointer value\n");
return;
}
/* Get the object header to check type */
void *ptr = JS_VALUE_GET_PTR (func_val);
objhdr_t hdr = *(objhdr_t *)ptr;
uint8_t type = objhdr_type (hdr);
if (type == OBJ_FUNCTION) {
/* It's a JSFunction - extract bytecode */
JSFunction *fn = (JSFunction *)ptr;
if (fn->kind != JS_FUNC_KIND_BYTECODE) {
printf ("JS_DumpFunctionBytecode: not a bytecode function (kind=%d)\n", fn->kind);
return;
}
b = fn->u.func.function_bytecode;
} else if (type == OBJ_CODE) {
/* It's raw bytecode from js_create_function */
b = (JSFunctionBytecode *)ptr;
} else {
printf ("JS_DumpFunctionBytecode: not a function or bytecode (type=%d)\n", type);
return;
}
if (!b) {
printf ("JS_DumpFunctionBytecode: no bytecode\n");
return;
}
char buf[KEY_GET_STR_BUF_SIZE];
printf ("=== Bytecode Dump ===\n");
/* Function name */
const char *fname = JS_KeyGetStr (ctx, buf, sizeof(buf), b->func_name);
printf ("Function: %s\n", fname ? fname : "<anonymous>");
/* Debug info */
if (b->has_debug && !JS_IsNull (b->debug.filename)) {
printf ("File: %s\n", JS_KeyGetStr (ctx, buf, sizeof(buf), b->debug.filename));
}
/* Basic stats */
printf ("Args: %d, Vars: %d, Stack: %d\n", b->arg_count, b->var_count, b->stack_size);
printf ("Bytecode length: %d bytes\n", b->byte_code_len);
/* Arguments */
if (b->arg_count > 0 && b->vardefs) {
printf ("\nArguments:\n");
for (int i = 0; i < b->arg_count; i++) {
printf (" %d: %s\n", i, JS_KeyGetStr (ctx, buf, sizeof(buf), b->vardefs[i].var_name));
}
}
/* Local variables */
if (b->var_count > 0 && b->vardefs) {
printf ("\nLocal variables:\n");
for (int i = 0; i < b->var_count; i++) {
JSVarDef *vd = &b->vardefs[b->arg_count + i];
const char *kind = vd->is_const ? "const" : vd->is_lexical ? "let" : "var";
printf (" %d: %s %s", i, kind, JS_KeyGetStr (ctx, buf, sizeof(buf), vd->var_name));
if (vd->scope_level) printf (" [scope:%d]", vd->scope_level);
printf ("\n");
}
}
/* Closure variables */
if (b->closure_var_count > 0) {
printf ("\nClosure variables:\n");
for (int i = 0; i < b->closure_var_count; i++) {
JSClosureVar *cv = &b->closure_var[i];
printf (" %d: %s (%s:%s%d)\n", i,
JS_KeyGetStr (ctx, buf, sizeof(buf), cv->var_name),
cv->is_local ? "local" : "parent",
cv->is_arg ? "arg" : "loc",
cv->var_idx);
}
}
/* Constant pool */
if (b->cpool_count > 0) {
printf ("\nConstant pool (%d entries):\n", b->cpool_count);
for (uint32_t i = 0; i < b->cpool_count; i++) {
printf (" [%u]: ", i);
JS_PrintValue (ctx, js_dump_value_write, stdout, b->cpool[i], NULL);
printf ("\n");
}
}
/* Bytecode instructions */
printf ("\nBytecode:\n");
dump_bytecode_opcodes (ctx, b);
printf ("=== End Bytecode Dump ===\n");
}
#endif /* dead code */
/* ----------------------------------------------------------------------------
* array function and sub-functions
* ----------------------------------------------------------------------------
@@ -11108,78 +10621,6 @@ void js_debug_sethook (JSContext *ctx, js_hook hook, int type, void *user) {
ctx->trace_data = user;
}
uint32_t js_debugger_stack_depth (JSContext *ctx) {
return ctx->stack_depth;
}
/* return an array of the actual fn objects as a backtrace */
JSValue js_debugger_backtrace_fns (JSContext *ctx) {
/* JSValue ret = JS_NewArray (ctx);
uint32_t stack_index = 0;
for (sf = ctx->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
uint32_t id = stack_index++;
JS_SetPropertyNumber (ctx, ret, id, sf->cur_func);
}
return ret;
*/
}
/* build a backtrace of info for printing */
JSValue js_debugger_build_backtrace (JSContext *ctx) {
/*
JSStackFrame *sf;
JSValue ret = JS_NewArray (ctx);
uint32_t stack_index = 0;
for (sf = ctx->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
JSValue current_frame = JS_NewObject (ctx);
uint32_t id = stack_index++;
JS_SetPropertyStr (ctx, current_frame, "id", JS_NewUint32 (ctx, id));
const char *func_name_str = get_func_name (ctx, sf->cur_func);
if (!func_name_str || func_name_str[0] == '\0')
JS_SetPropertyStr (ctx, current_frame, "name", JS_NewString (ctx, "<anonymous>"));
else
JS_SetPropertyStr (ctx, current_frame, "name", JS_NewString (ctx, func_name_str));
JS_FreeCString (ctx, func_name_str);
JS_SetPropertyNumber (ctx, ret, id, current_frame);
}
return ret;
*/
}
JSValue js_debugger_fn_info (JSContext *ctx, JSValue fn) {
(void)fn;
return JS_NewObject (ctx);
}
JSValue js_debugger_fn_bytecode (JSContext *ctx, JSValue fn) {
(void)fn;
return JS_NewArray (ctx);
}
JSValue js_debugger_local_variables (JSContext *ctx, int stack_index) {
(void)stack_index;
return JS_NewObject (ctx);
}
void js_debugger_set_closure_variable (JSContext *ctx, JSValue fn, JSValue var_name, JSValue val) {
/* TODO: Reimplement using outer_frame mechanism if debugging is needed */
(void)ctx; (void)fn; (void)var_name; (void)val;
}
JSValue js_debugger_closure_variables (JSContext *ctx, JSValue fn) {
/* TODO: Reimplement using outer_frame mechanism if debugging is needed */
(void)fn;
return JS_NewObject (ctx);
}
void *js_debugger_val_address (JSContext *ctx, JSValue val) {
return JS_VALUE_GET_PTR (val);
}
/* ============================================================================
* Cell Script Module: json
* Provides json.encode() and json.decode() using pure C implementation