mirror of
				https://github.com/bellard/quickjs.git
				synced 2025-05-29 01:49:18 +08:00 
			
		
		
		
	simplified and fixed backtrace_barrier (#306)
This commit is contained in:
		
							parent
							
								
									978756ad37
								
							
						
					
					
						commit
						9f65ef1950
					
				
							
								
								
									
										49
									
								
								quickjs.c
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								quickjs.c
									
									
									
									
									
								
							@ -288,6 +288,7 @@ struct JSClass {
 | 
				
			|||||||
#define JS_MODE_STRICT (1 << 0)
 | 
					#define JS_MODE_STRICT (1 << 0)
 | 
				
			||||||
#define JS_MODE_STRIP  (1 << 1)
 | 
					#define JS_MODE_STRIP  (1 << 1)
 | 
				
			||||||
#define JS_MODE_ASYNC  (1 << 2) /* async function */
 | 
					#define JS_MODE_ASYNC  (1 << 2) /* async function */
 | 
				
			||||||
 | 
					#define JS_MODE_BACKTRACE_BARRIER (1 << 3) /* stop backtrace before this frame */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct JSStackFrame {
 | 
					typedef struct JSStackFrame {
 | 
				
			||||||
    struct JSStackFrame *prev_frame; /* NULL if first stack frame */
 | 
					    struct JSStackFrame *prev_frame; /* NULL if first stack frame */
 | 
				
			||||||
@ -575,7 +576,6 @@ typedef struct JSFunctionBytecode {
 | 
				
			|||||||
    uint8_t super_allowed : 1;
 | 
					    uint8_t super_allowed : 1;
 | 
				
			||||||
    uint8_t arguments_allowed : 1;
 | 
					    uint8_t arguments_allowed : 1;
 | 
				
			||||||
    uint8_t has_debug : 1;
 | 
					    uint8_t has_debug : 1;
 | 
				
			||||||
    uint8_t backtrace_barrier : 1; /* stop backtrace on this function */
 | 
					 | 
				
			||||||
    uint8_t read_only_bytecode : 1;
 | 
					    uint8_t read_only_bytecode : 1;
 | 
				
			||||||
    uint8_t is_direct_or_indirect_eval : 1; /* used by JS_GetScriptOrModuleName() */
 | 
					    uint8_t is_direct_or_indirect_eval : 1; /* used by JS_GetScriptOrModuleName() */
 | 
				
			||||||
    /* XXX: 10 bits available */
 | 
					    /* XXX: 10 bits available */
 | 
				
			||||||
@ -6332,8 +6332,6 @@ static const char *get_func_name(JSContext *ctx, JSValueConst func)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL (1 << 0)
 | 
					#define JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL (1 << 0)
 | 
				
			||||||
/* only taken into account if filename is provided */
 | 
					 | 
				
			||||||
#define JS_BACKTRACE_FLAG_SINGLE_LEVEL     (1 << 1)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* if filename != NULL, an additional level is added with the filename
 | 
					/* if filename != NULL, an additional level is added with the filename
 | 
				
			||||||
   and line number information (used for parse error). */
 | 
					   and line number information (used for parse error). */
 | 
				
			||||||
@ -6347,7 +6345,6 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
 | 
				
			|||||||
    const char *func_name_str;
 | 
					    const char *func_name_str;
 | 
				
			||||||
    const char *str1;
 | 
					    const char *str1;
 | 
				
			||||||
    JSObject *p;
 | 
					    JSObject *p;
 | 
				
			||||||
    BOOL backtrace_barrier;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    js_dbuf_init(ctx, &dbuf);
 | 
					    js_dbuf_init(ctx, &dbuf);
 | 
				
			||||||
    if (filename) {
 | 
					    if (filename) {
 | 
				
			||||||
@ -6360,10 +6357,10 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
 | 
				
			|||||||
                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
 | 
					                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
 | 
				
			||||||
        JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_lineNumber, JS_NewInt32(ctx, line_num),
 | 
					        JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_lineNumber, JS_NewInt32(ctx, line_num),
 | 
				
			||||||
                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
 | 
					                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
 | 
				
			||||||
        if (backtrace_flags & JS_BACKTRACE_FLAG_SINGLE_LEVEL)
 | 
					 | 
				
			||||||
            goto done;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    for(sf = ctx->rt->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
 | 
					    for(sf = ctx->rt->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
 | 
				
			||||||
 | 
					        if (sf->js_mode & JS_MODE_BACKTRACE_BARRIER)
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        if (backtrace_flags & JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL) {
 | 
					        if (backtrace_flags & JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL) {
 | 
				
			||||||
            backtrace_flags &= ~JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL;
 | 
					            backtrace_flags &= ~JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL;
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
@ -6377,14 +6374,12 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
 | 
				
			|||||||
        JS_FreeCString(ctx, func_name_str);
 | 
					        JS_FreeCString(ctx, func_name_str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        p = JS_VALUE_GET_OBJ(sf->cur_func);
 | 
					        p = JS_VALUE_GET_OBJ(sf->cur_func);
 | 
				
			||||||
        backtrace_barrier = FALSE;
 | 
					 | 
				
			||||||
        if (js_class_has_bytecode(p->class_id)) {
 | 
					        if (js_class_has_bytecode(p->class_id)) {
 | 
				
			||||||
            JSFunctionBytecode *b;
 | 
					            JSFunctionBytecode *b;
 | 
				
			||||||
            const char *atom_str;
 | 
					            const char *atom_str;
 | 
				
			||||||
            int line_num1;
 | 
					            int line_num1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            b = p->u.func.function_bytecode;
 | 
					            b = p->u.func.function_bytecode;
 | 
				
			||||||
            backtrace_barrier = b->backtrace_barrier;
 | 
					 | 
				
			||||||
            if (b->has_debug) {
 | 
					            if (b->has_debug) {
 | 
				
			||||||
                line_num1 = find_line_num(ctx, b,
 | 
					                line_num1 = find_line_num(ctx, b,
 | 
				
			||||||
                                          sf->cur_pc - b->byte_code_buf - 1);
 | 
					                                          sf->cur_pc - b->byte_code_buf - 1);
 | 
				
			||||||
@ -6400,11 +6395,7 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
 | 
				
			|||||||
            dbuf_printf(&dbuf, " (native)");
 | 
					            dbuf_printf(&dbuf, " (native)");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        dbuf_putc(&dbuf, '\n');
 | 
					        dbuf_putc(&dbuf, '\n');
 | 
				
			||||||
        /* stop backtrace if JS_EVAL_FLAG_BACKTRACE_BARRIER was used */
 | 
					 | 
				
			||||||
        if (backtrace_barrier)
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 done:
 | 
					 | 
				
			||||||
    dbuf_putc(&dbuf, '\0');
 | 
					    dbuf_putc(&dbuf, '\0');
 | 
				
			||||||
    if (dbuf_error(&dbuf))
 | 
					    if (dbuf_error(&dbuf))
 | 
				
			||||||
        str = JS_NULL;
 | 
					        str = JS_NULL;
 | 
				
			||||||
@ -19272,7 +19263,6 @@ typedef struct JSFunctionDef {
 | 
				
			|||||||
    BOOL arguments_allowed; /* true if the 'arguments' identifier is allowed */
 | 
					    BOOL arguments_allowed; /* true if the 'arguments' identifier is allowed */
 | 
				
			||||||
    BOOL is_derived_class_constructor;
 | 
					    BOOL is_derived_class_constructor;
 | 
				
			||||||
    BOOL in_function_body;
 | 
					    BOOL in_function_body;
 | 
				
			||||||
    BOOL backtrace_barrier;
 | 
					 | 
				
			||||||
    JSFunctionKindEnum func_kind : 8;
 | 
					    JSFunctionKindEnum func_kind : 8;
 | 
				
			||||||
    JSParseFunctionEnum func_type : 8;
 | 
					    JSParseFunctionEnum func_type : 8;
 | 
				
			||||||
    uint8_t js_mode; /* bitmap of JS_MODE_x */
 | 
					    uint8_t js_mode; /* bitmap of JS_MODE_x */
 | 
				
			||||||
@ -19525,16 +19515,12 @@ int __attribute__((format(printf, 2, 3))) js_parse_error(JSParseState *s, const
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    JSContext *ctx = s->ctx;
 | 
					    JSContext *ctx = s->ctx;
 | 
				
			||||||
    va_list ap;
 | 
					    va_list ap;
 | 
				
			||||||
    int backtrace_flags;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    va_start(ap, fmt);
 | 
					    va_start(ap, fmt);
 | 
				
			||||||
    JS_ThrowError2(ctx, JS_SYNTAX_ERROR, fmt, ap, FALSE);
 | 
					    JS_ThrowError2(ctx, JS_SYNTAX_ERROR, fmt, ap, FALSE);
 | 
				
			||||||
    va_end(ap);
 | 
					    va_end(ap);
 | 
				
			||||||
    backtrace_flags = 0;
 | 
					 | 
				
			||||||
    if (s->cur_func && s->cur_func->backtrace_barrier)
 | 
					 | 
				
			||||||
        backtrace_flags = JS_BACKTRACE_FLAG_SINGLE_LEVEL;
 | 
					 | 
				
			||||||
    build_backtrace(ctx, ctx->rt->current_exception, s->filename, s->line_num,
 | 
					    build_backtrace(ctx, ctx->rt->current_exception, s->filename, s->line_num,
 | 
				
			||||||
                    backtrace_flags);
 | 
					                    0);
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -23753,7 +23739,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
 | 
				
			|||||||
    parse_regexp:
 | 
					    parse_regexp:
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            JSValue str;
 | 
					            JSValue str;
 | 
				
			||||||
            int ret, backtrace_flags;
 | 
					            int ret;
 | 
				
			||||||
            if (!s->ctx->compile_regexp)
 | 
					            if (!s->ctx->compile_regexp)
 | 
				
			||||||
                return js_parse_error(s, "RegExp are not supported");
 | 
					                return js_parse_error(s, "RegExp are not supported");
 | 
				
			||||||
            /* the previous token is '/' or '/=', so no need to free */
 | 
					            /* the previous token is '/' or '/=', so no need to free */
 | 
				
			||||||
@ -23764,12 +23750,8 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
 | 
				
			|||||||
                                         s->token.u.regexp.flags);
 | 
					                                         s->token.u.regexp.flags);
 | 
				
			||||||
            if (JS_IsException(str)) {
 | 
					            if (JS_IsException(str)) {
 | 
				
			||||||
                /* add the line number info */
 | 
					                /* add the line number info */
 | 
				
			||||||
                backtrace_flags = 0;
 | 
					 | 
				
			||||||
                if (s->cur_func && s->cur_func->backtrace_barrier)
 | 
					 | 
				
			||||||
                    backtrace_flags = JS_BACKTRACE_FLAG_SINGLE_LEVEL;
 | 
					 | 
				
			||||||
                build_backtrace(s->ctx, s->ctx->rt->current_exception,
 | 
					                build_backtrace(s->ctx, s->ctx->rt->current_exception,
 | 
				
			||||||
                                s->filename, s->token.line_num,
 | 
					                                s->filename, s->token.line_num, 0);
 | 
				
			||||||
                                backtrace_flags);
 | 
					 | 
				
			||||||
                return -1;
 | 
					                return -1;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ret = emit_push_const(s, str, 0);
 | 
					            ret = emit_push_const(s, str, 0);
 | 
				
			||||||
@ -32699,7 +32681,6 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
 | 
				
			|||||||
    b->super_call_allowed = fd->super_call_allowed;
 | 
					    b->super_call_allowed = fd->super_call_allowed;
 | 
				
			||||||
    b->super_allowed = fd->super_allowed;
 | 
					    b->super_allowed = fd->super_allowed;
 | 
				
			||||||
    b->arguments_allowed = fd->arguments_allowed;
 | 
					    b->arguments_allowed = fd->arguments_allowed;
 | 
				
			||||||
    b->backtrace_barrier = fd->backtrace_barrier;
 | 
					 | 
				
			||||||
    b->is_direct_or_indirect_eval = (fd->eval_type == JS_EVAL_TYPE_DIRECT ||
 | 
					    b->is_direct_or_indirect_eval = (fd->eval_type == JS_EVAL_TYPE_DIRECT ||
 | 
				
			||||||
                                     fd->eval_type == JS_EVAL_TYPE_INDIRECT);
 | 
					                                     fd->eval_type == JS_EVAL_TYPE_INDIRECT);
 | 
				
			||||||
    b->realm = JS_DupContext(ctx);
 | 
					    b->realm = JS_DupContext(ctx);
 | 
				
			||||||
@ -33670,7 +33651,6 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
 | 
				
			|||||||
    s->cur_func = fd;
 | 
					    s->cur_func = fd;
 | 
				
			||||||
    fd->eval_type = eval_type;
 | 
					    fd->eval_type = eval_type;
 | 
				
			||||||
    fd->has_this_binding = (eval_type != JS_EVAL_TYPE_DIRECT);
 | 
					    fd->has_this_binding = (eval_type != JS_EVAL_TYPE_DIRECT);
 | 
				
			||||||
    fd->backtrace_barrier = ((flags & JS_EVAL_FLAG_BACKTRACE_BARRIER) != 0);
 | 
					 | 
				
			||||||
    if (eval_type == JS_EVAL_TYPE_DIRECT) {
 | 
					    if (eval_type == JS_EVAL_TYPE_DIRECT) {
 | 
				
			||||||
        fd->new_target_allowed = b->new_target_allowed;
 | 
					        fd->new_target_allowed = b->new_target_allowed;
 | 
				
			||||||
        fd->super_call_allowed = b->super_call_allowed;
 | 
					        fd->super_call_allowed = b->super_call_allowed;
 | 
				
			||||||
@ -33739,11 +33719,22 @@ static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
 | 
				
			|||||||
                               const char *input, size_t input_len,
 | 
					                               const char *input, size_t input_len,
 | 
				
			||||||
                               const char *filename, int flags, int scope_idx)
 | 
					                               const char *filename, int flags, int scope_idx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    BOOL backtrace_barrier = ((flags & JS_EVAL_FLAG_BACKTRACE_BARRIER) != 0);
 | 
				
			||||||
 | 
					    int saved_js_mode = 0;
 | 
				
			||||||
 | 
					    JSValue ret;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    if (unlikely(!ctx->eval_internal)) {
 | 
					    if (unlikely(!ctx->eval_internal)) {
 | 
				
			||||||
        return JS_ThrowTypeError(ctx, "eval is not supported");
 | 
					        return JS_ThrowTypeError(ctx, "eval is not supported");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return ctx->eval_internal(ctx, this_obj, input, input_len, filename,
 | 
					    if (backtrace_barrier && ctx->rt->current_stack_frame) {
 | 
				
			||||||
                              flags, scope_idx);
 | 
					        saved_js_mode = ctx->rt->current_stack_frame->js_mode;
 | 
				
			||||||
 | 
					        ctx->rt->current_stack_frame->js_mode |= JS_MODE_BACKTRACE_BARRIER;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    ret = ctx->eval_internal(ctx, this_obj, input, input_len, filename,
 | 
				
			||||||
 | 
					                             flags, scope_idx);
 | 
				
			||||||
 | 
					    if (backtrace_barrier && ctx->rt->current_stack_frame)
 | 
				
			||||||
 | 
					        ctx->rt->current_stack_frame->js_mode = saved_js_mode;
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
 | 
					static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
 | 
				
			||||||
@ -34265,7 +34256,6 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)
 | 
				
			|||||||
    bc_set_flags(&flags, &idx, b->super_allowed, 1);
 | 
					    bc_set_flags(&flags, &idx, b->super_allowed, 1);
 | 
				
			||||||
    bc_set_flags(&flags, &idx, b->arguments_allowed, 1);
 | 
					    bc_set_flags(&flags, &idx, b->arguments_allowed, 1);
 | 
				
			||||||
    bc_set_flags(&flags, &idx, b->has_debug, 1);
 | 
					    bc_set_flags(&flags, &idx, b->has_debug, 1);
 | 
				
			||||||
    bc_set_flags(&flags, &idx, b->backtrace_barrier, 1);
 | 
					 | 
				
			||||||
    bc_set_flags(&flags, &idx, b->is_direct_or_indirect_eval, 1);
 | 
					    bc_set_flags(&flags, &idx, b->is_direct_or_indirect_eval, 1);
 | 
				
			||||||
    assert(idx <= 16);
 | 
					    assert(idx <= 16);
 | 
				
			||||||
    bc_put_u16(s, flags);
 | 
					    bc_put_u16(s, flags);
 | 
				
			||||||
@ -35132,7 +35122,6 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
 | 
				
			|||||||
    bc.super_allowed = bc_get_flags(v16, &idx, 1);
 | 
					    bc.super_allowed = bc_get_flags(v16, &idx, 1);
 | 
				
			||||||
    bc.arguments_allowed = bc_get_flags(v16, &idx, 1);
 | 
					    bc.arguments_allowed = bc_get_flags(v16, &idx, 1);
 | 
				
			||||||
    bc.has_debug = bc_get_flags(v16, &idx, 1);
 | 
					    bc.has_debug = bc_get_flags(v16, &idx, 1);
 | 
				
			||||||
    bc.backtrace_barrier = bc_get_flags(v16, &idx, 1);
 | 
					 | 
				
			||||||
    bc.is_direct_or_indirect_eval = bc_get_flags(v16, &idx, 1);
 | 
					    bc.is_direct_or_indirect_eval = bc_get_flags(v16, &idx, 1);
 | 
				
			||||||
    bc.read_only_bytecode = s->is_rom_data;
 | 
					    bc.read_only_bytecode = s->is_rom_data;
 | 
				
			||||||
    if (bc_get_u8(s, &v8))
 | 
					    if (bc_get_u8(s, &v8))
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user