Fix evaluation order of computed properties

The evaluation order is observable. Align with what test262 expects.
This commit is contained in:
Ben Noordhuis 2023-12-27 11:49:06 +01:00 committed by Saúl Ibarra Corretgé
parent 48e4c63a0e
commit e995085d0c
2 changed files with 29 additions and 4 deletions

View file

@ -23716,11 +23716,40 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, (op != '='), op) < 0)
return -1;
// comply with rather obtuse evaluation order of computed properties:
// obj[key]=val evaluates val->obj->key when obj is null/undefined
// but key->obj->val when an object
// FIXME(bnoordhuis) less stack shuffling; don't to_propkey twice in
// happy path; replace `dup is_undefined_or_null if_true` with new
// opcode if_undefined_or_null? replace `swap dup` with over?
if (op == '=' && opcode == OP_get_array_el) {
int label_next = -1;
JSFunctionDef *fd = s->cur_func;
assert(OP_to_propkey2 == fd->byte_code.buf[fd->last_opcode_pos]);
fd->byte_code.size = fd->last_opcode_pos;
fd->last_opcode_pos = -1;
emit_op(s, OP_swap); // obj key -> key obj
emit_op(s, OP_dup);
emit_op(s, OP_is_undefined_or_null);
label_next = emit_goto(s, OP_if_true, -1);
emit_op(s, OP_swap);
emit_op(s, OP_to_propkey);
emit_op(s, OP_swap);
emit_label(s, label_next);
emit_op(s, OP_swap);
}
if (js_parse_assign_expr2(s, parse_flags)) {
JS_FreeAtom(s->ctx, name);
return -1;
}
if (op == '=' && opcode == OP_get_array_el) {
emit_op(s, OP_swap); // obj key val -> obj val key
emit_op(s, OP_to_propkey);
emit_op(s, OP_swap);
}
if (op == '=') {
if (opcode == OP_get_ref_value && name == name0) {
set_object_name(s, name);

View file

@ -3,10 +3,6 @@ test262/test/built-ins/RegExp/lookahead-quantifier-match-groups.js:27: Test262Er
test262/test/built-ins/RegExp/lookahead-quantifier-match-groups.js:27: strict mode: Test262Error: Expected [a, abc] and [a, undefined] to have the same contents. ? quantifier
test262/test/language/expressions/arrow-function/static-init-await-reference.js:12: unexpected error type: Test262: This statement should not be evaluated.
test262/test/language/expressions/arrow-function/static-init-await-reference.js:12: strict mode: unexpected error type: Test262: This statement should not be evaluated.
test262/test/language/expressions/assignment/target-member-computed-reference-null.js:32: Test262Error: Expected a DummyError but got a TypeError
test262/test/language/expressions/assignment/target-member-computed-reference-null.js:32: strict mode: Test262Error: Expected a DummyError but got a TypeError
test262/test/language/expressions/assignment/target-member-computed-reference-undefined.js:32: Test262Error: Expected a DummyError but got a TypeError
test262/test/language/expressions/assignment/target-member-computed-reference-undefined.js:32: strict mode: Test262Error: Expected a DummyError but got a TypeError
test262/test/language/expressions/function/static-init-await-binding.js:16: SyntaxError: 'await' is a reserved identifier
test262/test/language/expressions/function/static-init-await-binding.js:16: strict mode: SyntaxError: 'await' is a reserved identifier
test262/test/language/expressions/generators/static-init-await-binding.js:16: SyntaxError: 'await' is a reserved identifier