diff --git a/TODO b/TODO index 550fcfc..e52ccd7 100644 --- a/TODO +++ b/TODO @@ -63,4 +63,4 @@ Test262o: 0/11262 errors, 463 excluded Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch) Test262: -Result: 56/83147 errors, 1646 excluded, 5538 skipped +Result: 66/83147 errors, 1646 excluded, 5538 skipped diff --git a/quickjs.c b/quickjs.c index 2a0fa19..b611372 100644 --- a/quickjs.c +++ b/quickjs.c @@ -25143,18 +25143,19 @@ done: return js_parse_expect(s, ']'); } -/* XXX: remove */ +/* check if scope chain contains a with statement */ static BOOL has_with_scope(JSFunctionDef *s, int scope_level) { - /* check if scope chain contains a with statement */ while (s) { - int scope_idx = s->scopes[scope_level].first; - while (scope_idx >= 0) { - JSVarDef *vd = &s->vars[scope_idx]; - - if (vd->var_name == JS_ATOM__with_) - return TRUE; - scope_idx = vd->scope_next; + /* no with in strict mode */ + if (!(s->js_mode & JS_MODE_STRICT)) { + int scope_idx = s->scopes[scope_level].first; + while (scope_idx >= 0) { + JSVarDef *vd = &s->vars[scope_idx]; + if (vd->var_name == JS_ATOM__with_) + return TRUE; + scope_idx = vd->scope_next; + } } /* check parent scopes */ scope_level = s->parent_scope_level; @@ -25187,7 +25188,11 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope, } if (name == JS_ATOM_this || name == JS_ATOM_new_target) goto invalid_lvalue; - depth = 2; /* will generate OP_get_ref_value */ + if (has_with_scope(fd, scope)) { + depth = 2; /* will generate OP_get_ref_value */ + } else { + depth = 0; + } break; case OP_get_field: name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1); @@ -25224,16 +25229,22 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope, /* get the value but keep the object/fields on the stack */ switch(opcode) { case OP_scope_get_var: - label = new_label(s); - if (label < 0) - return -1; - emit_op(s, OP_scope_make_ref); - emit_atom(s, name); - emit_u32(s, label); - emit_u16(s, scope); - update_label(fd, label, 1); - emit_op(s, OP_get_ref_value); - opcode = OP_get_ref_value; + if (depth != 0) { + label = new_label(s); + if (label < 0) + return -1; + emit_op(s, OP_scope_make_ref); + emit_atom(s, name); + emit_u32(s, label); + emit_u16(s, scope); + update_label(fd, label, 1); + emit_op(s, OP_get_ref_value); + opcode = OP_get_ref_value; + } else { + emit_op(s, OP_scope_get_var); + emit_atom(s, name); + emit_u16(s, scope); + } break; case OP_get_field: emit_op(s, OP_get_field2); @@ -25258,15 +25269,17 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope, } else { switch(opcode) { case OP_scope_get_var: - label = new_label(s); - if (label < 0) - return -1; - emit_op(s, OP_scope_make_ref); - emit_atom(s, name); - emit_u32(s, label); - emit_u16(s, scope); - update_label(fd, label, 1); - opcode = OP_get_ref_value; + if (depth != 0) { + label = new_label(s); + if (label < 0) + return -1; + emit_op(s, OP_scope_make_ref); + emit_atom(s, name); + emit_u32(s, label); + emit_u16(s, scope); + update_label(fd, label, 1); + opcode = OP_get_ref_value; + } break; default: break; @@ -25300,6 +25313,21 @@ static void put_lvalue(JSParseState *s, int opcode, int scope, BOOL is_let) { switch(opcode) { + case OP_scope_get_var: + /* depth = 0 */ + switch(special) { + case PUT_LVALUE_NOKEEP: + case PUT_LVALUE_NOKEEP_DEPTH: + case PUT_LVALUE_KEEP_SECOND: + case PUT_LVALUE_NOKEEP_BOTTOM: + break; + case PUT_LVALUE_KEEP_TOP: + emit_op(s, OP_dup); + break; + default: + abort(); + } + break; case OP_get_field: case OP_scope_get_private_field: /* depth = 1 */ @@ -25371,8 +25399,6 @@ static void put_lvalue(JSParseState *s, int opcode, int scope, switch(opcode) { case OP_scope_get_var: /* val -- */ - assert(special == PUT_LVALUE_NOKEEP || - special == PUT_LVALUE_NOKEEP_DEPTH); emit_op(s, is_let ? OP_scope_put_var_init : OP_scope_put_var); emit_u32(s, name); /* has refcount */ emit_u16(s, scope); @@ -25726,6 +25752,8 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, /* swap ref and lvalue object if any */ if (prop_name == JS_ATOM_NULL) { switch(depth_lvalue) { + case 0: + break; case 1: /* source prop x -> x source prop */ emit_op(s, OP_rot3r); @@ -25739,9 +25767,13 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, emit_op(s, OP_rot5l); emit_op(s, OP_rot5l); break; + default: + abort(); } } else { switch(depth_lvalue) { + case 0: + break; case 1: /* source x -> x source */ emit_op(s, OP_swap); @@ -25754,6 +25786,8 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, /* source x y z -> x y z source */ emit_op(s, OP_rot4l); break; + default: + abort(); } } } @@ -27405,7 +27439,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) } if (op == '=') { - if (opcode == OP_get_ref_value && name == name0) { + if ((opcode == OP_get_ref_value || opcode == OP_scope_get_var) && name == name0) { set_object_name(s, name); } } else { @@ -27440,11 +27474,14 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) return -1; } - if (opcode == OP_get_ref_value && name == name0) { + if ((opcode == OP_get_ref_value || opcode == OP_scope_get_var) && name == name0) { set_object_name(s, name); } switch(depth_lvalue) { + case 0: + emit_op(s, OP_dup); + break; case 1: emit_op(s, OP_insert2); break; @@ -32202,14 +32239,22 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, } } break; + case OP_scope_put_var: + if (!(var_idx & ARGUMENT_VAR_OFFSET) && + s->vars[var_idx].var_kind == JS_VAR_FUNCTION_NAME) { + /* in non strict mode, modifying the function name is ignored */ + dbuf_putc(bc, OP_drop); + goto done; + } + goto local_scope_var; case OP_scope_get_ref: dbuf_putc(bc, OP_undefined); - /* fall thru */ + goto local_scope_var; case OP_scope_get_var_checkthis: case OP_scope_get_var_undef: case OP_scope_get_var: - case OP_scope_put_var: case OP_scope_put_var_init: + local_scope_var: is_put = (op == OP_scope_put_var || op == OP_scope_put_var_init); if (var_idx & ARGUMENT_VAR_OFFSET) { dbuf_putc(bc, OP_get_arg + is_put); @@ -32497,15 +32542,22 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, dbuf_put_u16(bc, idx); } break; + case OP_scope_put_var: + if (s->closure_var[idx].var_kind == JS_VAR_FUNCTION_NAME) { + /* in non strict mode, modifying the function name is ignored */ + dbuf_putc(bc, OP_drop); + goto done; + } + goto closure_scope_var; case OP_scope_get_ref: /* XXX: should create a dummy object with a named slot that is a reference to the closure variable */ dbuf_putc(bc, OP_undefined); - /* fall thru */ + goto closure_scope_var; case OP_scope_get_var_undef: case OP_scope_get_var: - case OP_scope_put_var: case OP_scope_put_var_init: + closure_scope_var: is_put = (op == OP_scope_put_var || op == OP_scope_put_var_init); if (is_put) { diff --git a/test262_errors.txt b/test262_errors.txt index a3200e0..b62e444 100644 --- a/test262_errors.txt +++ b/test262_errors.txt @@ -5,6 +5,19 @@ test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in- test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-prefix-update.js:27: SyntaxError: invalid increment/decrement operand test262/test/annexB/language/expressions/assignmenttargettype/callexpression.js:33: SyntaxError: invalid assignment left-hand side test262/test/annexB/language/expressions/assignmenttargettype/cover-callexpression-and-asyncarrowhead.js:20: SyntaxError: invalid assignment left-hand side +test262/test/language/expressions/assignment/S11.13.1_A6_T1.js:23: Test262Error: #1: innerX === undefined. Actual: 1 +test262/test/language/expressions/assignment/S11.13.1_A6_T2.js:23: Test262Error: #1: innerX === 2. Actual: 1 +test262/test/language/expressions/compound-assignment/S11.13.2_A6.1_T1.js:24: Test262Error: #1: innerX === 2. Actual: 12 +test262/test/language/expressions/compound-assignment/S11.13.2_A6.2_T1.js:24: Test262Error: #1: innerX === 2. Actual: 5 +test262/test/language/expressions/compound-assignment/S11.13.2_A6.3_T1.js:24: Test262Error: #1: innerX === 2. Actual: 3 +test262/test/language/expressions/compound-assignment/S11.13.2_A6.4_T1.js:24: Test262Error: #1: innerX === 2. Actual: 4 +test262/test/language/expressions/compound-assignment/S11.13.2_A6.5_T1.js:24: Test262Error: #1: innerX === 2. Actual: 4 +test262/test/language/expressions/compound-assignment/S11.13.2_A6.6_T1.js:24: Test262Error: #1: innerX === 2. Actual: 8 +test262/test/language/expressions/compound-assignment/S11.13.2_A6.7_T1.js:24: Test262Error: #1: innerX === 2. Actual: 4 +test262/test/language/expressions/compound-assignment/S11.13.2_A6.8_T1.js:24: Test262Error: #1: innerX === 2. Actual: 4 +test262/test/language/expressions/compound-assignment/S11.13.2_A6.9_T1.js:24: Test262Error: #1: innerX === 2. Actual: 1 +test262/test/language/expressions/compound-assignment/S11.13.2_A6.10_T1.js:24: Test262Error: #1: innerX === 2. Actual: 5 +test262/test/language/expressions/compound-assignment/S11.13.2_A6.11_T1.js:24: Test262Error: #1: innerX === 2. Actual: 5 test262/test/language/identifier-resolution/assign-to-global-undefined.js:20: strict mode: expected error test262/test/staging/sm/Function/arguments-parameter-shadowing.js:14: Test262Error: Expected SameValue(«true», «false») to be true test262/test/staging/sm/Function/constructor-binding.js:11: Test262Error: Expected SameValue(«"function"», «"undefined"») to be true @@ -35,9 +48,6 @@ test262/test/staging/sm/class/boundFunctionSubclassing.js:9: strict mode: Test26 test262/test/staging/sm/class/strictExecution.js:13: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all test262/test/staging/sm/class/superPropOrdering.js:17: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all test262/test/staging/sm/class/superPropOrdering.js:17: strict mode: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all -test262/test/staging/sm/expressions/short-circuit-compound-assignment-const.js:96: TypeError: 'a' is read-only -test262/test/staging/sm/expressions/short-circuit-compound-assignment-tdz.js:18: Test262Error: Expected a ReferenceError but got a TypeError -test262/test/staging/sm/expressions/short-circuit-compound-assignment-tdz.js:18: strict mode: Test262Error: Expected a ReferenceError but got a TypeError test262/test/staging/sm/generators/syntax.js:50: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all test262/test/staging/sm/lexical-environment/block-scoped-functions-annex-b-arguments.js:13: Test262Error: Expected SameValue(«"object"», «"function"») to be true test262/test/staging/sm/lexical-environment/block-scoped-functions-annex-b-eval.js:11: Test262Error: Expected SameValue(«"outer-gouter-geval-gtruefalseq"», «"outer-geval-gwith-gtruefalseq"») to be true