mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Fix evaluation order in non-binding destructuring patterns (#4173)
JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
parent
28c186c98f
commit
2f08d8ac08
@ -30,7 +30,7 @@ extern "C"
|
||||
/**
|
||||
* Jerry snapshot format version.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_VERSION (56u)
|
||||
#define JERRY_SNAPSHOT_VERSION (57u)
|
||||
|
||||
/**
|
||||
* Flags for jerry_generate_snapshot and jerry_generate_function_snapshot.
|
||||
|
||||
@ -27,7 +27,7 @@ JERRY_STATIC_ASSERT ((sizeof (cbc_uint16_arguments_t) % sizeof (jmem_cpointer_t)
|
||||
*/
|
||||
JERRY_STATIC_ASSERT (CBC_END == 238,
|
||||
number_of_cbc_opcodes_changed);
|
||||
JERRY_STATIC_ASSERT (CBC_EXT_END == 136,
|
||||
JERRY_STATIC_ASSERT (CBC_EXT_END == 135,
|
||||
number_of_cbc_ext_opcodes_changed);
|
||||
|
||||
#if ENABLED (JERRY_PARSER)
|
||||
|
||||
@ -724,24 +724,22 @@
|
||||
VM_OC_APPEND_ARRAY) \
|
||||
CBC_OPCODE (CBC_EXT_REST_INITIALIZER, CBC_NO_FLAG, 1, \
|
||||
VM_OC_REST_INITIALIZER) \
|
||||
CBC_OPCODE (CBC_EXT_REST_INITIALIZER_2, CBC_NO_FLAG, 1, \
|
||||
VM_OC_REST_INITIALIZER) \
|
||||
CBC_OPCODE (CBC_EXT_REST_INITIALIZER_3, CBC_NO_FLAG, 1, \
|
||||
VM_OC_REST_INITIALIZER) \
|
||||
CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 1, \
|
||||
VM_OC_INITIALIZER_PUSH_PROP | VM_OC_GET_LITERAL) \
|
||||
CBC_OPCODE (CBC_EXT_SPREAD_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0, \
|
||||
VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_EXT_MOVE, CBC_NO_FLAG, 0, \
|
||||
VM_OC_MOVE) \
|
||||
CBC_OPCODE (CBC_EXT_MOVE_2, CBC_NO_FLAG, 0, \
|
||||
VM_OC_MOVE) \
|
||||
CBC_OPCODE (CBC_EXT_MOVE_3, CBC_NO_FLAG, 0, \
|
||||
VM_OC_MOVE) \
|
||||
\
|
||||
/* Iterator related opcodes. */ \
|
||||
CBC_OPCODE (CBC_EXT_GET_ITERATOR, CBC_NO_FLAG, 1, \
|
||||
VM_OC_GET_ITERATOR) \
|
||||
CBC_OPCODE (CBC_EXT_ITERATOR_STEP, CBC_NO_FLAG, 1, \
|
||||
VM_OC_ITERATOR_STEP) \
|
||||
CBC_OPCODE (CBC_EXT_ITERATOR_STEP_2, CBC_NO_FLAG, 1, \
|
||||
VM_OC_ITERATOR_STEP) \
|
||||
CBC_OPCODE (CBC_EXT_ITERATOR_STEP_3, CBC_NO_FLAG, 1, \
|
||||
VM_OC_ITERATOR_STEP) \
|
||||
CBC_OPCODE (CBC_EXT_ITERATOR_CLOSE, CBC_NO_FLAG, -1, \
|
||||
VM_OC_ITERATOR_CLOSE | VM_OC_GET_STACK) \
|
||||
\
|
||||
|
||||
@ -3192,13 +3192,10 @@ parser_pattern_form_assignment (parser_context_t *context_p, /**< context */
|
||||
parser_stack_push_uint8 (context_p, LEXER_EXPRESSION_START);
|
||||
uint8_t assign_opcode = parser_append_binary_single_assignment_token (context_p, flags);
|
||||
|
||||
if (flags & PARSER_PATTERN_ARRAY)
|
||||
{
|
||||
int32_t stack_adjustment = (CBC_STACK_ADJUST_BASE - (cbc_flags[assign_opcode] >> CBC_STACK_ADJUST_SHIFT));
|
||||
JERRY_ASSERT (stack_adjustment >= 1 && stack_adjustment <= 3);
|
||||
int32_t stack_adjustment = (CBC_STACK_ADJUST_BASE - (cbc_flags[assign_opcode] >> CBC_STACK_ADJUST_SHIFT));
|
||||
JERRY_ASSERT (stack_adjustment >= 1 && stack_adjustment <= 3);
|
||||
|
||||
rhs_opcode = (uint16_t) (rhs_opcode + stack_adjustment - 1);
|
||||
}
|
||||
rhs_opcode = (uint16_t) (rhs_opcode + stack_adjustment - 1);
|
||||
|
||||
parser_pattern_emit_rhs (context_p, rhs_opcode, literal_index);
|
||||
|
||||
@ -3366,6 +3363,9 @@ parser_pattern_process_assignment (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* RHS should be evaulated first */
|
||||
parser_pattern_emit_rhs (context_p, rhs_opcode, literal_index);
|
||||
|
||||
parser_flush_cbc (context_p);
|
||||
parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA | PARSE_EXPR_LEFT_HAND_SIDE);
|
||||
|
||||
@ -3373,6 +3373,9 @@ parser_pattern_process_assignment (parser_context_t *context_p, /**< context */
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN);
|
||||
}
|
||||
|
||||
rhs_opcode = CBC_EXT_MOVE;
|
||||
literal_index = PARSER_PATTERN_RHS_NO_LIT;
|
||||
}
|
||||
|
||||
parser_pattern_form_assignment (context_p, flags, rhs_opcode, literal_index, ident_line_counter);
|
||||
@ -3386,7 +3389,6 @@ parser_parse_array_initializer (parser_context_t *context_p, /**< context */
|
||||
parser_pattern_flags_t flags) /**< flags */
|
||||
{
|
||||
parser_pattern_end_marker_t end_pos = parser_pattern_get_target (context_p, flags);
|
||||
flags |= PARSER_PATTERN_ARRAY;
|
||||
|
||||
lexer_next_token (context_p);
|
||||
parser_emit_cbc_ext (context_p, CBC_EXT_GET_ITERATOR);
|
||||
|
||||
@ -115,7 +115,6 @@ typedef enum
|
||||
PARSER_PATTERN_LOCAL = (1u << 6), /**< pattern is a local (catch parameter) declaration */
|
||||
PARSER_PATTERN_REST_ELEMENT = (1u << 7), /**< parse rest array initializer */
|
||||
PARSER_PATTERN_ARGUMENTS = (1u << 8), /**< parse arguments binding */
|
||||
PARSER_PATTERN_ARRAY = (1u << 9), /**< array pattern is being parsed */
|
||||
} parser_pattern_flags_t;
|
||||
|
||||
/**
|
||||
|
||||
@ -2142,9 +2142,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
}
|
||||
case VM_OC_ITERATOR_STEP:
|
||||
{
|
||||
JERRY_ASSERT (opcode >= CBC_EXT_ITERATOR_STEP && opcode <= CBC_EXT_ITERATOR_STEP_3);
|
||||
const uint8_t index = (uint8_t) (1 + (opcode - CBC_EXT_ITERATOR_STEP));
|
||||
result = ecma_op_iterator_step (stack_top_p[-index], ECMA_VALUE_EMPTY);
|
||||
result = ecma_op_iterator_step (stack_top_p[-1], ECMA_VALUE_EMPTY);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
@ -2194,10 +2192,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
}
|
||||
case VM_OC_REST_INITIALIZER:
|
||||
{
|
||||
JERRY_ASSERT (opcode >= CBC_EXT_REST_INITIALIZER && opcode <= CBC_EXT_REST_INITIALIZER_3);
|
||||
const uint8_t iterator_index = (uint8_t) (1 + (opcode - CBC_EXT_REST_INITIALIZER));
|
||||
ecma_object_t *array_p = ecma_op_new_fast_array_object (0);
|
||||
ecma_value_t iterator = stack_top_p[-iterator_index];
|
||||
ecma_value_t iterator = stack_top_p[-1];
|
||||
uint32_t index = 0;
|
||||
|
||||
while (true)
|
||||
@ -2245,6 +2241,21 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
*stack_top_p++ = result;
|
||||
goto free_left_value;
|
||||
}
|
||||
case VM_OC_MOVE:
|
||||
{
|
||||
JERRY_ASSERT (opcode >= CBC_EXT_MOVE && opcode <= CBC_EXT_MOVE_3);
|
||||
const uint8_t index = (uint8_t) (1 + (opcode - CBC_EXT_MOVE));
|
||||
|
||||
ecma_value_t element = stack_top_p[-index];
|
||||
|
||||
for (int32_t i = -index; i < -1; i++)
|
||||
{
|
||||
stack_top_p[i] = stack_top_p[i + 1];
|
||||
}
|
||||
|
||||
stack_top_p[-1] = element;
|
||||
continue;
|
||||
}
|
||||
case VM_OC_SPREAD_ARGUMENTS:
|
||||
{
|
||||
uint8_t arguments_list_len = *byte_code_p++;
|
||||
|
||||
@ -274,6 +274,7 @@ typedef enum
|
||||
VM_OC_DEFAULT_INITIALIZER, /**< default initializer inside a pattern */
|
||||
VM_OC_REST_INITIALIZER, /**< create rest object inside an array pattern */
|
||||
VM_OC_INITIALIZER_PUSH_PROP, /**< push property for object initializer */
|
||||
VM_OC_MOVE, /**< move element to the stack-top */
|
||||
VM_OC_SPREAD_ARGUMENTS, /**< perform function call/construct with spreaded arguments */
|
||||
VM_OC_CREATE_GENERATOR, /**< create a generator object */
|
||||
VM_OC_YIELD, /**< yield operation */
|
||||
@ -350,6 +351,7 @@ typedef enum
|
||||
VM_OC_DEFAULT_INITIALIZER = VM_OC_NONE, /**< default initializer inside a pattern */
|
||||
VM_OC_REST_INITIALIZER = VM_OC_NONE, /**< create rest object inside an array pattern */
|
||||
VM_OC_INITIALIZER_PUSH_PROP = VM_OC_NONE, /**< push property for object initializer */
|
||||
VM_OC_MOVE = VM_OC_NONE, /**< move element to the stack-top */
|
||||
VM_OC_SPREAD_ARGUMENTS = VM_OC_NONE, /**< perform function call/construct with spreaded arguments */
|
||||
VM_OC_CREATE_GENERATOR = VM_OC_NONE, /**< create a generator object */
|
||||
VM_OC_YIELD = VM_OC_NONE, /**< yield operation */
|
||||
|
||||
@ -281,6 +281,54 @@ function __createIterableObject (arr, methods) {
|
||||
assert (b === 2);
|
||||
}) ();
|
||||
|
||||
(function () {
|
||||
var value = { y: "42" };
|
||||
var x = {};
|
||||
var assignmentResult, iterationResult, iter;
|
||||
|
||||
iter = (function*() {
|
||||
assignmentResult = { y: x[yield] } = value;
|
||||
}());
|
||||
|
||||
iterationResult = iter.next();
|
||||
|
||||
assert (assignmentResult === undefined);
|
||||
assert (iterationResult.value === undefined);
|
||||
assert (iterationResult.done === false);
|
||||
assert (x.prop === undefined);
|
||||
|
||||
iterationResult = iter.next('prop');
|
||||
|
||||
assert (assignmentResult === value);
|
||||
assert (iterationResult.value === undefined);
|
||||
assert (iterationResult.done === true);
|
||||
assert (x.prop === "42");
|
||||
}) ();
|
||||
|
||||
(function () {
|
||||
var value = { foo: "42" };
|
||||
var x = {};
|
||||
var assignmentResult, iterationResult, iter;
|
||||
|
||||
iter = (function*() {
|
||||
assignmentResult = { ['f' + 'o' + 'o']: x[yield] } = value;
|
||||
}());
|
||||
|
||||
iterationResult = iter.next();
|
||||
|
||||
assert (assignmentResult === undefined);
|
||||
assert (iterationResult.value === undefined);
|
||||
assert (iterationResult.done === false);
|
||||
assert (x.prop === undefined);
|
||||
|
||||
iterationResult = iter.next('prop');
|
||||
|
||||
assert (assignmentResult === value);
|
||||
assert (iterationResult.value === undefined);
|
||||
assert (iterationResult.done === true);
|
||||
assert (x.prop === "42");
|
||||
}) ();
|
||||
|
||||
mustThrow ("var iter = __createIterableObject([], "
|
||||
+ "{ get 'return'() { throw new TypeError() }});"
|
||||
+ "var [a] = iter");
|
||||
|
||||
@ -226,6 +226,14 @@ mustThrow ("function f ({}) {}; f();");
|
||||
assert (a === 7);
|
||||
}) ();
|
||||
|
||||
(function () {
|
||||
var o = {};
|
||||
|
||||
({ a : o.c } = { get a() { return 5.2 }})
|
||||
|
||||
assert(o.c == 5.2);
|
||||
}) ();
|
||||
|
||||
try {
|
||||
eval ("var a = 0; -{a} = {a:1}");
|
||||
assert (false);
|
||||
|
||||
@ -255,10 +255,6 @@
|
||||
<test id="language/block-scope/syntax/redeclaration-in-block/attempt-to-redeclare-function-declaration-with-function-declaration.js"><reason>No longer a SyntaxError in ES11</reason></test>
|
||||
<test id="language/default-parameters/function-length.js"><reason></reason></test>
|
||||
<test id="language/expressions/arrow-function/lexical-super-call-from-within-constructor.js"><reason></reason></test>
|
||||
<test id="language/expressions/assignment/destructuring/obj-prop-elem-target-yield-expr.js"><reason></reason></test>
|
||||
<test id="language/expressions/assignment/destructuring/obj-prop-elem-target-yield-ident-valid.js"><reason></reason></test>
|
||||
<test id="language/expressions/assignment/destructuring/obj-prop-put-prop-ref.js"><reason></reason></test>
|
||||
<test id="language/expressions/assignment/destructuring/obj-prop-put-prop-ref-no-get.js"><reason></reason></test>
|
||||
<test id="language/expressions/assignment/S11.13.1_A5_T1.js"><reason></reason></test>
|
||||
<test id="language/expressions/assignment/S11.13.1_A5_T2.js"><reason></reason></test>
|
||||
<test id="language/expressions/assignment/S11.13.1_A5_T3.js"><reason></reason></test>
|
||||
|
||||
@ -3047,10 +3047,6 @@
|
||||
<test id="language/expressions/assignment/dstr/obj-prop-elem-target-obj-literal-prop-ref-init-active.js"><reason></reason></test>
|
||||
<test id="language/expressions/assignment/dstr/obj-prop-elem-target-obj-literal-prop-ref-init.js"><reason></reason></test>
|
||||
<test id="language/expressions/assignment/dstr/obj-prop-elem-target-obj-literal-prop-ref.js"><reason></reason></test>
|
||||
<test id="language/expressions/assignment/dstr/obj-prop-elem-target-yield-expr.js"><reason></reason></test>
|
||||
<test id="language/expressions/assignment/dstr/obj-prop-elem-target-yield-ident-valid.js"><reason></reason></test>
|
||||
<test id="language/expressions/assignment/dstr/obj-prop-put-prop-ref-no-get.js"><reason></reason></test>
|
||||
<test id="language/expressions/assignment/dstr/obj-prop-put-prop-ref.js"><reason></reason></test>
|
||||
<test id="language/expressions/assignment/dstr/obj-rest-computed-property-no-strict.js"><reason></reason></test>
|
||||
<test id="language/expressions/assignment/dstr/obj-rest-computed-property.js"><reason></reason></test>
|
||||
<test id="language/expressions/assignment/dstr/obj-rest-descriptors.js"><reason></reason></test>
|
||||
@ -4624,10 +4620,6 @@
|
||||
<test id="language/statements/for-of/dstr/obj-prop-elem-target-obj-literal-prop-ref-init-active.js"><reason></reason></test>
|
||||
<test id="language/statements/for-of/dstr/obj-prop-elem-target-obj-literal-prop-ref-init.js"><reason></reason></test>
|
||||
<test id="language/statements/for-of/dstr/obj-prop-elem-target-obj-literal-prop-ref.js"><reason></reason></test>
|
||||
<test id="language/statements/for-of/dstr/obj-prop-elem-target-yield-expr.js"><reason></reason></test>
|
||||
<test id="language/statements/for-of/dstr/obj-prop-elem-target-yield-ident-valid.js"><reason></reason></test>
|
||||
<test id="language/statements/for-of/dstr/obj-prop-put-prop-ref-no-get.js"><reason></reason></test>
|
||||
<test id="language/statements/for-of/dstr/obj-prop-put-prop-ref.js"><reason></reason></test>
|
||||
<test id="language/statements/for-of/dstr/obj-rest-computed-property-no-strict.js"><reason></reason></test>
|
||||
<test id="language/statements/for-of/dstr/obj-rest-computed-property.js"><reason></reason></test>
|
||||
<test id="language/statements/for-of/dstr/obj-rest-descriptors.js"><reason></reason></test>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user