diff --git a/quickjs.c b/quickjs.c index 11a6367..7d9943f 100644 --- a/quickjs.c +++ b/quickjs.c @@ -16302,6 +16302,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSValue val; + sf->cur_pc = pc; val = JS_GetProperty(ctx, sp[-1], JS_ATOM_length); if (unlikely(JS_IsException(val))) goto exception; @@ -16654,6 +16655,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int magic; magic = get_u16(pc); pc += 2; + sf->cur_pc = pc; ret_val = js_function_apply(ctx, sp[-3], 2, (JSValueConst *)&sp[-2], magic); if (unlikely(JS_IsException(ret_val))) @@ -16800,6 +16802,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, scope_idx = get_u16(pc) + ARG_SCOPE_END; pc += 2; + sf->cur_pc = pc; tab = build_arg_list(ctx, &len, sp[-1]); if (!tab) goto exception; @@ -16835,6 +16838,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_get_super): { JSValue proto; + sf->cur_pc = pc; proto = JS_GetPrototype(ctx, sp[-1]); if (JS_IsException(proto)) goto exception; @@ -16846,6 +16850,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_import): { JSValue val; + sf->cur_pc = pc; val = js_dynamic_import(ctx, sp[-1]); if (JS_IsException(val)) goto exception; @@ -16860,6 +16865,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JSAtom atom; atom = get_u32(pc); pc += 4; + sf->cur_pc = pc; ret = JS_CheckGlobalVar(ctx, atom); if (ret < 0) @@ -16875,6 +16881,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JSAtom atom; atom = get_u32(pc); pc += 4; + sf->cur_pc = pc; val = JS_GetGlobalVar(ctx, atom, opcode - OP_get_var_undef); if (unlikely(JS_IsException(val))) @@ -16890,6 +16897,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JSAtom atom; atom = get_u32(pc); pc += 4; + sf->cur_pc = pc; ret = JS_SetGlobalVar(ctx, atom, sp[-1], opcode - OP_put_var); sp--; @@ -16904,6 +16912,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JSAtom atom; atom = get_u32(pc); pc += 4; + sf->cur_pc = pc; /* sp[-2] is JS_TRUE or JS_FALSE */ if (unlikely(!JS_VALUE_GET_INT(sp[-2]))) { @@ -16924,6 +16933,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, atom = get_u32(pc); flags = pc[4]; pc += 5; + sf->cur_pc = pc; if (JS_CheckDefineGlobalVar(ctx, atom, flags)) goto exception; } @@ -16935,6 +16945,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, atom = get_u32(pc); flags = pc[4]; pc += 5; + sf->cur_pc = pc; if (JS_DefineGlobalVar(ctx, atom, flags)) goto exception; } @@ -16946,6 +16957,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, atom = get_u32(pc); flags = pc[4]; pc += 5; + sf->cur_pc = pc; if (JS_DefineGlobalFunction(ctx, atom, sp[-1], flags)) goto exception; JS_FreeValue(ctx, sp[-1]); @@ -17224,6 +17236,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JSAtom atom; atom = get_u32(pc); pc += 4; + sf->cur_pc = pc; if (JS_GetGlobalVarRef(ctx, atom, sp)) goto exception; @@ -17369,15 +17382,18 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, BREAK; CASE(OP_for_in_start): + sf->cur_pc = pc; if (js_for_in_start(ctx, sp)) goto exception; BREAK; CASE(OP_for_in_next): + sf->cur_pc = pc; if (js_for_in_next(ctx, sp)) goto exception; sp += 2; BREAK; CASE(OP_for_of_start): + sf->cur_pc = pc; if (js_for_of_start(ctx, sp, FALSE)) goto exception; sp += 1; @@ -17387,23 +17403,27 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { int offset = -3 - pc[0]; pc += 1; + sf->cur_pc = pc; if (js_for_of_next(ctx, sp, offset)) goto exception; sp += 2; } BREAK; CASE(OP_for_await_of_next): + sf->cur_pc = pc; if (js_for_await_of_next(ctx, sp)) goto exception; sp++; BREAK; CASE(OP_for_await_of_start): + sf->cur_pc = pc; if (js_for_of_start(ctx, sp, TRUE)) goto exception; sp += 1; *sp++ = JS_NewCatchOffset(ctx, 0); BREAK; CASE(OP_iterator_get_value_done): + sf->cur_pc = pc; if (js_iterator_get_value_done(ctx, sp)) goto exception; sp += 1; @@ -17421,6 +17441,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JS_FreeValue(ctx, sp[-1]); /* drop the next method */ sp--; if (!JS_IsUndefined(sp[-1])) { + sf->cur_pc = pc; if (JS_IteratorClose(ctx, sp[-1], FALSE)) goto exception; JS_FreeValue(ctx, sp[-1]); @@ -17449,6 +17470,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, /* stack: iter_obj next catch_offset val */ { JSValue ret; + sf->cur_pc = pc; ret = JS_Call(ctx, sp[-3], sp[-4], 1, (JSValueConst *)(sp - 1)); if (JS_IsException(ret)) @@ -17465,6 +17487,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, BOOL ret_flag; int flags; flags = *pc++; + sf->cur_pc = pc; method = JS_GetProperty(ctx, sp[-4], (flags & 1) ? JS_ATOM_throw : JS_ATOM_return); if (JS_IsException(method)) @@ -17513,6 +17536,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, atom = get_u32(pc); pc += 4; + sf->cur_pc = pc; val = JS_GetProperty(ctx, sp[-1], atom); if (unlikely(JS_IsException(val))) goto exception; @@ -17528,6 +17552,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, atom = get_u32(pc); pc += 4; + sf->cur_pc = pc; val = JS_GetProperty(ctx, sp[-1], atom); if (unlikely(JS_IsException(val))) goto exception; @@ -17541,6 +17566,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JSAtom atom; atom = get_u32(pc); pc += 4; + sf->cur_pc = pc; ret = JS_SetPropertyInternal(ctx, sp[-2], atom, sp[-1], sp[-2], JS_PROP_THROW_STRICT); @@ -17640,6 +17666,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_set_proto): { JSValue proto; + sf->cur_pc = pc; proto = sp[-1]; if (JS_IsObject(proto) || JS_IsNull(proto)) { if (JS_SetPrototypeInternal(ctx, sp[-2], proto, TRUE) < 0) @@ -17732,6 +17759,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSValue val; + sf->cur_pc = pc; val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]); JS_FreeValue(ctx, sp[-2]); sp[-2] = val; @@ -17745,6 +17773,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSValue val; + sf->cur_pc = pc; val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]); sp[-1] = val; if (unlikely(JS_IsException(val))) @@ -17758,6 +17787,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JSAtom atom; int ret; + sf->cur_pc = pc; atom = JS_ValueToAtom(ctx, sp[-1]); if (atom == JS_ATOM_NULL) goto exception; @@ -17793,6 +17823,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSValue val; JSAtom atom; + sf->cur_pc = pc; atom = JS_ValueToAtom(ctx, sp[-1]); if (unlikely(atom == JS_ATOM_NULL)) goto exception; @@ -17812,6 +17843,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { int ret; + sf->cur_pc = pc; ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1], JS_PROP_THROW_STRICT); JS_FreeValue(ctx, sp[-3]); sp -= 3; @@ -17824,6 +17856,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { int ret; JSAtom atom; + sf->cur_pc = pc; atom = JS_ValueToAtom(ctx, sp[-2]); if (unlikely(atom == JS_ATOM_NULL)) goto exception; @@ -17862,6 +17895,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { int ret; JSAtom atom; + sf->cur_pc = pc; if (JS_VALUE_GET_TAG(sp[-3]) != JS_TAG_OBJECT) { JS_ThrowTypeErrorNotAnObject(ctx); goto exception; @@ -17894,6 +17928,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_append): /* array pos enumobj -- array pos */ { + sf->cur_pc = pc; if (js_append_enumerate(ctx, sp)) goto exception; JS_FreeValue(ctx, *--sp); @@ -17909,6 +17944,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, int mask; mask = *pc++; + sf->cur_pc = pc; if (JS_CopyDataProperties(ctx, sp[-1 - (mask & 3)], sp[-1 - ((mask >> 2) & 7)], sp[-1 - ((mask >> 5) & 7)], 0)) @@ -17939,6 +17975,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, goto exception; } else { add_slow: + sf->cur_pc = pc; if (js_add_slow(ctx, sp)) goto exception; sp--; @@ -17968,6 +18005,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp--; } else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING) { sp--; + sf->cur_pc = pc; op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE); if (JS_IsException(op2)) goto exception; @@ -17984,6 +18022,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, add_loc_slow: /* In case of exception, js_add_slow frees ops[0] and ops[1], so we must duplicate *pv */ + sf->cur_pc = pc; ops[0] = JS_DupValue(ctx, *pv); ops[1] = op2; sp--; @@ -18086,6 +18125,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, BREAK; CASE(OP_pow): binary_arith_slow: + sf->cur_pc = pc; if (js_binary_arith_slow(ctx, sp, opcode)) goto exception; sp--; @@ -18099,6 +18139,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, tag = JS_VALUE_GET_TAG(op1); if (tag == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag)) { } else { + sf->cur_pc = pc; if (js_unary_arith_slow(ctx, sp, opcode)) goto exception; } @@ -18129,6 +18170,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, neg_fp_res: sp[-1] = __JS_NewFloat64(ctx, d); } else { + sf->cur_pc = pc; if (js_unary_arith_slow(ctx, sp, opcode)) goto exception; } @@ -18146,6 +18188,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp[-1] = JS_NewInt32(ctx, val + 1); } else { inc_slow: + sf->cur_pc = pc; if (js_unary_arith_slow(ctx, sp, opcode)) goto exception; } @@ -18163,6 +18206,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp[-1] = JS_NewInt32(ctx, val - 1); } else { dec_slow: + sf->cur_pc = pc; if (js_unary_arith_slow(ctx, sp, opcode)) goto exception; } @@ -18170,6 +18214,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, BREAK; CASE(OP_post_inc): CASE(OP_post_dec): + sf->cur_pc = pc; if (js_post_inc_slow(ctx, sp, opcode)) goto exception; sp++; @@ -18190,6 +18235,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, var_buf[idx] = JS_NewInt32(ctx, val + 1); } else { inc_loc_slow: + sf->cur_pc = pc; /* must duplicate otherwise the variable value may be destroyed before JS code accesses it */ op1 = JS_DupValue(ctx, op1); @@ -18215,6 +18261,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, var_buf[idx] = JS_NewInt32(ctx, val - 1); } else { dec_loc_slow: + sf->cur_pc = pc; /* must duplicate otherwise the variable value may be destroyed before JS code accesses it */ op1 = JS_DupValue(ctx, op1); @@ -18231,6 +18278,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) { sp[-1] = JS_NewInt32(ctx, ~JS_VALUE_GET_INT(op1)); } else { + sf->cur_pc = pc; if (js_not_slow(ctx, sp)) goto exception; } @@ -18250,6 +18298,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp[-2] = JS_NewInt32(ctx, v1 << v2); sp--; } else { + sf->cur_pc = pc; if (js_binary_logic_slow(ctx, sp, opcode)) goto exception; sp--; @@ -18270,6 +18319,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, v2); sp--; } else { + sf->cur_pc = pc; if (js_shr_slow(ctx, sp)) goto exception; sp--; @@ -18289,6 +18339,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, (int)JS_VALUE_GET_INT(op1) >> v2); sp--; } else { + sf->cur_pc = pc; if (js_binary_logic_slow(ctx, sp, opcode)) goto exception; sp--; @@ -18306,6 +18357,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JS_VALUE_GET_INT(op2)); sp--; } else { + sf->cur_pc = pc; if (js_binary_logic_slow(ctx, sp, opcode)) goto exception; sp--; @@ -18323,6 +18375,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JS_VALUE_GET_INT(op2)); sp--; } else { + sf->cur_pc = pc; if (js_binary_logic_slow(ctx, sp, opcode)) goto exception; sp--; @@ -18340,6 +18393,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JS_VALUE_GET_INT(op2)); sp--; } else { + sf->cur_pc = pc; if (js_binary_logic_slow(ctx, sp, opcode)) goto exception; sp--; @@ -18358,6 +18412,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp[-2] = JS_NewBool(ctx, JS_VALUE_GET_INT(op1) binary_op JS_VALUE_GET_INT(op2)); \ sp--; \ } else { \ + sf->cur_pc = pc; \ if (slow_call) \ goto exception; \ sp--; \ @@ -18375,16 +18430,19 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, OP_CMP(OP_strict_neq, !=, js_strict_eq_slow(ctx, sp, 1)); CASE(OP_in): + sf->cur_pc = pc; if (js_operator_in(ctx, sp)) goto exception; sp--; BREAK; CASE(OP_private_in): + sf->cur_pc = pc; if (js_operator_private_in(ctx, sp)) goto exception; sp--; BREAK; CASE(OP_instanceof): + sf->cur_pc = pc; if (js_operator_instanceof(ctx, sp)) goto exception; sp--; @@ -18401,6 +18459,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } BREAK; CASE(OP_delete): + sf->cur_pc = pc; if (js_operator_delete(ctx, sp)) goto exception; sp--; @@ -18412,6 +18471,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, atom = get_u32(pc); pc += 4; + sf->cur_pc = pc; ret = JS_DeleteProperty(ctx, ctx->global_obj, atom, 0); if (unlikely(ret < 0)) @@ -18422,6 +18482,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_to_object): if (JS_VALUE_GET_TAG(sp[-1]) != JS_TAG_OBJECT) { + sf->cur_pc = pc; ret_val = JS_ToObject(ctx, sp[-1]); if (JS_IsException(ret_val)) goto exception; @@ -18437,6 +18498,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, case JS_TAG_SYMBOL: break; default: + sf->cur_pc = pc; ret_val = JS_ToPropertyKey(ctx, sp[-1]); if (JS_IsException(ret_val)) goto exception; @@ -18458,6 +18520,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, case JS_TAG_SYMBOL: break; default: + sf->cur_pc = pc; ret_val = JS_ToPropertyKey(ctx, sp[-1]); if (JS_IsException(ret_val)) goto exception; @@ -18491,6 +18554,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, diff = get_u32(pc + 4); is_with = pc[8]; pc += 9; + sf->cur_pc = pc; obj = sp[-1]; ret = JS_HasProperty(ctx, obj, atom); @@ -24692,14 +24756,13 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) case TOK_IDENT: { JSAtom name; + const uint8_t *source_ptr; if (s->token.u.ident.is_reserved) { return js_parse_error_reserved_identifier(s); } + source_ptr = s->token.ptr; if (token_is_pseudo_keyword(s, JS_ATOM_async) && peek_token(s, TRUE) != '\n') { - const uint8_t *source_ptr; - - source_ptr = s->token.ptr; if (next_token(s)) return -1; if (s->token.val == TOK_FUNCTION) { @@ -24718,11 +24781,12 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) return -1; } name = JS_DupAtom(s->ctx, s->token.u.ident.atom); - if (next_token(s)) { /* update line number before emitting code */ + if (next_token(s)) { JS_FreeAtom(s->ctx, name); return -1; } do_get_var: + emit_source_pos(s, source_ptr); emit_op(s, OP_scope_get_var); emit_u32(s, name); emit_u16(s, s->cur_func->scope_level); @@ -25315,6 +25379,7 @@ static __exception int js_parse_delete(JSParseState *s) static __exception int js_parse_unary(JSParseState *s, int parse_flags) { int op; + const uint8_t *op_token_ptr; switch(s->token.val) { case '+': @@ -25322,6 +25387,7 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) case '!': case '~': case TOK_VOID: + op_token_ptr = s->token.ptr; op = s->token.val; if (next_token(s)) return -1; @@ -25329,15 +25395,18 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) return -1; switch(op) { case '-': + emit_source_pos(s, op_token_ptr); emit_op(s, OP_neg); break; case '+': + emit_source_pos(s, op_token_ptr); emit_op(s, OP_plus); break; case '!': emit_op(s, OP_lnot); break; case '~': + emit_source_pos(s, op_token_ptr); emit_op(s, OP_not); break; case TOK_VOID: @@ -25355,12 +25424,14 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) int opcode, op, scope, label; JSAtom name; op = s->token.val; + op_token_ptr = s->token.ptr; if (next_token(s)) return -1; if (js_parse_unary(s, 0)) return -1; if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op)) return -1; + emit_source_pos(s, op_token_ptr); emit_op(s, OP_dec + op - TOK_DEC); put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP, FALSE); @@ -25409,8 +25480,10 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) int opcode, op, scope, label; JSAtom name; op = s->token.val; + op_token_ptr = s->token.ptr; if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op)) return -1; + emit_source_pos(s, op_token_ptr); emit_op(s, OP_post_dec + op - TOK_DEC); put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_SECOND, FALSE); @@ -25430,10 +25503,12 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) JS_ThrowSyntaxError(s->ctx, "unparenthesized unary expression can't appear on the left-hand side of '**'"); return -1; } + op_token_ptr = s->token.ptr; if (next_token(s)) return -1; if (js_parse_unary(s, PF_POW_ALLOWED)) return -1; + emit_source_pos(s, op_token_ptr); emit_op(s, OP_pow); } } @@ -25903,6 +25978,8 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) op = s->token.val; if (op == '=' || (op >= TOK_MUL_ASSIGN && op <= TOK_POW_ASSIGN)) { int label; + const uint8_t *op_token_ptr; + op_token_ptr = s->token.ptr; if (next_token(s)) return -1; if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, (op != '='), op) < 0) @@ -25924,6 +26001,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) OP_pow, }; op = assign_opcodes[op - TOK_MUL_ASSIGN]; + emit_source_pos(s, op_token_ptr); emit_op(s, op); } put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP, FALSE); diff --git a/tests/test_builtin.js b/tests/test_builtin.js index 174f216..423841d 100644 --- a/tests/test_builtin.js +++ b/tests/test_builtin.js @@ -509,28 +509,52 @@ function test_typed_array() assert(a.toString(), "1,2,10,11"); } -function check_error_pos(e, expected_error, line_num, col_num) +/* return [s, line_num, col_num] where line_num and col_num are the + position of the '@' character in 'str'. 's' is str without the '@' + character */ +function get_string_pos(str) { - var expected_pos; + var p, line_num, col_num, s, q, r; + p = str.indexOf('@'); + assert(p >= 0, true); + q = 0; + line_num = 1; + for(;;) { + r = str.indexOf('\n', q); + if (r < 0 || r >= p) + break; + q = r + 1; + line_num++; + } + col_num = p - q + 1; + s = str.slice(0, p) + str.slice(p + 1); + return [s, line_num, col_num]; +} + +function check_error_pos(e, expected_error, line_num, col_num, level) +{ + var expected_pos, tab, line; + level |= 0; expected_pos = ":" + line_num + ":" + col_num; - if (expected_error === SyntaxError) - expected_pos += "\n"; - else - expected_pos += ")"; - if (e.stack.indexOf(expected_pos) < 0) { + tab = e.stack.split("\n"); + line = tab[level]; + if (line.slice(-1) == ')') + line = line.slice(0, -1); + if (line.indexOf(expected_pos) < 0) { throw_error("unexpected line or column number. error=" + e.message + - ".got |" + e.stack + - "|, expected |" + expected_pos + "|"); + ".got |" + line + "|, expected |" + expected_pos + "|"); } } function assert_json_error(str, line_num, col_num) { var err = false; - var expected_pos; + var expected_pos, tab; + + tab = get_string_pos(str); try { - JSON.parse(str); + JSON.parse(tab[0]); } catch(e) { err = true; if (!(e instanceof SyntaxError)) { @@ -538,7 +562,7 @@ function assert_json_error(str, line_num, col_num) return; } /* XXX: the way quickjs returns JSON errors is not similar to Node or spiderMonkey */ - check_error_pos(e, SyntaxError, line_num, col_num); + check_error_pos(e, SyntaxError, tab[1], tab[2]); } if (!err) { throw_error("expected exception"); @@ -569,8 +593,8 @@ function test_json() ] ]`); - assert_json_error('\n" \\x"', 2, 4); - assert_json_error('\n{ "a": x }"', 2, 8); + assert_json_error('\n" @\\x"'); + assert_json_error('\n{ "a": @x }"'); } function test_date() @@ -1005,53 +1029,88 @@ function test_rope() rope_concat(100000, -1); } - -function eval_error(eval_str, expected_error, line_num, col_num) +function eval_error(eval_str, expected_error, level) { var err = false; - var expected_pos; + var expected_pos, tab; + + tab = get_string_pos(eval_str); try { - eval(eval_str); + eval(tab[0]); } catch(e) { err = true; if (!(e instanceof expected_error)) { throw_error("unexpected exception type"); return; } - check_error_pos(e, expected_error, line_num, col_num); + check_error_pos(e, expected_error, tab[1], tab[2], level); } if (!err) { throw_error("expected exception"); } } +var poisoned_number = { + valueOf: function() { throw Error("poisoned number") }, +}; + function test_line_column_numbers() { - var f, e; + var f, e, tab; + /* The '@' character provides the expected position of the + error. It is removed before evaluating the string. */ + /* parsing */ - eval_error("\n 123 a ", SyntaxError, 2, 6); - eval_error("\n /* ", SyntaxError, 2, 3); - eval_error("function f a", SyntaxError, 1, 13); + eval_error("\n 123 @a ", SyntaxError); + eval_error("\n @/* ", SyntaxError); + eval_error("function f @a", SyntaxError); /* currently regexp syntax errors point to the start of the regexp */ - eval_error("\n /aaa]/u", SyntaxError, 2, 3); + eval_error("\n @/aaa]/u", SyntaxError); /* function definitions */ - e = eval("\n function f() { }; f;"); - assert(e.lineNumber, 2); - assert(e.columnNumber, 4); + tab = get_string_pos("\n @function f() { }; f;"); + e = eval(tab[0]); + assert(e.lineNumber, tab[1]); + assert(e.columnNumber, tab[2]); /* errors */ - e = eval('\n Error("hello");'); - check_error_pos(e, Error, 2, 8); - eval_error('\n throw Error("hello");', Error, 2, 14); - eval_error('\n 2 * Symbol();', TypeError, 2, 5); - eval_error('\n "café" * Symbol();', TypeError, 2, 10); - eval_error('\n null[0];', TypeError, 2, 6); - eval_error('\n null . abcd;', TypeError, 2, 7); - eval_error('\n null ( 1234 );', TypeError, 2, 7); + tab = get_string_pos('\n Error@("hello");'); + e = eval(tab[0]); + check_error_pos(e, Error, tab[1], tab[2]); + + eval_error('\n throw Error@("hello");', Error); + + /* operators */ + eval_error('\n 1 + 2 @* poisoned_number;', Error, 1); + eval_error('\n 1 + "café" @* poisoned_number;', Error, 1); + eval_error('\n 1 + 2 @** poisoned_number;', Error, 1); + eval_error('\n 2 * @+ poisoned_number;', Error, 1); + eval_error('\n 2 * @- poisoned_number;', Error, 1); + eval_error('\n 2 * @~ poisoned_number;', Error, 1); + eval_error('\n 2 * @++ poisoned_number;', Error, 1); + eval_error('\n 2 * @-- poisoned_number;', Error, 1); + eval_error('\n 2 * poisoned_number @++;', Error, 1); + eval_error('\n 2 * poisoned_number @--;', Error, 1); + + /* accessors */ + eval_error('\n 1 + null@[0];', TypeError); + eval_error('\n 1 + null @. abcd;', TypeError); + eval_error('\n 1 + null @( 1234 );', TypeError); + eval_error('var obj = { get a() { throw Error("test"); } }\n 1 + obj @. a;', + Error, 1); + eval_error('var obj = { set a(b) { throw Error("test"); } }\n obj @. a = 1;', + Error, 1); + + /* variables reference */ + eval_error('\n 1 + @not_def', ReferenceError, 0); + + /* assignments */ + eval_error('1 + (@not_def = 1)', ReferenceError, 0); + eval_error('1 + (@not_def += 2)', ReferenceError, 0); + eval_error('var a;\n 1 + (a @+= poisoned_number);', Error, 1); } test();