diff --git a/jerry-core/parser/js/js-lexer.c b/jerry-core/parser/js/js-lexer.c index db94b3e0e..d6c2e60d1 100644 --- a/jerry-core/parser/js/js-lexer.c +++ b/jerry-core/parser/js/js-lexer.c @@ -2407,9 +2407,9 @@ lexer_construct_function_object (parser_context_t *context_p, /**< context */ parser_flush_cbc (context_p); - if (context_p->status_flags & (PARSER_RESOLVE_BASE_FOR_CALLS | PARSER_INSIDE_WITH)) + if (context_p->status_flags & PARSER_INSIDE_WITH) { - extra_status_flags |= PARSER_RESOLVE_BASE_FOR_CALLS; + extra_status_flags |= PARSER_INSIDE_WITH; } literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); diff --git a/jerry-core/parser/js/js-lexer.h b/jerry-core/parser/js/js-lexer.h index fc94fe288..e4f2f97a6 100644 --- a/jerry-core/parser/js/js-lexer.h +++ b/jerry-core/parser/js/js-lexer.h @@ -163,6 +163,9 @@ typedef enum LEXER_SCAN_SWITCH, /**< special value for switch pre-scan */ LEXER_CLASS_CONSTRUCTOR, /**< special value for class constructor method */ LEXER_INVALID_PATTERN, /**< special value for invalid destructuring pattern */ +#if ENABLED (JERRY_ES2015) + LEXER_ARROW_LEFT_PAREN, /**< start of arrow function argument list */ +#endif /* ENABLED (JERRY_ES2015) */ /* Keywords which are not keyword tokens. */ #define LEXER_FIRST_NON_RESERVED_KEYWORD LEXER_KEYW_EVAL diff --git a/jerry-core/parser/js/js-parser-expr.c b/jerry-core/parser/js/js-parser-expr.c index 4dac20c53..57503a672 100644 --- a/jerry-core/parser/js/js-parser-expr.c +++ b/jerry-core/parser/js/js-parser-expr.c @@ -1543,9 +1543,9 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */ && context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); parser_check_assignment_expr (context_p); - lexer_next_token (context_p); - parser_parse_function_expression (context_p, - PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION | PARSER_ARROW_PARSE_ARGS); + + context_p->token.type = LEXER_ARROW_LEFT_PAREN; + parser_parse_function_expression (context_p, PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION); return parser_abort_parsing_after_arrow (context_p); } case LEXER_KEYW_YIELD: @@ -1714,9 +1714,9 @@ parser_process_unary_expression (parser_context_t *context_p, /**< context */ opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_CALL); } #endif /* ENABLED (JERRY_ES2015) */ - else if (JERRY_UNLIKELY ((context_p->status_flags & (PARSER_INSIDE_WITH | PARSER_RESOLVE_BASE_FOR_CALLS)) - && PARSER_IS_PUSH_LITERAL (context_p->last_cbc_opcode) - && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL)) + else if (JERRY_UNLIKELY (context_p->status_flags & PARSER_INSIDE_WITH) + && PARSER_IS_PUSH_LITERAL (context_p->last_cbc_opcode) + && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL) { opcode = CBC_CALL_PROP; parser_emit_ident_reference (context_p, CBC_PUSH_IDENT_REFERENCE); diff --git a/jerry-core/parser/js/js-parser-internal.h b/jerry-core/parser/js/js-parser-internal.h index e3dfa5f60..d08224535 100644 --- a/jerry-core/parser/js/js-parser-internal.h +++ b/jerry-core/parser/js/js-parser-internal.h @@ -53,38 +53,35 @@ typedef enum PARSER_ARGUMENTS_NEEDED = (1u << 7), /**< arguments object must be created */ PARSER_LEXICAL_ENV_NEEDED = (1u << 8), /**< lexical environment object must be created */ PARSER_INSIDE_WITH = (1u << 9), /**< code block is inside a with statement */ - PARSER_RESOLVE_BASE_FOR_CALLS = (1u << 10), /**< the this object must be resolved when - * a function without a base object is called */ - PARSER_HAS_LATE_LIT_INIT = (1u << 11), /**< allocate memory for this string after - * the local parser data is freed */ - PARSER_NO_END_LABEL = (1u << 12), /**< return instruction must be inserted + PARSER_NO_END_LABEL = (1u << 10), /**< return instruction must be inserted * after the last byte code */ - PARSER_DEBUGGER_BREAKPOINT_APPENDED = (1u << 13), /**< pending (unsent) breakpoint + PARSER_DEBUGGER_BREAKPOINT_APPENDED = (1u << 11), /**< pending (unsent) breakpoint * info is available */ #if ENABLED (JERRY_ES2015) - PARSER_INSIDE_BLOCK = (1u << 14), /**< script has a lexical environment for let and const */ - PARSER_IS_ARROW_FUNCTION = (1u << 15), /**< an arrow function is parsed */ - PARSER_ARROW_PARSE_ARGS = (1u << 16), /**< parse the argument list of an arrow function */ - PARSER_IS_GENERATOR_FUNCTION = (1u << 17), /**< a generator function is parsed */ - PARSER_DISALLOW_YIELD = (1u << 18), /**< throw SyntaxError for yield expression */ - PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM = (1u << 19), /**< function has a non simple parameter */ - PARSER_FUNCTION_HAS_REST_PARAM = (1u << 20), /**< function has rest parameter */ + PARSER_INSIDE_BLOCK = (1u << 12), /**< script has a lexical environment for let and const */ + PARSER_IS_ARROW_FUNCTION = (1u << 13), /**< an arrow function is parsed */ + PARSER_IS_GENERATOR_FUNCTION = (1u << 14), /**< a generator function is parsed */ + PARSER_DISALLOW_YIELD = (1u << 15), /**< throw SyntaxError for yield expression */ + PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM = (1u << 16), /**< function has a non simple parameter */ + PARSER_FUNCTION_HAS_REST_PARAM = (1u << 17), /**< function has rest parameter */ /* These four status flags must be in this order. See PARSER_CLASS_PARSE_OPTS_OFFSET. */ - PARSER_CLASS_CONSTRUCTOR = (1u << 21), /**< a class constructor is parsed (this value must be kept in + PARSER_CLASS_CONSTRUCTOR = (1u << 18), /**< a class constructor is parsed (this value must be kept in * in sync with ECMA_PARSE_CLASS_CONSTRUCTOR) */ - PARSER_CLASS_HAS_SUPER = (1u << 22), /**< class has super reference */ - PARSER_CLASS_IMPLICIT_SUPER = (1u << 23), /**< class has implicit parent class */ - PARSER_CLASS_STATIC_FUNCTION = (1u << 24), /**< this function is a static class method */ - PARSER_CLASS_SUPER_PROP_REFERENCE = (1u << 25), /**< super property call or assignment */ - PARSER_IS_EVAL = (1u << 26), /**< eval code */ + PARSER_CLASS_HAS_SUPER = (1u << 19), /**< class has super reference */ + PARSER_CLASS_IMPLICIT_SUPER = (1u << 20), /**< class has implicit parent class */ + PARSER_CLASS_STATIC_FUNCTION = (1u << 21), /**< this function is a static class method */ + PARSER_CLASS_SUPER_PROP_REFERENCE = (1u << 22), /**< super property call or assignment */ + PARSER_IS_EVAL = (1u << 23), /**< eval code */ #endif /* ENABLED (JERRY_ES2015) */ #if ENABLED (JERRY_ES2015_MODULE_SYSTEM) - PARSER_IS_MODULE = (1u << 27), /**< an export / import keyword is encountered */ - PARSER_MODULE_DEFAULT_CLASS_OR_FUNC = (1u << 28), /**< parsing a function or class default export */ - PARSER_MODULE_STORE_IDENT = (1u << 29), /**< store identifier of the current export statement */ + PARSER_IS_MODULE = (1u << 24), /**< an export / import keyword is encountered */ + PARSER_MODULE_DEFAULT_CLASS_OR_FUNC = (1u << 25), /**< parsing a function or class default export */ + PARSER_MODULE_STORE_IDENT = (1u << 26), /**< store identifier of the current export statement */ #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ + PARSER_HAS_LATE_LIT_INIT = (1u << 30), /**< there are identifier or string literals which construction + * is postponed after the local parser data is freed */ #ifndef JERRY_NDEBUG - PARSER_SCANNING_SUCCESSFUL = (1u << 30), /**< scanning process was successful */ + PARSER_SCANNING_SUCCESSFUL = PARSER_HAS_LATE_LIT_INIT, /**< scanning process was successful */ #endif /* !JERRY_NDEBUG */ } parser_general_flags_t; diff --git a/jerry-core/parser/js/js-parser-statm.c b/jerry-core/parser/js/js-parser-statm.c index 519df5ae8..b0ef0a945 100644 --- a/jerry-core/parser/js/js-parser-statm.c +++ b/jerry-core/parser/js/js-parser-statm.c @@ -306,7 +306,7 @@ parser_statement_length (uint8_t type) /**< type of statement */ (uint8_t) (sizeof (parser_for_in_of_statement_t) + sizeof (parser_loop_statement_t) + 1), #endif /* ENABLED (JERRY_ES2015) */ /* PARSER_STATEMENT_WITH */ - (uint8_t) (sizeof (parser_with_statement_t) + 1), + (uint8_t) (sizeof (parser_with_statement_t) + 1 + 1), /* PARSER_STATEMENT_TRY */ (uint8_t) (sizeof (parser_try_statement_t) + 1), }; @@ -810,12 +810,15 @@ parser_parse_with_statement_start (parser_context_t *context_p) /**< context */ PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_WITH_CONTEXT_STACK_ALLOCATION); #endif /* !JERRY_NDEBUG */ + uint8_t inside_with = (context_p->status_flags & PARSER_INSIDE_WITH) != 0; + context_p->status_flags |= PARSER_INSIDE_WITH | PARSER_LEXICAL_ENV_NEEDED; parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_WITH_CREATE_CONTEXT, &with_statement.branch); parser_stack_push (context_p, &with_statement, sizeof (parser_with_statement_t)); + parser_stack_push_uint8 (context_p, inside_with); parser_stack_push_uint8 (context_p, PARSER_STATEMENT_WITH); parser_stack_iterator_init (context_p, &context_p->last_statement); } /* parser_parse_with_statement_start */ @@ -827,10 +830,16 @@ static void parser_parse_with_statement_end (parser_context_t *context_p) /**< context */ { parser_with_statement_t with_statement; - parser_stack_iterator_t iterator; JERRY_ASSERT (context_p->status_flags & PARSER_INSIDE_WITH); + parser_stack_pop_uint8 (context_p); + + if (!context_p->stack_top_uint8) + { + context_p->status_flags &= (uint32_t) ~PARSER_INSIDE_WITH; + } + parser_stack_pop_uint8 (context_p); parser_stack_pop (context_p, &with_statement, sizeof (parser_with_statement_t)); parser_stack_iterator_init (context_p, &context_p->last_statement); @@ -843,26 +852,6 @@ parser_parse_with_statement_end (parser_context_t *context_p) /**< context */ parser_emit_cbc (context_p, CBC_CONTEXT_END); parser_set_branch_to_current_position (context_p, &with_statement.branch); - - parser_stack_iterator_init (context_p, &iterator); - - while (true) - { - uint8_t type = parser_stack_iterator_read_uint8 (&iterator); - - if (type == PARSER_STATEMENT_START) - { - context_p->status_flags &= (uint32_t) ~PARSER_INSIDE_WITH; - return; - } - - if (type == PARSER_STATEMENT_WITH) - { - return; - } - - parser_stack_iterator_skip (&iterator, parser_statement_length (type)); - } } /* parser_parse_with_statement_end */ #if ENABLED (JERRY_ES2015) diff --git a/jerry-core/parser/js/js-parser.c b/jerry-core/parser/js/js-parser.c index b98b52d1a..683c89203 100644 --- a/jerry-core/parser/js/js-parser.c +++ b/jerry-core/parser/js/js-parser.c @@ -1818,6 +1818,11 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */ scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_BODY); } /* parser_parse_function_arguments */ +#ifndef JERRY_NDEBUG +JERRY_STATIC_ASSERT (PARSER_SCANNING_SUCCESSFUL == PARSER_HAS_LATE_LIT_INIT, + parser_scanning_successful_should_share_the_bit_position_with_parser_has_late_lit_init); +#endif /* !JERRY_NDEBUG */ + /** * Parse and compile EcmaScript source code * @@ -2048,13 +2053,16 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */ JERRY_ASSERT (context.last_cbc_opcode == PARSER_CBC_UNAVAILABLE); JERRY_ASSERT (context.u.allocated_buffer_p == NULL); - compiled_code_p = parser_post_processing (&context); - parser_list_free (&context.literal_pool); - #ifndef JERRY_NDEBUG JERRY_ASSERT (context.status_flags & PARSER_SCANNING_SUCCESSFUL); + context.status_flags &= (uint32_t) ~PARSER_SCANNING_SUCCESSFUL; #endif /* !JERRY_NDEBUG */ + JERRY_ASSERT (!(context.status_flags & PARSER_HAS_LATE_LIT_INIT)); + + compiled_code_p = parser_post_processing (&context); + parser_list_free (&context.literal_pool); + JERRY_ASSERT (arg_list_p != NULL || !(context.status_flags & PARSER_ARGUMENTS_NEEDED)); #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) @@ -2376,8 +2384,9 @@ parser_parse_arrow_function (parser_context_t *context_p, /**< context */ } #endif /* ENABLED (JERRY_DEBUGGER) */ - if (status_flags & PARSER_ARROW_PARSE_ARGS) + if (context_p->token.type == LEXER_ARROW_LEFT_PAREN) { + lexer_next_token (context_p); parser_parse_function_arguments (context_p, LEXER_RIGHT_PAREN); lexer_next_token (context_p); }