Improve destructuring patterns (#4527)

- Fix evaluation order of the operands
- Implement proper iterator closing of array destructuring
- Support next method caching

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
Robert Fancsik
2021-02-04 13:11:11 +01:00
committed by GitHub
parent 3bb67397a0
commit e7d11eaf9e
12 changed files with 389 additions and 354 deletions
+30
View File
@@ -562,6 +562,21 @@ ecma_gc_mark_executable_object (ecma_object_t *object_p) /**< object */
do do
{ {
if (VM_CONTEXT_IS_VARIABLE_LENGTH (VM_GET_CONTEXT_TYPE (context_top_p[-1])))
{
ecma_value_t *last_item_p = context_top_p - VM_GET_CONTEXT_END (context_top_p[-1]);
JERRY_ASSERT (last_item_p >= context_end_p);
context_top_p--;
do
{
ecma_gc_set_object_visited (ecma_get_object_from_value (*(--context_top_p)));
}
while (context_top_p > last_item_p);
continue;
}
uint32_t offsets = vm_get_context_value_offsets (context_top_p); uint32_t offsets = vm_get_context_value_offsets (context_top_p);
while (VM_CONTEXT_HAS_NEXT_OFFSET (offsets)) while (VM_CONTEXT_HAS_NEXT_OFFSET (offsets))
@@ -1245,6 +1260,21 @@ ecma_gc_free_executable_object (ecma_object_t *object_p) /**< object */
{ {
context_top_p[-1] &= (uint32_t) ~VM_CONTEXT_HAS_LEX_ENV; context_top_p[-1] &= (uint32_t) ~VM_CONTEXT_HAS_LEX_ENV;
if (VM_CONTEXT_IS_VARIABLE_LENGTH (VM_GET_CONTEXT_TYPE (context_top_p[-1])))
{
ecma_value_t *last_item_p = context_top_p - VM_GET_CONTEXT_END (context_top_p[-1]);
JERRY_ASSERT (last_item_p >= context_end_p);
context_top_p--;
do
{
ecma_free_value_if_not_object (*(--context_top_p));
}
while (context_top_p > last_item_p);
continue;
}
uint32_t offsets = vm_get_context_value_offsets (context_top_p); uint32_t offsets = vm_get_context_value_offsets (context_top_p);
while (VM_CONTEXT_HAS_NEXT_OFFSET (offsets)) while (VM_CONTEXT_HAS_NEXT_OFFSET (offsets))
@@ -175,11 +175,8 @@ ecma_op_get_iterator (ecma_value_t value, /**< value to get iterator from */
ecma_value_t method, /**< provided method argument */ ecma_value_t method, /**< provided method argument */
ecma_value_t *next_method_p) /**< [out] next method */ ecma_value_t *next_method_p) /**< [out] next method */
{ {
if (next_method_p != NULL) JERRY_ASSERT (next_method_p != NULL);
{ *next_method_p = ECMA_VALUE_UNDEFINED;
/* TODO: NULL support should be removed after all functions support next method caching. */
*next_method_p = ECMA_VALUE_UNDEFINED;
}
/* 1. */ /* 1. */
if (ECMA_IS_VALUE_ERROR (value)) if (ECMA_IS_VALUE_ERROR (value))
@@ -215,7 +212,7 @@ ecma_op_get_iterator (ecma_value_t value, /**< value to get iterator from */
} }
/* 3. */ /* 3. */
if (!ecma_is_value_object (method) || !ecma_op_is_callable (method)) if (!ecma_op_is_callable (method))
{ {
ecma_free_value (method); ecma_free_value (method);
return ecma_raise_type_error (ECMA_ERR_MSG ("Iterator is not function")); return ecma_raise_type_error (ECMA_ERR_MSG ("Iterator is not function"));
@@ -242,84 +239,28 @@ ecma_op_get_iterator (ecma_value_t value, /**< value to get iterator from */
return ecma_raise_type_error (ECMA_ERR_MSG ("Iterator is not an object")); return ecma_raise_type_error (ECMA_ERR_MSG ("Iterator is not an object"));
} }
if (next_method_p != NULL) ecma_object_t *obj_p = ecma_get_object_from_value (iterator);
ecma_value_t next_method = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_NEXT);
if (ECMA_IS_VALUE_ERROR (next_method))
{ {
ecma_object_t *obj_p = ecma_get_object_from_value (iterator); ecma_free_value (iterator);
ecma_value_t next_method = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_NEXT); return next_method;
}
if (ECMA_IS_VALUE_ERROR (next_method)) if (ecma_is_value_object (next_method) && ecma_op_is_callable (next_method))
{ {
ecma_free_value (iterator); *next_method_p = next_method;
return next_method; }
} else
{
if (ecma_is_value_object (next_method) && ecma_op_is_callable (next_method)) ecma_free_value (next_method);
{
*next_method_p = next_method;
}
else
{
ecma_free_value (next_method);
}
} }
/* 6. */ /* 6. */
return iterator; return iterator;
} /* ecma_op_get_iterator */ } /* ecma_op_get_iterator */
/**
* IteratorNext operation
*
* See also: ECMA-262 v6, 7.4.2
*
* Note:
* Returned value must be freed with ecma_free_value.
*
* @return iterator result object - if success
* raised error - otherwise
*/
static ecma_value_t
ecma_op_iterator_next_old (ecma_value_t iterator, /**< iterator value */
ecma_value_t value) /**< the routines's value argument */
{
JERRY_ASSERT (ecma_is_value_object (iterator));
/* 1 - 2. */
ecma_object_t *obj_p = ecma_get_object_from_value (iterator);
ecma_value_t func_next = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_NEXT);
if (ECMA_IS_VALUE_ERROR (func_next))
{
return func_next;
}
if (!ecma_is_value_object (func_next) || !ecma_op_is_callable (func_next))
{
ecma_free_value (func_next);
return ecma_raise_type_error (ECMA_ERR_MSG ("Iterator 'next' is not callable"));
}
ecma_object_t *next_obj_p = ecma_get_object_from_value (func_next);
bool has_value = !ecma_is_value_empty (value);
ecma_value_t result;
if (has_value)
{
result = ecma_op_function_call (next_obj_p, iterator, &value, 1);
}
else
{
result = ecma_op_function_call (next_obj_p, iterator, NULL, 0);
}
ecma_free_value (func_next);
/* 5. */
return result;
} /* ecma_op_iterator_next_old */
/** /**
* IteratorNext operation * IteratorNext operation
* *
@@ -386,7 +327,7 @@ ecma_op_iterator_return (ecma_value_t iterator, /**< iterator value */
return ecma_create_iter_result_object (value, ECMA_VALUE_TRUE); return ecma_create_iter_result_object (value, ECMA_VALUE_TRUE);
} }
if (!ecma_is_value_object (func_return) || !ecma_op_is_callable (func_return)) if (!ecma_op_is_callable (func_return))
{ {
ecma_free_value (func_return); ecma_free_value (func_return);
return ecma_raise_type_error (ECMA_ERR_MSG ("Iterator 'return' is not callable")); return ecma_raise_type_error (ECMA_ERR_MSG ("Iterator 'return' is not callable"));
@@ -582,16 +523,7 @@ ecma_op_iterator_step (ecma_value_t iterator, /**< iterator value */
ecma_value_t next_method) /**< next method */ ecma_value_t next_method) /**< next method */
{ {
/* 1. */ /* 1. */
ecma_value_t result; ecma_value_t result = ecma_op_iterator_next (iterator, next_method, ECMA_VALUE_EMPTY);
if (next_method == ECMA_VALUE_EMPTY)
{
/* TODO: EMPTY support should be removed after all functions support next method caching. */
result = ecma_op_iterator_next_old (iterator, ECMA_VALUE_EMPTY);
}
else
{
result = ecma_op_iterator_next (iterator, next_method, ECMA_VALUE_EMPTY);
}
/* 2. */ /* 2. */
if (ECMA_IS_VALUE_ERROR (result)) if (ECMA_IS_VALUE_ERROR (result))
+1 -1
View File
@@ -30,7 +30,7 @@ extern "C"
/** /**
* Jerry snapshot format version. * Jerry snapshot format version.
*/ */
#define JERRY_SNAPSHOT_VERSION (63u) #define JERRY_SNAPSHOT_VERSION (64u)
/** /**
* Flags for jerry_generate_snapshot and jerry_generate_function_snapshot. * Flags for jerry_generate_snapshot and jerry_generate_function_snapshot.
+1 -1
View File
@@ -27,7 +27,7 @@ JERRY_STATIC_ASSERT ((sizeof (cbc_uint16_arguments_t) % sizeof (jmem_cpointer_t)
*/ */
JERRY_STATIC_ASSERT (CBC_END == 238, JERRY_STATIC_ASSERT (CBC_END == 238,
number_of_cbc_opcodes_changed); number_of_cbc_opcodes_changed);
JERRY_STATIC_ASSERT (CBC_EXT_END == 148, JERRY_STATIC_ASSERT (CBC_EXT_END == 147,
number_of_cbc_ext_opcodes_changed); number_of_cbc_ext_opcodes_changed);
#if ENABLED (JERRY_PARSER) || ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) #if ENABLED (JERRY_PARSER) || ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
+19 -15
View File
@@ -202,6 +202,12 @@
#define PARSER_WITH_CONTEXT_STACK_ALLOCATION 1 #define PARSER_WITH_CONTEXT_STACK_ALLOCATION 1
/* PARSER_BLOCK_CONTEXT_STACK_ALLOCATION must be <= 3 */ /* PARSER_BLOCK_CONTEXT_STACK_ALLOCATION must be <= 3 */
#define PARSER_BLOCK_CONTEXT_STACK_ALLOCATION 1 #define PARSER_BLOCK_CONTEXT_STACK_ALLOCATION 1
/* PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION must be <= 3 */
#define PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION 3
/* PARSER_OBJECT_INITIALIZER_CONTEXT_STACK_ALLOCATION must be <= 2 */
#define PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION 1
/* PARSER_OBJECT_INITIALIZER_CONTEXT_STACK_ALLOCATION must be <= 2 */
#define PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION 2
/** /**
* Extra stack consumption for finally context. * Extra stack consumption for finally context.
@@ -573,7 +579,7 @@
CBC_FORWARD_BRANCH (CBC_EXT_FINALLY, PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION, \ CBC_FORWARD_BRANCH (CBC_EXT_FINALLY, PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION, \
VM_OC_FINALLY) \ VM_OC_FINALLY) \
CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP, CBC_NO_FLAG, 0, \ CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP, CBC_NO_FLAG, 0, \
VM_OC_INITIALIZER_PUSH_PROP | VM_OC_GET_STACK) \ VM_OC_INITIALIZER_PUSH_PROP) \
CBC_FORWARD_BRANCH (CBC_EXT_DEFAULT_INITIALIZER, -1, \ CBC_FORWARD_BRANCH (CBC_EXT_DEFAULT_INITIALIZER, -1, \
VM_OC_DEFAULT_INITIALIZER) \ VM_OC_DEFAULT_INITIALIZER) \
CBC_OPCODE (CBC_EXT_ERROR, CBC_NO_FLAG, 0, \ CBC_OPCODE (CBC_EXT_ERROR, CBC_NO_FLAG, 0, \
@@ -746,26 +752,24 @@
VM_OC_INITIALIZER_PUSH_PROP | VM_OC_GET_LITERAL) \ VM_OC_INITIALIZER_PUSH_PROP | VM_OC_GET_LITERAL) \
CBC_OPCODE (CBC_EXT_SPREAD_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0, \ CBC_OPCODE (CBC_EXT_SPREAD_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0, \
VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK) \ 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. */ \ /* Iterator related opcodes. */ \
CBC_OPCODE (CBC_EXT_GET_ITERATOR, CBC_NO_FLAG, 1, \ CBC_OPCODE (CBC_EXT_ITERATOR_CONTEXT_CREATE, CBC_NO_FLAG, PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION, \
VM_OC_GET_ITERATOR) \ VM_OC_ITERATOR_CONTEXT_CREATE) \
CBC_OPCODE (CBC_EXT_ITERATOR_CONTEXT_END, CBC_NO_FLAG, -PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION, \
VM_OC_ITERATOR_CONTEXT_END) \
CBC_OPCODE (CBC_EXT_ITERATOR_STEP, CBC_NO_FLAG, 1, \ CBC_OPCODE (CBC_EXT_ITERATOR_STEP, CBC_NO_FLAG, 1, \
VM_OC_ITERATOR_STEP) \ VM_OC_ITERATOR_STEP) \
CBC_OPCODE (CBC_EXT_ITERATOR_CLOSE, CBC_NO_FLAG, -1, \
VM_OC_ITERATOR_CLOSE | VM_OC_GET_STACK) \
\ \
/* Object initializer related opcodes. */ \ /* Object initializer related opcodes. */ \
CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_LIST, CBC_NO_FLAG, 1, \ CBC_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_CREATE, CBC_NO_FLAG, PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION, \
VM_OC_INITIALIZER_PUSH_LIST) \ VM_OC_OBJ_INIT_CONTEXT_CREATE) \
CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_REST, CBC_NO_FLAG, 0, \ CBC_OPCODE (CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE, CBC_NO_FLAG, PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION, \
VM_OC_INITIALIZER_PUSH_REST) \ VM_OC_OBJ_INIT_CONTEXT_CREATE) \
CBC_OPCODE (CBC_EXT_OBJ_INIT_PUSH_REST, CBC_NO_FLAG, 1, \
VM_OC_OBJ_INIT_PUSH_REST) \
CBC_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_END, CBC_NO_FLAG, -PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION, \
VM_OC_OBJ_INIT_CONTEXT_END) \
CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME, CBC_NO_FLAG, 0, \ CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME, CBC_NO_FLAG, 0, \
VM_OC_INITIALIZER_PUSH_NAME | VM_OC_GET_STACK) \ VM_OC_INITIALIZER_PUSH_NAME | VM_OC_GET_STACK) \
CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL, CBC_HAS_LITERAL_ARG, 1, \ CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL, CBC_HAS_LITERAL_ARG, 1, \
+18 -21
View File
@@ -2755,7 +2755,7 @@ parser_process_unary_expression (parser_context_t *context_p, /**< context */
* *
* @return - pushed assignment opcode onto the parser stack * @return - pushed assignment opcode onto the parser stack
*/ */
static uint8_t static void
parser_append_binary_single_assignment_token (parser_context_t *context_p, /**< context */ parser_append_binary_single_assignment_token (parser_context_t *context_p, /**< context */
uint32_t pattern_flags) /**< pattern flags */ uint32_t pattern_flags) /**< pattern flags */
{ {
@@ -2899,8 +2899,6 @@ parser_append_binary_single_assignment_token (parser_context_t *context_p, /**<
parser_stack_push_uint8 (context_p, assign_opcode); parser_stack_push_uint8 (context_p, assign_opcode);
parser_stack_push_uint8 (context_p, LEXER_ASSIGN); parser_stack_push_uint8 (context_p, LEXER_ASSIGN);
return assign_opcode;
} /* parser_append_binary_single_assignment_token */ } /* parser_append_binary_single_assignment_token */
#if ENABLED (JERRY_ESNEXT) #if ENABLED (JERRY_ESNEXT)
@@ -3326,13 +3324,7 @@ parser_pattern_form_assignment (parser_context_t *context_p, /**< context */
} }
parser_stack_push_uint8 (context_p, LEXER_EXPRESSION_START); parser_stack_push_uint8 (context_p, LEXER_EXPRESSION_START);
uint8_t assign_opcode = parser_append_binary_single_assignment_token (context_p, flags); parser_append_binary_single_assignment_token (context_p, flags);
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);
parser_pattern_emit_rhs (context_p, rhs_opcode, literal_index); parser_pattern_emit_rhs (context_p, rhs_opcode, literal_index);
if (context_p->token.type == LEXER_ASSIGN && !(flags & PARSER_PATTERN_REST_ELEMENT)) if (context_p->token.type == LEXER_ASSIGN && !(flags & PARSER_PATTERN_REST_ELEMENT))
@@ -3518,19 +3510,12 @@ parser_pattern_process_assignment (parser_context_t *context_p, /**< context */
} }
else 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); parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA | PARSE_EXPR_LEFT_HAND_SIDE);
if (!PARSER_IS_PUSH_LITERAL (context_p->last_cbc_opcode) && !PARSER_IS_PUSH_PROP (context_p->last_cbc_opcode)) if (!PARSER_IS_PUSH_LITERAL (context_p->last_cbc_opcode) && !PARSER_IS_PUSH_PROP (context_p->last_cbc_opcode))
{ {
parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN); 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); parser_pattern_form_assignment (context_p, flags, rhs_opcode, literal_index, ident_line_counter);
@@ -3547,7 +3532,7 @@ parser_parse_array_initializer (parser_context_t *context_p, /**< context */
parser_pattern_end_marker_t end_pos = parser_pattern_get_target (context_p, flags); parser_pattern_end_marker_t end_pos = parser_pattern_get_target (context_p, flags);
lexer_next_token (context_p); lexer_next_token (context_p);
parser_emit_cbc_ext (context_p, CBC_EXT_GET_ITERATOR); parser_emit_cbc_ext (context_p, CBC_EXT_ITERATOR_CONTEXT_CREATE);
while (context_p->token.type != LEXER_RIGHT_SQUARE) while (context_p->token.type != LEXER_RIGHT_SQUARE)
{ {
@@ -3583,7 +3568,7 @@ parser_parse_array_initializer (parser_context_t *context_p, /**< context */
} }
/* close the iterator */ /* close the iterator */
parser_emit_cbc_ext (context_p, CBC_EXT_ITERATOR_CLOSE); parser_emit_cbc_ext (context_p, CBC_EXT_ITERATOR_CONTEXT_END);
parser_pattern_finalize (context_p, flags, &end_pos); parser_pattern_finalize (context_p, flags, &end_pos);
} /* parser_parse_array_initializer */ } /* parser_parse_array_initializer */
@@ -3606,11 +3591,15 @@ parser_parse_object_initializer (parser_context_t *context_p, /**< context */
return; return;
} }
cbc_ext_opcode_t context_opcode = CBC_EXT_OBJ_INIT_CONTEXT_CREATE;
if (flags & PARSER_PATTERN_HAS_REST_ELEMENT) if (flags & PARSER_PATTERN_HAS_REST_ELEMENT)
{ {
parser_emit_cbc_ext (context_p, CBC_EXT_INITIALIZER_PUSH_LIST); context_opcode = CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE;
} }
parser_emit_cbc_ext (context_p, context_opcode);
while (true) while (true)
{ {
lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_OBJECT_PATTERN); lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_OBJECT_PATTERN);
@@ -3633,7 +3622,7 @@ parser_parse_object_initializer (parser_context_t *context_p, /**< context */
if (parser_pattern_process_assignment (context_p, if (parser_pattern_process_assignment (context_p,
flags, flags,
CBC_EXT_INITIALIZER_PUSH_REST, CBC_EXT_OBJ_INIT_PUSH_REST,
PARSER_PATTERN_RHS_NO_LIT, PARSER_PATTERN_RHS_NO_LIT,
LEXER_RIGHT_BRACE)) LEXER_RIGHT_BRACE))
{ {
@@ -3724,6 +3713,14 @@ parser_parse_object_initializer (parser_context_t *context_p, /**< context */
} }
} }
if (flags & PARSER_PATTERN_HAS_REST_ELEMENT)
{
PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, (PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION
- PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION));
}
parser_emit_cbc_ext (context_p, CBC_EXT_OBJ_INIT_CONTEXT_END);
parser_pattern_finalize (context_p, flags, &end_pos); parser_pattern_finalize (context_p, flags, &end_pos);
} /* parser_parse_object_initializer */ } /* parser_parse_object_initializer */
+123 -48
View File
@@ -41,6 +41,41 @@ JERRY_STATIC_ASSERT (PARSER_WITH_CONTEXT_STACK_ALLOCATION == PARSER_TRY_CONTEXT_
JERRY_STATIC_ASSERT (PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION == PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION, JERRY_STATIC_ASSERT (PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION == PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION,
for_of_context_stack_allocation_must_be_equal_to_for_await_of_context_stack_allocation); for_of_context_stack_allocation_must_be_equal_to_for_await_of_context_stack_allocation);
#if ENABLED (JERRY_ESNEXT)
/**
* Abort (finalize) the current variable length stack context, and remove it.
*
* @return new stack top
*/
ecma_value_t *
vm_stack_context_abort_variable_length (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
ecma_value_t *vm_stack_top_p, /**< current stack top */
uint32_t context_stack_allocation) /**< 0 - if all context element
* should be released
* context stack allocation - otherwise */
{
JERRY_ASSERT (VM_CONTEXT_IS_VARIABLE_LENGTH (VM_GET_CONTEXT_TYPE (vm_stack_top_p[-1])));
uint32_t context_size = VM_GET_CONTEXT_END (vm_stack_top_p[-1]);
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, context_size);
JERRY_ASSERT (context_size > 0);
--vm_stack_top_p;
if (context_stack_allocation == 0)
{
context_stack_allocation = context_size;
}
for (uint32_t i = 1; i < context_stack_allocation; i++)
{
ecma_free_value (*(--vm_stack_top_p));
}
return vm_stack_top_p;
} /* vm_stack_context_abort_variable_length */
#endif /* ENABLED (JERRY_ESNEXT) */
/** /**
* Abort (finalize) the current stack context, and remove it. * Abort (finalize) the current stack context, and remove it.
* *
@@ -86,6 +121,13 @@ vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
break; break;
} }
#if ENABLED (JERRY_ESNEXT) #if ENABLED (JERRY_ESNEXT)
case VM_CONTEXT_ITERATOR:
case VM_CONTEXT_OBJ_INIT:
case VM_CONTEXT_OBJ_INIT_REST:
{
vm_stack_top_p = vm_stack_context_abort_variable_length (frame_ctx_p, vm_stack_top_p, 0);
break;
}
case VM_CONTEXT_FOR_OF: case VM_CONTEXT_FOR_OF:
case VM_CONTEXT_FOR_AWAIT_OF: case VM_CONTEXT_FOR_AWAIT_OF:
{ {
@@ -189,16 +231,16 @@ vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
while (frame_ctx_p->context_depth > 0) while (frame_ctx_p->context_depth > 0)
{ {
vm_stack_context_type_t context_type; vm_stack_context_type_t context_type = VM_GET_CONTEXT_TYPE (stack_top_p[-1]);
uint32_t context_end = VM_GET_CONTEXT_END (stack_top_p[-1]); uint32_t context_end = VM_GET_CONTEXT_END (stack_top_p[-1]);
JERRY_ASSERT (!VM_CONTEXT_IS_VARIABLE_LENGTH (context_type) || finally_type != VM_CONTEXT_FINALLY_JUMP);
if (search_limit < context_end) if (!VM_CONTEXT_IS_VARIABLE_LENGTH (context_type) && search_limit < context_end)
{ {
frame_ctx_p->stack_top_p = stack_top_p; frame_ctx_p->stack_top_p = stack_top_p;
return VM_CONTEXT_FOUND_EXPECTED; return VM_CONTEXT_FOUND_EXPECTED;
} }
context_type = VM_GET_CONTEXT_TYPE (stack_top_p[-1]);
if (context_type == VM_CONTEXT_TRY || context_type == VM_CONTEXT_CATCH) if (context_type == VM_CONTEXT_TRY || context_type == VM_CONTEXT_CATCH)
{ {
const uint8_t *byte_code_p; const uint8_t *byte_code_p;
@@ -314,7 +356,9 @@ vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
#if ENABLED (JERRY_ESNEXT) #if ENABLED (JERRY_ESNEXT)
else if (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR) else if (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR)
{ {
JERRY_ASSERT (context_type == VM_CONTEXT_FOR_OF || context_type == VM_CONTEXT_FOR_AWAIT_OF); JERRY_ASSERT (context_type == VM_CONTEXT_FOR_OF
|| context_type == VM_CONTEXT_FOR_AWAIT_OF
|| context_type == VM_CONTEXT_ITERATOR);
JERRY_ASSERT (finally_type == VM_CONTEXT_FINALLY_THROW || !jcontext_has_pending_exception ()); JERRY_ASSERT (finally_type == VM_CONTEXT_FINALLY_THROW || !jcontext_has_pending_exception ());
ecma_value_t exception = ECMA_VALUE_UNDEFINED; ecma_value_t exception = ECMA_VALUE_UNDEFINED;
@@ -323,62 +367,71 @@ vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
exception = jcontext_take_exception (); exception = jcontext_take_exception ();
} }
ecma_value_t iterator = stack_top_p[-3]; ecma_value_t result;
ecma_value_t result = ecma_op_get_method_by_magic_id (iterator, LIT_MAGIC_STRING_RETURN);
if (!ECMA_IS_VALUE_ERROR (result) && !ecma_is_value_undefined (result)) if (context_type == VM_CONTEXT_ITERATOR)
{ {
if (!ecma_is_value_object (result) || !ecma_op_is_callable (result)) result = ecma_op_iterator_close (stack_top_p[-2]);
{ }
ecma_free_value (result); else
result = ecma_raise_type_error (ECMA_ERR_MSG ("Iterator 'return' is not callable")); {
} ecma_value_t iterator = stack_top_p[-3];
else result = ecma_op_get_method_by_magic_id (iterator, LIT_MAGIC_STRING_RETURN);
{
ecma_object_t *return_obj_p = ecma_get_object_from_value (result);
result = ecma_op_function_call (return_obj_p, iterator, NULL, 0);
ecma_deref_object (return_obj_p);
if (context_type == VM_CONTEXT_FOR_AWAIT_OF && !ECMA_IS_VALUE_ERROR (result)) if (!ECMA_IS_VALUE_ERROR (result) && !ecma_is_value_undefined (result))
{
if (!ecma_op_is_callable (result))
{ {
ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); ecma_free_value (result);
result = ecma_raise_type_error (ECMA_ERR_MSG ("Iterator 'return' is not callable"));
}
else
{
ecma_object_t *return_obj_p = ecma_get_object_from_value (result);
result = ecma_op_function_call (return_obj_p, iterator, NULL, 0);
ecma_deref_object (return_obj_p);
result = ecma_promise_async_await (async_generator_object_p, result); if (context_type == VM_CONTEXT_FOR_AWAIT_OF && !ECMA_IS_VALUE_ERROR (result))
{
ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p);
result = ecma_promise_async_await (async_generator_object_p, result);
if (!ECMA_IS_VALUE_ERROR (result))
{
uint16_t extra_flags = (ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD
| (ECMA_AWAIT_FOR_CLOSE << ECMA_AWAIT_STATE_SHIFT));
async_generator_object_p->u.class_prop.extra_info |= extra_flags;
stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p);
VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FINALLY_CONTEXT_STACK_ALLOCATION);
stack_top_p += PARSER_FINALLY_CONTEXT_STACK_ALLOCATION;
stack_top_p[-1] = VM_CREATE_CONTEXT ((uint32_t) finally_type, context_end);
if (finally_type == VM_CONTEXT_FINALLY_THROW)
{
stack_top_p[-2] = exception;
}
frame_ctx_p->call_operation = VM_EXEC_RETURN;
frame_ctx_p->byte_code_p = vm_stack_resume_executable_object_with_context_end;
frame_ctx_p->stack_top_p = stack_top_p;
return VM_CONTEXT_FOUND_AWAIT;
}
}
if (!ECMA_IS_VALUE_ERROR (result)) if (!ECMA_IS_VALUE_ERROR (result))
{ {
uint16_t extra_flags = (ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD bool is_object = ecma_is_value_object (result);
| (ECMA_AWAIT_FOR_CLOSE << ECMA_AWAIT_STATE_SHIFT));
async_generator_object_p->u.class_prop.extra_info |= extra_flags;
stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p); ecma_free_value (result);
result = ECMA_VALUE_UNDEFINED;
VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FINALLY_CONTEXT_STACK_ALLOCATION); if (!is_object)
stack_top_p += PARSER_FINALLY_CONTEXT_STACK_ALLOCATION;
stack_top_p[-1] = VM_CREATE_CONTEXT ((uint32_t) finally_type, context_end);
if (finally_type == VM_CONTEXT_FINALLY_THROW)
{ {
stack_top_p[-2] = exception; result = ecma_raise_type_error (ECMA_ERR_MSG ("Iterator 'return' result is not object"));
} }
frame_ctx_p->call_operation = VM_EXEC_RETURN;
frame_ctx_p->byte_code_p = vm_stack_resume_executable_object_with_context_end;
frame_ctx_p->stack_top_p = stack_top_p;
return VM_CONTEXT_FOUND_AWAIT;
}
}
if (!ECMA_IS_VALUE_ERROR (result))
{
bool is_object = ecma_is_value_object (result);
ecma_free_value (result);
result = ECMA_VALUE_UNDEFINED;
if (!is_object)
{
result = ecma_raise_type_error (ECMA_ERR_MSG ("Iterator 'return' result is not object"));
} }
} }
} }
@@ -487,6 +540,28 @@ vm_ref_lex_env_chain (ecma_object_t *lex_env_p, /**< top of lexical environment
lex_env_p = next_lex_env_p; lex_env_p = next_lex_env_p;
} }
if (VM_CONTEXT_IS_VARIABLE_LENGTH (VM_GET_CONTEXT_TYPE (context_top_p[-1])))
{
ecma_value_t *last_item_p = context_top_p - VM_GET_CONTEXT_END (context_top_p[-1]);
JERRY_ASSERT (last_item_p >= context_end_p);
context_top_p--;
do
{
if (do_ref)
{
ecma_ref_if_object (*(--context_top_p));
}
else
{
ecma_deref_if_object (*(--context_top_p));
}
}
while (context_top_p > last_item_p);
continue;
}
uint32_t offsets = vm_get_context_value_offsets (context_top_p); uint32_t offsets = vm_get_context_value_offsets (context_top_p);
while (VM_CONTEXT_HAS_NEXT_OFFSET (offsets)) while (VM_CONTEXT_HAS_NEXT_OFFSET (offsets))
+24
View File
@@ -75,6 +75,11 @@ typedef enum
#if ENABLED (JERRY_ESNEXT) #if ENABLED (JERRY_ESNEXT)
VM_CONTEXT_FOR_OF, /**< for-of context */ VM_CONTEXT_FOR_OF, /**< for-of context */
VM_CONTEXT_FOR_AWAIT_OF, /**< for-await-of context */ VM_CONTEXT_FOR_AWAIT_OF, /**< for-await-of context */
/* contexts with variable length */
VM_CONTEXT_ITERATOR, /**< iterator context */
VM_CONTEXT_OBJ_INIT, /**< object-initializer context */
VM_CONTEXT_OBJ_INIT_REST, /**< object-initializer-rest context */
#endif /* ENABLED (JERRY_ESNEXT) */ #endif /* ENABLED (JERRY_ESNEXT) */
} vm_stack_context_type_t; } vm_stack_context_type_t;
@@ -91,6 +96,21 @@ typedef enum
VM_CONTEXT_FOUND_EXPECTED, /**< found the type specified in finally_type */ VM_CONTEXT_FOUND_EXPECTED, /**< found the type specified in finally_type */
} vm_stack_found_type; } vm_stack_found_type;
/**
* Checks whether the context has variable context size
*
* Layout:
* - [context descriptor]
* - [JS values belong to the context]
* - [previous JS values stored by the VM stack]
*/
#if ENABLED (JERRY_ESNEXT)
#define VM_CONTEXT_IS_VARIABLE_LENGTH(context_type) \
((context_type) >= VM_CONTEXT_ITERATOR)
#else /* !ENABLED (JERRY_ESNEXT) */
#define VM_CONTEXT_IS_VARIABLE_LENGTH(context_type) false
#endif /* ENABLED (JERRY_ESNEXT) */
/** /**
* Checks whether the context type is a finally type. * Checks whether the context type is a finally type.
*/ */
@@ -112,6 +132,10 @@ typedef enum
*/ */
#define VM_CONTEXT_GET_NEXT_OFFSET(offsets) (-((int32_t) ((offsets) & ((1 << VM_CONTEXT_OFFSET_SHIFT) - 1)))) #define VM_CONTEXT_GET_NEXT_OFFSET(offsets) (-((int32_t) ((offsets) & ((1 << VM_CONTEXT_OFFSET_SHIFT) - 1))))
#if ENABLED (JERRY_ESNEXT)
ecma_value_t *vm_stack_context_abort_variable_length (vm_frame_ctx_t *frame_ctx_p, ecma_value_t *vm_stack_top_p,
uint32_t context_stack_allocation);
#endif /* ENABLED (JERRY_ESNEXT) */
ecma_value_t *vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, ecma_value_t *vm_stack_top_p); ecma_value_t *vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, ecma_value_t *vm_stack_top_p);
vm_stack_found_type vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, ecma_value_t *stack_top_p, vm_stack_found_type vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, ecma_value_t *stack_top_p,
vm_stack_context_type_t finally_type, uint32_t search_limit); vm_stack_context_type_t finally_type, uint32_t search_limit);
+115 -38
View File
@@ -1001,6 +1001,12 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
opcode_data &= (uint32_t) ~VM_OC_PUT_BLOCK; \ opcode_data &= (uint32_t) ~VM_OC_PUT_BLOCK; \
} }
/**
* Get the end of the existing topmost context
*/
#define VM_LAST_CONTEXT_END() \
(VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth)
/** /**
* Run generic byte code. * Run generic byte code.
* *
@@ -2307,24 +2313,39 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
*stack_top_p++ = result; *stack_top_p++ = result;
continue; continue;
} }
case VM_OC_GET_ITERATOR: case VM_OC_ITERATOR_CONTEXT_CREATE:
{ {
result = ecma_op_get_iterator (stack_top_p[-1], ECMA_VALUE_SYNC_ITERATOR, NULL); result = ecma_op_get_iterator (stack_top_p[-1], ECMA_VALUE_SYNC_ITERATOR, &left_value);
if (ECMA_IS_VALUE_ERROR (result)) if (ECMA_IS_VALUE_ERROR (result))
{ {
goto error; goto error;
} }
*stack_top_p++ = result; uint32_t context_size = (uint32_t) (stack_top_p
+ PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION
- VM_LAST_CONTEXT_END ());
stack_top_p += PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION;
VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, context_size);
stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_ITERATOR, context_size) | VM_CONTEXT_CLOSE_ITERATOR;
stack_top_p[-2] = result;
stack_top_p[-3] = left_value;
continue; continue;
} }
case VM_OC_ITERATOR_STEP: case VM_OC_ITERATOR_STEP:
{ {
result = ecma_op_iterator_step (stack_top_p[-1], ECMA_VALUE_EMPTY); ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END ();
ecma_value_t iterator = last_context_end_p[-2];
ecma_value_t next_method = last_context_end_p[-3];
result = ecma_op_iterator_step (iterator, next_method);
if (ECMA_IS_VALUE_ERROR (result)) if (ECMA_IS_VALUE_ERROR (result))
{ {
last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR;
goto error; goto error;
} }
@@ -2337,24 +2358,38 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
if (ECMA_IS_VALUE_ERROR (value)) if (ECMA_IS_VALUE_ERROR (value))
{ {
last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR;
result = value; result = value;
goto error; goto error;
} }
} }
else
{
last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR;
}
*stack_top_p++ = value; *stack_top_p++ = value;
continue; continue;
} }
case VM_OC_ITERATOR_CLOSE: case VM_OC_ITERATOR_CONTEXT_END:
{ {
result = ecma_op_iterator_close (left_value); JERRY_ASSERT (VM_LAST_CONTEXT_END () == stack_top_p);
if (ECMA_IS_VALUE_ERROR (result)) if (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR)
{ {
goto error; stack_top_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR;
result = ecma_op_iterator_close (stack_top_p[-2]);
if (ECMA_IS_VALUE_ERROR (result))
{
goto error;
}
} }
goto free_left_value; stack_top_p = vm_stack_context_abort_variable_length (frame_ctx_p,
stack_top_p,
PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION);
continue;
} }
case VM_OC_DEFAULT_INITIALIZER: case VM_OC_DEFAULT_INITIALIZER:
{ {
@@ -2373,21 +2408,26 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{ {
ecma_object_t *array_p = ecma_op_new_array_object (0); ecma_object_t *array_p = ecma_op_new_array_object (0);
JERRY_ASSERT (ecma_op_object_is_fast_array (array_p)); JERRY_ASSERT (ecma_op_object_is_fast_array (array_p));
ecma_value_t iterator = stack_top_p[-1];
ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END ();
ecma_value_t iterator = last_context_end_p[-2];
ecma_value_t next_method = last_context_end_p[-3];
uint32_t index = 0; uint32_t index = 0;
while (true) while (true)
{ {
result = ecma_op_iterator_step (iterator, ECMA_VALUE_EMPTY); result = ecma_op_iterator_step (iterator, next_method);
if (ECMA_IS_VALUE_ERROR (result)) if (ECMA_IS_VALUE_ERROR (result))
{ {
last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR;
ecma_deref_object (array_p); ecma_deref_object (array_p);
goto error; goto error;
} }
if (ecma_is_value_false (result)) if (ecma_is_value_false (result))
{ {
last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR;
break; break;
} }
@@ -2409,16 +2449,51 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
*stack_top_p++ = ecma_make_object_value (array_p); *stack_top_p++ = ecma_make_object_value (array_p);
continue; continue;
} }
case VM_OC_INITIALIZER_PUSH_LIST: case VM_OC_OBJ_INIT_CONTEXT_CREATE:
{ {
stack_top_p++; left_value = stack_top_p[-1];
stack_top_p[-1] = stack_top_p[-2]; vm_stack_context_type_t context_type = VM_CONTEXT_OBJ_INIT;
stack_top_p[-2] = ecma_make_object_value (ecma_op_new_array_object (0)); uint32_t context_stack_allocation = PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION;
if (opcode == CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE)
{
context_type = VM_CONTEXT_OBJ_INIT_REST;
context_stack_allocation = PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION;
}
uint32_t context_size = (uint32_t) (stack_top_p + context_stack_allocation - VM_LAST_CONTEXT_END ());
stack_top_p += context_stack_allocation;
VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, context_size);
stack_top_p[-1] = VM_CREATE_CONTEXT (context_type, context_size);
stack_top_p[-2] = left_value;
if (context_type == VM_CONTEXT_OBJ_INIT_REST)
{
stack_top_p[-3] = ecma_make_object_value (ecma_op_new_array_object (0));
}
continue; continue;
} }
case VM_OC_INITIALIZER_PUSH_REST: case VM_OC_OBJ_INIT_CONTEXT_END:
{ {
if (!ecma_op_require_object_coercible (stack_top_p[-1])) JERRY_ASSERT (stack_top_p == VM_LAST_CONTEXT_END ());
uint32_t context_stack_allocation = PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION;
if (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_OBJ_INIT_REST)
{
context_stack_allocation = PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION;
}
stack_top_p = vm_stack_context_abort_variable_length (frame_ctx_p,
stack_top_p,
context_stack_allocation);
continue;
}
case VM_OC_OBJ_INIT_PUSH_REST:
{
ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END ();
if (!ecma_op_require_object_coercible (last_context_end_p[-2]))
{ {
result = ECMA_VALUE_ERROR; result = ECMA_VALUE_ERROR;
goto error; goto error;
@@ -2428,16 +2503,18 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
ecma_object_t *result_object_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); ecma_object_t *result_object_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL);
left_value = ecma_make_object_value (result_object_p); left_value = ecma_make_object_value (result_object_p);
result = opfunc_copy_data_properties (left_value, stack_top_p[-1], stack_top_p[-2]); result = opfunc_copy_data_properties (left_value, last_context_end_p[-2], last_context_end_p[-3]);
if (ECMA_IS_VALUE_ERROR (result)) if (ECMA_IS_VALUE_ERROR (result))
{ {
goto error; goto error;
} }
ecma_free_value (stack_top_p[-2]); ecma_free_value (last_context_end_p[-3]);
stack_top_p[-2] = stack_top_p[-1]; last_context_end_p[-3] = last_context_end_p[-2];
stack_top_p[-1] = left_value; last_context_end_p[-2] = ECMA_VALUE_UNDEFINED;
*stack_top_p++ = left_value;
continue; continue;
} }
case VM_OC_INITIALIZER_PUSH_NAME: case VM_OC_INITIALIZER_PUSH_NAME:
@@ -2456,7 +2533,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
left_value = ecma_make_string_value (property_key); left_value = ecma_make_string_value (property_key);
} }
ecma_object_t *array_obj_p = ecma_get_object_from_value (stack_top_p[-2]); ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END ();
ecma_object_t *array_obj_p = ecma_get_object_from_value (last_context_end_p[-3]);
JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY); JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY);
ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p; ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p;
@@ -2465,7 +2543,21 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
} }
case VM_OC_INITIALIZER_PUSH_PROP: case VM_OC_INITIALIZER_PUSH_PROP:
{ {
result = vm_op_get_value (stack_top_p[-1], left_value); ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END ();
right_value = last_context_end_p[-2];
if (opcode == CBC_EXT_INITIALIZER_PUSH_PROP)
{
left_value = *last_context_end_p++;
while (last_context_end_p < stack_top_p)
{
last_context_end_p[-1] = *last_context_end_p;
last_context_end_p++;
}
stack_top_p--;
}
result = vm_op_get_value (right_value, left_value);
if (ECMA_IS_VALUE_ERROR (result)) if (ECMA_IS_VALUE_ERROR (result))
{ {
@@ -2475,21 +2567,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
*stack_top_p++ = result; *stack_top_p++ = result;
goto free_left_value; 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: case VM_OC_SPREAD_ARGUMENTS:
{ {
uint8_t arguments_list_len = *byte_code_p++; uint8_t arguments_list_len = *byte_code_p++;
+10 -10
View File
@@ -275,16 +275,16 @@ typedef enum
VM_OC_PUSH_SPREAD_ELEMENT, /**< push spread element */ VM_OC_PUSH_SPREAD_ELEMENT, /**< push spread element */
VM_OC_PUSH_REST_OBJECT, /**< push rest object */ VM_OC_PUSH_REST_OBJECT, /**< push rest object */
VM_OC_GET_ITERATOR, /**< GetIterator abstract operation */ VM_OC_ITERATOR_CONTEXT_CREATE, /**< create iterator conext */
VM_OC_ITERATOR_CONTEXT_END, /**< finalize iterator cotnext */
VM_OC_ITERATOR_STEP, /**< IteratorStep abstract operation */ VM_OC_ITERATOR_STEP, /**< IteratorStep abstract operation */
VM_OC_ITERATOR_CLOSE, /**< IteratorClose abstract operation */ VM_OC_OBJ_INIT_CONTEXT_CREATE, /**< create object initializer context */
VM_OC_INITIALIZER_PUSH_LIST, /**< push name list array */ VM_OC_OBJ_INIT_CONTEXT_END, /**< finalize object initializer context */
VM_OC_INITIALIZER_PUSH_REST, /**< push the object with the rest properties */ VM_OC_OBJ_INIT_PUSH_REST, /**< push the object with the rest properties */
VM_OC_INITIALIZER_PUSH_NAME, /**< append string to name list array and push the string */ VM_OC_INITIALIZER_PUSH_NAME, /**< append string to name list array and push the string */
VM_OC_DEFAULT_INITIALIZER, /**< default initializer inside a pattern */ VM_OC_DEFAULT_INITIALIZER, /**< default initializer inside a pattern */
VM_OC_REST_INITIALIZER, /**< create rest object inside an array pattern */ VM_OC_REST_INITIALIZER, /**< create rest object inside an array pattern */
VM_OC_INITIALIZER_PUSH_PROP, /**< push property for object initializer */ 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_SPREAD_ARGUMENTS, /**< perform function call/construct with spreaded arguments */
VM_OC_CREATE_GENERATOR, /**< create a generator object */ VM_OC_CREATE_GENERATOR, /**< create a generator object */
VM_OC_YIELD, /**< yield operation */ VM_OC_YIELD, /**< yield operation */
@@ -362,16 +362,16 @@ typedef enum
VM_OC_PUSH_SPREAD_ELEMENT = VM_OC_NONE, /**< push spread element */ VM_OC_PUSH_SPREAD_ELEMENT = VM_OC_NONE, /**< push spread element */
VM_OC_PUSH_REST_OBJECT = VM_OC_NONE, /**< push rest object */ VM_OC_PUSH_REST_OBJECT = VM_OC_NONE, /**< push rest object */
VM_OC_GET_ITERATOR = VM_OC_NONE, /**< GetIterator abstract operation */ VM_OC_ITERATOR_CONTEXT_CREATE = VM_OC_NONE, /**< create iterator context */
VM_OC_ITERATOR_STEP = VM_OC_NONE, /**< IteratorStep abstract operation */ VM_OC_ITERATOR_STEP = VM_OC_NONE, /**< IteratorStep abstract operation */
VM_OC_ITERATOR_CLOSE = VM_OC_NONE, /**< IteratorClose abstract operation */ VM_OC_ITERATOR_CONTEXT_END = VM_OC_NONE, /**< finalize iterator cotnext */
VM_OC_INITIALIZER_PUSH_LIST = VM_OC_NONE, /**< push name list array */ VM_OC_OBJ_INIT_CONTEXT_CREATE = VM_OC_NONE, /**< create object initializer context */
VM_OC_INITIALIZER_PUSH_REST = VM_OC_NONE, /**< push the object with the rest properties */ VM_OC_OBJ_INIT_CONTEXT_END = VM_OC_NONE, /**< finalize object initializer context */
VM_OC_OBJ_INIT_PUSH_REST = VM_OC_NONE, /**< push the object with the rest properties */
VM_OC_INITIALIZER_PUSH_NAME = VM_OC_NONE, /**< append string to name list array and push the string */ VM_OC_INITIALIZER_PUSH_NAME = VM_OC_NONE, /**< append string to name list array and push the string */
VM_OC_DEFAULT_INITIALIZER = VM_OC_NONE, /**< default initializer inside a pattern */ 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_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_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_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_CREATE_GENERATOR = VM_OC_NONE, /**< create a generator object */
VM_OC_YIELD = VM_OC_NONE, /**< yield operation */ VM_OC_YIELD = VM_OC_NONE, /**< yield operation */
+29 -21
View File
@@ -38,6 +38,14 @@ function mustThrow (str) {
} }
} }
function mustNotThrow (str) {
try {
eval (str);
} catch (e) {
assert (false);
}
}
checkSyntax ("var [a]"); checkSyntax ("var [a]");
checkSyntax ("var [a, o.a]"); checkSyntax ("var [a, o.a]");
checkSyntax ("var [a, ...b,]"); checkSyntax ("var [a, ...b,]");
@@ -329,32 +337,32 @@ function __createIterableObject (arr, methods) {
assert (x.prop === "42"); assert (x.prop === "42");
}) (); }) ();
mustThrow ("var iter = __createIterableObject([], " mustThrow (`var iter = __createIterableObject([],
+ "{ get 'return'() { throw new TypeError() }});" { get 'return'() { throw new TypeError() }});
+ "var [a] = iter"); var [a] = iter`);
mustThrow ("var iter = __createIterableObject([], " mustNotThrow (`var iter = __createIterableObject([],
+ "{ 'return': 5 });" { 'return': 5 });
+ "var [a] = iter"); var [a] = iter`);
mustThrow ("var iter = __createIterableObject([], " mustNotThrow (`var iter = __createIterableObject([],
+ "{ 'return': function() { return 5; }});" { 'return': function() { return 5; }});
+ "var [a] = iter"); var [a] = iter`);
mustThrow ("try { throw 5 } catch (e) {" mustThrow (`try { throw 5 } catch (e) {
+ "var iter = __createIterableObject([], " var iter = __createIterableObject([],
+ "{ get 'return'() { throw new TypeError() }});" { get 'return'() { throw new TypeError() }});
+ "var [a] = iter }"); var [a] = iter }`);
mustThrow ("try { throw 5 } catch (e) {" mustNotThrow (`try { throw 5 } catch (e) {
+ "var iter = __createIterableObject([], " var iter = __createIterableObject([],
+ "{ 'return': 5 });" { 'return': 5 });
+ "var [a] = iter }"); var [a] = iter }`);
mustThrow ("try { throw 5 } catch (e) {" mustNotThrow (`try { throw 5 } catch (e) {
+ "var iter = __createIterableObject([], " var iter = __createIterableObject([],
+ "{ 'return': function() { return 5; }});" { 'return': function() { return 5; }});
+ "var [a] = iter }"); var [a] = iter }`);
try { try {
eval ("var a = 0; 1 + [a] = [1]"); eval ("var a = 0; 1 + [a] = [1]");
-112
View File
@@ -203,8 +203,6 @@
<test id="language/eval-code/indirect/var-env-func-init-global-new.js"><reason></reason></test> <test id="language/eval-code/indirect/var-env-func-init-global-new.js"><reason></reason></test>
<test id="language/eval-code/indirect/var-env-func-init-global-update-configurable.js"><reason></reason></test> <test id="language/eval-code/indirect/var-env-func-init-global-update-configurable.js"><reason></reason></test>
<test id="language/eval-code/indirect/var-env-var-init-global-new.js"><reason></reason></test> <test id="language/eval-code/indirect/var-env-var-init-global-new.js"><reason></reason></test>
<test id="language/expressions/arrow-function/dstr/ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/arrow-function/dstr/dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/arrow-function/eval-var-scope-syntax-err.js"><reason></reason></test> <test id="language/expressions/arrow-function/eval-var-scope-syntax-err.js"><reason></reason></test>
<test id="language/expressions/arrow-function/param-dflt-yield-expr.js"><reason></reason></test> <test id="language/expressions/arrow-function/param-dflt-yield-expr.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_T1.js"><reason></reason></test>
@@ -220,34 +218,6 @@
<test id="language/expressions/assignment/S11.13.1_A7_T3.js"><reason></reason></test> <test id="language/expressions/assignment/S11.13.1_A7_T3.js"><reason></reason></test>
<test id="language/expressions/assignment/destructuring/iterator-destructuring-property-reference-target-evaluation-order.js"><reason></reason></test> <test id="language/expressions/assignment/destructuring/iterator-destructuring-property-reference-target-evaluation-order.js"><reason></reason></test>
<test id="language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order.js"><reason></reason></test> <test id="language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-iter-nrml-close-skip.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-iter-rtrn-close-err.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-iter-rtrn-close-null.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-iter-rtrn-close.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-iter-thrw-close-err.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-iter-thrw-close.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-trlg-iter-elision-iter-nrml-close-skip.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-trlg-iter-list-nrml-close-skip.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-trlg-iter-list-rtrn-close-err.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-trlg-iter-list-rtrn-close-null.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-trlg-iter-list-rtrn-close.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-trlg-iter-list-thrw-close-err.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-trlg-iter-list-thrw-close.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-trlg-iter-rest-nrml-close-skip.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-trlg-iter-rest-rtrn-close-err.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-trlg-iter-rest-rtrn-close-null.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-trlg-iter-rest-rtrn-close.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-trlg-iter-rest-thrw-close-err.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elem-trlg-iter-rest-thrw-close.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-elision-iter-nrml-close-skip.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-rest-iter-nrml-close-skip.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-rest-iter-rtrn-close-err.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-rest-iter-rtrn-close-null.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-rest-iter-rtrn-close.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-rest-iter-thrw-close-err.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-rest-iter-thrw-close.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-rest-lref-err.js"><reason></reason></test>
<test id="language/expressions/assignment/dstr/array-rest-lref.js"><reason></reason></test>
<test id="language/expressions/async-arrow-function/await-as-param-nested-arrow-body-position.js"><reason></reason></test> <test id="language/expressions/async-arrow-function/await-as-param-nested-arrow-body-position.js"><reason></reason></test>
<test id="language/expressions/async-arrow-function/await-as-param-nested-arrow-parameter-position.js"><reason></reason></test> <test id="language/expressions/async-arrow-function/await-as-param-nested-arrow-parameter-position.js"><reason></reason></test>
<test id="language/expressions/async-arrow-function/await-as-param-rest-nested-arrow-parameter-position.js"><reason></reason></test> <test id="language/expressions/async-arrow-function/await-as-param-rest-nested-arrow-parameter-position.js"><reason></reason></test>
@@ -262,14 +232,6 @@
<test id="language/expressions/class/class-name-ident-static.js"><reason></reason></test> <test id="language/expressions/class/class-name-ident-static.js"><reason></reason></test>
<test id="language/expressions/class/class-name-ident-yield-escaped.js"><reason></reason></test> <test id="language/expressions/class/class-name-ident-yield-escaped.js"><reason></reason></test>
<test id="language/expressions/class/class-name-ident-yield.js"><reason></reason></test> <test id="language/expressions/class/class-name-ident-yield.js"><reason></reason></test>
<test id="language/expressions/class/dstr/gen-meth-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/class/dstr/gen-meth-dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/class/dstr/gen-meth-static-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/class/dstr/gen-meth-static-dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/class/dstr/meth-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/class/dstr/meth-dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/class/dstr/meth-static-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/class/dstr/meth-static-dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/class/name.js"><reason></reason></test> <test id="language/expressions/class/name.js"><reason></reason></test>
<test id="language/expressions/compound-assignment/S11.13.2_A7.10_T4.js"><reason></reason></test> <test id="language/expressions/compound-assignment/S11.13.2_A7.10_T4.js"><reason></reason></test>
<test id="language/expressions/compound-assignment/S11.13.2_A7.11_T4.js"><reason></reason></test> <test id="language/expressions/compound-assignment/S11.13.2_A7.11_T4.js"><reason></reason></test>
@@ -282,21 +244,13 @@
<test id="language/expressions/compound-assignment/S11.13.2_A7.7_T4.js"><reason></reason></test> <test id="language/expressions/compound-assignment/S11.13.2_A7.7_T4.js"><reason></reason></test>
<test id="language/expressions/compound-assignment/S11.13.2_A7.8_T4.js"><reason></reason></test> <test id="language/expressions/compound-assignment/S11.13.2_A7.8_T4.js"><reason></reason></test>
<test id="language/expressions/compound-assignment/S11.13.2_A7.9_T4.js"><reason></reason></test> <test id="language/expressions/compound-assignment/S11.13.2_A7.9_T4.js"><reason></reason></test>
<test id="language/expressions/function/dstr/ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/function/dstr/dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/function/eval-var-scope-syntax-err.js"><reason></reason></test> <test id="language/expressions/function/eval-var-scope-syntax-err.js"><reason></reason></test>
<test id="language/expressions/generators/dstr/ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/generators/dstr/dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/generators/eval-var-scope-syntax-err.js"><reason></reason></test> <test id="language/expressions/generators/eval-var-scope-syntax-err.js"><reason></reason></test>
<test id="language/expressions/import.meta/distinct-for-each-module.js"><reason></reason></test> <test id="language/expressions/import.meta/distinct-for-each-module.js"><reason></reason></test>
<test id="language/expressions/import.meta/import-meta-is-an-ordinary-object.js"><reason></reason></test> <test id="language/expressions/import.meta/import-meta-is-an-ordinary-object.js"><reason></reason></test>
<test id="language/expressions/import.meta/same-object-returned.js"><reason></reason></test> <test id="language/expressions/import.meta/same-object-returned.js"><reason></reason></test>
<test id="language/expressions/import.meta/syntax/goal-module-nested-function.js"><reason></reason></test> <test id="language/expressions/import.meta/syntax/goal-module-nested-function.js"><reason></reason></test>
<test id="language/expressions/import.meta/syntax/goal-module.js"><reason></reason></test> <test id="language/expressions/import.meta/syntax/goal-module.js"><reason></reason></test>
<test id="language/expressions/object/dstr/gen-meth-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/object/dstr/gen-meth-dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/object/dstr/meth-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/object/dstr/meth-dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/object/method-definition/early-errors-object-async-method-duplicate-parameters.js"><reason></reason></test> <test id="language/expressions/object/method-definition/early-errors-object-async-method-duplicate-parameters.js"><reason></reason></test>
<test id="language/expressions/object/method-definition/early-errors-object-method-async-lineterminator.js"><reason></reason></test> <test id="language/expressions/object/method-definition/early-errors-object-method-async-lineterminator.js"><reason></reason></test>
<test id="language/expressions/object/method-definition/early-errors-object-method-duplicate-parameters.js"><reason></reason></test> <test id="language/expressions/object/method-definition/early-errors-object-method-duplicate-parameters.js"><reason></reason></test>
@@ -490,17 +444,8 @@
<test id="language/statements/class/class-name-ident-yield-escaped.js"><reason></reason></test> <test id="language/statements/class/class-name-ident-yield-escaped.js"><reason></reason></test>
<test id="language/statements/class/class-name-ident-yield.js"><reason></reason></test> <test id="language/statements/class/class-name-ident-yield.js"><reason></reason></test>
<test id="language/statements/class/constructor-inferred-observable-iteration.js"><reason></reason></test> <test id="language/statements/class/constructor-inferred-observable-iteration.js"><reason></reason></test>
<test id="language/statements/class/dstr/gen-meth-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/class/dstr/gen-meth-dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/class/dstr/gen-meth-static-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/class/dstr/gen-meth-static-dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/class/dstr/meth-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/class/dstr/meth-dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/class/dstr/meth-static-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/class/dstr/meth-static-dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/class/subclass/default-constructor-spread-override.js"><reason></reason></test> <test id="language/statements/class/subclass/default-constructor-spread-override.js"><reason></reason></test>
<test id="language/statements/class/super/in-constructor-superproperty-evaluation.js"><reason></reason></test> <test id="language/statements/class/super/in-constructor-superproperty-evaluation.js"><reason></reason></test>
<test id="language/statements/const/dstr/ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/do-while/cptn-abrupt-empty.js"><reason></reason></test> <test id="language/statements/do-while/cptn-abrupt-empty.js"><reason></reason></test>
<test id="language/statements/do-while/cptn-normal.js"><reason></reason></test> <test id="language/statements/do-while/cptn-normal.js"><reason></reason></test>
<test id="language/statements/for-in/cptn-decl-abrupt-empty.js"><reason></reason></test> <test id="language/statements/for-in/cptn-decl-abrupt-empty.js"><reason></reason></test>
@@ -523,37 +468,6 @@
<test id="language/statements/for-of/cptn-expr-abrupt-empty.js"><reason></reason></test> <test id="language/statements/for-of/cptn-expr-abrupt-empty.js"><reason></reason></test>
<test id="language/statements/for-of/cptn-expr-itr.js"><reason></reason></test> <test id="language/statements/for-of/cptn-expr-itr.js"><reason></reason></test>
<test id="language/statements/for-of/cptn-expr-no-itr.js"><reason></reason></test> <test id="language/statements/for-of/cptn-expr-no-itr.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-iter-nrml-close-skip.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-iter-rtrn-close-err.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-iter-rtrn-close-null.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-iter-rtrn-close.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-iter-thrw-close-err.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-iter-thrw-close.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-trlg-iter-elision-iter-nrml-close-skip.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-trlg-iter-list-nrml-close-skip.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-trlg-iter-list-rtrn-close-err.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-trlg-iter-list-rtrn-close-null.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-trlg-iter-list-rtrn-close.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-trlg-iter-list-thrw-close-err.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-trlg-iter-list-thrw-close.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-trlg-iter-rest-nrml-close-skip.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-trlg-iter-rest-rtrn-close-err.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-trlg-iter-rest-rtrn-close-null.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-trlg-iter-rest-rtrn-close.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-trlg-iter-rest-thrw-close-err.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elem-trlg-iter-rest-thrw-close.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-elision-iter-nrml-close-skip.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-rest-iter-nrml-close-skip.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-rest-iter-rtrn-close-err.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-rest-iter-rtrn-close-null.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-rest-iter-rtrn-close.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-rest-iter-thrw-close-err.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-rest-iter-thrw-close.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-rest-lref-err.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/array-rest-lref.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/const-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/let-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/for-of/dstr/var-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/for-of/head-const-init.js"><reason></reason></test> <test id="language/statements/for-of/head-const-init.js"><reason></reason></test>
<test id="language/statements/for-of/head-decl-no-expr.js"><reason></reason></test> <test id="language/statements/for-of/head-decl-no-expr.js"><reason></reason></test>
<test id="language/statements/for-of/head-expr-no-expr.js"><reason></reason></test> <test id="language/statements/for-of/head-expr-no-expr.js"><reason></reason></test>
@@ -568,19 +482,12 @@
<test id="language/statements/for/cptn-decl-expr-no-iter.js"><reason></reason></test> <test id="language/statements/for/cptn-decl-expr-no-iter.js"><reason></reason></test>
<test id="language/statements/for/cptn-expr-expr-iter.js"><reason></reason></test> <test id="language/statements/for/cptn-expr-expr-iter.js"><reason></reason></test>
<test id="language/statements/for/cptn-expr-expr-no-iter.js"><reason></reason></test> <test id="language/statements/for/cptn-expr-expr-no-iter.js"><reason></reason></test>
<test id="language/statements/for/dstr/const-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/for/dstr/let-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/for/dstr/var-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/for/head-init-expr-check-empty-inc-empty-completion.js"><reason></reason></test> <test id="language/statements/for/head-init-expr-check-empty-inc-empty-completion.js"><reason></reason></test>
<test id="language/statements/for/head-init-var-check-empty-inc-empty-completion.js"><reason></reason></test> <test id="language/statements/for/head-init-var-check-empty-inc-empty-completion.js"><reason></reason></test>
<test id="language/statements/for/let-block-with-newline.js"><reason></reason></test> <test id="language/statements/for/let-block-with-newline.js"><reason></reason></test>
<test id="language/statements/for/let-identifier-with-newline.js"><reason></reason></test> <test id="language/statements/for/let-identifier-with-newline.js"><reason></reason></test>
<test id="language/statements/for/scope-body-lex-open.js"><reason></reason></test> <test id="language/statements/for/scope-body-lex-open.js"><reason></reason></test>
<test id="language/statements/function/dstr/ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/function/dstr/dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/function/eval-var-scope-syntax-err.js"><reason></reason></test> <test id="language/statements/function/eval-var-scope-syntax-err.js"><reason></reason></test>
<test id="language/statements/generators/dstr/ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/generators/dstr/dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/generators/eval-var-scope-syntax-err.js"><reason></reason></test> <test id="language/statements/generators/eval-var-scope-syntax-err.js"><reason></reason></test>
<test id="language/statements/if/cptn-else-false-abrupt-empty.js"><reason></reason></test> <test id="language/statements/if/cptn-else-false-abrupt-empty.js"><reason></reason></test>
<test id="language/statements/if/cptn-else-false-nrml.js"><reason></reason></test> <test id="language/statements/if/cptn-else-false-nrml.js"><reason></reason></test>
@@ -598,7 +505,6 @@
<test id="language/statements/labeled/decl-gen.js"><reason></reason></test> <test id="language/statements/labeled/decl-gen.js"><reason></reason></test>
<test id="language/statements/labeled/let-block-with-newline.js"><reason></reason></test> <test id="language/statements/labeled/let-block-with-newline.js"><reason></reason></test>
<test id="language/statements/labeled/let-identifier-with-newline.js"><reason></reason></test> <test id="language/statements/labeled/let-identifier-with-newline.js"><reason></reason></test>
<test id="language/statements/let/dstr/ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/let/syntax/let-newline-yield-in-generator-function.js"><reason></reason></test> <test id="language/statements/let/syntax/let-newline-yield-in-generator-function.js"><reason></reason></test>
<test id="language/statements/switch/cptn-a-abrupt-empty.js"><reason></reason></test> <test id="language/statements/switch/cptn-a-abrupt-empty.js"><reason></reason></test>
<test id="language/statements/switch/cptn-abrupt-empty.js"><reason></reason></test> <test id="language/statements/switch/cptn-abrupt-empty.js"><reason></reason></test>
@@ -631,10 +537,8 @@
<test id="language/statements/try/cptn-finally-skip-catch.js"><reason></reason></test> <test id="language/statements/try/cptn-finally-skip-catch.js"><reason></reason></test>
<test id="language/statements/try/cptn-finally-wo-catch.js"><reason></reason></test> <test id="language/statements/try/cptn-finally-wo-catch.js"><reason></reason></test>
<test id="language/statements/try/cptn-try.js"><reason></reason></test> <test id="language/statements/try/cptn-try.js"><reason></reason></test>
<test id="language/statements/try/dstr/ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/try/scope-catch-block-lex-open.js"><reason></reason></test> <test id="language/statements/try/scope-catch-block-lex-open.js"><reason></reason></test>
<test id="language/statements/variable/binding-resolution.js"><reason></reason></test> <test id="language/statements/variable/binding-resolution.js"><reason></reason></test>
<test id="language/statements/variable/dstr/ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/while/cptn-abrupt-empty.js"><reason></reason></test> <test id="language/statements/while/cptn-abrupt-empty.js"><reason></reason></test>
<test id="language/statements/while/cptn-iter.js"><reason></reason></test> <test id="language/statements/while/cptn-iter.js"><reason></reason></test>
<test id="language/statements/while/cptn-no-iter.js"><reason></reason></test> <test id="language/statements/while/cptn-no-iter.js"><reason></reason></test>
@@ -7282,10 +7186,6 @@
<test id="language/block-scope/syntax/redeclaration/async-generator-name-redeclaration-attempt-with-generator.js"><reason></reason></test> <test id="language/block-scope/syntax/redeclaration/async-generator-name-redeclaration-attempt-with-generator.js"><reason></reason></test>
<test id="language/block-scope/syntax/redeclaration/function-name-redeclaration-attempt-with-async-generator.js"><reason></reason></test> <test id="language/block-scope/syntax/redeclaration/function-name-redeclaration-attempt-with-async-generator.js"><reason></reason></test>
<test id="language/block-scope/syntax/redeclaration/generator-name-redeclaration-attempt-with-async-generator.js"><reason></reason></test> <test id="language/block-scope/syntax/redeclaration/generator-name-redeclaration-attempt-with-async-generator.js"><reason></reason></test>
<test id="language/expressions/async-generator/dstr/ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/async-generator/dstr/dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/async-generator/dstr/named-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/async-generator/dstr/named-dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/async-generator/eval-var-scope-syntax-err.js"><reason></reason></test> <test id="language/expressions/async-generator/eval-var-scope-syntax-err.js"><reason></reason></test>
<test id="language/expressions/async-generator/named-eval-var-scope-syntax-err.js"><reason></reason></test> <test id="language/expressions/async-generator/named-eval-var-scope-syntax-err.js"><reason></reason></test>
<test id="language/expressions/async-generator/named-yield-promise-reject-next-catch.js"><reason></reason></test> <test id="language/expressions/async-generator/named-yield-promise-reject-next-catch.js"><reason></reason></test>
@@ -7341,10 +7241,6 @@
<test id="language/expressions/class/async-gen-method/yield-star-sync-next.js"><reason></reason></test> <test id="language/expressions/class/async-gen-method/yield-star-sync-next.js"><reason></reason></test>
<test id="language/expressions/class/async-gen-method/yield-star-sync-return.js"><reason></reason></test> <test id="language/expressions/class/async-gen-method/yield-star-sync-return.js"><reason></reason></test>
<test id="language/expressions/class/async-gen-method/yield-star-sync-throw.js"><reason></reason></test> <test id="language/expressions/class/async-gen-method/yield-star-sync-throw.js"><reason></reason></test>
<test id="language/expressions/class/dstr/async-gen-meth-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/class/dstr/async-gen-meth-dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/class/dstr/async-gen-meth-static-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/class/dstr/async-gen-meth-static-dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/class/dstr/async-private-gen-meth-ary-init-iter-close.js"><reason></reason></test> <test id="language/expressions/class/dstr/async-private-gen-meth-ary-init-iter-close.js"><reason></reason></test>
<test id="language/expressions/class/dstr/async-private-gen-meth-ary-init-iter-no-close.js"><reason></reason></test> <test id="language/expressions/class/dstr/async-private-gen-meth-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/class/dstr/async-private-gen-meth-ary-name-iter-val.js"><reason></reason></test> <test id="language/expressions/class/dstr/async-private-gen-meth-ary-name-iter-val.js"><reason></reason></test>
@@ -7810,8 +7706,6 @@
<test id="language/expressions/dynamic-import/usage/nested-async-gen-return-await-is-call-expression-square-brackets.js"><reason></reason></test> <test id="language/expressions/dynamic-import/usage/nested-async-gen-return-await-is-call-expression-square-brackets.js"><reason></reason></test>
<test id="language/expressions/dynamic-import/usage/nested-async-gen-return-await-returns-thenable.js"><reason></reason></test> <test id="language/expressions/dynamic-import/usage/nested-async-gen-return-await-returns-thenable.js"><reason></reason></test>
<test id="language/expressions/dynamic-import/usage/nested-async-gen-return-await-specifier-tostring.js"><reason></reason></test> <test id="language/expressions/dynamic-import/usage/nested-async-gen-return-await-specifier-tostring.js"><reason></reason></test>
<test id="language/expressions/object/dstr/async-gen-meth-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/object/dstr/async-gen-meth-dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/expressions/object/method-definition/async-gen-meth-eval-var-scope-syntax-err.js"><reason></reason></test> <test id="language/expressions/object/method-definition/async-gen-meth-eval-var-scope-syntax-err.js"><reason></reason></test>
<test id="language/expressions/object/method-definition/async-gen-yield-promise-reject-next-catch.js"><reason></reason></test> <test id="language/expressions/object/method-definition/async-gen-yield-promise-reject-next-catch.js"><reason></reason></test>
<test id="language/expressions/object/method-definition/async-gen-yield-promise-reject-next-for-await-of-async-iterator.js"><reason></reason></test> <test id="language/expressions/object/method-definition/async-gen-yield-promise-reject-next-for-await-of-async-iterator.js"><reason></reason></test>
@@ -7837,8 +7731,6 @@
<test id="language/module-code/top-level-await/syntax/for-await-await-expr-regexp.js"><reason></reason></test> <test id="language/module-code/top-level-await/syntax/for-await-await-expr-regexp.js"><reason></reason></test>
<test id="language/module-code/top-level-await/syntax/for-await-await-expr-template-literal.js"><reason></reason></test> <test id="language/module-code/top-level-await/syntax/for-await-await-expr-template-literal.js"><reason></reason></test>
<test id="language/module-code/top-level-await/syntax/for-await-await-expr-this.js"><reason></reason></test> <test id="language/module-code/top-level-await/syntax/for-await-await-expr-this.js"><reason></reason></test>
<test id="language/statements/async-generator/dstr/ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/async-generator/dstr/dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/async-generator/eval-var-scope-syntax-err.js"><reason></reason></test> <test id="language/statements/async-generator/eval-var-scope-syntax-err.js"><reason></reason></test>
<test id="language/statements/async-generator/return-undefined-implicit-and-explicit.js"><reason></reason></test> <test id="language/statements/async-generator/return-undefined-implicit-and-explicit.js"><reason></reason></test>
<test id="language/statements/async-generator/yield-promise-reject-next-catch.js"><reason></reason></test> <test id="language/statements/async-generator/yield-promise-reject-next-catch.js"><reason></reason></test>
@@ -7880,10 +7772,6 @@
<test id="language/statements/class/async-gen-method/yield-star-sync-next.js"><reason></reason></test> <test id="language/statements/class/async-gen-method/yield-star-sync-next.js"><reason></reason></test>
<test id="language/statements/class/async-gen-method/yield-star-sync-return.js"><reason></reason></test> <test id="language/statements/class/async-gen-method/yield-star-sync-return.js"><reason></reason></test>
<test id="language/statements/class/async-gen-method/yield-star-sync-throw.js"><reason></reason></test> <test id="language/statements/class/async-gen-method/yield-star-sync-throw.js"><reason></reason></test>
<test id="language/statements/class/dstr/async-gen-meth-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/class/dstr/async-gen-meth-dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/class/dstr/async-gen-meth-static-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/class/dstr/async-gen-meth-static-dflt-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/class/dstr/async-private-gen-meth-ary-init-iter-close.js"><reason></reason></test> <test id="language/statements/class/dstr/async-private-gen-meth-ary-init-iter-close.js"><reason></reason></test>
<test id="language/statements/class/dstr/async-private-gen-meth-ary-init-iter-no-close.js"><reason></reason></test> <test id="language/statements/class/dstr/async-private-gen-meth-ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/class/dstr/async-private-gen-meth-ary-name-iter-val.js"><reason></reason></test> <test id="language/statements/class/dstr/async-private-gen-meth-ary-name-iter-val.js"><reason></reason></test>