Merge branch 'runtime_rework' into pretty_mcode
This commit is contained in:
@@ -1,27 +1,15 @@
|
||||
#include "cell.h"
|
||||
|
||||
// Return the current stack depth.
|
||||
JSC_CCALL(debug_stack_depth, return number2js(js,js_debugger_stack_depth(js)))
|
||||
// TODO: Reimplement stack depth for register VM
|
||||
JSC_CCALL(debug_stack_depth, return number2js(js, 0))
|
||||
|
||||
// Return a backtrace of the current call stack.
|
||||
JSC_CCALL(debug_build_backtrace, return js_debugger_build_backtrace(js))
|
||||
|
||||
// Return the closure variables for a given function.
|
||||
JSC_CCALL(debug_closure_vars, return js_debugger_closure_variables(js,argv[0]))
|
||||
|
||||
JSC_CCALL(debug_set_closure_var,
|
||||
js_debugger_set_closure_variable(js,argv[0],argv[1],argv[2]);
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
// Return the local variables for a specific stack frame.
|
||||
JSC_CCALL(debug_local_vars, return js_debugger_local_variables(js, js2number(js,argv[0])))
|
||||
|
||||
// Return metadata about a given function.
|
||||
JSC_CCALL(debug_fn_info, return js_debugger_fn_info(js, argv[0]))
|
||||
|
||||
// Return an array of functions in the current backtrace.
|
||||
JSC_CCALL(debug_backtrace_fns, return js_debugger_backtrace_fns(js))
|
||||
// TODO: Reimplement debug introspection for register VM
|
||||
JSC_CCALL(debug_build_backtrace, return JS_NewArray(js))
|
||||
JSC_CCALL(debug_closure_vars, return JS_NewObject(js))
|
||||
JSC_CCALL(debug_set_closure_var, return JS_NULL;)
|
||||
JSC_CCALL(debug_local_vars, return JS_NewObject(js))
|
||||
JSC_CCALL(debug_fn_info, return JS_NewObject(js))
|
||||
JSC_CCALL(debug_backtrace_fns, return JS_NewArray(js))
|
||||
|
||||
static const JSCFunctionListEntry js_debug_funcs[] = {
|
||||
MIST_FUNC_DEF(debug, stack_depth, 0),
|
||||
@@ -37,4 +25,4 @@ JSValue js_debug_use(JSContext *js) {
|
||||
JSValue mod = JS_NewObject(js);
|
||||
JS_SetPropertyFunctionList(js,mod,js_debug_funcs,countof(js_debug_funcs));
|
||||
return mod;
|
||||
}
|
||||
}
|
||||
|
||||
42
debug/js.c
42
debug/js.c
@@ -1,48 +1,16 @@
|
||||
#include "cell.h"
|
||||
|
||||
JSC_CCALL(os_mem_limit, JS_SetMemoryLimit(JS_GetRuntime(js), js2number(js,argv[0])))
|
||||
JSC_CCALL(os_max_stacksize, JS_SetMaxStackSize(JS_GetRuntime(js), js2number(js,argv[0])))
|
||||
JSC_CCALL(os_max_stacksize, JS_SetMaxStackSize(js, js2number(js,argv[0])))
|
||||
|
||||
// Compute the approximate size of a single JS value in memory.
|
||||
// TODO: Reimplement memory usage reporting for new allocator
|
||||
JSC_CCALL(os_calc_mem,
|
||||
JSMemoryUsage mu;
|
||||
JS_ComputeMemoryUsage(JS_GetRuntime(js),&mu);
|
||||
ret = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js,ret,"malloc_size",number2js(js,mu.malloc_size));
|
||||
JS_SetPropertyStr(js,ret,"malloc_limit",number2js(js,mu.malloc_limit));
|
||||
JS_SetPropertyStr(js,ret,"memory_used_size",number2js(js,mu.memory_used_size));
|
||||
JS_SetPropertyStr(js,ret,"malloc_count",number2js(js,mu.malloc_count));
|
||||
JS_SetPropertyStr(js,ret,"memory_used_count",number2js(js,mu.memory_used_count));
|
||||
JS_SetPropertyStr(js,ret,"str_count",number2js(js,mu.str_count));
|
||||
JS_SetPropertyStr(js,ret,"str_size",number2js(js,mu.str_size));
|
||||
JS_SetPropertyStr(js,ret,"obj_count",number2js(js,mu.obj_count));
|
||||
JS_SetPropertyStr(js,ret,"obj_size",number2js(js,mu.obj_size));
|
||||
JS_SetPropertyStr(js,ret,"prop_count",number2js(js,mu.prop_count));
|
||||
JS_SetPropertyStr(js,ret,"prop_size",number2js(js,mu.prop_size));
|
||||
JS_SetPropertyStr(js,ret,"shape_count",number2js(js,mu.shape_count));
|
||||
JS_SetPropertyStr(js,ret,"shape_size",number2js(js,mu.shape_size));
|
||||
JS_SetPropertyStr(js,ret,"js_func_count",number2js(js,mu.js_func_count));
|
||||
JS_SetPropertyStr(js,ret,"js_func_size",number2js(js,mu.js_func_size));
|
||||
JS_SetPropertyStr(js,ret,"js_func_code_size",number2js(js,mu.js_func_code_size));
|
||||
JS_SetPropertyStr(js,ret,"js_func_pc2line_count",number2js(js,mu.js_func_pc2line_count));
|
||||
JS_SetPropertyStr(js,ret,"js_func_pc2line_size",number2js(js,mu.js_func_pc2line_size));
|
||||
JS_SetPropertyStr(js,ret,"c_func_count",number2js(js,mu.c_func_count));
|
||||
JS_SetPropertyStr(js,ret,"array_count",number2js(js,mu.array_count));
|
||||
JS_SetPropertyStr(js,ret,"fast_array_count",number2js(js,mu.fast_array_count));
|
||||
JS_SetPropertyStr(js,ret,"fast_array_elements",number2js(js,mu.fast_array_elements));
|
||||
JS_SetPropertyStr(js,ret,"binary_object_count",number2js(js,mu.binary_object_count));
|
||||
JS_SetPropertyStr(js,ret,"binary_object_size",number2js(js,mu.binary_object_size));
|
||||
)
|
||||
|
||||
// Disassemble a function object into a string.
|
||||
JSC_CCALL(js_disassemble,
|
||||
return js_debugger_fn_bytecode(js, argv[0]);
|
||||
)
|
||||
|
||||
// Return metadata about a given function.
|
||||
JSC_CCALL(js_fn_info,
|
||||
return js_debugger_fn_info(js, argv[0]);
|
||||
)
|
||||
// TODO: Reimplement for register VM
|
||||
JSC_CCALL(js_disassemble, return JS_NewArray(js);)
|
||||
JSC_CCALL(js_fn_info, return JS_NewObject(js);)
|
||||
|
||||
static const JSCFunctionListEntry js_js_funcs[] = {
|
||||
MIST_FUNC_DEF(os, calc_mem, 0),
|
||||
|
||||
@@ -78,8 +78,7 @@ void cell_trace_sethook(cell_hook);
|
||||
#define QJSCLASS(TYPE, ...)\
|
||||
JSClassID js_##TYPE##_id;\
|
||||
static void js_##TYPE##_finalizer(JSRuntime *rt, JSValue val){\
|
||||
JSContext *js = JS_GetContext(rt);\
|
||||
TYPE *n = JS_GetOpaque2(js, val, js_##TYPE##_id); \
|
||||
TYPE *n = JS_GetOpaque(val, js_##TYPE##_id); \
|
||||
TYPE##_free(rt,n);}\
|
||||
static JSClassDef js_##TYPE##_class = {\
|
||||
.class_name = #TYPE,\
|
||||
|
||||
@@ -294,7 +294,6 @@ typedef enum JSErrorEnum {
|
||||
#define __exception __attribute__ ((warn_unused_result))
|
||||
|
||||
/* Forward declaration for bytecode freeing */
|
||||
struct JSFunctionBytecode;
|
||||
|
||||
#define JS_VALUE_GET_ARRAY(v) ((JSArray *)chase (v))
|
||||
#define JS_VALUE_GET_OBJ(v) ((JSRecord *)chase (v))
|
||||
@@ -302,15 +301,12 @@ struct JSFunctionBytecode;
|
||||
#define JS_VALUE_GET_BLOB(v) ((JSBlob *)JS_VALUE_GET_PTR (v))
|
||||
#define JS_VALUE_GET_FUNCTION(v) ((JSFunction *)chase (v))
|
||||
#define JS_VALUE_GET_FRAME(v) ((JSFrame *)chase (v))
|
||||
#define JS_VALUE_GET_CODE(v) ((JSFunctionBytecode *)JS_VALUE_GET_PTR (v))
|
||||
#define JS_VALUE_GET_CODE(v) (JS_VALUE_GET_PTR (v))
|
||||
#define JS_VALUE_GET_STRING(v) ((JSText *)chase (v))
|
||||
|
||||
/* Compatibility: JS_TAG_STRING is an alias for text type checks */
|
||||
#define JS_TAG_STRING JS_TAG_STRING_IMM
|
||||
|
||||
/* JS_TAG_FUNCTION doesn't exist in new encoding - use JS_IsFunction check instead */
|
||||
#define JS_TAG_FUNCTION 0xFE /* dummy value, never matches any tag */
|
||||
|
||||
/* JS_ThrowMemoryError is an alias for JS_ThrowOutOfMemory */
|
||||
#define JS_ThrowMemoryError(ctx) JS_ThrowOutOfMemory(ctx)
|
||||
|
||||
@@ -319,8 +315,6 @@ static inline objhdr_t objhdr_set_cap56 (objhdr_t h, uint64_t cap) {
|
||||
return (h & 0xFF) | ((cap & OBJHDR_CAP_MASK) << OBJHDR_CAP_SHIFT);
|
||||
}
|
||||
|
||||
typedef enum OPCodeEnum OPCodeEnum;
|
||||
|
||||
/* ============================================================
|
||||
Buddy Allocator for Actor Memory Blocks
|
||||
============================================================ */
|
||||
@@ -776,27 +770,6 @@ typedef struct JSFrame {
|
||||
JSValue slots[]; /* [this][args][captured][locals][temps] */
|
||||
} JSFrame;
|
||||
|
||||
/* Execution state returned by vm_execute_frame */
|
||||
typedef enum {
|
||||
VM_EXEC_NORMAL, /* Continue executing current frame */
|
||||
VM_EXEC_RETURN, /* Frame returned, pop and resume caller */
|
||||
VM_EXEC_CALL, /* Need to push new frame for call */
|
||||
VM_EXEC_EXCEPTION, /* Exception thrown, unwind frames */
|
||||
} VMExecState;
|
||||
|
||||
/* Call info for frame push */
|
||||
typedef struct {
|
||||
JSValue func_obj;
|
||||
JSValue this_obj;
|
||||
int argc;
|
||||
JSValue *argv;
|
||||
const uint8_t *ret_pc;
|
||||
int ret_sp_offset;
|
||||
int call_argc;
|
||||
int call_has_this;
|
||||
int is_tail_call;
|
||||
} VMCallInfo;
|
||||
|
||||
static inline objhdr_t objhdr_set_s (objhdr_t h, bool s) {
|
||||
return s ? (h | OBJHDR_S_MASK) : (h & ~OBJHDR_S_MASK);
|
||||
}
|
||||
@@ -1068,9 +1041,6 @@ struct JSContext {
|
||||
// todo: want this, but should be a simple increment/decrement counter while frames are pushed
|
||||
size_t stack_depth;
|
||||
size_t stack_limit;
|
||||
|
||||
/* Parser state (for GC to scan cpool during parsing) */
|
||||
struct JSFunctionDef *current_parse_fd;
|
||||
};
|
||||
|
||||
/* ============================================================
|
||||
@@ -1237,11 +1207,6 @@ typedef struct JSFunction {
|
||||
uint8_t cproto;
|
||||
int16_t magic;
|
||||
} cfunc;
|
||||
struct {
|
||||
struct JSFunctionBytecode *function_bytecode;
|
||||
JSValue outer_frame; /* JSFrame JSValue, lexical parent for closures */
|
||||
JSValue env_record; /* stone record, module environment */
|
||||
} func;
|
||||
struct {
|
||||
JSCodeRegister *code; /* compiled register code (off-heap) */
|
||||
JSValue env_record; /* stone record, module environment */
|
||||
@@ -1250,150 +1215,11 @@ typedef struct JSFunction {
|
||||
} u;
|
||||
} JSFunction;
|
||||
|
||||
typedef struct JSClosureVar {
|
||||
uint8_t is_local : 1;
|
||||
uint8_t is_arg : 1;
|
||||
uint8_t is_const : 1;
|
||||
uint8_t is_lexical : 1;
|
||||
uint8_t var_kind : 4; /* see JSVarKindEnum */
|
||||
/* 8 bits available */
|
||||
uint16_t var_idx; /* is_local = TRUE: index to a normal variable of the
|
||||
parent function. otherwise: index to a closure
|
||||
variable of the parent function */
|
||||
JSValue var_name;
|
||||
} JSClosureVar;
|
||||
|
||||
#define ARG_SCOPE_INDEX 1
|
||||
#define ARG_SCOPE_END (-2)
|
||||
|
||||
typedef struct JSVarScope {
|
||||
int parent; /* index into fd->scopes of the enclosing scope */
|
||||
int first; /* index into fd->vars of the last variable in this scope */
|
||||
} JSVarScope;
|
||||
|
||||
typedef enum {
|
||||
/* XXX: add more variable kinds here instead of using bit fields */
|
||||
JS_VAR_NORMAL,
|
||||
JS_VAR_FUNCTION_DECL, /* lexical var with function declaration */
|
||||
JS_VAR_NEW_FUNCTION_DECL, /* lexical var with async/generator
|
||||
function declaration */
|
||||
JS_VAR_CATCH,
|
||||
JS_VAR_FUNCTION_NAME, /* function expression name */
|
||||
} JSVarKindEnum;
|
||||
|
||||
/* XXX: could use a different structure in bytecode functions to save
|
||||
memory */
|
||||
typedef struct JSVarDef {
|
||||
JSValue var_name;
|
||||
/* index into fd->scopes of this variable lexical scope */
|
||||
int scope_level;
|
||||
/* during compilation:
|
||||
- if scope_level = 0: scope in which the variable is defined
|
||||
- if scope_level != 0: index into fd->vars of the next
|
||||
variable in the same or enclosing lexical scope
|
||||
in a bytecode function:
|
||||
index into fd->vars of the next
|
||||
variable in the same or enclosing lexical scope
|
||||
*/
|
||||
int scope_next;
|
||||
uint8_t is_const : 1;
|
||||
uint8_t is_lexical : 1;
|
||||
uint8_t is_captured : 1;
|
||||
uint8_t var_kind : 4; /* see JSVarKindEnum */
|
||||
/* only used during compilation: function pool index for lexical
|
||||
variables with var_kind =
|
||||
JS_VAR_FUNCTION_DECL/JS_VAR_NEW_FUNCTION_DECL or scope level of
|
||||
the definition of the 'var' variables (they have scope_level =
|
||||
0) */
|
||||
int func_pool_idx : 24; /* only used during compilation : index in
|
||||
the constant pool for hoisted function
|
||||
definition */
|
||||
} JSVarDef;
|
||||
|
||||
/* for the encoding of the pc2line table */
|
||||
#define PC2LINE_BASE (-1)
|
||||
#define PC2LINE_RANGE 5
|
||||
#define PC2LINE_OP_FIRST 1
|
||||
#define PC2LINE_DIFF_PC_MAX ((255 - PC2LINE_OP_FIRST) / PC2LINE_RANGE)
|
||||
|
||||
typedef struct JSFunctionBytecode {
|
||||
objhdr_t header; /* must come first */
|
||||
uint8_t js_mode;
|
||||
uint8_t has_prototype : 1; /* true if a prototype field is necessary */
|
||||
uint8_t has_simple_parameter_list : 1;
|
||||
uint8_t func_kind : 2;
|
||||
uint8_t has_debug : 1;
|
||||
uint8_t read_only_bytecode : 1;
|
||||
uint8_t is_direct_or_indirect_eval
|
||||
: 1; /* used by JS_GetScriptOrModuleName() */
|
||||
/* XXX: 10 bits available */
|
||||
uint8_t *byte_code_buf; /* (self pointer) */
|
||||
int byte_code_len;
|
||||
JSValue func_name;
|
||||
JSVarDef *vardefs; /* arguments + local variables (arg_count + var_count)
|
||||
(self pointer) */
|
||||
JSClosureVar
|
||||
*closure_var; /* list of variables in the closure (self pointer) */
|
||||
uint16_t arg_count;
|
||||
uint16_t var_count;
|
||||
uint16_t defined_arg_count; /* for length function property */
|
||||
uint16_t stack_size; /* maximum stack size */
|
||||
JSValue *cpool; /* constant pool (self pointer) */
|
||||
int cpool_count;
|
||||
int closure_var_count;
|
||||
struct {
|
||||
/* debug info, move to separate structure to save memory? */
|
||||
JSValue filename;
|
||||
int source_len;
|
||||
int pc2line_len;
|
||||
uint8_t *pc2line_buf;
|
||||
char *source;
|
||||
} debug;
|
||||
} JSFunctionBytecode;
|
||||
|
||||
/* New simplified compiled unit structure for Phase 1+ simplification.
|
||||
Replaces JSFunctionBytecode with a simpler model:
|
||||
- No closure machinery (uses outer_frame chain at runtime)
|
||||
- Free variables resolved at link time against env + globals
|
||||
- Nested functions stored as separate units in cpool */
|
||||
typedef struct JSCompiledUnit {
|
||||
objhdr_t header; /* must come first */
|
||||
|
||||
/* Bytecode (self pointer) */
|
||||
uint8_t *byte_code_buf;
|
||||
int byte_code_len;
|
||||
|
||||
/* Constants - strings, numbers, nested unit refs (self pointer) */
|
||||
JSValue *cpool;
|
||||
int cpool_count;
|
||||
|
||||
/* Stack requirements */
|
||||
uint16_t local_count; /* total local slots (args + vars) */
|
||||
uint16_t stack_size; /* operand stack depth */
|
||||
|
||||
/* Flags */
|
||||
uint8_t has_debug : 1;
|
||||
uint8_t read_only_bytecode : 1;
|
||||
|
||||
/* Debug info (optional - only present if has_debug) */
|
||||
struct {
|
||||
JSValue filename;
|
||||
int source_len;
|
||||
int pc2line_len;
|
||||
uint8_t *pc2line_buf;
|
||||
char *source;
|
||||
} debug;
|
||||
} JSCompiledUnit;
|
||||
|
||||
/* ============================================================
|
||||
Context-Neutral Module Format (Phase 2+)
|
||||
Struct definitions are in quickjs.h
|
||||
============================================================ */
|
||||
|
||||
typedef struct JSProperty {
|
||||
JSValue value;
|
||||
} JSProperty;
|
||||
|
||||
#define JS_PROP_INITIAL_SIZE 2
|
||||
#define JS_PROP_INITIAL_HASH_SIZE 4 /* must be a power of two */
|
||||
#define JS_ARRAY_INITIAL_SIZE 2
|
||||
@@ -1406,7 +1232,6 @@ typedef struct JSProperty {
|
||||
#endif
|
||||
|
||||
JSValue js_call_c_function (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv);
|
||||
JSValue js_call_bound_function (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv);
|
||||
JSValue JS_CallInternal (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv, int flags);
|
||||
JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code, JSValue this_obj, int argc, JSValue *argv, JSValue env, JSValue outer_frame);
|
||||
int JS_DeleteProperty (JSContext *ctx, JSValue obj, JSValue prop);
|
||||
@@ -1421,17 +1246,9 @@ void js_dump_value_write (void *opaque, const char *buf, size_t len);
|
||||
void js_regexp_finalizer (JSRuntime *rt, JSValue val);
|
||||
JSValue js_new_function (JSContext *ctx, JSFunctionKind kind);
|
||||
|
||||
/* Forward declarations for intrinsics (now declared in quickjs.h) */
|
||||
|
||||
/* Forward declaration - helper to set cap in objhdr */
|
||||
static inline objhdr_t objhdr_set_cap56 (objhdr_t h, uint64_t cap);
|
||||
|
||||
/* JS_VALUE_GET_STRING is an alias for getting JSText from a string value */
|
||||
/* Note: Uses chase() for GC safety - already defined at line 293 */
|
||||
|
||||
/* JS_ThrowMemoryError is an alias for JS_ThrowOutOfMemory */
|
||||
#define JS_ThrowMemoryError(ctx) JS_ThrowOutOfMemory(ctx)
|
||||
|
||||
/* GC-SAFE: JS_SetPropertyInternal: same as JS_SetProperty but doesn't check stone.
|
||||
Internal use only. May trigger GC if record needs to resize. */
|
||||
|
||||
@@ -1611,118 +1428,6 @@ static inline __exception int js_poll_interrupts (JSContext *ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
/* === Token enum (shared by parser, tokenizer, AST) === */
|
||||
enum {
|
||||
TOK_NUMBER = -128,
|
||||
TOK_STRING,
|
||||
TOK_TEMPLATE,
|
||||
TOK_IDENT,
|
||||
TOK_REGEXP,
|
||||
/* warning: order matters (see js_parse_assign_expr) */
|
||||
TOK_MUL_ASSIGN,
|
||||
TOK_DIV_ASSIGN,
|
||||
TOK_MOD_ASSIGN,
|
||||
TOK_PLUS_ASSIGN,
|
||||
TOK_MINUS_ASSIGN,
|
||||
TOK_SHL_ASSIGN,
|
||||
TOK_SAR_ASSIGN,
|
||||
TOK_SHR_ASSIGN,
|
||||
TOK_AND_ASSIGN,
|
||||
TOK_XOR_ASSIGN,
|
||||
TOK_OR_ASSIGN,
|
||||
TOK_POW_ASSIGN,
|
||||
TOK_LAND_ASSIGN,
|
||||
TOK_LOR_ASSIGN,
|
||||
TOK_DEC,
|
||||
TOK_INC,
|
||||
TOK_SHL,
|
||||
TOK_SAR,
|
||||
TOK_SHR,
|
||||
TOK_LT,
|
||||
TOK_LTE,
|
||||
TOK_GT,
|
||||
TOK_GTE,
|
||||
TOK_EQ,
|
||||
TOK_STRICT_EQ,
|
||||
TOK_NEQ,
|
||||
TOK_STRICT_NEQ,
|
||||
TOK_LAND,
|
||||
TOK_LOR,
|
||||
TOK_POW,
|
||||
TOK_ARROW,
|
||||
TOK_ERROR,
|
||||
TOK_PRIVATE_NAME,
|
||||
TOK_EOF,
|
||||
/* whitespace/comment tokens for tokenizer */
|
||||
TOK_COMMENT,
|
||||
TOK_NEWLINE,
|
||||
TOK_SPACE,
|
||||
/* keywords: WARNING: same order as atoms */
|
||||
TOK_NULL, /* must be first */
|
||||
TOK_FALSE,
|
||||
TOK_TRUE,
|
||||
TOK_IF,
|
||||
TOK_ELSE,
|
||||
TOK_RETURN,
|
||||
TOK_GO,
|
||||
TOK_VAR,
|
||||
TOK_DEF,
|
||||
TOK_THIS,
|
||||
TOK_DELETE,
|
||||
TOK_IN,
|
||||
TOK_DO,
|
||||
TOK_WHILE,
|
||||
TOK_FOR,
|
||||
TOK_BREAK,
|
||||
TOK_CONTINUE,
|
||||
TOK_DISRUPT,
|
||||
TOK_DISRUPTION,
|
||||
TOK_FUNCTION,
|
||||
TOK_DEBUGGER,
|
||||
TOK_WITH,
|
||||
/* FutureReservedWord */
|
||||
TOK_CLASS,
|
||||
TOK_CONST,
|
||||
TOK_ENUM,
|
||||
TOK_EXPORT,
|
||||
TOK_EXTENDS,
|
||||
TOK_IMPORT,
|
||||
TOK_SUPER,
|
||||
/* FutureReservedWords when parsing strict mode code */
|
||||
TOK_IMPLEMENTS,
|
||||
TOK_INTERFACE,
|
||||
TOK_LET,
|
||||
TOK_PRIVATE,
|
||||
TOK_PROTECTED,
|
||||
TOK_PUBLIC,
|
||||
TOK_STATIC,
|
||||
TOK_YIELD,
|
||||
TOK_AWAIT, /* must be last */
|
||||
TOK_OF, /* only used for js_parse_skip_parens_token() */
|
||||
};
|
||||
|
||||
#define TOK_FIRST_KEYWORD TOK_NULL
|
||||
#define TOK_LAST_KEYWORD TOK_AWAIT
|
||||
|
||||
/* unicode code points */
|
||||
#define CP_NBSP 0x00a0
|
||||
#define CP_BOM 0xfeff
|
||||
|
||||
#define CP_LS 0x2028
|
||||
#define CP_PS 0x2029
|
||||
|
||||
|
||||
/* === Line/column cache === */
|
||||
typedef struct {
|
||||
/* last source position */
|
||||
const uint8_t *ptr;
|
||||
int line_num;
|
||||
int col_num;
|
||||
const uint8_t *buf_start;
|
||||
} GetLineColCache;
|
||||
|
||||
|
||||
|
||||
/* === PPretext (parser pretext, system-malloc, used by cell_js.c parser) === */
|
||||
typedef struct PPretext {
|
||||
uint32_t *data;
|
||||
@@ -1730,8 +1435,6 @@ typedef struct PPretext {
|
||||
int cap;
|
||||
} PPretext;
|
||||
|
||||
#define JS_CALL_FLAG_COPY_ARGV (1 << 1)
|
||||
|
||||
extern JSClassID js_class_id_alloc;
|
||||
|
||||
/* === Forward declarations for functions split across modules === */
|
||||
@@ -1739,16 +1442,8 @@ extern JSClassID js_class_id_alloc;
|
||||
/* runtime.c — line/column, GC, and VM dispatch */
|
||||
int ctx_gc (JSContext *ctx, int allow_grow, size_t alloc_size);
|
||||
JSValue JS_CallInternal (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv, int flags);
|
||||
int get_line_col (int *pcol_num, const uint8_t *buf, size_t len);
|
||||
int get_line_col_cached (GetLineColCache *s, int *pcol_num, const uint8_t *ptr);
|
||||
|
||||
/* runtime.c exports */
|
||||
JSValue JS_ThrowStackOverflow (JSContext *ctx);
|
||||
int JS_DefineObjectName (JSContext *ctx, JSValue obj, JSValue name);
|
||||
int JS_DefineObjectNameComputed (JSContext *ctx, JSValue obj, JSValue str);
|
||||
int js_method_set_properties (JSContext *ctx, JSValue func_obj, JSValue name, int flags, JSValue home_obj);
|
||||
JSValue JS_GetPropertyValue (JSContext *ctx, JSValue this_obj, JSValue prop);
|
||||
__exception int JS_CopyDataProperties (JSContext *ctx, JSValue target, JSValue source, JSValue excluded, BOOL setprop);
|
||||
int js_string_compare_value (JSContext *ctx, JSValue op1, JSValue op2, BOOL eq_only);
|
||||
int js_string_compare_value_nocase (JSContext *ctx, JSValue op1, JSValue op2);
|
||||
JSValue js_regexp_constructor (JSContext *ctx, JSValue this_val, int argc, JSValue *argv);
|
||||
@@ -1757,11 +1452,6 @@ int JS_HasPropertyKey (JSContext *ctx, JSValue obj, JSValue key);
|
||||
void *js_realloc_rt (void *ptr, size_t size);
|
||||
char *js_strdup_rt (const char *str);
|
||||
JSValue JS_ConcatString (JSContext *ctx, JSValue op1, JSValue op2);
|
||||
__exception int js_post_inc_slow (JSContext *ctx, JSValue *sp, OPCodeEnum op);
|
||||
no_inline int js_not_slow (JSContext *ctx, JSValue *sp);
|
||||
no_inline int js_relational_slow (JSContext *ctx, JSValue *sp, OPCodeEnum op);
|
||||
__exception int js_operator_in (JSContext *ctx, JSValue *sp);
|
||||
__exception int js_operator_delete (JSContext *ctx, JSValue *sp);
|
||||
JSText *pretext_init (JSContext *ctx, int capacity);
|
||||
JSText *pretext_putc (JSContext *ctx, JSText *s, uint32_t c);
|
||||
JSText *pretext_concat_value (JSContext *ctx, JSText *s, JSValue v);
|
||||
@@ -1787,19 +1477,6 @@ uint64_t get_text_hash (JSText *text);
|
||||
void pack_utf32_to_words (const uint32_t *utf32, uint32_t len, uint64_t *packed);
|
||||
int text_equal (JSText *a, const uint64_t *packed_b, uint32_t len_b);
|
||||
|
||||
static inline JSValue *get_upvalue_ptr (JSValue frame_val, int depth, int slot) {
|
||||
if (JS_IsNull(frame_val)) return NULL;
|
||||
JSFrame *frame = JS_VALUE_GET_FRAME(frame_val);
|
||||
while (depth > 0) {
|
||||
JSFunction *fn = JS_VALUE_GET_FUNCTION(frame->function);
|
||||
frame_val = fn->u.func.outer_frame;
|
||||
if (JS_IsNull(frame_val)) return NULL;
|
||||
frame = JS_VALUE_GET_FRAME(frame_val);
|
||||
depth--;
|
||||
}
|
||||
return &frame->slots[slot];
|
||||
}
|
||||
|
||||
void print_backtrace (JSContext *ctx, const char *filename, int line_num, int col_num);
|
||||
JSValue JS_ThrowError2 (JSContext *ctx, JSErrorEnum error_num, const char *fmt, va_list ap, BOOL add_backtrace);
|
||||
JSValue gc_copy_value (JSContext *ctx, JSValue v, uint8_t *from_base, uint8_t *from_end, uint8_t *to_base, uint8_t **to_free, uint8_t *to_end);
|
||||
@@ -1811,10 +1488,6 @@ PPretext *ppretext_append_jsvalue (PPretext *p, JSValue str);
|
||||
PPretext *ppretext_append_int (PPretext *p, int n);
|
||||
JSValue js_atof (JSContext *ctx, const char *str, const char **pp, int radix, int flags);
|
||||
|
||||
/* Defines from runtime section needed by cell_js.c */
|
||||
#define DEFINE_GLOBAL_LEX_VAR (1 << 7)
|
||||
#define DEFINE_GLOBAL_FUNC_VAR (1 << 6)
|
||||
|
||||
#define ATOD_INT_ONLY (1 << 0)
|
||||
/* accept Oo and Ob prefixes in addition to 0x prefix if radix = 0 */
|
||||
#define ATOD_ACCEPT_BIN_OCT (1 << 2)
|
||||
@@ -1831,14 +1504,6 @@ JSValue js_atof (JSContext *ctx, const char *str, const char **pp, int radix, in
|
||||
/* accept -0x1 */
|
||||
#define ATOD_ACCEPT_PREFIX_AFTER_SIGN (1 << 10)
|
||||
|
||||
#define GLOBAL_VAR_OFFSET 0x40000000
|
||||
#define ARGUMENT_VAR_OFFSET 0x20000000
|
||||
|
||||
/* Inline functions from runtime section needed by cell_js.c */
|
||||
static inline void js_dbuf_init (JSContext *ctx, DynBuf *s) {
|
||||
dbuf_init2 (s, ctx->rt, NULL);
|
||||
}
|
||||
|
||||
static inline int to_digit (int c) {
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
else if (c >= 'A' && c <= 'Z') return c - 'A' + 10;
|
||||
@@ -1846,54 +1511,6 @@ static inline int to_digit (int c) {
|
||||
else return 36;
|
||||
}
|
||||
|
||||
static inline void dbuf_put_leb128 (DynBuf *s, uint32_t v) {
|
||||
uint32_t a;
|
||||
for (;;) {
|
||||
a = v & 0x7f;
|
||||
v >>= 7;
|
||||
if (v != 0) {
|
||||
dbuf_putc (s, a | 0x80);
|
||||
} else {
|
||||
dbuf_putc (s, a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dbuf_put_sleb128 (DynBuf *s, int32_t v1) {
|
||||
uint32_t v = v1;
|
||||
dbuf_put_leb128 (s, (2 * v) ^ -(v >> 31));
|
||||
}
|
||||
|
||||
static inline int get_leb128 (uint32_t *pval, const uint8_t *buf, const uint8_t *buf_end) {
|
||||
const uint8_t *ptr = buf;
|
||||
uint32_t v, a, i;
|
||||
v = 0;
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (unlikely (ptr >= buf_end)) break;
|
||||
a = *ptr++;
|
||||
v |= (a & 0x7f) << (i * 7);
|
||||
if (!(a & 0x80)) {
|
||||
*pval = v;
|
||||
return ptr - buf;
|
||||
}
|
||||
}
|
||||
*pval = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int get_sleb128 (int32_t *pval, const uint8_t *buf, const uint8_t *buf_end) {
|
||||
int ret;
|
||||
uint32_t val;
|
||||
ret = get_leb128 (&val, buf, buf_end);
|
||||
if (ret < 0) {
|
||||
*pval = 0;
|
||||
return -1;
|
||||
}
|
||||
*pval = (val >> 1) ^ -(val & 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
no_inline int js_realloc_array (JSContext *ctx, void **parray, int elem_size, int *psize, int req_size);
|
||||
static inline int js_resize_array (JSContext *ctx, void **parray, int elem_size, int *psize, int req_size) {
|
||||
if (unlikely (req_size > *psize))
|
||||
@@ -1908,7 +1525,6 @@ JSValue js_key_from_string (JSContext *ctx, JSValue val);
|
||||
/* mach.c exports */
|
||||
JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code, JSValue this_obj, int argc, JSValue *argv, JSValue env, JSValue outer_frame);
|
||||
JSFrameRegister *alloc_frame_register(JSContext *ctx, int slot_count);
|
||||
cJSON *mach_find_scope_record(cJSON *scopes, int function_nr);
|
||||
int reg_vm_check_interrupt(JSContext *ctx);
|
||||
|
||||
|
||||
|
||||
@@ -92,7 +92,6 @@ static inline int objhdr_s (objhdr_t h) { return (h & OBJHDR_S_MASK) != 0; }
|
||||
typedef struct JSRuntime JSRuntime; // the entire VM
|
||||
typedef struct JSContext JSContext; // Each actor
|
||||
typedef struct JSClass JSClass;
|
||||
typedef struct JSFunctionBytecode JSFunctionBytecode;
|
||||
typedef uint32_t JSClassID;
|
||||
|
||||
/* Forward declaration - JSGCRef moved after JSValue definition */
|
||||
@@ -284,13 +283,6 @@ JS_IsShortFloat (JSValue v) {
|
||||
#define JS_TRUE ((JSValue)(JS_TAG_BOOL | (1 << 5)))
|
||||
#define JS_EXCEPTION ((JSValue)JS_TAG_EXCEPTION)
|
||||
|
||||
/* flags for object properties - simplified model:
|
||||
- No per-property writable/configurable (use stone() for immutability)
|
||||
- Text keys are enumerable, object keys are not */
|
||||
#define JS_PROP_TMASK (3 << 4) /* mask for NORMAL, VARREF */
|
||||
#define JS_PROP_NORMAL (0 << 4)
|
||||
#define JS_PROP_VARREF (2 << 4) /* used internally for closures */
|
||||
|
||||
#ifndef JS_DEFAULT_STACK_SIZE
|
||||
#define JS_DEFAULT_STACK_SIZE (1024 * 1024)
|
||||
#endif
|
||||
@@ -313,16 +305,10 @@ JSRuntime *JS_NewRuntime (void);
|
||||
void JS_SetMemoryLimit (JSRuntime *rt, size_t limit);
|
||||
/* use 0 to disable maximum stack size check */
|
||||
void JS_SetMaxStackSize (JSContext *ctx, size_t stack_size);
|
||||
/* should be called when changing thread to update the stack top value
|
||||
used to check stack overflow. */
|
||||
void JS_UpdateStackTop (JSContext *ctx);
|
||||
void JS_FreeRuntime (JSRuntime *rt);
|
||||
JS_BOOL JS_IsLiveObject (JSRuntime *rt, JSValue obj);
|
||||
|
||||
JSContext *JS_NewContext (JSRuntime *rt);
|
||||
void JS_FreeContext (JSContext *s);
|
||||
JSContext *JS_DupContext (JSContext *ctx);
|
||||
JSContext *JS_GetContext (JSRuntime *rt);
|
||||
void *JS_GetContextOpaque (JSContext *ctx);
|
||||
void JS_SetContextOpaque (JSContext *ctx, void *opaque);
|
||||
JSRuntime *JS_GetRuntime (JSContext *ctx);
|
||||
@@ -331,24 +317,6 @@ JSValue JS_GetClassProto (JSContext *ctx, JSClassID class_id);
|
||||
|
||||
JSContext *JS_NewContextWithHeapSize (JSRuntime *rt, size_t heap_size);
|
||||
|
||||
typedef struct JSMemoryUsage {
|
||||
int64_t malloc_size, malloc_limit, memory_used_size;
|
||||
int64_t malloc_count;
|
||||
int64_t memory_used_count;
|
||||
int64_t str_count, str_size;
|
||||
int64_t obj_count, obj_size;
|
||||
int64_t prop_count, prop_size;
|
||||
int64_t shape_count, shape_size;
|
||||
int64_t js_func_count, js_func_size, js_func_code_size;
|
||||
int64_t js_func_pc2line_count, js_func_pc2line_size;
|
||||
int64_t c_func_count, array_count;
|
||||
int64_t fast_array_count, fast_array_elements;
|
||||
int64_t binary_object_count, binary_object_size;
|
||||
} JSMemoryUsage;
|
||||
|
||||
void JS_ComputeMemoryUsage (JSRuntime *rt, JSMemoryUsage *s);
|
||||
void JS_DumpMemoryUsage (FILE *fp, const JSMemoryUsage *s, JSRuntime *rt);
|
||||
|
||||
typedef void JSClassFinalizer (JSRuntime *rt, JSValue val);
|
||||
typedef JSValue JSClassCall (JSContext *ctx, JSValue func_obj,
|
||||
JSValue this_val, int argc,
|
||||
@@ -523,7 +491,6 @@ static inline JSValue JS_NewString (JSContext *ctx, const char *str) {
|
||||
return JS_NewStringLen (ctx, str, strlen (str));
|
||||
}
|
||||
JSValue JS_ToString (JSContext *ctx, JSValue val);
|
||||
JSValue JS_ToPropertyKey (JSContext *ctx, JSValue val);
|
||||
const char *JS_ToCStringLen2 (JSContext *ctx, size_t *plen, JSValue val1, JS_BOOL cesu8);
|
||||
static inline const char * JS_ToCStringLen (JSContext *ctx, size_t *plen, JSValue val1) {
|
||||
return JS_ToCStringLen2 (ctx, plen, val1, 0);
|
||||
@@ -946,17 +913,6 @@ typedef void (*js_hook) (JSContext *, int type, js_debug *dbg, void *user);
|
||||
#define JS_HOOK_GC 8
|
||||
void js_debug_sethook (JSContext *ctx, js_hook, int type, void *user);
|
||||
|
||||
uint32_t js_debugger_stack_depth (JSContext *ctx);
|
||||
JSValue js_debugger_backtrace_fns (JSContext *ctx);
|
||||
JSValue js_debugger_closure_variables (JSContext *ctx, JSValue fn);
|
||||
JSValue js_debugger_local_variables (JSContext *ctx, int stack_index);
|
||||
void js_debugger_set_closure_variable (JSContext *js, JSValue fn,
|
||||
JSValue var_name, JSValue val);
|
||||
JSValue js_debugger_build_backtrace (JSContext *ctx);
|
||||
JSValue js_debugger_fn_info (JSContext *ctx, JSValue fn);
|
||||
JSValue js_debugger_fn_bytecode (JSContext *js, JSValue fn);
|
||||
void *js_debugger_val_address (JSContext *js, JSValue val);
|
||||
|
||||
/* Memory allocation functions (bump allocator) */
|
||||
void *js_malloc (JSContext *ctx, size_t size);
|
||||
void *js_mallocz (JSContext *ctx, size_t size);
|
||||
@@ -974,12 +930,6 @@ struct cJSON;
|
||||
/* Compiled bytecode (context-free, serializable) */
|
||||
typedef struct MachCode MachCode;
|
||||
|
||||
/* Compile AST cJSON tree to context-free MachCode. */
|
||||
MachCode *JS_CompileMachTree(struct cJSON *ast);
|
||||
|
||||
/* Compile AST JSON string to context-free MachCode. */
|
||||
MachCode *JS_CompileMach(const char *ast_json);
|
||||
|
||||
/* Free a compiled MachCode tree. */
|
||||
void JS_FreeMachCode(MachCode *mc);
|
||||
|
||||
|
||||
569
source/runtime.c
569
source/runtime.c
@@ -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;
|
||||
@@ -6563,22 +6338,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;
|
||||
}
|
||||
@@ -7628,259 +7394,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
|
||||
* ----------------------------------------------------------------------------
|
||||
@@ -11109,78 +10622,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
|
||||
|
||||
Reference in New Issue
Block a user