Skip to content

Commit e995085

Browse files
bnoordhuissaghul
authored andcommittedJan 16, 2024
Fix evaluation order of computed properties
The evaluation order is observable. Align with what test262 expects.
1 parent 48e4c63 commit e995085

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed
 

‎quickjs.c

+29
Original file line numberDiff line numberDiff line change
@@ -23716,11 +23716,40 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
2371623716
if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, (op != '='), op) < 0)
2371723717
return -1;
2371823718

23719+
// comply with rather obtuse evaluation order of computed properties:
23720+
// obj[key]=val evaluates val->obj->key when obj is null/undefined
23721+
// but key->obj->val when an object
23722+
// FIXME(bnoordhuis) less stack shuffling; don't to_propkey twice in
23723+
// happy path; replace `dup is_undefined_or_null if_true` with new
23724+
// opcode if_undefined_or_null? replace `swap dup` with over?
23725+
if (op == '=' && opcode == OP_get_array_el) {
23726+
int label_next = -1;
23727+
JSFunctionDef *fd = s->cur_func;
23728+
assert(OP_to_propkey2 == fd->byte_code.buf[fd->last_opcode_pos]);
23729+
fd->byte_code.size = fd->last_opcode_pos;
23730+
fd->last_opcode_pos = -1;
23731+
emit_op(s, OP_swap); // obj key -> key obj
23732+
emit_op(s, OP_dup);
23733+
emit_op(s, OP_is_undefined_or_null);
23734+
label_next = emit_goto(s, OP_if_true, -1);
23735+
emit_op(s, OP_swap);
23736+
emit_op(s, OP_to_propkey);
23737+
emit_op(s, OP_swap);
23738+
emit_label(s, label_next);
23739+
emit_op(s, OP_swap);
23740+
}
23741+
2371923742
if (js_parse_assign_expr2(s, parse_flags)) {
2372023743
JS_FreeAtom(s->ctx, name);
2372123744
return -1;
2372223745
}
2372323746

23747+
if (op == '=' && opcode == OP_get_array_el) {
23748+
emit_op(s, OP_swap); // obj key val -> obj val key
23749+
emit_op(s, OP_to_propkey);
23750+
emit_op(s, OP_swap);
23751+
}
23752+
2372423753
if (op == '=') {
2372523754
if (opcode == OP_get_ref_value && name == name0) {
2372623755
set_object_name(s, name);

‎test262_errors.txt

-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@ test262/test/built-ins/RegExp/lookahead-quantifier-match-groups.js:27: Test262Er
33
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
44
test262/test/language/expressions/arrow-function/static-init-await-reference.js:12: unexpected error type: Test262: This statement should not be evaluated.
55
test262/test/language/expressions/arrow-function/static-init-await-reference.js:12: strict mode: unexpected error type: Test262: This statement should not be evaluated.
6-
test262/test/language/expressions/assignment/target-member-computed-reference-null.js:32: Test262Error: Expected a DummyError but got a TypeError
7-
test262/test/language/expressions/assignment/target-member-computed-reference-null.js:32: strict mode: Test262Error: Expected a DummyError but got a TypeError
8-
test262/test/language/expressions/assignment/target-member-computed-reference-undefined.js:32: Test262Error: Expected a DummyError but got a TypeError
9-
test262/test/language/expressions/assignment/target-member-computed-reference-undefined.js:32: strict mode: Test262Error: Expected a DummyError but got a TypeError
106
test262/test/language/expressions/function/static-init-await-binding.js:16: SyntaxError: 'await' is a reserved identifier
117
test262/test/language/expressions/function/static-init-await-binding.js:16: strict mode: SyntaxError: 'await' is a reserved identifier
128
test262/test/language/expressions/generators/static-init-await-binding.js:16: SyntaxError: 'await' is a reserved identifier

0 commit comments

Comments
 (0)
Please sign in to comment.