initial attempt change functions to intrinsic type
This commit is contained in:
@@ -162,6 +162,10 @@ globalThis.log = function(name, args) {
|
||||
}
|
||||
}
|
||||
|
||||
log.console(
|
||||
'hello'
|
||||
)
|
||||
|
||||
function disrupt(err)
|
||||
{
|
||||
if (is_function(err.toString)) {
|
||||
|
||||
525
source/quickjs.c
525
source/quickjs.c
@@ -367,6 +367,7 @@ typedef enum {
|
||||
JS_GC_OBJ_TYPE_VAR_REF,
|
||||
JS_GC_OBJ_TYPE_JS_CONTEXT,
|
||||
JS_GC_OBJ_TYPE_ARRAY,
|
||||
JS_GC_OBJ_TYPE_FUNCTION,
|
||||
} JSGCObjectTypeEnum;
|
||||
|
||||
/* header for GC objects. GC objects are C data structures with a
|
||||
@@ -679,11 +680,37 @@ typedef struct JSRecord {
|
||||
|
||||
} JSRecord;
|
||||
|
||||
typedef struct JSFunction {
|
||||
typedef enum {
|
||||
JS_FUNC_KIND_C,
|
||||
JS_FUNC_KIND_BYTECODE,
|
||||
JS_FUNC_KIND_BOUND,
|
||||
JS_FUNC_KIND_C_DATA,
|
||||
} JSFunctionKind;
|
||||
|
||||
typedef struct JSFunction {
|
||||
JSGCObjectHeader header; /* must come first */
|
||||
JSAtom name;
|
||||
uint8_t length;
|
||||
uint8_t kind;
|
||||
uint8_t free_mark : 1;
|
||||
union {
|
||||
struct {
|
||||
JSContext *realm;
|
||||
JSCFunctionType c_function;
|
||||
uint8_t cproto;
|
||||
int16_t magic;
|
||||
} cfunc;
|
||||
struct {
|
||||
struct JSFunctionBytecode *function_bytecode;
|
||||
JSVarRef **var_refs;
|
||||
} func;
|
||||
struct JSBoundFunction *bound_function;
|
||||
struct JSCFunctionDataRecord *c_function_data_record;
|
||||
} u;
|
||||
} JSFunction;
|
||||
|
||||
#define JS_VALUE_GET_ARRAY(v) ((JSArray *)JS_VALUE_GET_PTR(v))
|
||||
#define JS_VALUE_GET_FUNCTION(v) ((JSFunction *)JS_VALUE_GET_PTR(v))
|
||||
|
||||
typedef struct JSClosureVar {
|
||||
uint8_t is_local : 1;
|
||||
@@ -1021,6 +1048,16 @@ static void js_bound_function_finalizer(JSRuntime *rt, JSValue val);
|
||||
static void js_bound_function_mark(JSRuntime *rt, JSValueConst val,
|
||||
JS_MarkFunc *mark_func);
|
||||
static void js_regexp_finalizer(JSRuntime *rt, JSValue val);
|
||||
static JSValue js_new_function(JSContext *ctx, JSFunctionKind kind);
|
||||
static void free_function(JSRuntime *rt, JSFunction *func);
|
||||
static void mark_function_children(JSRuntime *rt, JSFunction *func, JS_MarkFunc *mark_func);
|
||||
static void mark_function_children_decref(JSRuntime *rt, JSFunction *func);
|
||||
#ifdef RC_TRACE
|
||||
static void gc_decref_child_dbg(JSRuntime *rt, JSGCObjectHeader *parent,
|
||||
const char *edge, JSAtom atom, int prop_index,
|
||||
JSGCObjectHeader *child,
|
||||
const char *file, int line);
|
||||
#endif
|
||||
|
||||
int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValue val);
|
||||
|
||||
@@ -4907,25 +4944,19 @@ static BOOL js_class_has_bytecode(JSClassID class_id)
|
||||
/* Check if a value is a function that uses proxy-call syntax (fn.a -> fn("a")) */
|
||||
static BOOL js_is_proxy_callable(JSValueConst v)
|
||||
{
|
||||
JSObject *p;
|
||||
if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT)
|
||||
return FALSE;
|
||||
p = JS_VALUE_GET_OBJ(v);
|
||||
return p->class_id == JS_CLASS_BYTECODE_FUNCTION ||
|
||||
p->class_id == JS_CLASS_C_FUNCTION ||
|
||||
p->class_id == JS_CLASS_C_FUNCTION_DATA;
|
||||
return JS_VALUE_GET_TAG(v) == JS_TAG_FUNCTION;
|
||||
}
|
||||
|
||||
/* return NULL without exception if not a function or no bytecode */
|
||||
static JSFunctionBytecode *JS_GetFunctionBytecode(JSValueConst val)
|
||||
{
|
||||
JSObject *p;
|
||||
if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
|
||||
JSFunction *f;
|
||||
if (JS_VALUE_GET_TAG(val) != JS_TAG_FUNCTION)
|
||||
return NULL;
|
||||
p = JS_VALUE_GET_OBJ(val);
|
||||
if (!js_class_has_bytecode(p->class_id))
|
||||
f = JS_VALUE_GET_FUNCTION(val);
|
||||
if (f->kind != JS_FUNC_KIND_BYTECODE)
|
||||
return NULL;
|
||||
return p->u.func.function_bytecode;
|
||||
return f->u.func.function_bytecode;
|
||||
}
|
||||
|
||||
static JSValue js_get_function_name(JSContext *ctx, JSAtom name)
|
||||
@@ -4963,18 +4994,20 @@ static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,
|
||||
JSValueConst proto_val)
|
||||
{
|
||||
JSValue func_obj;
|
||||
JSObject *p;
|
||||
JSFunction *f;
|
||||
JSAtom name_atom;
|
||||
|
||||
func_obj = JS_NewObjectProtoClass(ctx, proto_val, JS_CLASS_C_FUNCTION);
|
||||
(void)proto_val; /* unused - intrinsic functions have no prototype */
|
||||
|
||||
func_obj = js_new_function(ctx, JS_FUNC_KIND_C);
|
||||
if (JS_IsException(func_obj))
|
||||
return func_obj;
|
||||
p = JS_VALUE_GET_OBJ(func_obj);
|
||||
p->u.cfunc.realm = JS_DupContext(ctx);
|
||||
p->u.cfunc.c_function.generic = func;
|
||||
p->u.cfunc.length = length;
|
||||
p->u.cfunc.cproto = cproto;
|
||||
p->u.cfunc.magic = magic;
|
||||
f = JS_VALUE_GET_FUNCTION(func_obj);
|
||||
f->u.cfunc.realm = JS_DupContext(ctx);
|
||||
f->u.cfunc.c_function.generic = func;
|
||||
f->u.cfunc.cproto = cproto;
|
||||
f->u.cfunc.magic = magic;
|
||||
f->length = length;
|
||||
if (!name)
|
||||
name = "";
|
||||
name_atom = JS_NewAtom(ctx, name);
|
||||
@@ -4982,8 +5015,7 @@ static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,
|
||||
JS_FreeValue(ctx, func_obj);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
js_function_set_properties(ctx, func_obj, name_atom, length);
|
||||
JS_FreeAtom(ctx, name_atom);
|
||||
f->name = name_atom;
|
||||
return func_obj;
|
||||
}
|
||||
|
||||
@@ -5034,10 +5066,13 @@ static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,
|
||||
JSValueConst this_val,
|
||||
int argc, JSValueConst *argv, int flags)
|
||||
{
|
||||
JSCFunctionDataRecord *s = JS_GetOpaque(func_obj, JS_CLASS_C_FUNCTION_DATA);
|
||||
JSFunction *f = JS_VALUE_GET_FUNCTION(func_obj);
|
||||
JSCFunctionDataRecord *s = f->u.c_function_data_record;
|
||||
JSValueConst *arg_buf;
|
||||
int i;
|
||||
|
||||
(void)flags; /* unused */
|
||||
|
||||
/* XXX: could add the function on the stack for debug */
|
||||
if (unlikely(argc < s->length)) {
|
||||
arg_buf = alloca(sizeof(arg_buf[0]) * s->length);
|
||||
@@ -5058,10 +5093,10 @@ JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
|
||||
{
|
||||
JSCFunctionDataRecord *s;
|
||||
JSValue func_obj;
|
||||
JSFunction *f;
|
||||
int i;
|
||||
|
||||
func_obj = JS_NewObjectProtoClass(ctx, ctx->function_proto,
|
||||
JS_CLASS_C_FUNCTION_DATA);
|
||||
func_obj = js_new_function(ctx, JS_FUNC_KIND_C_DATA);
|
||||
if (JS_IsException(func_obj))
|
||||
return func_obj;
|
||||
s = js_malloc(ctx, sizeof(*s) + data_len * sizeof(JSValue));
|
||||
@@ -5075,9 +5110,10 @@ JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
|
||||
s->magic = magic;
|
||||
for(i = 0; i < data_len; i++)
|
||||
s->data[i] = JS_DupValue(ctx, data[i]);
|
||||
JS_SetOpaque(func_obj, s);
|
||||
js_function_set_properties(ctx, func_obj,
|
||||
JS_ATOM_empty_string, length);
|
||||
f = JS_VALUE_GET_FUNCTION(func_obj);
|
||||
f->u.c_function_data_record = s;
|
||||
f->length = length;
|
||||
f->name = JS_ATOM_empty_string;
|
||||
return func_obj;
|
||||
}
|
||||
|
||||
@@ -5258,6 +5294,187 @@ static void js_c_function_mark(JSRuntime *rt, JSValueConst val,
|
||||
mark_func(rt, &p->u.cfunc.realm->header);
|
||||
}
|
||||
|
||||
/* Allocate intrinsic function (JS_TAG_FUNCTION) */
|
||||
static JSValue js_new_function(JSContext *ctx, JSFunctionKind kind)
|
||||
{
|
||||
JSRuntime *rt = ctx->rt;
|
||||
JSFunction *func = js_mallocz(ctx, sizeof(JSFunction));
|
||||
if (!func)
|
||||
return JS_EXCEPTION;
|
||||
func->header.ref_count = 1;
|
||||
func->kind = kind;
|
||||
func->name = JS_ATOM_NULL;
|
||||
func->length = 0;
|
||||
func->free_mark = 0;
|
||||
add_gc_object(rt, &func->header, JS_GC_OBJ_TYPE_FUNCTION);
|
||||
return JS_MKPTR(JS_TAG_FUNCTION, func);
|
||||
}
|
||||
|
||||
/* Free intrinsic function (JS_TAG_FUNCTION) */
|
||||
static void free_function(JSRuntime *rt, JSFunction *func)
|
||||
{
|
||||
assert(func->header.gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION);
|
||||
|
||||
func->free_mark = 1; /* used to tell the function is invalid when
|
||||
freeing cycles */
|
||||
|
||||
JS_FreeAtomRT(rt, func->name);
|
||||
|
||||
switch (func->kind) {
|
||||
case JS_FUNC_KIND_C:
|
||||
if (func->u.cfunc.realm)
|
||||
JS_FreeContext(func->u.cfunc.realm);
|
||||
break;
|
||||
case JS_FUNC_KIND_BYTECODE:
|
||||
if (func->u.func.function_bytecode) {
|
||||
JSFunctionBytecode *b = func->u.func.function_bytecode;
|
||||
JSVarRef **var_refs = func->u.func.var_refs;
|
||||
if (var_refs) {
|
||||
for (int i = 0; i < b->closure_var_count; i++)
|
||||
free_var_ref(rt, var_refs[i]);
|
||||
js_free_rt(rt, var_refs);
|
||||
}
|
||||
JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b));
|
||||
}
|
||||
break;
|
||||
case JS_FUNC_KIND_BOUND:
|
||||
if (func->u.bound_function) {
|
||||
JSBoundFunction *bf = func->u.bound_function;
|
||||
JS_FreeValueRT(rt, bf->func_obj);
|
||||
JS_FreeValueRT(rt, bf->this_val);
|
||||
for (int i = 0; i < bf->argc; i++) {
|
||||
JS_FreeValueRT(rt, bf->argv[i]);
|
||||
}
|
||||
js_free_rt(rt, bf);
|
||||
}
|
||||
break;
|
||||
case JS_FUNC_KIND_C_DATA:
|
||||
if (func->u.c_function_data_record) {
|
||||
JSCFunctionDataRecord *s = func->u.c_function_data_record;
|
||||
for (int i = 0; i < s->data_len; i++) {
|
||||
JS_FreeValueRT(rt, s->data[i]);
|
||||
}
|
||||
js_free_rt(rt, s);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
func->u.c_function_data_record = NULL;
|
||||
func->length = 0;
|
||||
func->name = JS_ATOM_NULL;
|
||||
|
||||
remove_gc_object(&func->header);
|
||||
if (func->header.ref_count == 0)
|
||||
js_free_rt(rt, func);
|
||||
else
|
||||
list_add_tail(&func->header.link, &rt->gc_zero_ref_count_list);
|
||||
}
|
||||
|
||||
static void mark_function_children(JSRuntime *rt, JSFunction *func,
|
||||
JS_MarkFunc *mark_func)
|
||||
{
|
||||
switch (func->kind) {
|
||||
case JS_FUNC_KIND_C:
|
||||
if (func->u.cfunc.realm)
|
||||
mark_func(rt, &func->u.cfunc.realm->header);
|
||||
break;
|
||||
case JS_FUNC_KIND_BYTECODE:
|
||||
if (func->u.func.function_bytecode) {
|
||||
JSFunctionBytecode *b = func->u.func.function_bytecode;
|
||||
if (func->u.func.var_refs) {
|
||||
for (int i = 0; i < b->closure_var_count; i++) {
|
||||
JSVarRef *var_ref = func->u.func.var_refs[i];
|
||||
if (var_ref) {
|
||||
mark_func(rt, &var_ref->header);
|
||||
}
|
||||
}
|
||||
}
|
||||
JS_MarkValue(rt, JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b), mark_func);
|
||||
}
|
||||
break;
|
||||
case JS_FUNC_KIND_BOUND:
|
||||
if (func->u.bound_function) {
|
||||
JSBoundFunction *bf = func->u.bound_function;
|
||||
JS_MarkValue(rt, bf->func_obj, mark_func);
|
||||
JS_MarkValue(rt, bf->this_val, mark_func);
|
||||
for (int i = 0; i < bf->argc; i++) {
|
||||
JS_MarkValue(rt, bf->argv[i], mark_func);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case JS_FUNC_KIND_C_DATA:
|
||||
if (func->u.c_function_data_record) {
|
||||
JSCFunctionDataRecord *s = func->u.c_function_data_record;
|
||||
for (int i = 0; i < s->data_len; i++) {
|
||||
JS_MarkValue(rt, s->data[i], mark_func);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void mark_function_children_decref(JSRuntime *rt, JSFunction *func)
|
||||
{
|
||||
switch (func->kind) {
|
||||
case JS_FUNC_KIND_C:
|
||||
if (func->u.cfunc.realm) {
|
||||
#ifdef RC_TRACE
|
||||
gc_decref_child_dbg(rt, &func->header, "func.realm", 0, -1,
|
||||
&func->u.cfunc.realm->header,
|
||||
__FILE__, __LINE__);
|
||||
#else
|
||||
gc_decref_child(rt, &func->u.cfunc.realm->header);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case JS_FUNC_KIND_BYTECODE:
|
||||
if (func->u.func.function_bytecode) {
|
||||
JSFunctionBytecode *b = func->u.func.function_bytecode;
|
||||
if (func->u.func.var_refs) {
|
||||
for (int i = 0; i < b->closure_var_count; i++) {
|
||||
JSVarRef *var_ref = func->u.func.var_refs[i];
|
||||
if (var_ref) {
|
||||
#ifdef RC_TRACE
|
||||
gc_decref_child_dbg(rt, &func->header, "func.var_ref",
|
||||
0, i, &var_ref->header,
|
||||
__FILE__, __LINE__);
|
||||
#else
|
||||
gc_decref_child(rt, &var_ref->header);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
JS_MarkValueEdge(rt, JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b), &func->header,
|
||||
"func.bytecode");
|
||||
}
|
||||
break;
|
||||
case JS_FUNC_KIND_BOUND:
|
||||
if (func->u.bound_function) {
|
||||
JSBoundFunction *bf = func->u.bound_function;
|
||||
JS_MarkValueEdge(rt, bf->func_obj, &func->header, "func.bound.func_obj");
|
||||
JS_MarkValueEdge(rt, bf->this_val, &func->header, "func.bound.this_val");
|
||||
for (int i = 0; i < bf->argc; i++) {
|
||||
JS_MarkValueEdge(rt, bf->argv[i], &func->header, "func.bound.argv");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case JS_FUNC_KIND_C_DATA:
|
||||
if (func->u.c_function_data_record) {
|
||||
JSCFunctionDataRecord *s = func->u.c_function_data_record;
|
||||
for (int i = 0; i < s->data_len; i++) {
|
||||
JS_MarkValueEdge(rt, s->data[i], &func->header, "func.cdata");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val)
|
||||
{
|
||||
JSObject *p = JS_VALUE_GET_OBJ(val);
|
||||
@@ -5396,6 +5613,9 @@ static void free_gc_object(JSRuntime *rt, JSGCObjectHeader *gp)
|
||||
case JS_GC_OBJ_TYPE_ARRAY:
|
||||
free_array(rt, (JSArray *)gp);
|
||||
break;
|
||||
case JS_GC_OBJ_TYPE_FUNCTION:
|
||||
free_function(rt, (JSFunction *)gp);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
@@ -5461,6 +5681,7 @@ void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
|
||||
case JS_TAG_ARRAY:
|
||||
case JS_TAG_OBJECT:
|
||||
case JS_TAG_FUNCTION_BYTECODE:
|
||||
case JS_TAG_FUNCTION:
|
||||
{
|
||||
JSGCObjectHeader *p = JS_VALUE_GET_PTR(v);
|
||||
if (rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES) {
|
||||
@@ -5511,6 +5732,7 @@ void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func)
|
||||
case JS_TAG_ARRAY:
|
||||
case JS_TAG_OBJECT:
|
||||
case JS_TAG_FUNCTION_BYTECODE:
|
||||
case JS_TAG_FUNCTION:
|
||||
mark_func(rt, JS_VALUE_GET_PTR(val));
|
||||
break;
|
||||
default:
|
||||
@@ -5580,6 +5802,12 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp,
|
||||
mark_func(rt, &b->realm->header);
|
||||
}
|
||||
break;
|
||||
case JS_GC_OBJ_TYPE_FUNCTION:
|
||||
{
|
||||
JSFunction *func = (JSFunction *)gp;
|
||||
mark_function_children(rt, func, mark_func);
|
||||
}
|
||||
break;
|
||||
case JS_GC_OBJ_TYPE_VAR_REF:
|
||||
{
|
||||
JSVarRef *var_ref = (JSVarRef *)gp;
|
||||
@@ -5690,6 +5918,7 @@ static inline void JS_MarkValueEdgeEx(JSRuntime *rt, JSValueConst val,
|
||||
case JS_TAG_ARRAY:
|
||||
case JS_TAG_OBJECT:
|
||||
case JS_TAG_FUNCTION_BYTECODE:
|
||||
case JS_TAG_FUNCTION:
|
||||
{
|
||||
JSGCObjectHeader *child = JS_VALUE_GET_PTR(val);
|
||||
#ifdef RC_TRACE
|
||||
@@ -5808,6 +6037,12 @@ static void mark_children_decref(JSRuntime *rt, JSGCObjectHeader *gp)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case JS_GC_OBJ_TYPE_FUNCTION:
|
||||
{
|
||||
JSFunction *func = (JSFunction *)gp;
|
||||
mark_function_children_decref(rt, func);
|
||||
}
|
||||
break;
|
||||
case JS_GC_OBJ_TYPE_VAR_REF:
|
||||
{
|
||||
JSVarRef *var_ref = (JSVarRef *)gp;
|
||||
@@ -5935,6 +6170,7 @@ static void gc_free_cycles(JSRuntime *rt)
|
||||
case JS_GC_OBJ_TYPE_JS_OBJECT:
|
||||
case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:
|
||||
case JS_GC_OBJ_TYPE_ARRAY:
|
||||
case JS_GC_OBJ_TYPE_FUNCTION:
|
||||
#ifdef DUMP_GC_FREE
|
||||
if (!header_done) {
|
||||
printf("Freeing cycles:\n");
|
||||
@@ -5957,7 +6193,8 @@ static void gc_free_cycles(JSRuntime *rt)
|
||||
p = list_entry(el, JSGCObjectHeader, link);
|
||||
assert(p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT ||
|
||||
p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE ||
|
||||
p->gc_obj_type == JS_GC_OBJ_TYPE_ARRAY);
|
||||
p->gc_obj_type == JS_GC_OBJ_TYPE_ARRAY ||
|
||||
p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION);
|
||||
js_free_rt(rt, p);
|
||||
}
|
||||
|
||||
@@ -6612,13 +6849,14 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
|
||||
dbuf_printf(&dbuf, " at %s", str1);
|
||||
JS_FreeCString(ctx, func_name_str);
|
||||
|
||||
p = JS_VALUE_GET_OBJ(sf->cur_func);
|
||||
if (js_class_has_bytecode(p->class_id)) {
|
||||
if (JS_VALUE_GET_TAG(sf->cur_func) == JS_TAG_FUNCTION) {
|
||||
JSFunction *fn = JS_VALUE_GET_FUNCTION(sf->cur_func);
|
||||
if (fn->kind == JS_FUNC_KIND_BYTECODE) {
|
||||
JSFunctionBytecode *b;
|
||||
const char *atom_str;
|
||||
int line_num1, col_num1;
|
||||
|
||||
b = p->u.func.function_bytecode;
|
||||
b = fn->u.func.function_bytecode;
|
||||
if (b->has_debug) {
|
||||
line_num1 = find_line_num(ctx, b,
|
||||
sf->cur_pc - b->byte_code_buf - 1, &col_num1);
|
||||
@@ -6633,6 +6871,9 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
|
||||
} else {
|
||||
dbuf_printf(&dbuf, " (native)");
|
||||
}
|
||||
} else {
|
||||
dbuf_printf(&dbuf, " (native)");
|
||||
}
|
||||
dbuf_putc(&dbuf, '\n');
|
||||
}
|
||||
dbuf_putc(&dbuf, '\0');
|
||||
@@ -7953,26 +8194,19 @@ int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop)
|
||||
|
||||
BOOL JS_IsFunction(JSContext *ctx, JSValueConst val)
|
||||
{
|
||||
JSObject *p;
|
||||
if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
|
||||
return FALSE;
|
||||
p = JS_VALUE_GET_OBJ(val);
|
||||
switch(p->class_id) {
|
||||
case JS_CLASS_BYTECODE_FUNCTION:
|
||||
return TRUE;
|
||||
default:
|
||||
return (ctx->rt->class_array[p->class_id].call != NULL);
|
||||
}
|
||||
(void)ctx; /* unused */
|
||||
return JS_VALUE_GET_TAG(val) == JS_TAG_FUNCTION;
|
||||
}
|
||||
|
||||
BOOL JS_IsCFunction(JSContext *ctx, JSValueConst val, JSCFunction *func, int magic)
|
||||
{
|
||||
JSObject *p;
|
||||
if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
|
||||
JSFunction *f;
|
||||
(void)ctx; /* unused */
|
||||
if (JS_VALUE_GET_TAG(val) != JS_TAG_FUNCTION)
|
||||
return FALSE;
|
||||
p = JS_VALUE_GET_OBJ(val);
|
||||
if (p->class_id == JS_CLASS_C_FUNCTION)
|
||||
return (p->u.cfunc.c_function.generic == func && p->u.cfunc.magic == magic);
|
||||
f = JS_VALUE_GET_FUNCTION(val);
|
||||
if (f->kind == JS_FUNC_KIND_C)
|
||||
return (f->u.cfunc.c_function.generic == func && f->u.cfunc.magic == magic);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
@@ -9276,6 +9510,23 @@ static void js_print_value(JSPrintValueState *s, JSValueConst val)
|
||||
js_putc(s, ']');
|
||||
}
|
||||
break;
|
||||
case JS_TAG_FUNCTION:
|
||||
{
|
||||
JSFunction *f = JS_VALUE_GET_FUNCTION(val);
|
||||
js_puts(s, "[Function");
|
||||
if (f->name != JS_ATOM_NULL) {
|
||||
js_putc(s, ' ');
|
||||
js_print_atom(s, f->name);
|
||||
} else if (f->kind == JS_FUNC_KIND_BYTECODE && f->u.func.function_bytecode) {
|
||||
JSAtom name = f->u.func.function_bytecode->func_name;
|
||||
if (name != JS_ATOM_NULL) {
|
||||
js_putc(s, ' ');
|
||||
js_print_atom(s, name);
|
||||
}
|
||||
}
|
||||
js_putc(s, ']');
|
||||
}
|
||||
break;
|
||||
case JS_TAG_OBJECT:
|
||||
{
|
||||
JSObject *p = JS_VALUE_GET_OBJ(val);
|
||||
@@ -10085,18 +10336,18 @@ static JSValue js_closure2(JSContext *ctx, JSValue func_obj,
|
||||
JSVarRef **cur_var_refs,
|
||||
JSStackFrame *sf)
|
||||
{
|
||||
JSObject *p;
|
||||
JSFunction *f;
|
||||
JSVarRef **var_refs;
|
||||
int i;
|
||||
|
||||
p = JS_VALUE_GET_OBJ(func_obj);
|
||||
p->u.func.function_bytecode = b;
|
||||
p->u.func.var_refs = NULL;
|
||||
f = JS_VALUE_GET_FUNCTION(func_obj);
|
||||
f->u.func.function_bytecode = b;
|
||||
f->u.func.var_refs = NULL;
|
||||
if (b->closure_var_count) {
|
||||
var_refs = js_mallocz(ctx, sizeof(var_refs[0]) * b->closure_var_count);
|
||||
if (!var_refs)
|
||||
goto fail;
|
||||
p->u.func.var_refs = var_refs;
|
||||
f->u.func.var_refs = var_refs;
|
||||
for(i = 0; i < b->closure_var_count; i++) {
|
||||
JSClosureVar *cv = &b->closure_var[i];
|
||||
JSVarRef *var_ref;
|
||||
@@ -10125,10 +10376,11 @@ static JSValue js_closure(JSContext *ctx, JSValue bfunc,
|
||||
{
|
||||
JSFunctionBytecode *b;
|
||||
JSValue func_obj;
|
||||
JSFunction *f;
|
||||
JSAtom name_atom;
|
||||
|
||||
b = JS_VALUE_GET_PTR(bfunc);
|
||||
func_obj = JS_NewObjectClass(ctx, JS_CLASS_BYTECODE_FUNCTION);
|
||||
func_obj = js_new_function(ctx, JS_FUNC_KIND_BYTECODE);
|
||||
if (JS_IsException(func_obj)) {
|
||||
JS_FreeValue(ctx, bfunc);
|
||||
return JS_EXCEPTION;
|
||||
@@ -10138,11 +10390,12 @@ static JSValue js_closure(JSContext *ctx, JSValue bfunc,
|
||||
/* bfunc has been freed */
|
||||
goto fail;
|
||||
}
|
||||
f = JS_VALUE_GET_FUNCTION(func_obj);
|
||||
name_atom = b->func_name;
|
||||
if (name_atom == JS_ATOM_NULL)
|
||||
name_atom = JS_ATOM_empty_string;
|
||||
js_function_set_properties(ctx, func_obj, name_atom,
|
||||
b->defined_arg_count);
|
||||
f->name = JS_DupAtom(ctx, name_atom);
|
||||
f->length = b->defined_arg_count;
|
||||
return func_obj;
|
||||
fail:
|
||||
/* bfunc is freed when func_obj is freed */
|
||||
@@ -10194,16 +10447,17 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
|
||||
{
|
||||
JSRuntime *rt = ctx->rt;
|
||||
JSCFunctionType func;
|
||||
JSObject *p;
|
||||
JSFunction *f;
|
||||
JSStackFrame sf_s, *sf = &sf_s, *prev_sf;
|
||||
JSValue ret_val;
|
||||
JSValueConst *arg_buf;
|
||||
int arg_count, i;
|
||||
JSCFunctionEnum cproto;
|
||||
|
||||
p = JS_VALUE_GET_OBJ(func_obj);
|
||||
cproto = p->u.cfunc.cproto;
|
||||
arg_count = p->u.cfunc.length;
|
||||
(void)flags; /* unused */
|
||||
f = JS_VALUE_GET_FUNCTION(func_obj);
|
||||
cproto = f->u.cfunc.cproto;
|
||||
arg_count = f->length;
|
||||
|
||||
/* better to always check stack overflow */
|
||||
if (js_check_stack_overflow(rt, sizeof(arg_buf[0]) * arg_count))
|
||||
@@ -10212,7 +10466,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
|
||||
prev_sf = rt->current_stack_frame;
|
||||
sf->prev_frame = prev_sf;
|
||||
rt->current_stack_frame = sf;
|
||||
ctx = p->u.cfunc.realm; /* change the current realm */
|
||||
ctx = f->u.cfunc.realm; /* change the current realm */
|
||||
sf->js_mode = 0;
|
||||
sf->cur_func = (JSValue)func_obj;
|
||||
sf->arg_count = argc;
|
||||
@@ -10229,7 +10483,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
|
||||
}
|
||||
sf->arg_buf = (JSValue*)arg_buf;
|
||||
|
||||
func = p->u.cfunc.c_function;
|
||||
func = f->u.cfunc.c_function;
|
||||
|
||||
if (unlikely(ctx->trace_hook) && (ctx->trace_type & JS_HOOK_CALL)) {
|
||||
js_debug dbg = {0};
|
||||
@@ -10244,7 +10498,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
|
||||
break;
|
||||
case JS_CFUNC_generic_magic:
|
||||
ret_val = func.generic_magic(ctx, this_obj, argc, arg_buf,
|
||||
p->u.cfunc.magic);
|
||||
f->u.cfunc.magic);
|
||||
break;
|
||||
case JS_CFUNC_f_f:
|
||||
{
|
||||
@@ -10292,13 +10546,15 @@ static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,
|
||||
JSValueConst this_obj,
|
||||
int argc, JSValueConst *argv, int flags)
|
||||
{
|
||||
JSObject *p;
|
||||
JSFunction *f;
|
||||
JSBoundFunction *bf;
|
||||
JSValueConst *arg_buf;
|
||||
int arg_count, i;
|
||||
|
||||
p = JS_VALUE_GET_OBJ(func_obj);
|
||||
bf = p->u.bound_function;
|
||||
(void)this_obj; /* unused - bound function uses bf->this_val */
|
||||
(void)flags; /* unused */
|
||||
f = JS_VALUE_GET_FUNCTION(func_obj);
|
||||
bf = f->u.bound_function;
|
||||
arg_count = bf->argc + argc;
|
||||
if (js_check_stack_overflow(ctx->rt, sizeof(JSValue) * arg_count))
|
||||
return JS_ThrowStackOverflow(ctx);
|
||||
@@ -10400,14 +10656,14 @@ static struct VMFrame *vm_push_frame(JSContext *ctx,
|
||||
const uint8_t *ret_pc, int ret_sp_offset,
|
||||
int call_argc, int call_has_this)
|
||||
{
|
||||
JSObject *p;
|
||||
JSFunction *f;
|
||||
JSFunctionBytecode *b;
|
||||
struct VMFrame *frame;
|
||||
int total_slots, i, arg_allocated_size;
|
||||
JSValue *stack_base, *arg_buf, *var_buf;
|
||||
|
||||
p = JS_VALUE_GET_OBJ(func_obj);
|
||||
b = p->u.func.function_bytecode;
|
||||
f = JS_VALUE_GET_FUNCTION(func_obj);
|
||||
b = f->u.func.function_bytecode;
|
||||
|
||||
/* Check frame stack capacity */
|
||||
if (ctx->frame_stack_top + 1 >= ctx->frame_stack_capacity) {
|
||||
@@ -10467,7 +10723,7 @@ static struct VMFrame *vm_push_frame(JSContext *ctx,
|
||||
frame->ctx = b->realm;
|
||||
frame->pc = b->byte_code_buf;
|
||||
frame->js_mode = b->js_mode;
|
||||
frame->var_refs = p->u.func.var_refs;
|
||||
frame->var_refs = f->u.func.var_refs;
|
||||
init_list_head(&frame->var_ref_list);
|
||||
|
||||
/* Continuation info for return */
|
||||
@@ -10612,7 +10868,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
{
|
||||
JSRuntime *rt = caller_ctx->rt;
|
||||
JSContext *ctx;
|
||||
JSObject *p;
|
||||
JSFunction *f;
|
||||
JSFunctionBytecode *b;
|
||||
JSStackFrame sf_s, *sf = &sf_s;
|
||||
const uint8_t *pc;
|
||||
@@ -10652,21 +10908,27 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
|
||||
if (js_poll_interrupts(caller_ctx))
|
||||
return JS_EXCEPTION;
|
||||
if (unlikely(JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)) {
|
||||
goto not_a_function;
|
||||
}
|
||||
p = JS_VALUE_GET_OBJ(func_obj);
|
||||
if (unlikely(p->class_id != JS_CLASS_BYTECODE_FUNCTION)) {
|
||||
JSClassCall *call_func;
|
||||
call_func = rt->class_array[p->class_id].call;
|
||||
if (!call_func) {
|
||||
if (unlikely(JS_VALUE_GET_TAG(func_obj) != JS_TAG_FUNCTION)) {
|
||||
not_a_function:
|
||||
return JS_ThrowTypeError(caller_ctx, "not a function");
|
||||
}
|
||||
return call_func(caller_ctx, func_obj, this_obj, argc,
|
||||
f = JS_VALUE_GET_FUNCTION(func_obj);
|
||||
switch (f->kind) {
|
||||
case JS_FUNC_KIND_C:
|
||||
return js_call_c_function(caller_ctx, func_obj, this_obj, argc,
|
||||
(JSValueConst *)argv, flags);
|
||||
case JS_FUNC_KIND_BOUND:
|
||||
return js_call_bound_function(caller_ctx, func_obj, this_obj, argc,
|
||||
(JSValueConst *)argv, flags);
|
||||
case JS_FUNC_KIND_C_DATA:
|
||||
return js_c_function_data_call(caller_ctx, func_obj, this_obj, argc,
|
||||
(JSValueConst *)argv, flags);
|
||||
case JS_FUNC_KIND_BYTECODE:
|
||||
break; /* continue to bytecode execution below */
|
||||
default:
|
||||
goto not_a_function;
|
||||
}
|
||||
b = p->u.func.function_bytecode;
|
||||
b = f->u.func.function_bytecode;
|
||||
|
||||
#ifdef DUMP_PROFILE
|
||||
/* Increment function entry count */
|
||||
@@ -10696,7 +10958,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
sf->arg_count = argc;
|
||||
sf->cur_func = (JSValue)func_obj;
|
||||
init_list_head(&sf->var_ref_list);
|
||||
var_refs = p->u.func.var_refs;
|
||||
var_refs = f->u.func.var_refs;
|
||||
|
||||
local_buf = alloca(alloca_size);
|
||||
if (unlikely(arg_allocated_size)) {
|
||||
@@ -13044,29 +13306,30 @@ static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_o
|
||||
NULL in case of exception (case of revoked proxy only) */
|
||||
static JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValueConst func_obj)
|
||||
{
|
||||
JSObject *p;
|
||||
JSFunction *f;
|
||||
JSContext *realm;
|
||||
|
||||
if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)
|
||||
if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_FUNCTION)
|
||||
return ctx;
|
||||
p = JS_VALUE_GET_OBJ(func_obj);
|
||||
switch(p->class_id) {
|
||||
case JS_CLASS_C_FUNCTION:
|
||||
realm = p->u.cfunc.realm;
|
||||
f = JS_VALUE_GET_FUNCTION(func_obj);
|
||||
switch(f->kind) {
|
||||
case JS_FUNC_KIND_C:
|
||||
realm = f->u.cfunc.realm;
|
||||
break;
|
||||
case JS_CLASS_BYTECODE_FUNCTION:
|
||||
case JS_FUNC_KIND_BYTECODE:
|
||||
{
|
||||
JSFunctionBytecode *b;
|
||||
b = p->u.func.function_bytecode;
|
||||
b = f->u.func.function_bytecode;
|
||||
realm = b->realm;
|
||||
}
|
||||
break;
|
||||
case JS_CLASS_BOUND_FUNCTION:
|
||||
case JS_FUNC_KIND_BOUND:
|
||||
{
|
||||
JSBoundFunction *bf = p->u.bound_function;
|
||||
JSBoundFunction *bf = f->u.bound_function;
|
||||
realm = JS_GetFunctionRealm(ctx, bf->func_obj);
|
||||
}
|
||||
break;
|
||||
case JS_FUNC_KIND_C_DATA:
|
||||
default:
|
||||
realm = ctx;
|
||||
break;
|
||||
@@ -22859,14 +23122,14 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
|
||||
|
||||
eval_type = flags & JS_EVAL_TYPE_MASK;
|
||||
if (eval_type == JS_EVAL_TYPE_DIRECT) {
|
||||
JSObject *p;
|
||||
JSFunction *fn;
|
||||
sf = ctx->rt->current_stack_frame;
|
||||
assert(sf != NULL);
|
||||
assert(JS_VALUE_GET_TAG(sf->cur_func) == JS_TAG_OBJECT);
|
||||
p = JS_VALUE_GET_OBJ(sf->cur_func);
|
||||
assert(js_class_has_bytecode(p->class_id));
|
||||
b = p->u.func.function_bytecode;
|
||||
var_refs = p->u.func.var_refs;
|
||||
assert(JS_VALUE_GET_TAG(sf->cur_func) == JS_TAG_FUNCTION);
|
||||
fn = JS_VALUE_GET_FUNCTION(sf->cur_func);
|
||||
assert(fn->kind == JS_FUNC_KIND_BYTECODE);
|
||||
b = fn->u.func.function_bytecode;
|
||||
var_refs = fn->u.func.var_refs;
|
||||
js_mode = b->js_mode;
|
||||
} else {
|
||||
sf = NULL;
|
||||
@@ -27297,9 +27560,9 @@ array_fail:
|
||||
|
||||
/* Handle function - return source or native stub */
|
||||
if (JS_IsFunction(ctx, arg)) {
|
||||
JSObject *p = JS_VALUE_GET_OBJ(arg);
|
||||
if (js_class_has_bytecode(p->class_id)) {
|
||||
JSFunctionBytecode *b = p->u.func.function_bytecode;
|
||||
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);
|
||||
}
|
||||
@@ -27309,12 +27572,15 @@ array_fail:
|
||||
const char *name = "";
|
||||
const char *name_cstr = NULL;
|
||||
|
||||
JSObject *fp = JS_VALUE_GET_OBJ(arg);
|
||||
if (js_class_has_bytecode(fp->class_id)) {
|
||||
JSFunctionBytecode *fb = fp->u.func.function_bytecode;
|
||||
if (fn->kind == JS_FUNC_KIND_BYTECODE) {
|
||||
JSFunctionBytecode *fb = fn->u.func.function_bytecode;
|
||||
name_cstr = JS_AtomToCString(ctx, fb->func_name);
|
||||
if (name_cstr)
|
||||
name = name_cstr;
|
||||
} else if (fn->name != JS_ATOM_NULL) {
|
||||
name_cstr = JS_AtomToCString(ctx, fn->name);
|
||||
if (name_cstr)
|
||||
name = name_cstr;
|
||||
}
|
||||
|
||||
size_t plen = strlen(pref);
|
||||
@@ -30166,17 +30432,8 @@ static JSValue js_cell_length(JSContext *ctx, JSValueConst this_val,
|
||||
|
||||
/* Functions return arity (accessed directly, not via properties) */
|
||||
if (JS_IsFunction(ctx, val)) {
|
||||
JSObject *p = JS_VALUE_GET_OBJ(val);
|
||||
switch (p->class_id) {
|
||||
case JS_CLASS_BYTECODE_FUNCTION:
|
||||
return JS_NewInt32(ctx, p->u.func.function_bytecode->defined_arg_count);
|
||||
case JS_CLASS_C_FUNCTION:
|
||||
return JS_NewInt32(ctx, p->u.cfunc.length);
|
||||
case JS_CLASS_C_FUNCTION_DATA:
|
||||
return JS_NewInt32(ctx, p->u.c_function_data_record->length);
|
||||
default:
|
||||
return JS_NewInt32(ctx, 0);
|
||||
}
|
||||
JSFunction *f = JS_VALUE_GET_FUNCTION(val);
|
||||
return JS_NewInt32(ctx, f->length);
|
||||
}
|
||||
|
||||
int tag = JS_VALUE_GET_TAG(val);
|
||||
@@ -30667,10 +30924,15 @@ void js_debug_info(JSContext *js, JSValue fn, js_debug *dbg)
|
||||
{
|
||||
memset(dbg, 0, sizeof(*dbg));
|
||||
|
||||
if (!JS_IsObject(fn)) return;
|
||||
JSObject *p = JS_VALUE_GET_OBJ(fn);
|
||||
if (!JS_IsFunction(js, fn)) return;
|
||||
JSFunction *f = JS_VALUE_GET_FUNCTION(fn);
|
||||
|
||||
const char *fn_name = get_prop_string(js, fn, JS_ATOM_name);
|
||||
const char *fn_name = NULL;
|
||||
if (f->name != JS_ATOM_NULL) {
|
||||
fn_name = JS_AtomToCString(js, f->name);
|
||||
} else if (f->kind == JS_FUNC_KIND_BYTECODE && f->u.func.function_bytecode) {
|
||||
fn_name = JS_AtomToCString(js, f->u.func.function_bytecode->func_name);
|
||||
}
|
||||
|
||||
if (!fn_name)
|
||||
dbg->name = js_strdup(js, "<anonymous>");
|
||||
@@ -30682,11 +30944,11 @@ void js_debug_info(JSContext *js, JSValue fn, js_debug *dbg)
|
||||
JS_FreeCString(js,fn_name);
|
||||
}
|
||||
|
||||
dbg->unique = (int)p;
|
||||
dbg->unique = (int)(uintptr_t)f;
|
||||
|
||||
switch(p->class_id) {
|
||||
case JS_CLASS_BYTECODE_FUNCTION: {
|
||||
JSFunctionBytecode *b = p->u.func.function_bytecode;
|
||||
switch(f->kind) {
|
||||
case JS_FUNC_KIND_BYTECODE: {
|
||||
JSFunctionBytecode *b = f->u.func.function_bytecode;
|
||||
// get filename
|
||||
const char *filename = JS_AtomToCString(js, b->debug.filename);
|
||||
if (!filename)
|
||||
@@ -30709,15 +30971,18 @@ void js_debug_info(JSContext *js, JSValue fn, js_debug *dbg)
|
||||
dbg->srclen = b->debug.source_len;
|
||||
break;
|
||||
}
|
||||
case JS_CLASS_C_FUNCTION:
|
||||
case JS_FUNC_KIND_C:
|
||||
case JS_FUNC_KIND_C_DATA:
|
||||
dbg->filename = js_strdup(js, "<native C>");
|
||||
dbg->what = "C";
|
||||
dbg->nparams = 0;
|
||||
dbg->nparams = f->length;
|
||||
dbg->vararg = 1;
|
||||
dbg->line = 0;
|
||||
dbg->source = CSTR;
|
||||
dbg->srclen = STRLEN(CSTR);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30761,7 +31026,7 @@ JSValue js_debugger_build_backtrace(JSContext *ctx, const uint8_t *cur_pc)
|
||||
{
|
||||
JSStackFrame *sf;
|
||||
const char *func_name_str;
|
||||
JSObject *p;
|
||||
JSFunction *f;
|
||||
JSValue ret = JS_NewArray(ctx);
|
||||
uint32_t stack_index = 0;
|
||||
|
||||
@@ -30778,12 +31043,13 @@ JSValue js_debugger_build_backtrace(JSContext *ctx, const uint8_t *cur_pc)
|
||||
JS_SetPropertyStr(ctx, current_frame, "name", JS_NewString(ctx, func_name_str));
|
||||
JS_FreeCString(ctx, func_name_str);
|
||||
|
||||
p = JS_VALUE_GET_OBJ(sf->cur_func);
|
||||
if (p && js_class_has_bytecode(p->class_id)) {
|
||||
if (JS_VALUE_GET_TAG(sf->cur_func) == JS_TAG_FUNCTION) {
|
||||
f = JS_VALUE_GET_FUNCTION(sf->cur_func);
|
||||
if (f->kind == JS_FUNC_KIND_BYTECODE) {
|
||||
JSFunctionBytecode *b;
|
||||
int line_num1;
|
||||
|
||||
b = p->u.func.function_bytecode;
|
||||
b = f->u.func.function_bytecode;
|
||||
if (b->has_debug) {
|
||||
const uint8_t *pc = sf != ctx->rt->current_stack_frame || !cur_pc ? sf->cur_pc : cur_pc;
|
||||
int col_num;
|
||||
@@ -30795,6 +31061,9 @@ JSValue js_debugger_build_backtrace(JSContext *ctx, const uint8_t *cur_pc)
|
||||
} else {
|
||||
JS_SetPropertyStr(ctx, current_frame, "name", JS_NewString(ctx, "(native)"));
|
||||
}
|
||||
} else {
|
||||
JS_SetPropertyStr(ctx, current_frame, "name", JS_NewString(ctx, "(native)"));
|
||||
}
|
||||
JS_SetPropertyUint32(ctx, ret, id, current_frame);
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -79,6 +79,7 @@ enum {
|
||||
JS_TAG_STRING = -8,
|
||||
JS_TAG_STRING_ROPE = -7,
|
||||
JS_TAG_ARRAY = -6, /* intrinsic array type */
|
||||
JS_TAG_FUNCTION = -5, /* intrinsic function type */
|
||||
JS_TAG_MODULE = -3, /* used internally */
|
||||
JS_TAG_FUNCTION_BYTECODE = -2, /* used internally */
|
||||
JS_TAG_OBJECT = -1,
|
||||
|
||||
Reference in New Issue
Block a user