Implement rest parameter support for destructuring object patterns. (#4318)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -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 == 145,
|
||||
JERRY_STATIC_ASSERT (CBC_EXT_END == 149,
|
||||
number_of_cbc_ext_opcodes_changed);
|
||||
|
||||
#if ENABLED (JERRY_PARSER)
|
||||
|
||||
@@ -763,6 +763,16 @@
|
||||
CBC_OPCODE (CBC_EXT_ITERATOR_CLOSE, CBC_NO_FLAG, -1, \
|
||||
VM_OC_ITERATOR_CLOSE | VM_OC_GET_STACK) \
|
||||
\
|
||||
/* Object initializer related opcodes. */ \
|
||||
CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_LIST, CBC_NO_FLAG, 1, \
|
||||
VM_OC_INITIALIZER_PUSH_LIST) \
|
||||
CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_REST, CBC_NO_FLAG, 0, \
|
||||
VM_OC_INITIALIZER_PUSH_REST) \
|
||||
CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME, CBC_NO_FLAG, 0, \
|
||||
VM_OC_INITIALIZER_PUSH_NAME | VM_OC_GET_STACK) \
|
||||
CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL, CBC_HAS_LITERAL_ARG, 1, \
|
||||
VM_OC_INITIALIZER_PUSH_NAME | VM_OC_GET_LITERAL) \
|
||||
\
|
||||
/* Executable object related opcodes. */ \
|
||||
CBC_OPCODE (CBC_EXT_CREATE_GENERATOR, CBC_NO_FLAG, 1, \
|
||||
VM_OC_CREATE_GENERATOR) \
|
||||
|
||||
@@ -3334,7 +3334,7 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
case LIT_CHAR_DOT:
|
||||
{
|
||||
if (ident_opts != LEXER_OBJ_IDENT_NO_OPTS
|
||||
if ((ident_opts & ((uint32_t) ~LEXER_OBJ_IDENT_OBJECT_PATTERN))
|
||||
|| context_p->source_p + 2 >= context_p->source_end_p
|
||||
|| context_p->source_p[1] != LIT_CHAR_DOT
|
||||
|| context_p->source_p[2] != LIT_CHAR_DOT)
|
||||
|
||||
@@ -273,11 +273,11 @@ typedef enum
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LEXER_OBJ_IDENT_NO_OPTS = (1u << 0), /**< no options */
|
||||
LEXER_OBJ_IDENT_ONLY_IDENTIFIERS = (1u << 1), /**< only identifiers are accepted */
|
||||
LEXER_OBJ_IDENT_CLASS_IDENTIFIER = (1u << 2), /**< expect identifier inside a class body */
|
||||
LEXER_OBJ_IDENT_CLASS_NO_STATIC = (1u << 3), /**< static keyword was not present before the identifier */
|
||||
LEXER_OBJ_IDENT_OBJECT_PATTERN = (1u << 4), /**< parse "get"/"set" as string literal in object pattern */
|
||||
LEXER_OBJ_IDENT_NO_OPTS = 0, /**< no options */
|
||||
LEXER_OBJ_IDENT_ONLY_IDENTIFIERS = (1u << 0), /**< only identifiers are accepted */
|
||||
LEXER_OBJ_IDENT_CLASS_IDENTIFIER = (1u << 1), /**< expect identifier inside a class body */
|
||||
LEXER_OBJ_IDENT_CLASS_NO_STATIC = (1u << 2), /**< static keyword was not present before the identifier */
|
||||
LEXER_OBJ_IDENT_OBJECT_PATTERN = (1u << 3), /**< parse "get"/"set" as string literal in object pattern */
|
||||
} lexer_obj_ident_opts_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1146,10 +1146,15 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */
|
||||
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_OBJECT_LITERAL_WITH_SUPER);
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS);
|
||||
|
||||
if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_SUPER)
|
||||
{
|
||||
parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT);
|
||||
has_super_env = true;
|
||||
}
|
||||
|
||||
scanner_release_next (context_p, sizeof (scanner_info_t));
|
||||
parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT);
|
||||
has_super_env = true;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
@@ -2114,7 +2119,14 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
|
||||
{
|
||||
if (parser_is_assignment_expr (context_p))
|
||||
{
|
||||
parser_parse_object_initializer (context_p, PARSER_PATTERN_NO_OPTS);
|
||||
uint32_t flags = PARSER_PATTERN_NO_OPTS;
|
||||
|
||||
if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST)
|
||||
{
|
||||
flags |= PARSER_PATTERN_HAS_REST_ELEMENT;
|
||||
}
|
||||
|
||||
parser_parse_object_initializer (context_p, flags);
|
||||
return parser_abort_parsing_after_assignment_expression (context_p);
|
||||
}
|
||||
|
||||
@@ -2130,15 +2142,23 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER);
|
||||
|
||||
if (parser_is_assignment_expr (context_p))
|
||||
if (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER)
|
||||
{
|
||||
parser_parse_array_initializer (context_p, PARSER_PATTERN_NO_OPTS);
|
||||
return parser_abort_parsing_after_assignment_expression (context_p);
|
||||
}
|
||||
if (parser_is_assignment_expr (context_p))
|
||||
{
|
||||
parser_parse_array_initializer (context_p, PARSER_PATTERN_NO_OPTS);
|
||||
return parser_abort_parsing_after_assignment_expression (context_p);
|
||||
}
|
||||
|
||||
scanner_release_next (context_p, sizeof (scanner_location_info_t));
|
||||
scanner_release_next (context_p, sizeof (scanner_location_info_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS
|
||||
&& context_p->next_scanner_info_p->u8_arg == SCANNER_LITERAL_NO_DESTRUCTURING);
|
||||
|
||||
scanner_release_next (context_p, sizeof (scanner_info_t));
|
||||
}
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
@@ -3389,18 +3409,33 @@ parser_pattern_process_nested_pattern (parser_context_t *context_p, /**< context
|
||||
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->source_p != context_p->source_p
|
||||
|| context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER
|
||||
|| context_p->next_scanner_info_p->type == SCANNER_TYPE_OBJECT_LITERAL_WITH_SUPER);
|
||||
|| context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS);
|
||||
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p
|
||||
&& context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER)
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
|
||||
{
|
||||
if (!(flags & PARSER_PATTERN_REST_ELEMENT))
|
||||
if (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER)
|
||||
{
|
||||
options |= PARSER_PATTERN_TARGET_DEFAULT;
|
||||
if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST)
|
||||
{
|
||||
options |= PARSER_PATTERN_HAS_REST_ELEMENT;
|
||||
}
|
||||
|
||||
if (!(flags & PARSER_PATTERN_REST_ELEMENT))
|
||||
{
|
||||
options |= PARSER_PATTERN_TARGET_DEFAULT;
|
||||
}
|
||||
else
|
||||
{
|
||||
scanner_release_next (context_p, sizeof (scanner_location_info_t));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
scanner_release_next (context_p, sizeof (scanner_location_info_t));
|
||||
if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST)
|
||||
{
|
||||
options |= PARSER_PATTERN_HAS_REST_ELEMENT;
|
||||
}
|
||||
scanner_release_next (context_p, sizeof (scanner_info_t));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3420,18 +3455,22 @@ parser_pattern_process_nested_pattern (parser_context_t *context_p, /**< context
|
||||
|
||||
/**
|
||||
* Process the current {Binding, Assignment}Property
|
||||
*
|
||||
* @return true, if a nested pattern is processed, false otherwise
|
||||
*/
|
||||
static void
|
||||
static bool
|
||||
parser_pattern_process_assignment (parser_context_t *context_p, /**< context */
|
||||
parser_pattern_flags_t flags, /**< flags */
|
||||
uint16_t rhs_opcode, /**< opcode to process the rhs value */
|
||||
uint16_t literal_index, /**< literal index for object pattern */
|
||||
lexer_token_type_t end_type) /**< end type token */
|
||||
{
|
||||
if (context_p->token.type == LEXER_LEFT_BRACE || context_p->token.type == LEXER_LEFT_SQUARE)
|
||||
if ((context_p->token.type == LEXER_LEFT_BRACE || context_p->token.type == LEXER_LEFT_SQUARE)
|
||||
&& (context_p->next_scanner_info_p->source_p != context_p->source_p
|
||||
|| !(context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_NO_DESTRUCTURING)))
|
||||
{
|
||||
parser_pattern_process_nested_pattern (context_p, flags, rhs_opcode, literal_index);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
parser_line_counter_t ident_line_counter = context_p->token.line;
|
||||
@@ -3497,6 +3536,7 @@ parser_pattern_process_assignment (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
|
||||
parser_pattern_form_assignment (context_p, flags, rhs_opcode, literal_index, ident_line_counter);
|
||||
return false;
|
||||
} /* parser_pattern_process_assignment */
|
||||
|
||||
/**
|
||||
@@ -3568,6 +3608,11 @@ parser_parse_object_initializer (parser_context_t *context_p, /**< context */
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags & PARSER_PATTERN_HAS_REST_ELEMENT)
|
||||
{
|
||||
parser_emit_cbc_ext (context_p, CBC_EXT_INITIALIZER_PUSH_LIST);
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_OBJECT_PATTERN);
|
||||
@@ -3581,10 +3626,41 @@ parser_parse_object_initializer (parser_context_t *context_p, /**< context */
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (context_p->token.type == LEXER_RIGHT_SQUARE)
|
||||
|
||||
if (context_p->token.type == LEXER_THREE_DOTS)
|
||||
{
|
||||
lexer_next_token (context_p);
|
||||
|
||||
flags |= PARSER_PATTERN_REST_ELEMENT;
|
||||
|
||||
if (parser_pattern_process_assignment (context_p,
|
||||
flags,
|
||||
CBC_EXT_INITIALIZER_PUSH_REST,
|
||||
PARSER_PATTERN_RHS_NO_LIT,
|
||||
LEXER_RIGHT_BRACE))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_LHS_ASSIGNMENT);
|
||||
}
|
||||
|
||||
if (context_p->token.type != LEXER_RIGHT_BRACE)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED);
|
||||
}
|
||||
|
||||
/* Checked at the end because there might be syntax errors before. */
|
||||
JERRY_ASSERT (flags & PARSER_PATTERN_HAS_REST_ELEMENT);
|
||||
break;
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_RIGHT_SQUARE)
|
||||
{
|
||||
prop_index = PARSER_PATTERN_RHS_NO_LIT;
|
||||
push_prop_opcode = CBC_EXT_INITIALIZER_PUSH_PROP;
|
||||
push_prop_opcode = ((flags & PARSER_PATTERN_HAS_REST_ELEMENT) ? CBC_EXT_INITIALIZER_PUSH_NAME
|
||||
: CBC_EXT_INITIALIZER_PUSH_PROP);
|
||||
}
|
||||
else if (flags & PARSER_PATTERN_HAS_REST_ELEMENT)
|
||||
{
|
||||
push_prop_opcode = CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL;
|
||||
}
|
||||
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
|
||||
@@ -3602,7 +3678,8 @@ parser_parse_object_initializer (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (push_prop_opcode == CBC_EXT_INITIALIZER_PUSH_PROP)
|
||||
if (push_prop_opcode == CBC_EXT_INITIALIZER_PUSH_NAME
|
||||
|| push_prop_opcode == CBC_EXT_INITIALIZER_PUSH_PROP)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_COLON_EXPECTED);
|
||||
}
|
||||
@@ -3681,6 +3758,22 @@ parser_parse_initializer_by_next_char (parser_context_t *context_p, /**< context
|
||||
|
||||
if (lexer_consume_next_character (context_p) == LIT_CHAR_LEFT_BRACE)
|
||||
{
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER
|
||||
|| context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS);
|
||||
|
||||
if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST)
|
||||
{
|
||||
flags |= PARSER_PATTERN_HAS_REST_ELEMENT;
|
||||
}
|
||||
|
||||
if (context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS)
|
||||
{
|
||||
scanner_release_next (context_p, sizeof (scanner_info_t));
|
||||
}
|
||||
}
|
||||
|
||||
parser_parse_object_initializer (context_p, flags);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -110,12 +110,13 @@ typedef enum
|
||||
PARSER_PATTERN_BINDING = (1u << 0), /**< parse BindingPattern */
|
||||
PARSER_PATTERN_TARGET_ON_STACK = (1u << 1), /**< assignment target is the topmost element on the stack */
|
||||
PARSER_PATTERN_TARGET_DEFAULT = (1u << 2), /**< perform default value comparison for assignment target */
|
||||
PARSER_PATTERN_NESTED_PATTERN = (1u << 3), /**< parse patter inside a pattern */
|
||||
PARSER_PATTERN_NESTED_PATTERN = (1u << 3), /**< parse pattern inside a pattern */
|
||||
PARSER_PATTERN_LET = (1u << 4), /**< pattern is a let declaration */
|
||||
PARSER_PATTERN_CONST = (1u << 5), /**< pattern is a const declaration */
|
||||
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_REST_ELEMENT = (1u << 7), /**< parse rest array / object element */
|
||||
PARSER_PATTERN_HAS_REST_ELEMENT = (1u << 8), /**< object literal rest element will be present */
|
||||
PARSER_PATTERN_ARGUMENTS = (1u << 9), /**< parse arguments binding */
|
||||
} parser_pattern_flags_t;
|
||||
|
||||
/**
|
||||
@@ -668,6 +669,7 @@ void parser_stack_free (parser_context_t *context_p);
|
||||
void parser_stack_push_uint8 (parser_context_t *context_p, uint8_t uint8_value);
|
||||
void parser_stack_pop_uint8 (parser_context_t *context_p);
|
||||
void parser_stack_change_last_uint8 (parser_context_t *context_p, uint8_t new_value);
|
||||
uint8_t *parser_stack_get_prev_uint8 (parser_context_t *context_p);
|
||||
void parser_stack_push_uint16 (parser_context_t *context_p, uint16_t uint16_value);
|
||||
uint16_t parser_stack_pop_uint16 (parser_context_t *context_p);
|
||||
void parser_stack_push (parser_context_t *context_p, const void *data_p, uint32_t length);
|
||||
|
||||
@@ -452,6 +452,26 @@ parser_stack_change_last_uint8 (parser_context_t *context_p, /**< context */
|
||||
context_p->stack_top_uint8 = new_value;
|
||||
} /* parser_stack_change_last_uint8 */
|
||||
|
||||
/**
|
||||
* Get the uint8 value before the top of the stack.
|
||||
*
|
||||
* Pointer to the uint8 value
|
||||
*/
|
||||
uint8_t *
|
||||
parser_stack_get_prev_uint8 (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
parser_mem_page_t *page_p = context_p->stack.first_p;
|
||||
|
||||
JERRY_ASSERT (page_p != NULL && (context_p->stack.last_position >= 2 || page_p->next_p != NULL));
|
||||
|
||||
if (context_p->stack.last_position >= 2)
|
||||
{
|
||||
return page_p->bytes + (context_p->stack.last_position - 2);
|
||||
}
|
||||
|
||||
return page_p->next_p->bytes + (PARSER_STACK_PAGE_SIZE - 1);
|
||||
} /* parser_stack_get_prev_uint8 */
|
||||
|
||||
/**
|
||||
* Pushes an uint16_t value onto the stack.
|
||||
*/
|
||||
|
||||
@@ -1430,13 +1430,21 @@ parser_parse_for_statement_start (parser_context_t *context_p) /**< context */
|
||||
case LEXER_LEFT_SQUARE:
|
||||
{
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p
|
||||
&& context_p->next_scanner_info_p->type == SCANNER_TYPE_FOR_PATTERN)
|
||||
&& context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS
|
||||
&& (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_DESTRUCTURING_FOR))
|
||||
{
|
||||
parser_emit_cbc_ext (context_p, is_for_in ? CBC_EXT_FOR_IN_GET_NEXT
|
||||
: CBC_EXT_FOR_OF_GET_NEXT);
|
||||
|
||||
uint32_t flags = PARSER_PATTERN_TARGET_ON_STACK;
|
||||
|
||||
if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST)
|
||||
{
|
||||
flags |= PARSER_PATTERN_HAS_REST_ELEMENT;
|
||||
}
|
||||
|
||||
scanner_release_next (context_p, sizeof (scanner_info_t));
|
||||
parser_parse_initializer (context_p, PARSER_PATTERN_TARGET_ON_STACK);
|
||||
parser_parse_initializer (context_p, flags);
|
||||
/* Pop the value returned by GET_NEXT. */
|
||||
parser_emit_cbc (context_p, CBC_POP);
|
||||
break;
|
||||
|
||||
@@ -1884,22 +1884,37 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */
|
||||
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
|
||||
{
|
||||
if (context_p->next_scanner_info_p->type != SCANNER_TYPE_INITIALIZER)
|
||||
if (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER)
|
||||
{
|
||||
if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST)
|
||||
{
|
||||
flags |= PARSER_PATTERN_HAS_REST_ELEMENT;
|
||||
}
|
||||
|
||||
if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_REST_PARAMETER_DEFAULT_INITIALIZER);
|
||||
}
|
||||
|
||||
if (context_p->argument_length == UINT16_MAX)
|
||||
{
|
||||
context_p->argument_length = context_p->argument_count;
|
||||
}
|
||||
|
||||
flags |= PARSER_PATTERN_TARGET_DEFAULT;
|
||||
}
|
||||
else if (context_p->next_scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS)
|
||||
{
|
||||
if (context_p->next_scanner_info_p->u8_arg & SCANNER_LITERAL_OBJECT_HAS_REST)
|
||||
{
|
||||
flags |= PARSER_PATTERN_HAS_REST_ELEMENT;
|
||||
}
|
||||
scanner_release_next (context_p, sizeof (scanner_info_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN);
|
||||
}
|
||||
|
||||
if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_REST_PARAMETER_DEFAULT_INITIALIZER);
|
||||
}
|
||||
|
||||
if (context_p->argument_length == UINT16_MAX)
|
||||
{
|
||||
context_p->argument_length = context_p->argument_count;
|
||||
}
|
||||
|
||||
flags |= PARSER_PATTERN_TARGET_DEFAULT;
|
||||
}
|
||||
|
||||
parser_parse_initializer (context_p, flags);
|
||||
|
||||
@@ -118,7 +118,6 @@ typedef enum
|
||||
SCAN_STACK_FUNCTION_PARAMETERS, /**< function parameter initializer */
|
||||
SCAN_STACK_FOR_START_PATTERN, /**< possible assignment pattern for "for" iterator */
|
||||
SCAN_STACK_USE_ASYNC, /**< an "async" identifier is used */
|
||||
SCAN_STACK_OBJECT_LITERAL_WITH_SUPER, /**< object literal with inner super reference */
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
} scan_stack_modes_t;
|
||||
|
||||
|
||||
@@ -245,6 +245,9 @@ scanner_check_arrow_arg (parser_context_t *context_p, /**< context */
|
||||
|
||||
if (context_p->token.type == LEXER_LEFT_BRACE)
|
||||
{
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
parser_stack_push_uint8 (context_p, 0);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
|
||||
scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
|
||||
return;
|
||||
|
||||
@@ -1916,10 +1916,9 @@ scanner_cleanup (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS
|
||||
|| scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION
|
||||
|| scanner_info_p->type == SCANNER_TYPE_FOR_PATTERN
|
||||
|| scanner_info_p->type == SCANNER_TYPE_LITERAL_FLAGS
|
||||
|| scanner_info_p->type == SCANNER_TYPE_CLASS_CONSTRUCTOR
|
||||
|| scanner_info_p->type == SCANNER_TYPE_OBJECT_LITERAL_WITH_SUPER
|
||||
|| scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION
|
||||
|| scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED
|
||||
|| scanner_info_p->type == SCANNER_TYPE_ERR_ASYNC_FUNCTION
|
||||
|| scanner_info_p->type == SCANNER_TYPE_EXPORT_MODULE_SPECIFIER);
|
||||
|
||||
@@ -147,6 +147,7 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
|
||||
{
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_NONE, false);
|
||||
parser_stack_push_uint8 (context_p, 0);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
|
||||
@@ -452,7 +453,6 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
|
||||
return SCAN_NEXT_TOKEN;
|
||||
}
|
||||
case SCAN_STACK_OBJECT_LITERAL_WITH_SUPER:
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
case SCAN_STACK_OBJECT_LITERAL:
|
||||
{
|
||||
@@ -566,7 +566,6 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
|
||||
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARRAY_LITERAL
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL_WITH_SUPER
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_LET
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_CONST
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_FOR_LET_START
|
||||
@@ -598,7 +597,6 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
|
||||
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARRAY_LITERAL
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL_WITH_SUPER
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_LET
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_CONST
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_FOR_LET_START
|
||||
@@ -607,9 +605,7 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS);
|
||||
|
||||
JERRY_ASSERT (SCANNER_NEEDS_BINDING_LIST (scanner_context_p->binding_type)
|
||||
|| (stack_top != SCAN_STACK_ARRAY_LITERAL
|
||||
&& stack_top != SCAN_STACK_OBJECT_LITERAL
|
||||
&& stack_top != SCAN_STACK_OBJECT_LITERAL_WITH_SUPER));
|
||||
|| (stack_top != SCAN_STACK_ARRAY_LITERAL && stack_top != SCAN_STACK_OBJECT_LITERAL));
|
||||
|
||||
if (binding_literal.literal_p->type & SCANNER_LITERAL_IS_USED)
|
||||
{
|
||||
@@ -838,30 +834,46 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
case SCAN_STACK_ARRAY_LITERAL:
|
||||
case SCAN_STACK_OBJECT_LITERAL:
|
||||
case SCAN_STACK_OBJECT_LITERAL_WITH_SUPER:
|
||||
{
|
||||
bool is_array = stack_top == SCAN_STACK_ARRAY_LITERAL;
|
||||
|
||||
if ((is_array && (type != LEXER_RIGHT_SQUARE))
|
||||
|| (!is_array && (type != LEXER_RIGHT_BRACE)))
|
||||
if ((stack_top == SCAN_STACK_ARRAY_LITERAL && type != LEXER_RIGHT_SQUARE)
|
||||
|| (stack_top == SCAN_STACK_OBJECT_LITERAL && type != LEXER_RIGHT_BRACE))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
scanner_source_start_t source_start;
|
||||
uint8_t binding_type = scanner_context_p->binding_type;
|
||||
uint8_t object_literal_flags = 0;
|
||||
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
|
||||
if (stack_top == SCAN_STACK_OBJECT_LITERAL)
|
||||
{
|
||||
object_literal_flags = context_p->stack_top_uint8;
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
}
|
||||
|
||||
scanner_context_p->binding_type = context_p->stack_top_uint8;
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t));
|
||||
|
||||
lexer_next_token (context_p);
|
||||
|
||||
if (binding_type == SCANNER_BINDING_CATCH && context_p->stack_top_uint8 == SCAN_STACK_CATCH_STATEMENT)
|
||||
stack_top = (scan_stack_modes_t) context_p->stack_top_uint8;
|
||||
|
||||
if (binding_type == SCANNER_BINDING_CATCH && stack_top == SCAN_STACK_CATCH_STATEMENT)
|
||||
{
|
||||
scanner_pop_binding_list (scanner_context_p);
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (object_literal_flags != 0)
|
||||
{
|
||||
scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t));
|
||||
info_p->type = SCANNER_TYPE_LITERAL_FLAGS;
|
||||
info_p->u8_arg = object_literal_flags;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
if (context_p->token.type != LEXER_RIGHT_PAREN)
|
||||
{
|
||||
scanner_raise_error (context_p);
|
||||
@@ -878,7 +890,7 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
return SCAN_NEXT_TOKEN;
|
||||
}
|
||||
|
||||
if (context_p->stack_top_uint8 == SCAN_STACK_FOR_START_PATTERN)
|
||||
if (stack_top == SCAN_STACK_FOR_START_PATTERN)
|
||||
{
|
||||
JERRY_ASSERT (binding_type == SCANNER_BINDING_NONE);
|
||||
|
||||
@@ -887,7 +899,8 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
if (context_p->token.type == LEXER_KEYW_IN || SCANNER_IDENTIFIER_IS_OF ())
|
||||
{
|
||||
scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t));
|
||||
info_p->type = SCANNER_TYPE_FOR_PATTERN;
|
||||
info_p->type = SCANNER_TYPE_LITERAL_FLAGS;
|
||||
info_p->u8_arg = object_literal_flags | SCANNER_LITERAL_DESTRUCTURING_FOR;
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
}
|
||||
@@ -900,12 +913,24 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (stack_top == SCAN_STACK_OBJECT_LITERAL_WITH_SUPER)
|
||||
if ((stack_top == SCAN_STACK_ARRAY_LITERAL || stack_top == SCAN_STACK_OBJECT_LITERAL)
|
||||
&& (binding_type == SCANNER_BINDING_NONE || binding_type == SCANNER_BINDING_ARROW_ARG)
|
||||
&& context_p->token.type != LEXER_EOS
|
||||
&& context_p->token.type != LEXER_COMMA
|
||||
&& context_p->token.type != LEXER_RIGHT_BRACE
|
||||
&& context_p->token.type != LEXER_RIGHT_SQUARE)
|
||||
{
|
||||
object_literal_flags |= SCANNER_LITERAL_NO_DESTRUCTURING;
|
||||
}
|
||||
|
||||
if (object_literal_flags != 0)
|
||||
{
|
||||
scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t));
|
||||
info_p->type = SCANNER_TYPE_OBJECT_LITERAL_WITH_SUPER;
|
||||
info_p->type = SCANNER_TYPE_LITERAL_FLAGS;
|
||||
info_p->u8_arg = object_literal_flags;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
@@ -915,6 +940,7 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
source_start.source_p,
|
||||
sizeof (scanner_location_info_t));
|
||||
location_info_p->info.type = SCANNER_TYPE_INITIALIZER;
|
||||
location_info_p->info.u8_arg = object_literal_flags;
|
||||
scanner_get_location (&location_info_p->location, context_p);
|
||||
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
||||
|
||||
@@ -933,6 +959,17 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
return SCAN_NEXT_TOKEN;
|
||||
}
|
||||
#else /* !ENABLED (JERRY_ESNEXT) */
|
||||
case SCAN_STACK_OBJECT_LITERAL:
|
||||
{
|
||||
if (type != LEXER_RIGHT_BRACE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
return SCAN_NEXT_TOKEN;
|
||||
}
|
||||
case SCAN_STACK_ARRAY_LITERAL:
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
case SCAN_STACK_PROPERTY_ACCESSOR:
|
||||
@@ -946,19 +983,6 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
return SCAN_NEXT_TOKEN;
|
||||
}
|
||||
#if !ENABLED (JERRY_ESNEXT)
|
||||
case SCAN_STACK_OBJECT_LITERAL:
|
||||
{
|
||||
if (type != LEXER_RIGHT_BRACE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
return SCAN_NEXT_TOKEN;
|
||||
}
|
||||
#endif /* !ENABLED (JERRY_ESNEXT) */
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
case SCAN_STACK_COMPUTED_PROPERTY:
|
||||
{
|
||||
@@ -1004,8 +1028,7 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (stack_top == SCAN_STACK_OBJECT_LITERAL
|
||||
|| stack_top == SCAN_STACK_OBJECT_LITERAL_WITH_SUPER);
|
||||
JERRY_ASSERT (stack_top == SCAN_STACK_OBJECT_LITERAL);
|
||||
|
||||
if (context_p->token.type == LEXER_LEFT_PAREN)
|
||||
{
|
||||
@@ -1042,7 +1065,6 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
|
||||
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL_WITH_SUPER
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_PROPERTY);
|
||||
|
||||
uint16_t status_flags = (uint16_t) (SCANNER_LITERAL_POOL_FUNCTION
|
||||
@@ -2149,7 +2171,7 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
|
||||
|
||||
if (has_super_reference && context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL)
|
||||
{
|
||||
parser_stack_change_last_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL_WITH_SUPER);
|
||||
*parser_stack_get_prev_uint8 (context_p) |= SCANNER_LITERAL_OBJECT_HAS_SUPER;
|
||||
}
|
||||
#else /* ENABLED (JERRY_ESNEXT) */
|
||||
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL);
|
||||
@@ -2367,6 +2389,7 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
|
||||
return SCAN_NEXT_TOKEN;
|
||||
}
|
||||
|
||||
parser_stack_push_uint8 (context_p, 0);
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
|
||||
scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
|
||||
return SCAN_KEEP_TOKEN;
|
||||
@@ -2792,6 +2815,7 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
break;
|
||||
}
|
||||
|
||||
parser_stack_push_uint8 (context_p, 0);
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
|
||||
scanner_context.mode = SCAN_MODE_PROPERTY_NAME;
|
||||
continue;
|
||||
@@ -2998,6 +3022,7 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
break;
|
||||
}
|
||||
|
||||
parser_stack_push_uint8 (context_p, 0);
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
|
||||
scanner_context.mode = SCAN_MODE_PROPERTY_NAME;
|
||||
continue;
|
||||
@@ -3092,12 +3117,7 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
case SCAN_MODE_PROPERTY_NAME:
|
||||
{
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
JERRY_ASSERT (stack_top == SCAN_STACK_OBJECT_LITERAL
|
||||
|| stack_top == SCAN_STACK_OBJECT_LITERAL_WITH_SUPER);
|
||||
#else /* !ENABLED (JERRY_ESNEXT) */
|
||||
JERRY_ASSERT (stack_top == SCAN_STACK_OBJECT_LITERAL);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
if (lexer_scan_identifier (context_p))
|
||||
{
|
||||
@@ -3114,6 +3134,7 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
|
||||
if (context_p->token.type == LEXER_THREE_DOTS)
|
||||
{
|
||||
*parser_stack_get_prev_uint8 (context_p) |= SCANNER_LITERAL_OBJECT_HAS_REST;
|
||||
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
||||
|
||||
if (scanner_context.binding_type != SCANNER_BINDING_NONE)
|
||||
@@ -3281,6 +3302,7 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
break;
|
||||
}
|
||||
|
||||
parser_stack_push_uint8 (context_p, 0);
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
|
||||
scanner_context.mode = SCAN_MODE_PROPERTY_NAME;
|
||||
continue;
|
||||
@@ -3729,15 +3751,13 @@ scan_completed:
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
case SCANNER_TYPE_INITIALIZER:
|
||||
{
|
||||
name_p = "INITIALIZER";
|
||||
print_location = true;
|
||||
break;
|
||||
}
|
||||
case SCANNER_TYPE_FOR_PATTERN:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" SCANNER_TYPE_FOR_PATTERN: source:%d\n",
|
||||
(int) (info_p->source_p - source_start_p));
|
||||
print_location = false;
|
||||
scanner_location_info_t *location_info_p = (scanner_location_info_t *) info_p;
|
||||
JERRY_DEBUG_MSG (" INITIALIZER: flags: 0x%x source:%d location:%d[%d:%d]\n",
|
||||
(int) info_p->u8_arg,
|
||||
(int) (location_info_p->info.source_p - source_start_p),
|
||||
(int) (location_info_p->location.source_p - source_start_p),
|
||||
(int) location_info_p->location.line,
|
||||
(int) location_info_p->location.column);
|
||||
break;
|
||||
}
|
||||
case SCANNER_TYPE_CLASS_CONSTRUCTOR:
|
||||
@@ -3771,9 +3791,10 @@ scan_completed:
|
||||
(int) (info_p->source_p - source_start_p));
|
||||
break;
|
||||
}
|
||||
case SCANNER_TYPE_OBJECT_LITERAL_WITH_SUPER:
|
||||
case SCANNER_TYPE_LITERAL_FLAGS:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" OBJECT_LITERAL_WITH_SUPER: source:%d\n",
|
||||
JERRY_DEBUG_MSG (" SCANNER_TYPE_LITERAL_FLAGS: flags: 0x%x source:%d\n",
|
||||
(int) info_p->u8_arg,
|
||||
(int) (info_p->source_p - source_start_p));
|
||||
print_location = false;
|
||||
break;
|
||||
|
||||
@@ -46,13 +46,12 @@ typedef enum
|
||||
SCANNER_TYPE_CASE, /**< case statement */
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
SCANNER_TYPE_INITIALIZER, /**< destructuring binding or assignment pattern with initializer */
|
||||
SCANNER_TYPE_FOR_PATTERN, /**< assignment pattern for for-in or for-of interators */
|
||||
SCANNER_TYPE_LITERAL_FLAGS, /**< object or array literal with non-zero flags (stored in u8_arg) */
|
||||
SCANNER_TYPE_CLASS_CONSTRUCTOR, /**< class constructor */
|
||||
SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END, /**< class field initializer end */
|
||||
SCANNER_TYPE_LET_EXPRESSION, /**< let expression */
|
||||
SCANNER_TYPE_ERR_REDECLARED, /**< syntax error: a variable is redeclared */
|
||||
SCANNER_TYPE_ERR_ASYNC_FUNCTION, /**< an invalid async function follows */
|
||||
SCANNER_TYPE_OBJECT_LITERAL_WITH_SUPER, /**< object literal with inner super reference */
|
||||
SCANNER_TYPE_EXPORT_MODULE_SPECIFIER, /**< export with module specifier */
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
} scanner_info_type_t;
|
||||
@@ -261,6 +260,23 @@ typedef enum
|
||||
SCANNER_FUNCTION_IS_STRICT = (1 << 5), /**< function is strict */
|
||||
} scanner_function_flags_t;
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
/**
|
||||
* Object or array literal constants for u8_arg flags in scanner_info_t.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/* These flags affects both array and object literals */
|
||||
SCANNER_LITERAL_DESTRUCTURING_FOR = (1 << 0), /**< for loop with destructuring pattern */
|
||||
SCANNER_LITERAL_NO_DESTRUCTURING = (1 << 1), /**< this literal cannot be a destructuring pattern */
|
||||
/* These flags affects only object literals */
|
||||
SCANNER_LITERAL_OBJECT_HAS_SUPER = (1 << 2), /**< super keyword is used in the object literal */
|
||||
SCANNER_LITERAL_OBJECT_HAS_REST = (1 << 3), /**< the object literal has a member prefixed with three dots */
|
||||
} scanner_literal_flags_t;
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/**
|
||||
* Option bits for scanner_create_variables function.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user