Fix the initialization of let/const patterns when block context is needed. (#3320)

Also some code cuplication is removed.

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
Robert Fancsik
2019-11-15 14:38:14 +01:00
committed by Dániel Bátyai
parent 8eda9bc1c3
commit fca0c94002
8 changed files with 297 additions and 205 deletions
+220 -199
View File
@@ -1819,6 +1819,109 @@ parser_process_unary_expression (parser_context_t *context_p, /**< context */
} }
} /* parser_process_unary_expression */ } /* parser_process_unary_expression */
/**
* Append a binary '=' token.
*/
static void
parser_append_binary_single_assignment_token (parser_context_t *context_p, /**< context */
uint8_t assign_ident_opcode) /**< assign ident opcode */
{
JERRY_ASSERT (assign_ident_opcode == CBC_ASSIGN_SET_IDENT
|| assign_ident_opcode == CBC_ASSIGN_LET_CONST);
/* Unlike other tokens, the whole byte code is saved for binary
* assignment, since it has multiple forms depending on the
* previous instruction. */
if (PARSER_IS_PUSH_LITERAL (context_p->last_cbc_opcode)
&& context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL)
{
JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_LITERAL, assign_ident_opcode));
parser_check_invalid_assign (context_p);
uint16_t literal_index;
if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
{
literal_index = context_p->last_cbc.literal_index;
context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
}
else if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS)
{
literal_index = context_p->last_cbc.value;
context_p->last_cbc_opcode = CBC_PUSH_LITERAL;
}
else
{
JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_THREE_LITERALS);
literal_index = context_p->last_cbc.third_literal_index;
context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS;
}
parser_stack_push_uint16 (context_p, literal_index);
parser_stack_push_uint8 (context_p, assign_ident_opcode);
}
else if (context_p->last_cbc_opcode == CBC_PUSH_PROP)
{
JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP, CBC_ASSIGN));
parser_stack_push_uint8 (context_p, CBC_ASSIGN);
context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
}
else if (context_p->last_cbc_opcode == CBC_PUSH_PROP_LITERAL)
{
if (context_p->last_cbc.literal_type != LEXER_IDENT_LITERAL)
{
JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP_LITERAL, CBC_ASSIGN_PROP_LITERAL));
parser_stack_push_uint16 (context_p, context_p->last_cbc.literal_index);
parser_stack_push_uint8 (context_p, CBC_ASSIGN_PROP_LITERAL);
context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
#if ENABLED (JERRY_ES2015)
if (context_p->status_flags & PARSER_CLASS_SUPER_PROP_REFERENCE)
{
parser_emit_cbc_ext (context_p, CBC_EXT_SUPER_PROP_ASSIGN);
parser_flush_cbc (context_p);
}
context_p->status_flags &= (uint32_t) ~PARSER_CLASS_SUPER_PROP_REFERENCE;
#endif /* ENABLED (JERRY_ES2015) */
}
else
{
context_p->last_cbc_opcode = CBC_PUSH_LITERAL;
parser_stack_push_uint8 (context_p, CBC_ASSIGN);
}
}
else if (context_p->last_cbc_opcode == CBC_PUSH_PROP_LITERAL_LITERAL)
{
JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP_LITERAL_LITERAL, CBC_PUSH_TWO_LITERALS));
context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS;
parser_stack_push_uint8 (context_p, CBC_ASSIGN);
}
else if (context_p->last_cbc_opcode == CBC_PUSH_PROP_THIS_LITERAL)
{
if (context_p->last_cbc.literal_type != LEXER_IDENT_LITERAL)
{
JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP_THIS_LITERAL, CBC_ASSIGN_PROP_THIS_LITERAL));
parser_stack_push_uint16 (context_p, context_p->last_cbc.literal_index);
parser_stack_push_uint8 (context_p, CBC_ASSIGN_PROP_THIS_LITERAL);
context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
}
else
{
context_p->last_cbc_opcode = CBC_PUSH_THIS_LITERAL;
parser_stack_push_uint8 (context_p, CBC_ASSIGN);
}
}
else
{
/* Invalid LeftHandSide expression. */
parser_emit_cbc_ext (context_p, CBC_EXT_THROW_REFERENCE_ERROR);
parser_stack_push_uint8 (context_p, CBC_ASSIGN);
}
parser_stack_push_uint8 (context_p, LEXER_ASSIGN);
} /* parser_append_binary_single_assignment_token */
/** /**
* Append a binary token. * Append a binary token.
*/ */
@@ -1831,97 +1934,11 @@ parser_append_binary_token (parser_context_t *context_p) /**< context */
if (context_p->token.type == LEXER_ASSIGN) if (context_p->token.type == LEXER_ASSIGN)
{ {
/* Unlike other tokens, the whole byte code is saved for binary parser_append_binary_single_assignment_token (context_p, CBC_ASSIGN_SET_IDENT);
* assignment, since it has multiple forms depending on the return;
* previous instruction. */
if (PARSER_IS_PUSH_LITERAL (context_p->last_cbc_opcode)
&& context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL)
{
JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_LITERAL, CBC_ASSIGN_SET_IDENT));
parser_check_invalid_assign (context_p);
uint16_t literal_index;
if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
{
literal_index = context_p->last_cbc.literal_index;
context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
}
else if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS)
{
literal_index = context_p->last_cbc.value;
context_p->last_cbc_opcode = CBC_PUSH_LITERAL;
}
else
{
JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_THREE_LITERALS);
literal_index = context_p->last_cbc.third_literal_index;
context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS;
}
parser_stack_push_uint16 (context_p, literal_index);
parser_stack_push_uint8 (context_p, CBC_ASSIGN_SET_IDENT);
}
else if (context_p->last_cbc_opcode == CBC_PUSH_PROP)
{
JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP, CBC_ASSIGN));
parser_stack_push_uint8 (context_p, CBC_ASSIGN);
context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
}
else if (context_p->last_cbc_opcode == CBC_PUSH_PROP_LITERAL)
{
if (context_p->last_cbc.literal_type != LEXER_IDENT_LITERAL)
{
JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP_LITERAL, CBC_ASSIGN_PROP_LITERAL));
parser_stack_push_uint16 (context_p, context_p->last_cbc.literal_index);
parser_stack_push_uint8 (context_p, CBC_ASSIGN_PROP_LITERAL);
context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
#if ENABLED (JERRY_ES2015)
if (context_p->status_flags & PARSER_CLASS_SUPER_PROP_REFERENCE)
{
parser_emit_cbc_ext (context_p, CBC_EXT_SUPER_PROP_ASSIGN);
parser_flush_cbc (context_p);
}
context_p->status_flags &= (uint32_t) ~PARSER_CLASS_SUPER_PROP_REFERENCE;
#endif /* ENABLED (JERRY_ES2015) */
}
else
{
context_p->last_cbc_opcode = CBC_PUSH_LITERAL;
parser_stack_push_uint8 (context_p, CBC_ASSIGN);
}
}
else if (context_p->last_cbc_opcode == CBC_PUSH_PROP_LITERAL_LITERAL)
{
JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP_LITERAL_LITERAL, CBC_PUSH_TWO_LITERALS));
context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS;
parser_stack_push_uint8 (context_p, CBC_ASSIGN);
}
else if (context_p->last_cbc_opcode == CBC_PUSH_PROP_THIS_LITERAL)
{
if (context_p->last_cbc.literal_type != LEXER_IDENT_LITERAL)
{
JERRY_ASSERT (CBC_SAME_ARGS (CBC_PUSH_PROP_THIS_LITERAL, CBC_ASSIGN_PROP_THIS_LITERAL));
parser_stack_push_uint16 (context_p, context_p->last_cbc.literal_index);
parser_stack_push_uint8 (context_p, CBC_ASSIGN_PROP_THIS_LITERAL);
context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
}
else
{
context_p->last_cbc_opcode = CBC_PUSH_THIS_LITERAL;
parser_stack_push_uint8 (context_p, CBC_ASSIGN);
}
}
else
{
/* Invalid LeftHandSide expression. */
parser_emit_cbc_ext (context_p, CBC_EXT_THROW_REFERENCE_ERROR);
parser_stack_push_uint8 (context_p, CBC_ASSIGN);
}
} }
else if (LEXER_IS_BINARY_LVALUE_TOKEN (context_p->token.type))
if (LEXER_IS_BINARY_LVALUE_TOKEN (context_p->token.type))
{ {
if (PARSER_IS_PUSH_LITERAL (context_p->last_cbc_opcode) if (PARSER_IS_PUSH_LITERAL (context_p->last_cbc_opcode)
&& context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL) && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL)
@@ -2073,6 +2090,11 @@ typedef struct
lexer_token_t token; /**< token at the end position */ lexer_token_t token; /**< token at the end position */
} parser_pattern_end_marker_t; } parser_pattern_end_marker_t;
/**
* Literal index should not be emitted while processing rhs target value
*/
#define PARSER_PATTERN_RHS_NO_LIT UINT16_MAX
/** /**
* Process the target of an initializer pattern. * Process the target of an initializer pattern.
*/ */
@@ -2097,7 +2119,8 @@ parser_pattern_get_target (parser_context_t *context_p, /**< context */
scanner_location_t start_location; scanner_location_t start_location;
if (context_p->next_scanner_info_p->source_p != context_p->source_p if (context_p->next_scanner_info_p->source_p != context_p->source_p
|| context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED) || context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED
|| (flags & PARSER_PATTERN_REST_ELEMENT))
{ {
/* Found invalid pattern, push null value to fake the rhs target. */ /* Found invalid pattern, push null value to fake the rhs target. */
parser_emit_cbc (context_p, CBC_PUSH_NULL); parser_emit_cbc (context_p, CBC_PUSH_NULL);
@@ -2148,9 +2171,14 @@ parser_pattern_finalize (parser_context_t *context_p, /**< context */
scanner_set_location (context_p, &(end_marker_p->location)); scanner_set_location (context_p, &(end_marker_p->location));
context_p->token = end_marker_p->token; context_p->token = end_marker_p->token;
} }
else
{
JERRY_ASSERT (!(flags & PARSER_PATTERN_TARGET_DEFAULT));
lexer_next_token (context_p);
}
if ((flags & PARSER_PATTERN_BINDING) if ((flags & PARSER_PATTERN_BINDING)
&& !(flags & PARSER_PATTERN_INNER_PATTERN)) && !(flags & PARSER_PATTERN_NESTED_PATTERN))
{ {
/* Pop the result of the expression. */ /* Pop the result of the expression. */
parser_emit_cbc (context_p, CBC_POP); parser_emit_cbc (context_p, CBC_POP);
@@ -2167,7 +2195,7 @@ parser_pattern_emit_rhs (parser_context_t *context_p, /**< context */
uint16_t rhs_opcode, /**< opcode to process the rhs value */ uint16_t rhs_opcode, /**< opcode to process the rhs value */
uint16_t literal_index) /**< literal index for object pattern */ uint16_t literal_index) /**< literal index for object pattern */
{ {
if (literal_index != UINT16_MAX) if (literal_index != PARSER_PATTERN_RHS_NO_LIT)
{ {
parser_emit_cbc_ext_literal (context_p, rhs_opcode, literal_index); parser_emit_cbc_ext_literal (context_p, rhs_opcode, literal_index);
} }
@@ -2182,21 +2210,27 @@ parser_pattern_emit_rhs (parser_context_t *context_p, /**< context */
*/ */
static void static void
parser_pattern_form_assignment (parser_context_t *context_p, /**< context */ parser_pattern_form_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 rhs_opcode, /**< opcode to process the rhs value */
uint16_t literal_index, /**< literal index for object pattern */ uint16_t literal_index, /**< literal index for object pattern */
parser_line_counter_t ident_line_counter) /**< identifier line counter */ parser_line_counter_t ident_line_counter) /**< identifier line counter */
{ {
JERRY_UNUSED (ident_line_counter); JERRY_UNUSED (ident_line_counter);
parser_stack_push_uint8 (context_p, LEXER_EXPRESSION_START); uint8_t assign_opcode = CBC_ASSIGN_SET_IDENT;
lexer_token_type_t current_token_type = context_p->token.type;
context_p->token.type = LEXER_ASSIGN; if (flags & PARSER_PATTERN_LEXICAL
parser_append_binary_token (context_p); && context_p->lit_object.index < PARSER_REGISTER_START)
{
assign_opcode = CBC_ASSIGN_LET_CONST;
}
parser_stack_push_uint8 (context_p, LEXER_EXPRESSION_START);
parser_append_binary_single_assignment_token (context_p, assign_opcode);
parser_pattern_emit_rhs (context_p, rhs_opcode, literal_index); parser_pattern_emit_rhs (context_p, rhs_opcode, literal_index);
if (current_token_type == LEXER_ASSIGN) if (context_p->token.type == LEXER_ASSIGN)
{ {
parser_branch_t skip_init; parser_branch_t skip_init;
lexer_next_token (context_p); lexer_next_token (context_p);
@@ -2206,10 +2240,6 @@ parser_pattern_form_assignment (parser_context_t *context_p, /**< context */
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);
parser_set_branch_to_current_position (context_p, &skip_init); parser_set_branch_to_current_position (context_p, &skip_init);
} }
else
{
context_p->token.type = current_token_type;
}
parser_process_binary_opcodes (context_p, 0); parser_process_binary_opcodes (context_p, 0);
@@ -2241,23 +2271,21 @@ parser_pattern_form_assignment (parser_context_t *context_p, /**< context */
* Parse pattern inside a pattern. * Parse pattern inside a pattern.
*/ */
static void static void
parser_pattern_process_inner_pattern (parser_context_t *context_p, /**< context */ parser_pattern_process_nested_pattern (parser_context_t *context_p, /**< context */
parser_pattern_flags_t flags, /**< flags */ parser_pattern_flags_t flags, /**< flags */
uint16_t rhs_opcode, /**< opcode to process the rhs value */ uint16_t rhs_opcode, /**< opcode to process the rhs value */
uint16_t literal_index) /**< literal index for object pattern */ uint16_t literal_index) /**< literal index for object pattern */
{ {
JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE || context_p->token.type == LEXER_LEFT_SQUARE); JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE || context_p->token.type == LEXER_LEFT_SQUARE);
parser_pattern_flags_t options = (PARSER_PATTERN_INNER_PATTERN parser_pattern_flags_t options = (PARSER_PATTERN_NESTED_PATTERN
| PARSER_PATTERN_TARGET_ON_STACK | PARSER_PATTERN_TARGET_ON_STACK
| (flags & PARSER_PATTERN_BINDING)); | (flags & (PARSER_PATTERN_BINDING
| PARSER_PATTERN_LEXICAL
| PARSER_PATTERN_REST_ELEMENT)));
if (context_p->next_scanner_info_p->source_p == context_p->source_p) if (context_p->next_scanner_info_p->source_p == context_p->source_p)
{ {
if (rhs_opcode == CBC_EXT_REST_INITIALIZER)
{
parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN);
}
options |= PARSER_PATTERN_TARGET_DEFAULT; options |= PARSER_PATTERN_TARGET_DEFAULT;
} }
@@ -2272,13 +2300,77 @@ parser_pattern_process_inner_pattern (parser_context_t *context_p, /**< context
parser_parse_array_initializer (context_p, options); parser_parse_array_initializer (context_p, options);
} }
if (!(options & PARSER_PATTERN_TARGET_DEFAULT)) parser_emit_cbc (context_p, CBC_POP);
} /* parser_pattern_process_nested_pattern */
/**
* Process the current {Binding, Assignment}Property
*/
static void
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)
{ {
lexer_next_token (context_p); parser_pattern_process_nested_pattern (context_p, flags, rhs_opcode, literal_index);
return;
} }
parser_emit_cbc (context_p, CBC_POP); parser_line_counter_t ident_line_counter = context_p->token.line;
} /* parser_pattern_process_inner_pattern */
if (flags & PARSER_PATTERN_BINDING)
{
if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
{
parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
}
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
{
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
}
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
parser_module_append_export_name (context_p);
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);
lexer_next_token (context_p);
if (context_p->token.type != end_type
&& context_p->token.type != LEXER_ASSIGN
&& context_p->token.type != LEXER_COMMA)
{
parser_raise_error (context_p, PARSER_ERR_ILLEGAL_PROPERTY_IN_DECLARATION);
}
}
else
{
parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA | PARSE_EXPR_LEFT_HAND_SIDE);
if (!PARSER_IS_PUSH_LITERAL (context_p->last_cbc_opcode))
{
if (!PARSER_IS_PUSH_PROP (context_p->last_cbc_opcode)
&& context_p->last_cbc_opcode != CBC_EXT_PUSH_CONSTRUCTOR_SUPER_PROP)
{
parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN);
}
if (end_type == LEXER_RIGHT_SQUARE)
{
PARSER_PLUS_EQUAL_U16 (rhs_opcode, 1);
}
}
}
parser_pattern_form_assignment (context_p, flags, rhs_opcode, literal_index, ident_line_counter);
} /* parser_pattern_process_assignment */
/** /**
* Parse array initializer. * Parse array initializer.
@@ -2295,82 +2387,28 @@ parser_parse_array_initializer (parser_context_t *context_p, /**< context */
while (context_p->token.type != LEXER_RIGHT_SQUARE) while (context_p->token.type != LEXER_RIGHT_SQUARE)
{ {
uint16_t step_opcode = CBC_EXT_ITERATOR_STEP; uint16_t rhs_opcode = CBC_EXT_ITERATOR_STEP;
if (context_p->token.type == LEXER_COMMA) if (context_p->token.type == LEXER_COMMA)
{ {
parser_emit_cbc_ext (context_p, step_opcode); parser_emit_cbc_ext (context_p, rhs_opcode);
parser_emit_cbc (context_p, CBC_POP); parser_emit_cbc (context_p, CBC_POP);
lexer_next_token (context_p); lexer_next_token (context_p);
continue; continue;
} }
parser_pattern_flags_t options = flags;
if (context_p->token.type == LEXER_THREE_DOTS) if (context_p->token.type == LEXER_THREE_DOTS)
{ {
lexer_next_token (context_p); lexer_next_token (context_p);
step_opcode = CBC_EXT_REST_INITIALIZER; rhs_opcode = CBC_EXT_REST_INITIALIZER;
options |= PARSER_PATTERN_REST_ELEMENT;
} }
if (context_p->token.type == LEXER_LEFT_BRACE || context_p->token.type == LEXER_LEFT_SQUARE) parser_pattern_process_assignment (context_p, options, rhs_opcode, PARSER_PATTERN_RHS_NO_LIT, LEXER_RIGHT_SQUARE);
{
parser_pattern_process_inner_pattern (context_p, flags, step_opcode, UINT16_MAX);
if (step_opcode == CBC_EXT_REST_INITIALIZER) if (context_p->token.type == LEXER_COMMA && rhs_opcode != CBC_EXT_REST_INITIALIZER)
{
break;
}
}
else
{
parser_line_counter_t ident_line_counter = context_p->token.line;
if (flags & PARSER_PATTERN_BINDING)
{
if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
{
parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
}
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
{
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
}
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
parser_module_append_export_name (context_p);
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);
lexer_next_token (context_p);
}
else
{
parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA | PARSE_EXPR_LEFT_HAND_SIDE);
if (!PARSER_IS_PUSH_LITERAL (context_p->last_cbc_opcode))
{
if (!PARSER_IS_PUSH_PROP (context_p->last_cbc_opcode)
&& context_p->last_cbc_opcode != CBC_EXT_PUSH_CONSTRUCTOR_SUPER_PROP)
{
parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN);
}
PARSER_PLUS_EQUAL_U16 (step_opcode, 1);
}
}
if (step_opcode == CBC_EXT_REST_INITIALIZER
&& context_p->token.type != LEXER_RIGHT_SQUARE)
{
parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN);
}
parser_pattern_form_assignment (context_p, step_opcode, UINT16_MAX, ident_line_counter);
}
if (context_p->token.type == LEXER_COMMA)
{ {
lexer_next_token (context_p); lexer_next_token (context_p);
} }
@@ -2411,7 +2449,7 @@ parser_parse_object_initializer (parser_context_t *context_p, /**< context */
} }
else if (context_p->token.type == LEXER_RIGHT_SQUARE) else if (context_p->token.type == LEXER_RIGHT_SQUARE)
{ {
prop_index = UINT16_MAX; prop_index = PARSER_PATTERN_RHS_NO_LIT;
push_prop_opcode = CBC_EXT_INITIALIZER_PUSH_PROP; push_prop_opcode = CBC_EXT_INITIALIZER_PUSH_PROP;
} }
@@ -2432,36 +2470,19 @@ parser_parse_object_initializer (parser_context_t *context_p, /**< context */
lexer_next_token (context_p); lexer_next_token (context_p);
} }
bool is_inner_pattern = false;
if (context_p->token.type == LEXER_COLON) if (context_p->token.type == LEXER_COLON)
{ {
lexer_next_token (context_p); lexer_next_token (context_p);
parser_pattern_process_assignment (context_p, flags, push_prop_opcode, prop_index, LEXER_RIGHT_BRACE);
if (context_p->token.type == LEXER_LEFT_BRACE || context_p->token.type == LEXER_LEFT_SQUARE)
{
parser_pattern_process_inner_pattern (context_p, flags, push_prop_opcode, prop_index);
is_inner_pattern = true;
}
else
{
if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
{
parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
}
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
lexer_next_token (context_p);
}
} }
else
if (!is_inner_pattern)
{ {
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM) #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
parser_module_append_export_name (context_p); parser_module_append_export_name (context_p);
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);
parser_pattern_form_assignment (context_p, push_prop_opcode, prop_index, start_line); parser_pattern_form_assignment (context_p, flags, push_prop_opcode, prop_index, start_line);
} }
if (context_p->token.type == LEXER_RIGHT_BRACE) if (context_p->token.type == LEXER_RIGHT_BRACE)
+7 -5
View File
@@ -104,11 +104,13 @@ typedef enum
*/ */
typedef enum typedef enum
{ {
PARSER_PATTERN_NO_OPTS = 0, /**< parse the expression after '=' */ PARSER_PATTERN_NO_OPTS = 0, /**< parse the expression after '=' */
PARSER_PATTERN_BINDING = (1u << 0), /**< parse BindingPattern */ 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_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_TARGET_DEFAULT = (1u << 3), /**< perform default value comparison for assignment target */
PARSER_PATTERN_INNER_PATTERN = (1u << 3), /**< parse patter inside a pattern */ PARSER_PATTERN_NESTED_PATTERN = (1u << 4), /**< parse patter inside a pattern */
PARSER_PATTERN_LEXICAL = (1u << 5), /**< pattern is a lexical (let/const) declaration */
PARSER_PATTERN_REST_ELEMENT = (1u << 6), /**< parse rest array initializer */
} parser_pattern_flags_t; } parser_pattern_flags_t;
/** /**
+7 -1
View File
@@ -451,7 +451,13 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
|| lexer_check_next_character (context_p, LIT_CHAR_LEFT_SQUARE)) || lexer_check_next_character (context_p, LIT_CHAR_LEFT_SQUARE))
{ {
lexer_next_token (context_p); lexer_next_token (context_p);
parser_parse_initializer (context_p, PARSER_PATTERN_BINDING); parser_pattern_flags_t options = PARSER_PATTERN_BINDING;
if (declaration_type != LEXER_KEYW_VAR)
{
options |= PARSER_PATTERN_LEXICAL;
}
parser_parse_initializer (context_p, options);
} }
else else
{ {
+4
View File
@@ -1125,6 +1125,10 @@ parser_error_to_string (parser_error_t error) /**< error code */
{ {
return "Invalid destructuring assignment target."; return "Invalid destructuring assignment target.";
} }
case PARSER_ERR_ILLEGAL_PROPERTY_IN_DECLARATION:
{
return "Illegal property in declaration context.";
}
case PARSER_ERR_FORMAL_PARAM_AFTER_REST_PARAMETER: case PARSER_ERR_FORMAL_PARAM_AFTER_REST_PARAMETER:
{ {
return "Rest parameter must be the last formal parameter."; return "Rest parameter must be the last formal parameter.";
+1
View File
@@ -129,6 +129,7 @@ typedef enum
PARSER_ERR_REST_PARAMETER_DEFAULT_INITIALIZER, /**< rest parameter default initializer */ PARSER_ERR_REST_PARAMETER_DEFAULT_INITIALIZER, /**< rest parameter default initializer */
PARSER_ERR_DUPLICATED_ARGUMENT_NAMES, /**< duplicated argument names */ PARSER_ERR_DUPLICATED_ARGUMENT_NAMES, /**< duplicated argument names */
PARSER_ERR_INVALID_DESTRUCTURING_PATTERN, /**< invalid destructuring pattern */ PARSER_ERR_INVALID_DESTRUCTURING_PATTERN, /**< invalid destructuring pattern */
PARSER_ERR_ILLEGAL_PROPERTY_IN_DECLARATION, /**< illegal property in declaration context */
#endif /* ENABLED (JERRY_ES2015) */ #endif /* ENABLED (JERRY_ES2015) */
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM) #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
PARSER_ERR_FILE_NOT_FOUND, /**< file not found*/ PARSER_ERR_FILE_NOT_FOUND, /**< file not found*/
+7
View File
@@ -432,6 +432,13 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
scanner_raise_error (context_p); scanner_raise_error (context_p);
} }
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
#if ENABLED (JERRY_ES2015)
if (scanner_context_p->binding_type != SCANNER_BINDING_NONE)
{
scanner_context_p->mode = SCAN_MODE_BINDING;
}
#endif /* ENABLED (JERRY_ES2015) */
break; break;
} }
case LEXER_RIGHT_PAREN: case LEXER_RIGHT_PAREN:
+25
View File
@@ -58,6 +58,8 @@ checkSyntax ("[super] = []");
checkSyntax ("[this] = []"); checkSyntax ("[this] = []");
checkSyntax ("[()] = []"); checkSyntax ("[()] = []");
checkSyntax ("try { let [$] = $;"); checkSyntax ("try { let [$] = $;");
checkSyntax ("let a, [ b.c ] = [6];");
checkSyntax ("let [(a)] = [1]");
mustThrow ("var [a] = 4"); mustThrow ("var [a] = 4");
mustThrow ("var [a] = 5"); mustThrow ("var [a] = 5");
@@ -222,3 +224,26 @@ mustThrow ("var [a] = { [Symbol.iterator] () { return { next () { return { get d
assert (a === 1); assert (a === 1);
assert (b === 2); assert (b === 2);
}) (); }) ();
// Force the creation of lexical environment I.
(function () {
const [a] = [1];
eval();
assert (a === 1);
}) ();
// Force the creation of lexical environment II.
(function () {
let [a] = [1];
eval();
assert (a === 1);
}) ();
// Check the parsing of AssignmentElement
(function () {
var a = 6;
[((a))] = [7];
assert (a === 7);
}) ();
+26
View File
@@ -48,6 +48,9 @@ checkSyntax ("let {a : b, b} = []");
checkSyntax ("const {a,a} = []"); checkSyntax ("const {a,a} = []");
checkSyntax ("const {a : b, b} = []"); checkSyntax ("const {a : b, b} = []");
checkSyntax ("try { let {$} = $;"); checkSyntax ("try { let {$} = $;");
checkSyntax ("let a, { 'x': a } = {x : 4};");
checkSyntax ("let a, { x: b.c } = {x : 6};");
checkSyntax ("let {a:(a)} = {a:1}");
mustThrow ("var {a} = null"); mustThrow ("var {a} = null");
mustThrow ("var {a} = undefined"); mustThrow ("var {a} = undefined");
@@ -197,3 +200,26 @@ mustThrow ("var {a} = undefined");
assert (a === 1); assert (a === 1);
assert (b === 2); assert (b === 2);
}) (); }) ();
// Force the creation of lexical environment I.
(function () {
const {a} = {a : 1};
eval();
assert (a === 1);
}) ();
// Force the creation of lexical environment II.
(function () {
let {a} = {a : 1};
eval();
assert (a === 1);
}) ();
// Check the parsing of AssignmentElement
(function () {
var a = 6;
({"a": ((a)) } = {a : 7});
assert (a === 7);
}) ();