diff --git a/jerry-core/parser/js/js-lexer.c b/jerry-core/parser/js/js-lexer.c index 1bb5cc924..f9b415b29 100644 --- a/jerry-core/parser/js/js-lexer.c +++ b/jerry-core/parser/js/js-lexer.c @@ -100,12 +100,18 @@ typedef enum * Skip spaces. */ static void -skip_spaces (parser_context_t *context_p) /**< context */ +lexer_skip_spaces (parser_context_t *context_p) /**< context */ { skip_mode_t mode = LEXER_SKIP_SPACES; const uint8_t *source_end_p = context_p->source_end_p; - context_p->token.was_newline = 0; + if (context_p->token.flags & LEXER_NO_SKIP_SPACES) + { + context_p->token.flags = (uint8_t) (context_p->token.flags & ~LEXER_NO_SKIP_SPACES); + return; + } + + context_p->token.flags = 0; while (true) { @@ -134,7 +140,7 @@ skip_spaces (parser_context_t *context_p) /**< context */ { context_p->line++; context_p->column = 0; - context_p->token.was_newline = 1; + context_p->token.flags = LEXER_WAS_NEWLINE; if (mode == LEXER_SKIP_SINGLE_LINE_COMMENT) { @@ -221,7 +227,7 @@ skip_spaces (parser_context_t *context_p) /**< context */ context_p->source_p += 3; context_p->line++; context_p->column = 1; - context_p->token.was_newline = 1; + context_p->token.flags = LEXER_WAS_NEWLINE; if (mode == LEXER_SKIP_SINGLE_LINE_COMMENT) { @@ -265,7 +271,7 @@ skip_spaces (parser_context_t *context_p) /**< context */ context_p->column++; } } -} /* skip_spaces */ +} /* lexer_skip_spaces */ /** * Keyword data. @@ -953,28 +959,6 @@ lexer_parse_number (parser_context_t *context_p) /**< context */ break; \ } -#define LEXER_TYPE_D_TOKEN(char1, type1, char2, type2, char3, type3) \ - case (uint8_t) (char1) : \ - { \ - if (length >= 2 && context_p->source_p[1] == (uint8_t) (char2)) \ - { \ - if (length >= 3 && context_p->source_p[2] == (uint8_t) (char3)) \ - { \ - context_p->token.type = (type3); \ - length = 3; \ - break; \ - } \ - \ - context_p->token.type = (type2); \ - length = 2; \ - break; \ - } \ - \ - context_p->token.type = (type1); \ - length = 1; \ - break; \ - } - /** * Get next token. */ @@ -983,7 +967,7 @@ lexer_next_token (parser_context_t *context_p) /**< context */ { size_t length; - skip_spaces (context_p); + lexer_skip_spaces (context_p); context_p->token.line = context_p->line; context_p->token.column = context_p->column; @@ -1019,7 +1003,7 @@ lexer_next_token (parser_context_t *context_p) /**< context */ LEXER_TYPE_A_TOKEN (LIT_CHAR_SEMICOLON, LEXER_SEMICOLON); LEXER_TYPE_A_TOKEN (LIT_CHAR_COMMA, LEXER_COMMA); - case (uint8_t) LIT_CHAR_DOT : + case (uint8_t) LIT_CHAR_DOT: { if (length >= 2 && (context_p->source_p[1] >= LIT_CHAR_0 && context_p->source_p[1] <= LIT_CHAR_9)) @@ -1064,7 +1048,7 @@ lexer_next_token (parser_context_t *context_p) /**< context */ break; } - case LIT_CHAR_GREATER_THAN: + case (uint8_t) LIT_CHAR_GREATER_THAN: { if (length >= 2) { @@ -1112,10 +1096,59 @@ lexer_next_token (parser_context_t *context_p) /**< context */ break; } - LEXER_TYPE_D_TOKEN (LIT_CHAR_EQUALS, LEXER_ASSIGN, LIT_CHAR_EQUALS, - LEXER_EQUAL, LIT_CHAR_EQUALS, LEXER_STRICT_EQUAL) - LEXER_TYPE_D_TOKEN (LIT_CHAR_EXCLAMATION, LEXER_LOGICAL_NOT, LIT_CHAR_EQUALS, - LEXER_NOT_EQUAL, LIT_CHAR_EQUALS, LEXER_STRICT_NOT_EQUAL) + case (uint8_t) LIT_CHAR_EQUALS: + { + if (length >= 2) + { + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_EQUALS) + { + if (length >= 3 && context_p->source_p[2] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_STRICT_EQUAL; + length = 3; + break; + } + + context_p->token.type = LEXER_EQUAL; + length = 2; + break; + } + +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION + if (context_p->source_p[1] == (uint8_t) LIT_CHAR_GREATER_THAN) + { + context_p->token.type = LEXER_ARROW; + length = 2; + break; + } +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ + } + + context_p->token.type = LEXER_ASSIGN; + length = 1; + break; + } + + case (uint8_t) LIT_CHAR_EXCLAMATION: + { + if (length >= 2 && context_p->source_p[1] == (uint8_t) LIT_CHAR_EQUALS) + { + if (length >= 3 && context_p->source_p[2] == (uint8_t) LIT_CHAR_EQUALS) + { + context_p->token.type = LEXER_STRICT_NOT_EQUAL; + length = 3; + break; + } + + context_p->token.type = LEXER_NOT_EQUAL; + length = 2; + break; + } + + context_p->token.type = LEXER_LOGICAL_NOT; + length = 1; + break; + } LEXER_TYPE_C_TOKEN (LIT_CHAR_PLUS, LEXER_ADD, LIT_CHAR_EQUALS, LEXER_ASSIGN_ADD, LIT_CHAR_PLUS, LEXER_INCREASE) @@ -1163,6 +1196,71 @@ lexer_next_token (parser_context_t *context_p) /**< context */ #undef LEXER_TYPE_C_TOKEN #undef LEXER_TYPE_D_TOKEN +/** + * Checks whether the next token is a colon. + * + * @return true - if the next token is a colon + * false - otherwise + */ +bool +lexer_check_colon (parser_context_t *context_p) /**< context */ +{ + lexer_skip_spaces (context_p); + + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + + return (context_p->source_p < context_p->source_end_p + && context_p->source_p[0] == (uint8_t) LIT_CHAR_COLON); +} /* lexer_check_colon */ + +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION + +/** + * Checks whether the next token is a type used for detecting arrow functions. + * + * @return identified token type + */ +lexer_token_type_t +lexer_check_arrow (parser_context_t *context_p) /**< context */ +{ + lexer_skip_spaces (context_p); + + context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES); + + if (context_p->source_p < context_p->source_end_p) + { + switch (context_p->source_p[0]) + { + case LIT_CHAR_COMMA: + { + return LEXER_COMMA; + } + case LIT_CHAR_RIGHT_PAREN: + { + return LEXER_RIGHT_PAREN; + } + case LIT_CHAR_EQUALS: + { + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) + && context_p->source_p + 1 < context_p->source_end_p + && context_p->source_p[1] == (uint8_t) LIT_CHAR_GREATER_THAN) + { + return LEXER_ARROW; + } + break; + } + default: + { + break; + } + } + } + + return LEXER_EOS; +} /* lexer_check_arrow */ + +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ + /** * Search or append the string to the literal pool. */ @@ -1655,7 +1753,18 @@ lexer_construct_function_object (parser_context_t *context_p, /**< context */ result_index = context_p->literal_count; context_p->literal_count++; +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION + if (!(extra_status_flags & PARSER_IS_ARROW_FUNCTION)) + { + compiled_code_p = parser_parse_function (context_p, extra_status_flags); + } + else + { + compiled_code_p = parser_parse_arrow_function (context_p, extra_status_flags); + } +#else /* CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ compiled_code_p = parser_parse_function (context_p, extra_status_flags); +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ literal_p->u.bytecode_p = compiled_code_p; literal_p->type = LEXER_FUNCTION_LITERAL; @@ -1884,7 +1993,7 @@ lexer_expect_identifier (parser_context_t *context_p, /**< context */ JERRY_ASSERT (literal_type == LEXER_STRING_LITERAL || literal_type == LEXER_IDENT_LITERAL); - skip_spaces (context_p); + lexer_skip_spaces (context_p); context_p->token.line = context_p->line; context_p->token.column = context_p->column; @@ -1943,7 +2052,7 @@ void lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */ bool must_be_identifier) /**< only identifiers are accepted */ { - skip_spaces (context_p); + lexer_skip_spaces (context_p); context_p->token.line = context_p->line; context_p->token.column = context_p->column; @@ -1959,7 +2068,7 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */ if (!must_be_identifier && context_p->token.lit_location.length == 3) { - skip_spaces (context_p); + lexer_skip_spaces (context_p); if (context_p->source_p < context_p->source_end_p && context_p->source_p[0] != LIT_CHAR_COLON) @@ -2030,7 +2139,7 @@ void lexer_scan_identifier (parser_context_t *context_p, /**< context */ bool propety_name) /**< property name */ { - skip_spaces (context_p); + lexer_skip_spaces (context_p); context_p->token.line = context_p->line; context_p->token.column = context_p->column; @@ -2041,7 +2150,7 @@ lexer_scan_identifier (parser_context_t *context_p, /**< context */ if (propety_name && context_p->token.lit_location.length == 3) { - skip_spaces (context_p); + lexer_skip_spaces (context_p); if (context_p->source_p < context_p->source_end_p && context_p->source_p[0] != LIT_CHAR_COLON) diff --git a/jerry-core/parser/js/js-lexer.h b/jerry-core/parser/js/js-lexer.h index 45b3beced..06c56642e 100644 --- a/jerry-core/parser/js/js-lexer.h +++ b/jerry-core/parser/js/js-lexer.h @@ -115,6 +115,9 @@ typedef enum LEXER_SEMICOLON, /**< ";" */ LEXER_COLON, /**< ":" */ LEXER_COMMA, /**< "," */ +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION + LEXER_ARROW, /**< "=>" */ +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ LEXER_KEYW_BREAK, /**< break */ LEXER_KEYW_DO, /**< do */ @@ -192,6 +195,15 @@ typedef enum #define LEXER_BINARY_LVALUE_OP_TOKEN_TO_OPCODE(token_type) \ ((cbc_opcode_t) ((((token_type) - LEXER_ASSIGN_ADD) * 2) + CBC_ASSIGN_ADD)) +/** + * Lexer newline flags. + */ +typedef enum +{ + LEXER_WAS_NEWLINE = (1u << 0), /**< newline was seen */ + LEXER_NO_SKIP_SPACES = (1u << 1) /**< ignore skip spaces */ +} lexer_newline_flags_t; + /** * Lexer literal object types. */ @@ -243,7 +255,7 @@ typedef struct uint8_t literal_is_reserved; /**< future reserved keyword * (when char_literal.type is LEXER_IDENT_LITERAL) */ uint8_t extra_value; /**< helper value for different purposes */ - uint8_t was_newline; /**< newline occured before this token */ + uint8_t flags; /**< flag bits for the current token */ parser_line_counter_t line; /**< token start line */ parser_line_counter_t column; /**< token start column */ lexer_lit_location_t lit_location; /**< extra data for character literals */ diff --git a/jerry-core/parser/js/js-parser-expr.c b/jerry-core/parser/js/js-parser-expr.c index cac23439f..91a0a18f3 100644 --- a/jerry-core/parser/js/js-parser-expr.c +++ b/jerry-core/parser/js/js-parser-expr.c @@ -454,6 +454,142 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */ parser_stack_pop_uint8 (context_p); } /* parser_parse_object_literal */ +/** + * Parse function literal. + */ +static void +parser_parse_function_expression (parser_context_t *context_p, /**< context */ + uint32_t status_flags) /**< function status flags */ +{ + int literals = 0; + uint16_t literal1 = 0; + uint16_t literal2 = 0; + uint16_t function_literal_index; + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + literals = 1; + literal1 = 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) + { + literals = 2; + literal1 = context_p->last_cbc.literal_index; + literal2 = context_p->last_cbc.value; + context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; + } + else + { + parser_flush_cbc (context_p); + } + + if (context_p->status_flags & PARSER_INSIDE_WITH) + { + status_flags |= PARSER_RESOLVE_THIS_FOR_CALLS; + } + + function_literal_index = lexer_construct_function_object (context_p, status_flags); + + JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + + if (literals == 1) + { + context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; + context_p->last_cbc.literal_index = literal1; + context_p->last_cbc.value = function_literal_index; + } + else if (literals == 2) + { + context_p->last_cbc_opcode = CBC_PUSH_THREE_LITERALS; + context_p->last_cbc.literal_index = literal1; + context_p->last_cbc.value = literal2; + context_p->last_cbc.third_literal_index = function_literal_index; + } + else + { + parser_emit_cbc_literal (context_p, + CBC_PUSH_LITERAL, + function_literal_index); + } + + context_p->last_cbc.literal_type = LEXER_FUNCTION_LITERAL; + context_p->last_cbc.literal_object_type = LEXER_LITERAL_OBJECT_ANY; +} /* parser_parse_function_expression */ + +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION + +/** + * Checks whether the bracketed expression is an argument list of an arrow function. + * + * @return true - if an arrow function is found + * false - otherwise + */ +static bool +parser_check_arrow_function (parser_context_t *context_p) /**< context */ +{ + lexer_range_t range; + + range.source_p = context_p->token.lit_location.char_p; + range.line = context_p->token.line; + range.column = context_p->token.column; + + lexer_next_token (context_p); + + bool is_arrow_function = true; + + while (true) + { + if (context_p->token.type == LEXER_RIGHT_PAREN) + { + break; + } + + if (context_p->token.type == LEXER_COMMA) + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + lexer_next_token (context_p); + continue; + } + } + + is_arrow_function = false; + break; + } + + if (is_arrow_function) + { + lexer_next_token (context_p); + + if (context_p->token.type != LEXER_ARROW) + { + is_arrow_function = false; + } + } + + context_p->source_p = range.source_p; + context_p->line = range.line; + context_p->column = range.column; + + /* Re-parse the original identifier. */ + lexer_next_token (context_p); + + if (is_arrow_function) + { + parser_parse_function_expression (context_p, + PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION | PARSER_ARROW_PARSE_ARGS); + return true; + } + + return false; +} /* parser_check_arrow_function */ + +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ + /** * Parse and record unary operators, and parse the primary literal. */ @@ -503,6 +639,37 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */ { case LEXER_LITERAL: { +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION + if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + switch (lexer_check_arrow (context_p)) + { + case LEXER_COMMA: + case LEXER_RIGHT_PAREN: + { + if (context_p->stack_top_uint8 == LEXER_LEFT_PAREN + && parser_check_arrow_function (context_p)) + { + (*grouping_level_p)--; + parser_stack_pop_uint8 (context_p); + return; + } + break; + } + case LEXER_ARROW: + { + parser_parse_function_expression (context_p, + PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION); + return; + } + default: + { + break; + } + } + } +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ + cbc_opcode_t opcode = CBC_PUSH_LITERAL; if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL @@ -573,62 +740,8 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */ } case LEXER_KEYW_FUNCTION: { - int literals = 0; - uint16_t literal1 = 0; - uint16_t literal2 = 0; - uint16_t function_literal_index; - - if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) - { - literals = 1; - literal1 = 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) - { - literals = 2; - literal1 = context_p->last_cbc.literal_index; - literal2 = context_p->last_cbc.value; - context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE; - } - else - { - parser_flush_cbc (context_p); - } - - uint32_t status_flags = PARSER_IS_FUNCTION | PARSER_IS_FUNC_EXPRESSION | PARSER_IS_CLOSURE; - - if (context_p->status_flags & PARSER_INSIDE_WITH) - { - status_flags |= PARSER_RESOLVE_THIS_FOR_CALLS; - } - - function_literal_index = lexer_construct_function_object (context_p, status_flags); - - JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); - - if (literals == 1) - { - context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; - context_p->last_cbc.literal_index = literal1; - context_p->last_cbc.value = function_literal_index; - } - else if (literals == 2) - { - context_p->last_cbc_opcode = CBC_PUSH_THREE_LITERALS; - context_p->last_cbc.literal_index = literal1; - context_p->last_cbc.value = literal2; - context_p->last_cbc.third_literal_index = function_literal_index; - } - else - { - parser_emit_cbc_literal (context_p, - CBC_PUSH_LITERAL, - function_literal_index); - } - - context_p->last_cbc.literal_type = LEXER_FUNCTION_LITERAL; - context_p->last_cbc.literal_object_type = LEXER_LITERAL_OBJECT_ANY; + parser_parse_function_expression (context_p, + PARSER_IS_FUNCTION | PARSER_IS_FUNC_EXPRESSION | PARSER_IS_CLOSURE); break; } case LEXER_LEFT_BRACE: @@ -687,6 +800,22 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */ parser_emit_cbc (context_p, CBC_PUSH_NULL); break; } +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION + case LEXER_RIGHT_PAREN: + { + if (context_p->stack_top_uint8 == LEXER_LEFT_PAREN + && lexer_check_arrow (context_p) == LEXER_ARROW) + { + parser_parse_function_expression (context_p, + PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION | PARSER_ARROW_PARSE_ARGS); + + (*grouping_level_p)--; + parser_stack_pop_uint8 (context_p); + return; + } + /* FALLTHRU */ + } +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ default: { parser_raise_error (context_p, PARSER_ERR_PRIMARY_EXP_EXPECTED); @@ -945,7 +1074,7 @@ parser_process_unary_expression (parser_context_t *context_p) /**< context */ continue; } - if (!context_p->token.was_newline + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) && (context_p->token.type == LEXER_INCREASE || context_p->token.type == LEXER_DECREASE)) { cbc_opcode_t opcode = (context_p->token.type == LEXER_INCREASE) ? CBC_POST_INCR : CBC_POST_DECR; diff --git a/jerry-core/parser/js/js-parser-internal.h b/jerry-core/parser/js/js-parser-internal.h index d06d36a3e..55d0c506a 100644 --- a/jerry-core/parser/js/js-parser-internal.h +++ b/jerry-core/parser/js/js-parser-internal.h @@ -35,24 +35,28 @@ */ /* General parser flags. */ -#define PARSER_IS_STRICT 0x00001u -#define PARSER_IS_FUNCTION 0x00002u -#define PARSER_IS_CLOSURE 0x00004u -#define PARSER_IS_PROPERTY_GETTER 0x00008u -#define PARSER_IS_PROPERTY_SETTER 0x00010u -#define PARSER_IS_FUNC_EXPRESSION 0x00020u -#define PARSER_HAS_NON_STRICT_ARG 0x00040u -#define PARSER_INSIDE_WITH 0x00080u -#define PARSER_RESOLVE_THIS_FOR_CALLS 0x00100u -#define PARSER_NAMED_FUNCTION_EXP 0x00200u -#define PARSER_HAS_INITIALIZED_VARS 0x00400u -#define PARSER_NO_END_LABEL 0x00800u -#define PARSER_NO_REG_STORE 0x01000u -#define PARSER_ARGUMENTS_NEEDED 0x02000u -#define PARSER_ARGUMENTS_NOT_NEEDED 0x04000u -#define PARSER_LEXICAL_ENV_NEEDED 0x08000u -#define PARSER_HAS_LATE_LIT_INIT 0x10000u -#define PARSER_DEBUGGER_BREAKPOINT_APPENDED 0x20000u +#define PARSER_IS_STRICT 0x00000001u +#define PARSER_IS_FUNCTION 0x00000002u +#define PARSER_IS_CLOSURE 0x00000004u +#define PARSER_IS_PROPERTY_GETTER 0x00000008u +#define PARSER_IS_PROPERTY_SETTER 0x00000010u +#define PARSER_IS_FUNC_EXPRESSION 0x00000020u +#define PARSER_NAMED_FUNCTION_EXP 0x00000040u +#define PARSER_HAS_NON_STRICT_ARG 0x00000080u +#define PARSER_ARGUMENTS_NEEDED 0x00000100u +#define PARSER_ARGUMENTS_NOT_NEEDED 0x00000200u +#define PARSER_LEXICAL_ENV_NEEDED 0x00000400u +#define PARSER_INSIDE_WITH 0x00000800u +#define PARSER_RESOLVE_THIS_FOR_CALLS 0x00001000u +#define PARSER_HAS_INITIALIZED_VARS 0x00002000u +#define PARSER_HAS_LATE_LIT_INIT 0x00004000u +#define PARSER_NO_END_LABEL 0x00008000u +#define PARSER_NO_REG_STORE 0x00010000u +#define PARSER_DEBUGGER_BREAKPOINT_APPENDED 0x00020000u +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION +#define PARSER_IS_ARROW_FUNCTION 0x00040000u +#define PARSER_ARROW_PARSE_ARGS 0x00080000u +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ /* Expression parsing flags. */ #define PARSE_EXPR 0x00 @@ -392,6 +396,10 @@ void parser_set_continues_to_current_position (parser_context_t *context_p, pars /* Lexer functions */ void lexer_next_token (parser_context_t *context_p); +bool lexer_check_colon (parser_context_t *context_p); +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION +lexer_token_type_t lexer_check_arrow (parser_context_t *context_p); +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ void lexer_expect_identifier (parser_context_t *context_p, uint8_t literal_type); void lexer_scan_identifier (parser_context_t *context_p, bool propety_name); ecma_char_t lexer_hex_to_character (parser_context_t *context_p, const uint8_t *source_p, int length); @@ -441,6 +449,9 @@ void parser_free_jumps (parser_stack_iterator_t iterator); */ ecma_compiled_code_t *parser_parse_function (parser_context_t *context_p, uint32_t status_flags); +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION +ecma_compiled_code_t *parser_parse_arrow_function (parser_context_t *context_p, uint32_t status_flags); +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ /* Error management. */ diff --git a/jerry-core/parser/js/js-parser-scanner.c b/jerry-core/parser/js/js-parser-scanner.c index 5179c0d49..91a003b07 100644 --- a/jerry-core/parser/js/js-parser-scanner.c +++ b/jerry-core/parser/js/js-parser-scanner.c @@ -34,8 +34,11 @@ typedef enum { SCAN_MODE_PRIMARY_EXPRESSION, /**< scanning primary expression */ SCAN_MODE_PRIMARY_EXPRESSION_AFTER_NEW, /**< scanning primary expression after new */ +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION + SCAN_MODE_ARROW_FUNCTION, /**< arrow function might follows */ +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ SCAN_MODE_POST_PRIMARY_EXPRESSION, /**< scanning post primary expression */ - SCAN_MODE_PRIMARY_EXPRESSION_END, /**< scanning prymary expression end */ + SCAN_MODE_PRIMARY_EXPRESSION_END, /**< scanning primary expression end */ SCAN_MODE_STATEMENT, /**< scanning statement */ SCAN_MODE_FUNCTION_ARGUMENTS, /**< scanning function arguments */ SCAN_MODE_PROPERTY_NAME, /**< scanning property name */ @@ -54,7 +57,7 @@ typedef enum SCAN_STACK_SQUARE_BRACKETED_EXPRESSION, /**< square bracketed expression group */ SCAN_STACK_OBJECT_LITERAL, /**< object literal group */ SCAN_STACK_BLOCK_STATEMENT, /**< block statement group */ - SCAN_STACK_BLOCK_EXPRESSION, /**< block expression group*/ + SCAN_STACK_BLOCK_EXPRESSION, /**< block expression group */ SCAN_STACK_BLOCK_PROPERTY, /**< block property group */ } scan_stack_modes_t; @@ -108,6 +111,15 @@ parser_scan_primary_expression (parser_context_t *context_p, /**< context */ return true; } case LEXER_LITERAL: +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION + { + bool is_ident = (context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + *mode = (is_ident ? SCAN_MODE_ARROW_FUNCTION + : SCAN_MODE_POST_PRIMARY_EXPRESSION); + break; + } +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ case LEXER_KEYW_THIS: case LEXER_LIT_TRUE: case LEXER_LIT_FALSE: @@ -137,7 +149,12 @@ parser_scan_primary_expression (parser_context_t *context_p, /**< context */ } case LEXER_RIGHT_PAREN: { +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION + *mode = SCAN_MODE_ARROW_FUNCTION; +#else /* CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ *mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ + if (stack_top == SCAN_STACK_PAREN_STATEMENT) { *mode = SCAN_MODE_STATEMENT; @@ -200,7 +217,7 @@ parser_scan_post_primary_expression (parser_context_t *context_p, /**< context * case LEXER_INCREASE: case LEXER_DECREASE: { - if (!context_p->token.was_newline) + if (!(context_p->token.flags & LEXER_WAS_NEWLINE)) { *mode = SCAN_MODE_PRIMARY_EXPRESSION_END; return true; @@ -283,6 +300,12 @@ parser_scan_primary_expression_end (parser_context_t *context_p, /**< context */ { parser_stack_pop_uint8 (context_p); *mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION + if (type == LEXER_RIGHT_PAREN) + { + *mode = SCAN_MODE_ARROW_FUNCTION; + } +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ return false; } @@ -302,7 +325,7 @@ parser_scan_primary_expression_end (parser_context_t *context_p, /**< context */ } if (type == LEXER_RIGHT_BRACE - || context_p->token.was_newline) + || (context_p->token.flags & LEXER_WAS_NEWLINE)) { return true; } @@ -380,7 +403,7 @@ parser_scan_statement (parser_context_t *context_p, /**< context */ case LEXER_KEYW_RETURN: { lexer_next_token (context_p); - if (!context_p->token.was_newline + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->token.type != LEXER_SEMICOLON) { *mode = SCAN_MODE_PRIMARY_EXPRESSION; @@ -391,7 +414,7 @@ parser_scan_statement (parser_context_t *context_p, /**< context */ case LEXER_KEYW_CONTINUE: { lexer_next_token (context_p); - if (!context_p->token.was_newline + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) { @@ -469,7 +492,11 @@ parser_scan_statement (parser_context_t *context_p, /**< context */ *mode = SCAN_MODE_STATEMENT; return false; } +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION + *mode = SCAN_MODE_ARROW_FUNCTION; +#else /* CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ *mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ } return true; @@ -552,6 +579,30 @@ parser_scan_until (parser_context_t *context_p, /**< context */ } break; } +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION + case SCAN_MODE_ARROW_FUNCTION: + { + if (type == LEXER_ARROW) + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LEFT_BRACE) + { + parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_EXPRESSION); + mode = SCAN_MODE_STATEMENT; + } + else + { + mode = SCAN_MODE_PRIMARY_EXPRESSION; + range_p->source_end_p = context_p->source_p; + continue; + } + break; + } + mode = SCAN_MODE_POST_PRIMARY_EXPRESSION; + /* FALLTHRU */ + } +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ case SCAN_MODE_POST_PRIMARY_EXPRESSION: { if (parser_scan_post_primary_expression (context_p, type, &mode)) diff --git a/jerry-core/parser/js/js-parser-statm.c b/jerry-core/parser/js/js-parser-statm.c index d0f1f2549..57866a9d3 100644 --- a/jerry-core/parser/js/js-parser-statm.c +++ b/jerry-core/parser/js/js-parser-statm.c @@ -1368,7 +1368,7 @@ parser_parse_break_statement (parser_context_t *context_p) /**< context */ lexer_next_token (context_p); parser_stack_iterator_init (context_p, &iterator); - if (!context_p->token.was_newline + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) { @@ -1463,7 +1463,7 @@ parser_parse_continue_statement (parser_context_t *context_p) /**< context */ lexer_next_token (context_p); parser_stack_iterator_init (context_p, &iterator); - if (!context_p->token.was_newline + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) { @@ -1575,8 +1575,7 @@ parser_parse_continue_statement (parser_context_t *context_p) /**< context */ * Parse label statement. */ static void -parser_parse_label (parser_context_t *context_p, /**< context */ - lexer_lit_location_t *label_literal_p) /**< saved literal */ +parser_parse_label (parser_context_t *context_p) /**< context */ { parser_stack_iterator_t iterator; parser_label_statement_t label_statement; @@ -1608,7 +1607,7 @@ parser_parse_label (parser_context_t *context_p, /**< context */ } } - label_statement.label_ident = *label_literal_p; + label_statement.label_ident = context_p->token.lit_location; label_statement.break_list_p = NULL; parser_stack_push (context_p, &label_statement, sizeof (parser_label_statement_t)); parser_stack_push_uint8 (context_p, PARSER_STATEMENT_LABEL); @@ -1664,7 +1663,7 @@ parser_parse_statements (parser_context_t *context_p) /**< context */ if (context_p->token.type != LEXER_SEMICOLON && context_p->token.type != LEXER_RIGHT_BRACE) { - if (!context_p->token.was_newline + if (!(context_p->token.flags & LEXER_WAS_NEWLINE) || LEXER_IS_BINARY_OP_TOKEN (context_p->token.type) || context_p->token.type == LEXER_LEFT_PAREN || context_p->token.type == LEXER_LEFT_SQUARE @@ -1901,7 +1900,7 @@ parser_parse_statements (parser_context_t *context_p) /**< context */ case LEXER_KEYW_THROW: { lexer_next_token (context_p); - if (context_p->token.was_newline) + if (context_p->token.flags & LEXER_WAS_NEWLINE) { parser_raise_error (context_p, PARSER_ERR_EXPRESSION_EXPECTED); } @@ -1918,7 +1917,7 @@ parser_parse_statements (parser_context_t *context_p) /**< context */ } lexer_next_token (context_p); - if (context_p->token.was_newline + if ((context_p->token.flags & LEXER_WAS_NEWLINE) || context_p->token.type == LEXER_SEMICOLON || context_p->token.type == LEXER_RIGHT_BRACE) { @@ -1947,24 +1946,14 @@ parser_parse_statements (parser_context_t *context_p) /**< context */ case LEXER_LITERAL: { - if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL + && lexer_check_colon (context_p)) { - lexer_lit_location_t lit_location = context_p->token.lit_location; - + parser_parse_label (context_p); lexer_next_token (context_p); - - if (context_p->token.type == LEXER_COLON) - { - parser_parse_label (context_p, &lit_location); - lexer_next_token (context_p); - continue; - } - - lexer_construct_literal_object (context_p, &lit_location, LEXER_IDENT_LITERAL); - parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL); - /* The extra_value is used for saving the token. */ - context_p->token.extra_value = context_p->token.type; - context_p->token.type = LEXER_EXPRESSION_START; + JERRY_ASSERT (context_p->token.type == LEXER_COLON); + lexer_next_token (context_p); + continue; } /* FALLTHRU */ } @@ -2048,7 +2037,7 @@ parser_parse_statements (parser_context_t *context_p) /**< context */ lexer_next_token (context_p); } else if (context_p->token.type != LEXER_EOS - && !context_p->token.was_newline) + && !(context_p->token.flags & LEXER_WAS_NEWLINE)) { parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED); } diff --git a/jerry-core/parser/js/js-parser.c b/jerry-core/parser/js/js-parser.c index 87fd9d8d2..1ca283b54 100644 --- a/jerry-core/parser/js/js-parser.c +++ b/jerry-core/parser/js/js-parser.c @@ -2117,6 +2117,7 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */ context.status_flags |= PARSER_IS_STRICT; } + context.token.flags = 0; context.line = 1; context.column = 1; @@ -2243,17 +2244,12 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */ } /* parser_parse_source */ /** - * Parse function code - * - * @return compiled code + * Save parser context before function parsing. */ -ecma_compiled_code_t * -parser_parse_function (parser_context_t *context_p, /**< context */ - uint32_t status_flags) /**< extra status flags */ +static void +parser_save_context (parser_context_t *context_p, /**< context */ + parser_saved_context_t *saved_context_p) /**< target for saving the context */ { - parser_saved_context_t saved_context; - ecma_compiled_code_t *compiled_code_p; - JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); #ifdef JERRY_DEBUGGER @@ -2267,33 +2263,30 @@ parser_parse_function (parser_context_t *context_p, /**< context */ /* Save private part of the context. */ - saved_context.status_flags = context_p->status_flags; - saved_context.stack_depth = context_p->stack_depth; - saved_context.stack_limit = context_p->stack_limit; - saved_context.prev_context_p = context_p->last_context_p; - saved_context.last_statement = context_p->last_statement; + saved_context_p->status_flags = context_p->status_flags; + saved_context_p->stack_depth = context_p->stack_depth; + saved_context_p->stack_limit = context_p->stack_limit; + saved_context_p->prev_context_p = context_p->last_context_p; + saved_context_p->last_statement = context_p->last_statement; - saved_context.argument_count = context_p->argument_count; - saved_context.register_count = context_p->register_count; - saved_context.literal_count = context_p->literal_count; + saved_context_p->argument_count = context_p->argument_count; + saved_context_p->register_count = context_p->register_count; + saved_context_p->literal_count = context_p->literal_count; - saved_context.byte_code = context_p->byte_code; - saved_context.byte_code_size = context_p->byte_code_size; - saved_context.literal_pool_data = context_p->literal_pool.data; + saved_context_p->byte_code = context_p->byte_code; + saved_context_p->byte_code_size = context_p->byte_code_size; + saved_context_p->literal_pool_data = context_p->literal_pool.data; #ifndef JERRY_NDEBUG - saved_context.context_stack_depth = context_p->context_stack_depth; + saved_context_p->context_stack_depth = context_p->context_stack_depth; #endif /* !JERRY_NDEBUG */ /* Reset private part of the context. */ - JERRY_ASSERT (status_flags & PARSER_IS_FUNCTION); - context_p->status_flags &= PARSER_IS_STRICT; - context_p->status_flags |= status_flags; context_p->stack_depth = 0; context_p->stack_limit = 0; - context_p->last_context_p = &saved_context; + context_p->last_context_p = saved_context_p; context_p->last_statement.current_p = NULL; context_p->argument_count = 0; @@ -2307,6 +2300,55 @@ parser_parse_function (parser_context_t *context_p, /**< context */ #ifndef JERRY_NDEBUG context_p->context_stack_depth = 0; #endif /* !JERRY_NDEBUG */ +} /* parser_save_context */ + +/** + * Restore parser context after function parsing. + */ +static void +parser_restore_context (parser_context_t *context_p, /**< context */ + parser_saved_context_t *saved_context_p) /**< target for saving the context */ +{ + parser_list_free (&context_p->literal_pool); + + /* Restore private part of the context. */ + + JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); + + context_p->status_flags = saved_context_p->status_flags; + context_p->stack_depth = saved_context_p->stack_depth; + context_p->stack_limit = saved_context_p->stack_limit; + context_p->last_context_p = saved_context_p->prev_context_p; + context_p->last_statement = saved_context_p->last_statement; + + context_p->argument_count = saved_context_p->argument_count; + context_p->register_count = saved_context_p->register_count; + context_p->literal_count = saved_context_p->literal_count; + + context_p->byte_code = saved_context_p->byte_code; + context_p->byte_code_size = saved_context_p->byte_code_size; + context_p->literal_pool.data = saved_context_p->literal_pool_data; + +#ifndef JERRY_NDEBUG + context_p->context_stack_depth = saved_context_p->context_stack_depth; +#endif /* !JERRY_NDEBUG */ +} /* parser_restore_context */ + +/** + * Parse function code + * + * @return compiled code + */ +ecma_compiled_code_t * +parser_parse_function (parser_context_t *context_p, /**< context */ + uint32_t status_flags) /**< extra status flags */ +{ + parser_saved_context_t saved_context; + ecma_compiled_code_t *compiled_code_p; + + JERRY_ASSERT (status_flags & PARSER_IS_FUNCTION); + parser_save_context (context_p, &saved_context); + context_p->status_flags |= status_flags; #ifdef PARSER_DUMP_BYTE_CODE if (context_p->is_show_opcodes) @@ -2413,33 +2455,128 @@ parser_parse_function (parser_context_t *context_p, /**< context */ } #endif /* PARSER_DUMP_BYTE_CODE */ - parser_list_free (&context_p->literal_pool); - - /* Restore private part of the context. */ - - JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); - - context_p->status_flags = saved_context.status_flags; - context_p->stack_depth = saved_context.stack_depth; - context_p->stack_limit = saved_context.stack_limit; - context_p->last_context_p = saved_context.prev_context_p; - context_p->last_statement = saved_context.last_statement; - - context_p->argument_count = saved_context.argument_count; - context_p->register_count = saved_context.register_count; - context_p->literal_count = saved_context.literal_count; - - context_p->byte_code = saved_context.byte_code; - context_p->byte_code_size = saved_context.byte_code_size; - context_p->literal_pool.data = saved_context.literal_pool_data; - -#ifndef JERRY_NDEBUG - context_p->context_stack_depth = saved_context.context_stack_depth; -#endif /* !JERRY_NDEBUG */ + parser_restore_context (context_p, &saved_context); return compiled_code_p; } /* parser_parse_function */ +#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION + +/** + * Parse arrow function code + * + * @return compiled code + */ +ecma_compiled_code_t * +parser_parse_arrow_function (parser_context_t *context_p, /**< context */ + uint32_t status_flags) /**< extra status flags */ +{ + parser_saved_context_t saved_context; + ecma_compiled_code_t *compiled_code_p; + + JERRY_ASSERT ((status_flags & PARSER_IS_FUNCTION) + && (status_flags & PARSER_IS_ARROW_FUNCTION)); + parser_save_context (context_p, &saved_context); + context_p->status_flags |= status_flags | PARSER_ARGUMENTS_NOT_NEEDED; + +#ifdef PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- Arrow function parsing start ---\n\n"); + } +#endif /* PARSER_DUMP_BYTE_CODE */ + +#ifdef JERRY_DEBUGGER + if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) + && jerry_debugger_send_parse_function (context_p->token.line, context_p->token.column)) + { + /* This option has a high memory and performance costs, + * but it is necessary for executing eval operations by the debugger. */ + context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED | PARSER_NO_REG_STORE; + } +#endif /* JERRY_DEBUGGER */ + + if (status_flags & PARSER_ARROW_PARSE_ARGS) + { + parser_parse_function_arguments (context_p, LEXER_RIGHT_PAREN); + } + else + { + JERRY_ASSERT (context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL); + + lexer_construct_literal_object (context_p, + &context_p->token.lit_location, + LEXER_IDENT_LITERAL); + + JERRY_ASSERT (context_p->argument_count == 0 && context_p->literal_count == 1); + + if (context_p->token.literal_is_reserved + || context_p->lit_object.type != LEXER_LITERAL_OBJECT_ANY) + { + context_p->status_flags |= PARSER_HAS_NON_STRICT_ARG; + } + + uint8_t lexer_flags = LEXER_FLAG_VAR | LEXER_FLAG_INITIALIZED | LEXER_FLAG_FUNCTION_ARGUMENT; + context_p->lit_object.literal_p->status_flags |= lexer_flags; + + context_p->argument_count = 1; + context_p->register_count = 1; + } + + lexer_next_token (context_p); + JERRY_ASSERT (context_p->token.type == LEXER_ARROW); + + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LEFT_BRACE) + { + lexer_next_token (context_p); + + context_p->status_flags |= PARSER_IS_CLOSURE; + parser_parse_statements (context_p); + + /* Unlike normal function, arrow functions consume their close brace. */ + JERRY_ASSERT (context_p->token.type == LEXER_RIGHT_BRACE); + lexer_next_token (context_p); + } + else + { + if (context_p->status_flags & PARSER_IS_STRICT + && context_p->status_flags & PARSER_HAS_NON_STRICT_ARG) + { + parser_raise_error (context_p, PARSER_ERR_NON_STRICT_ARG_DEFINITION); + } + + parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + context_p->last_cbc_opcode = CBC_RETURN_WITH_LITERAL; + } + else + { + parser_emit_cbc (context_p, CBC_RETURN); + } + parser_flush_cbc (context_p); + } + + compiled_code_p = parser_post_processing (context_p); + +#ifdef PARSER_DUMP_BYTE_CODE + if (context_p->is_show_opcodes) + { + JERRY_DEBUG_MSG ("\n--- Arrow function parsing end ---\n\n"); + } +#endif /* PARSER_DUMP_BYTE_CODE */ + + parser_restore_context (context_p, &saved_context); + + return compiled_code_p; +} /* parser_parse_arrow_function */ + +#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ + /** * Raise a parse error */ diff --git a/jerry-core/profiles/es5.1.profile b/jerry-core/profiles/es5.1.profile index af0401815..57ce9cf8f 100644 --- a/jerry-core/profiles/es5.1.profile +++ b/jerry-core/profiles/es5.1.profile @@ -1,3 +1,4 @@ +CONFIG_DISABLE_ES2015_ARROW_FUNCTION CONFIG_DISABLE_ES2015_BUILTIN CONFIG_DISABLE_ES2015_PROMISE_BUILTIN CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN diff --git a/jerry-core/profiles/minimal.profile b/jerry-core/profiles/minimal.profile index c56cc8bb1..f561545b3 100644 --- a/jerry-core/profiles/minimal.profile +++ b/jerry-core/profiles/minimal.profile @@ -3,6 +3,7 @@ CONFIG_DISABLE_ARRAY_BUILTIN CONFIG_DISABLE_BOOLEAN_BUILTIN CONFIG_DISABLE_DATE_BUILTIN CONFIG_DISABLE_ERROR_BUILTINS +CONFIG_DISABLE_ES2015_ARROW_FUNCTION CONFIG_DISABLE_ES2015_BUILTIN CONFIG_DISABLE_ES2015_PROMISE_BUILTIN CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN diff --git a/targets/curie_bsp/setup.py b/targets/curie_bsp/setup.py index cc5a7b492..bc918c2b6 100755 --- a/targets/curie_bsp/setup.py +++ b/targets/curie_bsp/setup.py @@ -97,6 +97,7 @@ def build_jerry_data(jerry_path): '-DCONFIG_DISABLE_DATE_BUILTIN', '-DCONFIG_DISABLE_REGEXP_BUILTIN', '-DCONFIG_DISABLE_ANNEXB_BUILTIN', + '-DCONFIG_DISABLE_ES2015_ARROW_FUNCTION' '-DCONFIG_DISABLE_ES2015_ARRAYBUFFER_BUILTIN', '-DCONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN', '-DCONFIG_ECMA_LCACHE_DISABLE', diff --git a/tests/jerry/es2015/arrow-function.js b/tests/jerry/es2015/arrow-function.js new file mode 100644 index 000000000..9a8e90e15 --- /dev/null +++ b/tests/jerry/es2015/arrow-function.js @@ -0,0 +1,142 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function must_throw (str) +{ + try + { + eval ("switch (1) { default: " + str + "}"); + assert (false); + } + catch (e) + { + } + + try + { + eval (str); + assert (false); + } + catch (e) + { + } +} + +function must_throw_strict (str) +{ + try + { + eval ("'use strict'; switch (1) { default: " + str + "}"); + assert (false); + } + catch (e) + { + } + + try + { + eval ("'use strict'; " + str); + assert (false); + } + catch (e) + { + } +} + +switch (1) +{ +default: + + var func = x => { return x + 3 } + assert (func(5) == 8); + + a => 5 /* no semicolon after */ + + assert (((x => + x + 1))(4) == 5) + + assert ((a => a += 3, b => b -= 3)(4) == 1); + + func = true ? x=>x+2:y=>y-2 + assert (func(10) == 12); + + func = arguments => + { return arguments + 4; } + assert (func(2) == 6); + + func = ( + ) => { return typeof + arguments + } + assert (func() === "undefined"); + + if (a => 0) + { + } + else + { + assert (false); + } + + assert (( + ( + static + , + package + ) => static + package + ) (2, 12) == 14); + + var global_var = 7; + + assert ( + ( + static + , + package + ) => { global_var = 5; return static + package } + (4, 5) == 9); + + assert (global_var == 5); + + func = (x , y) => {} + assert (func() === undefined) + + assert ((x => y => z => 6)()()() == 6) + + func = x => x - 6 + var func2 = y => func(y) + assert (func2 (17) == 11) + + func = (m) => m++ + assert (func (4) == 4) + + func = () => + ((([0,0,0]))) + assert (func ().length == 3); +} + +must_throw ("var x => x;"); +must_throw ("(()) => 0"); +must_throw ("((x)) => 0"); +must_throw ("(x,) => 0"); +must_throw ("(x y) => 0"); +must_throw ("(x,y,) => 0"); +must_throw ("x\n => 0"); +must_throw ("this => 0"); +must_throw ("(true) => 0"); +must_throw_strict ("(package) => 0"); +must_throw_strict ("(package) => { return 5 }"); +must_throw_strict ("(x,x,x) => 0"); +must_throw_strict ("(x,x,x) => { }");