Implement parsing await. (#3738)
Several bugs fixed for parsing yield as well. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -30,7 +30,7 @@ extern "C"
|
||||
/**
|
||||
* Jerry snapshot format version.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_VERSION (43u)
|
||||
#define JERRY_SNAPSHOT_VERSION (44u)
|
||||
|
||||
/**
|
||||
* Flags for jerry_generate_snapshot and jerry_generate_function_snapshot.
|
||||
|
||||
@@ -707,9 +707,11 @@
|
||||
CBC_OPCODE (CBC_EXT_CREATE_GENERATOR, CBC_NO_FLAG, 1, \
|
||||
VM_OC_CREATE_GENERATOR) \
|
||||
CBC_OPCODE (CBC_EXT_YIELD, CBC_NO_FLAG, 0, \
|
||||
VM_OC_YIELD | VM_OC_GET_STACK) \
|
||||
VM_OC_YIELD) \
|
||||
CBC_OPCODE (CBC_EXT_YIELD_ITERATOR, CBC_NO_FLAG, 0, \
|
||||
VM_OC_YIELD | VM_OC_GET_STACK) \
|
||||
VM_OC_YIELD) \
|
||||
CBC_OPCODE (CBC_EXT_AWAIT, CBC_NO_FLAG, 0, \
|
||||
VM_OC_AWAIT) \
|
||||
CBC_OPCODE (CBC_EXT_RETURN, CBC_NO_FLAG, -1, \
|
||||
VM_OC_EXT_RETURN | VM_OC_GET_STACK) \
|
||||
CBC_OPCODE (CBC_EXT_RETURN_PROMISE, CBC_NO_FLAG, -1, \
|
||||
|
||||
@@ -817,6 +817,29 @@ lexer_parse_identifier (parser_context_t *context_p, /**< context */
|
||||
|
||||
if (JERRY_LIKELY (keyword_p->type < LEXER_FIRST_NON_RESERVED_KEYWORD))
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (JERRY_UNLIKELY (keyword_p->type == LEXER_KEYW_AWAIT))
|
||||
{
|
||||
if (!(context_p->status_flags & PARSER_IS_ASYNC_FUNCTION)
|
||||
&& !(context_p->global_status_flags & ECMA_PARSE_MODULE))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (context_p->status_flags & PARSER_DISALLOW_AWAIT_YIELD)
|
||||
{
|
||||
if (ident_start_p == buffer_p)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD);
|
||||
}
|
||||
parser_raise_error (context_p, PARSER_ERR_AWAIT_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
context_p->token.type = (uint8_t) LEXER_KEYW_AWAIT;
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (ident_start_p == buffer_p)
|
||||
{
|
||||
/* Escape sequences are not allowed in a keyword. */
|
||||
@@ -828,30 +851,31 @@ lexer_parse_identifier (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (keyword_p->type == LEXER_KEYW_YIELD && (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION))
|
||||
if (keyword_p->type == LEXER_KEYW_LET && (context_p->status_flags & PARSER_IS_STRICT))
|
||||
{
|
||||
if (ident_start_p == buffer_p)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD);
|
||||
}
|
||||
|
||||
if (context_p->status_flags & PARSER_DISALLOW_YIELD)
|
||||
context_p->token.type = (uint8_t) LEXER_KEYW_LET;
|
||||
break;
|
||||
}
|
||||
|
||||
if (keyword_p->type == LEXER_KEYW_YIELD && (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION))
|
||||
{
|
||||
if (context_p->status_flags & PARSER_DISALLOW_AWAIT_YIELD)
|
||||
{
|
||||
if (ident_start_p == buffer_p)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD);
|
||||
}
|
||||
parser_raise_error (context_p, PARSER_ERR_YIELD_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
context_p->token.type = (uint8_t) LEXER_KEYW_YIELD;
|
||||
break;
|
||||
}
|
||||
|
||||
if (keyword_p->type == LEXER_KEYW_LET && ident_start_p != buffer_p)
|
||||
{
|
||||
if (context_p->status_flags & PARSER_IS_STRICT)
|
||||
{
|
||||
context_p->token.type = (uint8_t) LEXER_KEYW_LET;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (keyword_p->type >= LEXER_FIRST_FUTURE_STRICT_RESERVED_WORD
|
||||
@@ -1948,8 +1972,11 @@ lexer_check_yield_no_arg (parser_context_t *context_p) /**< context */
|
||||
bool
|
||||
lexer_consume_generator (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
JERRY_ASSERT (context_p->token.flags & LEXER_NO_SKIP_SPACES);
|
||||
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_ASYNC);
|
||||
if (!(context_p->token.flags & LEXER_NO_SKIP_SPACES))
|
||||
{
|
||||
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
|
||||
|| context_p->source_p[0] != LIT_CHAR_ASTERISK
|
||||
@@ -1964,6 +1991,54 @@ lexer_consume_generator (parser_context_t *context_p) /**< context */
|
||||
return true;
|
||||
} /* lexer_consume_generator */
|
||||
|
||||
/**
|
||||
* Update await / yield keywords after an arrow function with expression.
|
||||
*/
|
||||
void
|
||||
lexer_update_await_yield (parser_context_t *context_p, /**< context */
|
||||
uint32_t status_flags) /**< parser status flags after restore */
|
||||
{
|
||||
if (!(status_flags & PARSER_IS_STRICT))
|
||||
{
|
||||
if (status_flags & PARSER_IS_GENERATOR_FUNCTION)
|
||||
{
|
||||
if (context_p->token.type == LEXER_LITERAL
|
||||
&& context_p->token.keyword_type == LEXER_KEYW_YIELD)
|
||||
{
|
||||
context_p->token.type = LEXER_KEYW_YIELD;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (context_p->token.type == LEXER_KEYW_YIELD)
|
||||
{
|
||||
JERRY_ASSERT (context_p->token.keyword_type == LEXER_KEYW_YIELD);
|
||||
context_p->token.type = LEXER_LITERAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(context_p->global_status_flags & ECMA_PARSE_MODULE))
|
||||
{
|
||||
if (status_flags & PARSER_IS_ASYNC_FUNCTION)
|
||||
{
|
||||
if (context_p->token.type == LEXER_LITERAL
|
||||
&& context_p->token.keyword_type == LEXER_KEYW_AWAIT)
|
||||
{
|
||||
context_p->token.type = LEXER_KEYW_AWAIT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (context_p->token.type == LEXER_KEYW_AWAIT)
|
||||
{
|
||||
JERRY_ASSERT (context_p->token.keyword_type == LEXER_KEYW_AWAIT);
|
||||
context_p->token.type = LEXER_LITERAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* lexer_update_await_yield */
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
@@ -2853,6 +2928,16 @@ lexer_expect_identifier (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (context_p->token.type == LEXER_KEYW_YIELD)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_YIELD_NOT_ALLOWED);
|
||||
}
|
||||
if (context_p->token.type == LEXER_KEYW_AWAIT)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_AWAIT_NOT_ALLOWED);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
|
||||
} /* lexer_expect_identifier */
|
||||
|
||||
|
||||
@@ -58,6 +58,9 @@ typedef enum
|
||||
LEXER_BIT_NOT, /**< "~" */
|
||||
LEXER_KEYW_VOID, /**< void */
|
||||
LEXER_KEYW_TYPEOF, /**< typeof */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
LEXER_KEYW_AWAIT, /**< await */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
LEXER_KEYW_DELETE, /**< delete */
|
||||
LEXER_INCREASE, /**< "++" */
|
||||
LEXER_DECREASE, /**< "--" */
|
||||
@@ -164,9 +167,6 @@ typedef enum
|
||||
LEXER_KEYW_EXPORT, /**< export */
|
||||
LEXER_KEYW_IMPORT, /**< import */
|
||||
LEXER_KEYW_ENUM, /**< enum */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
LEXER_KEYW_AWAIT, /**< await */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/* These are virtual tokens. */
|
||||
LEXER_EXPRESSION_START, /**< expression start */
|
||||
@@ -177,7 +177,6 @@ typedef enum
|
||||
LEXER_ASSIGN_CONST, /**< a const binding is reassigned */
|
||||
LEXER_CLASS_CONSTRUCTOR, /**< special value for class constructor method */
|
||||
LEXER_INVALID_PATTERN, /**< special value for invalid destructuring pattern */
|
||||
LEXER_ARROW_LEFT_PAREN, /**< start of arrow function argument list */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|
||||
@@ -644,8 +644,14 @@ parser_parse_class_literal (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
}
|
||||
|
||||
status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION
|
||||
| PARSER_IS_ASYNC_FUNCTION
|
||||
| PARSER_DISALLOW_AWAIT_YIELD);
|
||||
|
||||
if (context_p->token.type == LEXER_KEYW_ASYNC)
|
||||
{
|
||||
status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
|
||||
|
||||
if (!lexer_consume_generator (context_p))
|
||||
{
|
||||
lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_ONLY_IDENTIFIERS);
|
||||
@@ -655,11 +661,7 @@ parser_parse_class_literal (parser_context_t *context_p, /**< context */
|
||||
if (context_p->token.type == LEXER_MULTIPLY)
|
||||
{
|
||||
lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_ONLY_IDENTIFIERS);
|
||||
status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_YIELD;
|
||||
}
|
||||
else
|
||||
{
|
||||
status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_YIELD);
|
||||
status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_RIGHT_SQUARE)
|
||||
@@ -1006,17 +1008,19 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */
|
||||
break;
|
||||
}
|
||||
case LEXER_KEYW_ASYNC:
|
||||
{
|
||||
lexer_consume_generator (context_p);
|
||||
/* FALLTHRU */
|
||||
}
|
||||
case LEXER_MULTIPLY:
|
||||
{
|
||||
uint32_t status_flags = PARSER_FUNCTION_CLOSURE;
|
||||
|
||||
if (context_p->token.type == LEXER_KEYW_ASYNC)
|
||||
{
|
||||
status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
|
||||
lexer_consume_generator (context_p);
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_MULTIPLY)
|
||||
{
|
||||
status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_YIELD;
|
||||
status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
|
||||
}
|
||||
|
||||
lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_ONLY_IDENTIFIERS);
|
||||
@@ -1164,8 +1168,15 @@ parser_parse_function_expression (parser_context_t *context_p, /**< context */
|
||||
uint16_t function_literal_index;
|
||||
int32_t function_name_index = -1;
|
||||
|
||||
#if !ENABLED (JERRY_ES2015)
|
||||
JERRY_ASSERT (status_flags & PARSER_IS_FUNC_EXPRESSION);
|
||||
#endif /* !ENABLED (JERRY_ES2015) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (status_flags & PARSER_IS_FUNC_EXPRESSION)
|
||||
{
|
||||
#endif /* !ENABLED (JERRY_ES2015) */
|
||||
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
parser_line_counter_t debugger_line = context_p->token.line;
|
||||
parser_line_counter_t debugger_column = context_p->token.column;
|
||||
@@ -1174,16 +1185,21 @@ parser_parse_function_expression (parser_context_t *context_p, /**< context */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
uint32_t parent_status_flags = context_p->status_flags;
|
||||
|
||||
if (lexer_check_next_character (context_p, LIT_CHAR_ASTERISK))
|
||||
context_p->status_flags &= (uint32_t) ~(PARSER_IS_ASYNC_FUNCTION
|
||||
| PARSER_IS_GENERATOR_FUNCTION
|
||||
| PARSER_DISALLOW_AWAIT_YIELD);
|
||||
|
||||
if (status_flags & PARSER_IS_ASYNC_FUNCTION)
|
||||
{
|
||||
/* The name of the function cannot be await. */
|
||||
context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
|
||||
}
|
||||
|
||||
if (lexer_consume_generator (context_p))
|
||||
{
|
||||
/* The name of the function cannot be yield. */
|
||||
context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_YIELD;
|
||||
status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_YIELD;
|
||||
lexer_consume_next_character (context_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_YIELD);
|
||||
context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
|
||||
status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
@@ -1225,8 +1241,8 @@ parser_parse_function_expression (parser_context_t *context_p, /**< context */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
context_p->status_flags = parent_status_flags;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
|
||||
{
|
||||
@@ -1486,13 +1502,28 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
|
||||
while (true)
|
||||
{
|
||||
/* Convert plus and minus binary operators to unary operators. */
|
||||
if (context_p->token.type == LEXER_ADD)
|
||||
switch (context_p->token.type)
|
||||
{
|
||||
context_p->token.type = LEXER_PLUS;
|
||||
}
|
||||
else if (context_p->token.type == LEXER_SUBTRACT)
|
||||
{
|
||||
context_p->token.type = LEXER_NEGATE;
|
||||
case LEXER_ADD:
|
||||
{
|
||||
context_p->token.type = LEXER_PLUS;
|
||||
break;
|
||||
}
|
||||
case LEXER_SUBTRACT:
|
||||
{
|
||||
context_p->token.type = LEXER_NEGATE;
|
||||
break;
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case LEXER_KEYW_AWAIT:
|
||||
{
|
||||
if (JERRY_UNLIKELY (context_p->token.lit_location.has_escape))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
}
|
||||
|
||||
/* Bracketed expressions are primary expressions. At this
|
||||
@@ -1561,30 +1592,41 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
|
||||
case LEXER_LITERAL:
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
|
||||
if (JERRY_UNLIKELY (context_p->next_scanner_info_p->source_p == context_p->source_p))
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
|
||||
|
||||
uint32_t arrow_status_flags = (PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION);
|
||||
|
||||
if (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_ASYNC)
|
||||
{
|
||||
JERRY_ASSERT (lexer_token_is_async (context_p));
|
||||
JERRY_ASSERT (!(context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_STATEMENT));
|
||||
|
||||
uint32_t saved_status_flags = context_p->status_flags;
|
||||
|
||||
context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
|
||||
lexer_next_token (context_p);
|
||||
context_p->status_flags = saved_status_flags;
|
||||
|
||||
if (context_p->token.type == LEXER_KEYW_FUNCTION)
|
||||
{
|
||||
parser_parse_function_expression (context_p, PARSER_FUNCTION_CLOSURE | PARSER_IS_FUNC_EXPRESSION);
|
||||
uint32_t status_flags = (PARSER_FUNCTION_CLOSURE
|
||||
| PARSER_IS_FUNC_EXPRESSION
|
||||
| PARSER_IS_ASYNC_FUNCTION
|
||||
| PARSER_DISALLOW_AWAIT_YIELD);
|
||||
parser_parse_function_expression (context_p, status_flags);
|
||||
break;
|
||||
}
|
||||
if (context_p->token.type == LEXER_LEFT_PAREN)
|
||||
{
|
||||
context_p->token.type = LEXER_ARROW_LEFT_PAREN;
|
||||
}
|
||||
|
||||
arrow_status_flags = (PARSER_IS_FUNCTION
|
||||
| PARSER_IS_ARROW_FUNCTION
|
||||
| PARSER_IS_ASYNC_FUNCTION
|
||||
| PARSER_DISALLOW_AWAIT_YIELD);
|
||||
}
|
||||
|
||||
parser_check_assignment_expr (context_p);
|
||||
parser_parse_function_expression (context_p, PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION);
|
||||
parser_parse_function_expression (context_p, arrow_status_flags);
|
||||
return parser_abort_parsing_after_arrow (context_p);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
@@ -1789,14 +1831,18 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
|
||||
|
||||
parser_check_assignment_expr (context_p);
|
||||
|
||||
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:
|
||||
{
|
||||
JERRY_ASSERT ((context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION)
|
||||
&& !(context_p->status_flags & PARSER_DISALLOW_YIELD));
|
||||
&& !(context_p->status_flags & PARSER_DISALLOW_AWAIT_YIELD));
|
||||
|
||||
if (context_p->token.lit_location.has_escape)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD);
|
||||
}
|
||||
|
||||
parser_check_assignment_expr (context_p);
|
||||
lexer_next_token (context_p);
|
||||
@@ -2216,6 +2262,12 @@ parser_process_unary_expression (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
parser_emit_unary_lvalue_opcode (context_p, (cbc_opcode_t) token);
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
else if (JERRY_UNLIKELY (token == LEXER_KEYW_AWAIT))
|
||||
{
|
||||
parser_emit_cbc_ext (context_p, CBC_EXT_AWAIT);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
else
|
||||
{
|
||||
token = (uint8_t) (LEXER_UNARY_OP_TOKEN_TO_OPCODE (token));
|
||||
|
||||
@@ -63,7 +63,7 @@ typedef enum
|
||||
PARSER_IS_ARROW_FUNCTION = (1u << 13), /**< an arrow function is parsed */
|
||||
PARSER_IS_GENERATOR_FUNCTION = (1u << 14), /**< a generator function is parsed */
|
||||
PARSER_IS_ASYNC_FUNCTION = (1u << 15), /**< an async function is parsed */
|
||||
PARSER_DISALLOW_YIELD = (1u << 16), /**< throw SyntaxError for yield expression */
|
||||
PARSER_DISALLOW_AWAIT_YIELD = (1u << 16), /**< throw SyntaxError for await / yield keywords */
|
||||
PARSER_FUNCTION_IS_PARSING_ARGS = (1u << 17), /**< set when parsing function arguments */
|
||||
PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM = (1u << 18), /**< function has a non simple parameter */
|
||||
PARSER_FUNCTION_HAS_REST_PARAM = (1u << 19), /**< function has rest parameter */
|
||||
@@ -681,6 +681,7 @@ bool lexer_check_arrow (parser_context_t *context_p);
|
||||
bool lexer_check_arrow_param (parser_context_t *context_p);
|
||||
bool lexer_check_yield_no_arg (parser_context_t *context_p);
|
||||
bool lexer_consume_generator (parser_context_t *context_p);
|
||||
void lexer_update_await_yield (parser_context_t *context_p, uint32_t status_flags);
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
void lexer_parse_string (parser_context_t *context_p, lexer_string_options_t opts);
|
||||
void lexer_expect_identifier (parser_context_t *context_p, uint8_t literal_type);
|
||||
|
||||
@@ -684,10 +684,9 @@ parser_parse_function_statement (parser_context_t *context_p) /**< context */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
bool is_generator_function = false;
|
||||
|
||||
if (lexer_check_next_character (context_p, LIT_CHAR_ASTERISK))
|
||||
if (lexer_consume_generator (context_p))
|
||||
{
|
||||
is_generator_function = true;
|
||||
lexer_consume_next_character (context_p);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
@@ -715,10 +714,17 @@ parser_parse_function_statement (parser_context_t *context_p) /**< context */
|
||||
status_flags |= PARSER_HAS_NON_STRICT_ARG;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (is_generator_function)
|
||||
{
|
||||
status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_YIELD;
|
||||
status_flags |= PARSER_IS_GENERATOR_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
|
||||
}
|
||||
|
||||
if (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_ASYNC)
|
||||
{
|
||||
status_flags |= PARSER_IS_ASYNC_FUNCTION | PARSER_DISALLOW_AWAIT_YIELD;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
@@ -3054,12 +3060,23 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
|
||||
if (JERRY_UNLIKELY (lexer_token_is_async (context_p))
|
||||
&& context_p->next_scanner_info_p->source_p == context_p->source_p)
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
|
||||
bool is_statement = true;
|
||||
|
||||
if (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_STATEMENT)
|
||||
if (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION)
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_ASYNC);
|
||||
is_statement = (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_STATEMENT) != 0;
|
||||
|
||||
JERRY_ASSERT (!is_statement || (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_ASYNC));
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_ASYNC_FUNCTION);
|
||||
|
||||
scanner_release_next (context_p, sizeof (scanner_info_t));
|
||||
}
|
||||
|
||||
if (is_statement)
|
||||
{
|
||||
if (parser_statement_flags[context_p->stack_top_uint8] & PARSER_STATM_SINGLE_STATM)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_LEXICAL_SINGLE_STATEMENT);
|
||||
|
||||
@@ -951,7 +951,11 @@ parser_error_to_string (parser_error_t error) /**< error code */
|
||||
}
|
||||
case PARSER_ERR_YIELD_NOT_ALLOWED:
|
||||
{
|
||||
return "Incorrect use of yield keyword.";
|
||||
return "Yield expression is not allowed here.";
|
||||
}
|
||||
case PARSER_ERR_AWAIT_NOT_ALLOWED:
|
||||
{
|
||||
return "Await expression is not allowed here.";
|
||||
}
|
||||
case PARSER_ERR_FOR_IN_OF_DECLARATION:
|
||||
{
|
||||
|
||||
@@ -1718,10 +1718,10 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */
|
||||
bool has_duplicated_arg_names = false;
|
||||
|
||||
/* TODO: Currently async iterators are not supported, so generators ignore the async modifier. */
|
||||
if ((context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_ASYNC)
|
||||
&& !(context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION))
|
||||
uint32_t mask = (PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION);
|
||||
if ((context_p->status_flags & mask) == mask)
|
||||
{
|
||||
context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION;
|
||||
context_p->status_flags &= (uint32_t) ~PARSER_IS_ASYNC_FUNCTION;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
@@ -1734,7 +1734,7 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */
|
||||
parser_emit_cbc (context_p, CBC_POP);
|
||||
}
|
||||
|
||||
context_p->status_flags &= (uint32_t) ~PARSER_DISALLOW_YIELD;
|
||||
context_p->status_flags &= (uint32_t) ~PARSER_DISALLOW_AWAIT_YIELD;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS);
|
||||
return;
|
||||
@@ -1972,7 +1972,7 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
}
|
||||
|
||||
context_p->status_flags &= (uint32_t) ~(PARSER_DISALLOW_YIELD | PARSER_FUNCTION_IS_PARSING_ARGS);
|
||||
context_p->status_flags &= (uint32_t) ~(PARSER_DISALLOW_AWAIT_YIELD | PARSER_FUNCTION_IS_PARSING_ARGS);
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_BODY);
|
||||
@@ -2529,7 +2529,7 @@ parser_parse_arrow_function (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
|
||||
if (context_p->token.type == LEXER_ARROW_LEFT_PAREN)
|
||||
if (context_p->token.type == LEXER_LEFT_PAREN)
|
||||
{
|
||||
lexer_next_token (context_p);
|
||||
parser_parse_function_arguments (context_p, LEXER_RIGHT_PAREN);
|
||||
@@ -2581,6 +2581,8 @@ parser_parse_arrow_function (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
}
|
||||
parser_flush_cbc (context_p);
|
||||
|
||||
lexer_update_await_yield (context_p, saved_context.status_flags);
|
||||
}
|
||||
|
||||
compiled_code_p = parser_post_processing (context_p);
|
||||
|
||||
@@ -79,7 +79,8 @@ typedef enum
|
||||
PARSER_ERR_ARGUMENTS_NOT_ALLOWED, /**< arguments is not allowed here in strict mode */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
PARSER_ERR_USE_STRICT_NOT_ALLOWED, /**< use strict directive is not allowed */
|
||||
PARSER_ERR_YIELD_NOT_ALLOWED, /**< yield keyword is not allowed */
|
||||
PARSER_ERR_YIELD_NOT_ALLOWED, /**< yield expression is not allowed */
|
||||
PARSER_ERR_AWAIT_NOT_ALLOWED, /**< await expression is not allowed */
|
||||
PARSER_ERR_FOR_IN_OF_DECLARATION, /**< variable declaration in for-in or for-of loop */
|
||||
PARSER_ERR_DUPLICATED_PROTO, /**< duplicated __proto__ fields are not allowed */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
@@ -95,10 +95,13 @@ typedef enum
|
||||
SCAN_STACK_CATCH_STATEMENT, /**< catch statement */
|
||||
SCAN_STACK_ARRAY_LITERAL, /**< array literal or destructuring assignment or binding */
|
||||
SCAN_STACK_OBJECT_LITERAL, /**< object literal group */
|
||||
SCAN_STACK_PROPERTY_ACCESSOR, /**< property accessor in squarey brackets */
|
||||
SCAN_STACK_PROPERTY_ACCESSOR, /**< property accessor in square brackets */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
/* These four must be in this order. */
|
||||
SCAN_STACK_COMPUTED_PROPERTY, /**< computed property name */
|
||||
SCAN_STACK_COMPUTED_GENERATOR_FUNCTION, /**< computed property name */
|
||||
SCAN_STACK_COMPUTED_GENERATOR, /**< computed generator function */
|
||||
SCAN_STACK_COMPUTED_ASYNC, /**< computed async function */
|
||||
SCAN_STACK_COMPUTED_ASYNC_GENERATOR, /**< computed async function */
|
||||
SCAN_STACK_TEMPLATE_STRING, /**< template string */
|
||||
SCAN_STACK_TAGGED_TEMPLATE_LITERAL, /**< tagged template literal */
|
||||
SCAN_STACK_PRIVATE_BLOCK_EARLY, /**< private block for single statements (force early declarations) */
|
||||
@@ -115,6 +118,20 @@ typedef enum
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
} scan_stack_modes_t;
|
||||
|
||||
/**
|
||||
* Scanner context flag types.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SCANNER_CONTEXT_NO_FLAGS = 0, /**< no flags are set */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION = (1 << 0), /**< throw async function error */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
SCANNER_CONTEXT_DEBUGGER_ENABLED = (1 << 1), /**< debugger is enabled */
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
} scanner_context_flags_t;
|
||||
|
||||
/**
|
||||
* Checks whether the stack top is a for statement start.
|
||||
*/
|
||||
@@ -269,6 +286,7 @@ typedef enum
|
||||
SCANNER_LITERAL_POOL_FUNCTION_STATEMENT = (1 << 8), /**< function statement */
|
||||
SCANNER_LITERAL_POOL_GENERATOR = (1 << 9), /**< generator function */
|
||||
SCANNER_LITERAL_POOL_ASYNC = (1 << 10), /**< async function */
|
||||
SCANNER_LITERAL_POOL_ASYNC_ARROW = (1 << 11), /**< can be an async arrow function */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
} scanner_literal_pool_flags_t;
|
||||
|
||||
@@ -278,6 +296,18 @@ typedef enum
|
||||
#define SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS \
|
||||
(SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_NO_ARGUMENTS)
|
||||
|
||||
/**
|
||||
* Getting the generator and async properties of literal pool status flags.
|
||||
*/
|
||||
#define SCANNER_FROM_LITERAL_POOL_TO_COMPUTED(status_flags) \
|
||||
((uint8_t) ((((status_flags) >> 9) & 0x3) + SCAN_STACK_COMPUTED_PROPERTY))
|
||||
|
||||
/**
|
||||
* Setting the generator and async properties of literal pool status flags.
|
||||
*/
|
||||
#define SCANNER_FROM_COMPUTED_TO_LITERAL_POOL(mode) \
|
||||
(((mode) - SCAN_STACK_COMPUTED_PROPERTY) << 9)
|
||||
|
||||
/**
|
||||
* Local literal pool.
|
||||
*/
|
||||
@@ -297,11 +327,11 @@ struct scanner_context_t
|
||||
{
|
||||
uint32_t context_status_flags; /**< original status flags of the context */
|
||||
uint8_t mode; /**< scanner mode */
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
uint8_t debugger_enabled; /**< debugger is enabled */
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
uint8_t binding_type; /**< current destructuring binding type */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
uint16_t status_flags; /**< scanner status flags */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
scanner_binding_list_t *active_binding_list_p; /**< currently active binding list */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
scanner_literal_pool_t *active_literal_pool_p; /**< currently active literal pool */
|
||||
|
||||
@@ -108,14 +108,24 @@ scanner_check_arrow (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
|
||||
scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
|
||||
uint16_t status_flags = literal_pool_p->status_flags;
|
||||
|
||||
literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS;
|
||||
literal_pool_p->status_flags &= (uint16_t) ~(SCANNER_LITERAL_POOL_IN_WITH | SCANNER_LITERAL_POOL_GENERATOR);
|
||||
status_flags |= SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS;
|
||||
status_flags &= (uint16_t) ~(SCANNER_LITERAL_POOL_IN_WITH
|
||||
| SCANNER_LITERAL_POOL_GENERATOR
|
||||
| SCANNER_LITERAL_POOL_ASYNC);
|
||||
|
||||
context_p->status_flags &= (uint32_t) ~PARSER_IS_GENERATOR_FUNCTION;
|
||||
context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION);
|
||||
|
||||
if (status_flags & SCANNER_LITERAL_POOL_ASYNC_ARROW)
|
||||
{
|
||||
status_flags |= SCANNER_LITERAL_POOL_ASYNC;
|
||||
context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION;
|
||||
}
|
||||
|
||||
literal_pool_p->status_flags = status_flags;
|
||||
|
||||
scanner_filter_arguments (context_p, scanner_context_p);
|
||||
|
||||
scanner_check_arrow_body (context_p, scanner_context_p);
|
||||
} /* scanner_check_arrow */
|
||||
|
||||
@@ -127,10 +137,19 @@ scanner_scan_simple_arrow (parser_context_t *context_p, /**< context */
|
||||
scanner_context_t *scanner_context_p, /**< scanner context */
|
||||
const uint8_t *source_p) /**< identifier end position */
|
||||
{
|
||||
scanner_literal_pool_t *literal_pool_p;
|
||||
literal_pool_p = scanner_push_literal_pool (context_p,
|
||||
scanner_context_p,
|
||||
SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS);
|
||||
uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS;
|
||||
|
||||
context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION);
|
||||
|
||||
if (scanner_context_p->async_source_p != NULL)
|
||||
{
|
||||
JERRY_ASSERT (scanner_context_p->async_source_p == source_p);
|
||||
|
||||
status_flags |= SCANNER_LITERAL_POOL_ASYNC;
|
||||
context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION;
|
||||
}
|
||||
|
||||
scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, status_flags);
|
||||
literal_pool_p->source_p = source_p;
|
||||
|
||||
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
|
||||
@@ -141,8 +160,6 @@ scanner_scan_simple_arrow (parser_context_t *context_p, /**< context */
|
||||
PARSER_PLUS_EQUAL_LC (context_p->column, 2);
|
||||
context_p->token.flags = (uint8_t) (context_p->token.flags & ~LEXER_NO_SKIP_SPACES);
|
||||
|
||||
context_p->status_flags &= (uint32_t) ~PARSER_IS_GENERATOR_FUNCTION;
|
||||
|
||||
scanner_check_arrow_body (context_p, scanner_context_p);
|
||||
} /* scanner_scan_simple_arrow */
|
||||
|
||||
@@ -266,7 +283,6 @@ scanner_check_async_function (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
|
||||
scanner_scan_simple_arrow (context_p, scanner_context_p, scanner_context_p->async_source_p);
|
||||
scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_ASYNC;
|
||||
scanner_context_p->async_source_p = NULL;
|
||||
return false;
|
||||
}
|
||||
@@ -475,7 +491,7 @@ scanner_scan_bracket (parser_context_t *context_p, /**< context */
|
||||
|
||||
if (JERRY_UNLIKELY (scanner_context_p->async_source_p != NULL))
|
||||
{
|
||||
status_flags |= SCANNER_LITERAL_POOL_ASYNC;
|
||||
status_flags |= SCANNER_LITERAL_POOL_ASYNC_ARROW;
|
||||
arrow_source_p = scanner_context_p->async_source_p;
|
||||
scanner_context_p->async_source_p = NULL;
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ scanner_raise_error (parser_context_t *context_p) /**< context */
|
||||
* Raise a variable redeclaration error.
|
||||
*/
|
||||
void
|
||||
scanner_raise_redeclaration_error (parser_context_t *context_p)
|
||||
scanner_raise_redeclaration_error (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
scanner_info_t *info_p = scanner_insert_info (context_p, context_p->source_p, sizeof (scanner_info_t));
|
||||
info_p->type = SCANNER_TYPE_ERR_REDECLARED;
|
||||
@@ -403,13 +403,31 @@ scanner_push_literal_pool (parser_context_t *context_p, /**< context */
|
||||
status_flags |= SCANNER_LITERAL_POOL_NO_ARGUMENTS;
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
const uint16_t copied_flags = SCANNER_LITERAL_POOL_IN_WITH | SCANNER_LITERAL_POOL_GENERATOR;
|
||||
const uint16_t copied_flags = (SCANNER_LITERAL_POOL_IN_WITH
|
||||
| SCANNER_LITERAL_POOL_GENERATOR
|
||||
| SCANNER_LITERAL_POOL_ASYNC);
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
const uint16_t copied_flags = SCANNER_LITERAL_POOL_IN_WITH;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
status_flags |= (uint16_t) (prev_literal_pool_p->status_flags & copied_flags);
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
else
|
||||
{
|
||||
context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION);
|
||||
|
||||
if (status_flags & SCANNER_LITERAL_POOL_GENERATOR)
|
||||
{
|
||||
context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION;
|
||||
}
|
||||
|
||||
if (status_flags & SCANNER_LITERAL_POOL_ASYNC)
|
||||
{
|
||||
context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION;
|
||||
}
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (prev_literal_pool_p != NULL)
|
||||
{
|
||||
@@ -486,7 +504,7 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
if (scanner_context_p->debugger_enabled)
|
||||
if (scanner_context_p->status_flags & SCANNER_CONTEXT_DEBUGGER_ENABLED)
|
||||
{
|
||||
/* When debugger is enabled, identifiers are not stored in registers. However,
|
||||
* this does not affect 'eval' detection, so 'arguments' object is not created. */
|
||||
@@ -899,6 +917,15 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
{
|
||||
context_p->status_flags &= (uint32_t) ~PARSER_IS_GENERATOR_FUNCTION;
|
||||
}
|
||||
|
||||
if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_ASYNC)
|
||||
{
|
||||
context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
context_p->status_flags &= (uint32_t) ~PARSER_IS_ASYNC_FUNCTION;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
}
|
||||
|
||||
@@ -1611,7 +1638,8 @@ scanner_cleanup (parser_context_t *context_p) /**< context */
|
||||
JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS
|
||||
|| scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION
|
||||
|| scanner_info_p->type == SCANNER_TYPE_CLASS_CONSTRUCTOR
|
||||
|| scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
|
||||
|| scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED
|
||||
|| scanner_info_p->type == SCANNER_TYPE_ERR_ASYNC_FUNCTION);
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS);
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
@@ -50,12 +50,19 @@ typedef enum
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|
||||
/**
|
||||
* Returns the correct computed property mode based on the literal_pool_flags.
|
||||
*/
|
||||
#define GET_COMPUTED_PROPERTY_MODE(literal_pool_flags) \
|
||||
(((literal_pool_flags) & SCANNER_LITERAL_POOL_GENERATOR) ? SCAN_STACK_COMPUTED_GENERATOR_FUNCTION \
|
||||
: SCAN_STACK_COMPUTED_PROPERTY)
|
||||
JERRY_STATIC_ASSERT (SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (SCANNER_LITERAL_POOL_GENERATOR)
|
||||
== SCAN_STACK_COMPUTED_GENERATOR,
|
||||
scanner_invalid_conversion_from_literal_pool_generator_to_computed_generator);
|
||||
JERRY_STATIC_ASSERT (SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (SCANNER_LITERAL_POOL_ASYNC)
|
||||
== SCAN_STACK_COMPUTED_ASYNC,
|
||||
scanner_invalid_conversion_from_literal_pool_async_to_computed_async);
|
||||
|
||||
JERRY_STATIC_ASSERT (SCANNER_FROM_COMPUTED_TO_LITERAL_POOL (SCAN_STACK_COMPUTED_GENERATOR)
|
||||
== SCANNER_LITERAL_POOL_GENERATOR,
|
||||
scanner_invalid_conversion_from_computed_generator_to_literal_pool_generator);
|
||||
JERRY_STATIC_ASSERT (SCANNER_FROM_COMPUTED_TO_LITERAL_POOL (SCAN_STACK_COMPUTED_ASYNC)
|
||||
== SCANNER_LITERAL_POOL_ASYNC,
|
||||
scanner_invalid_conversion_from_computed_async_to_literal_pool_async);
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
@@ -93,23 +100,24 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
case LEXER_KEYW_FUNCTION:
|
||||
{
|
||||
scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
|
||||
uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION;
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
context_p->status_flags &= (uint32_t) ~PARSER_IS_GENERATOR_FUNCTION;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
lexer_next_token (context_p);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (context_p->token.type == LEXER_MULTIPLY)
|
||||
if (scanner_context_p->async_source_p != NULL)
|
||||
{
|
||||
scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_GENERATOR;
|
||||
context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION;
|
||||
lexer_next_token (context_p);
|
||||
status_flags |= SCANNER_LITERAL_POOL_ASYNC;
|
||||
}
|
||||
|
||||
if (lexer_consume_generator (context_p))
|
||||
{
|
||||
status_flags |= SCANNER_LITERAL_POOL_GENERATOR;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
scanner_push_literal_pool (context_p, scanner_context_p, status_flags);
|
||||
|
||||
lexer_next_token (context_p);
|
||||
|
||||
if (context_p->token.type == LEXER_LITERAL
|
||||
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
|
||||
{
|
||||
@@ -957,7 +965,9 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
}
|
||||
return SCAN_NEXT_TOKEN;
|
||||
}
|
||||
case SCAN_STACK_COMPUTED_GENERATOR_FUNCTION:
|
||||
case SCAN_STACK_COMPUTED_GENERATOR:
|
||||
case SCAN_STACK_COMPUTED_ASYNC:
|
||||
case SCAN_STACK_COMPUTED_ASYNC_GENERATOR:
|
||||
{
|
||||
if (type != LEXER_RIGHT_SQUARE)
|
||||
{
|
||||
@@ -970,10 +980,11 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_PROPERTY);
|
||||
|
||||
scanner_push_literal_pool (context_p,
|
||||
scanner_context_p,
|
||||
SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_GENERATOR);
|
||||
context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION;
|
||||
uint16_t status_flags = (uint16_t) (SCANNER_LITERAL_POOL_FUNCTION
|
||||
| SCANNER_LITERAL_POOL_GENERATOR
|
||||
| SCANNER_FROM_COMPUTED_TO_LITERAL_POOL (stack_top));
|
||||
|
||||
scanner_push_literal_pool (context_p, scanner_context_p, status_flags);
|
||||
|
||||
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
|
||||
return SCAN_KEEP_TOKEN;
|
||||
@@ -1015,6 +1026,7 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
{
|
||||
scanner_pop_literal_pool (context_p, scanner_context_p);
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
lexer_update_await_yield (context_p, context_p->status_flags);
|
||||
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
@@ -1358,24 +1370,24 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
case LEXER_KEYW_FUNCTION:
|
||||
{
|
||||
lexer_next_token (context_p);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_FUNCTION_STATEMENT;
|
||||
|
||||
if (scanner_context_p->async_source_p != NULL)
|
||||
{
|
||||
scanner_context_p->status_flags |= SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION;
|
||||
status_flags |= SCANNER_LITERAL_POOL_ASYNC;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
lexer_next_token (context_p);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (context_p->token.type == LEXER_MULTIPLY)
|
||||
{
|
||||
status_flags |= SCANNER_LITERAL_POOL_GENERATOR;
|
||||
lexer_next_token (context_p);
|
||||
/* This flag should be set after the function name is read. */
|
||||
context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
context_p->status_flags &= (uint32_t) ~PARSER_IS_GENERATOR_FUNCTION;
|
||||
}
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (context_p->token.type != LEXER_LITERAL
|
||||
@@ -1397,8 +1409,12 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
|
||||
literal_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_FUNC_DECLARATION;
|
||||
|
||||
scanner_context_p->status_flags &= (uint16_t) ~SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION;
|
||||
#else
|
||||
literal_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC;
|
||||
|
||||
uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
scanner_push_literal_pool (context_p, scanner_context_p, status_flags);
|
||||
@@ -2254,8 +2270,12 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
|
||||
|
||||
scanner_context.context_status_flags = context_p->status_flags;
|
||||
scanner_context.status_flags = SCANNER_CONTEXT_NO_FLAGS;
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
scanner_context.debugger_enabled = (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) ? 1 : 0;
|
||||
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
|
||||
{
|
||||
scanner_context.status_flags |= SCANNER_CONTEXT_DEBUGGER_ENABLED;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
scanner_context.binding_type = SCANNER_BINDING_NONE;
|
||||
@@ -2310,6 +2330,13 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
status_flags |= SCANNER_LITERAL_POOL_IS_STRICT;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION)
|
||||
{
|
||||
status_flags |= SCANNER_LITERAL_POOL_GENERATOR;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
scanner_push_literal_pool (context_p, &scanner_context, status_flags);
|
||||
scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_SCRIPT_FUNCTION);
|
||||
@@ -2459,7 +2486,7 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
|
||||
if (context_p->token.type == LEXER_LEFT_SQUARE)
|
||||
{
|
||||
parser_stack_push_uint8 (context_p, GET_COMPUTED_PROPERTY_MODE (literal_pool_flags));
|
||||
parser_stack_push_uint8 (context_p, SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (literal_pool_flags));
|
||||
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
||||
break;
|
||||
}
|
||||
@@ -2889,15 +2916,10 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (context_p->token.type == LEXER_LEFT_SQUARE)
|
||||
{
|
||||
parser_stack_push_uint8 (context_p, GET_COMPUTED_PROPERTY_MODE (literal_pool_flags));
|
||||
parser_stack_push_uint8 (context_p, SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (literal_pool_flags));
|
||||
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
||||
break;
|
||||
}
|
||||
|
||||
if (literal_pool_flags & SCANNER_LITERAL_POOL_GENERATOR)
|
||||
{
|
||||
context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (context_p->token.type != LEXER_LITERAL)
|
||||
@@ -3150,9 +3172,20 @@ scan_completed:
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/* The following loop may allocate memory, so it is enclosed in a try/catch. */
|
||||
/* The following code may allocate memory, so it is enclosed in a try/catch. */
|
||||
PARSER_TRY (context_p->try_buffer)
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (scanner_context.status_flags & SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION)
|
||||
{
|
||||
JERRY_ASSERT (scanner_context.async_source_p != NULL);
|
||||
|
||||
scanner_info_t *info_p;
|
||||
info_p = scanner_insert_info (context_p, scanner_context.async_source_p, sizeof (scanner_info_t));
|
||||
info_p->type = SCANNER_TYPE_ERR_ASYNC_FUNCTION;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
while (scanner_context.active_literal_pool_p != NULL)
|
||||
{
|
||||
scanner_pop_literal_pool (context_p, &scanner_context);
|
||||
@@ -3426,6 +3459,12 @@ scan_completed:
|
||||
(int) (info_p->source_p - source_start_p));
|
||||
break;
|
||||
}
|
||||
case SCANNER_TYPE_ERR_ASYNC_FUNCTION:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" ERR_ASYNC_FUNCTION: source:%d\n",
|
||||
(int) (info_p->source_p - source_start_p));
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ typedef enum
|
||||
SCANNER_TYPE_CLASS_CONSTRUCTOR, /**< class constructor */
|
||||
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 */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
} scanner_info_type_t;
|
||||
|
||||
|
||||
+6
-2
@@ -1990,8 +1990,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
{
|
||||
frame_ctx_p->call_operation = VM_EXEC_RETURN;
|
||||
frame_ctx_p->byte_code_p = byte_code_p;
|
||||
frame_ctx_p->stack_top_p = stack_top_p;
|
||||
return left_value;
|
||||
frame_ctx_p->stack_top_p = --stack_top_p;
|
||||
return *stack_top_p;
|
||||
}
|
||||
case VM_OC_AWAIT:
|
||||
{
|
||||
continue;
|
||||
}
|
||||
case VM_OC_EXT_RETURN:
|
||||
{
|
||||
|
||||
@@ -265,6 +265,7 @@ typedef enum
|
||||
VM_OC_SPREAD_ARGUMENTS, /**< perform function call/construct with spreaded arguments */
|
||||
VM_OC_CREATE_GENERATOR, /**< create a generator object */
|
||||
VM_OC_YIELD, /**< yield operation */
|
||||
VM_OC_AWAIT, /**< await operation */
|
||||
VM_OC_EXT_RETURN, /**< return which also clears the stack */
|
||||
VM_OC_RETURN_PROMISE, /**< return from an async function */
|
||||
VM_OC_STRING_CONCAT, /**< string concatenation */
|
||||
@@ -329,6 +330,7 @@ typedef enum
|
||||
VM_OC_SPREAD_ARGUMENTS = VM_OC_NONE, /**< perform function call/construct with spreaded arguments */
|
||||
VM_OC_CREATE_GENERATOR = VM_OC_NONE, /**< create a generator object */
|
||||
VM_OC_YIELD = VM_OC_NONE, /**< yield operation */
|
||||
VM_OC_AWAIT = VM_OC_NONE, /**< await operation */
|
||||
VM_OC_EXT_RETURN = VM_OC_NONE, /**< return which also clears the stack */
|
||||
VM_OC_RETURN_PROMISE = VM_OC_NONE, /**< return from an async function */
|
||||
VM_OC_STRING_CONCAT = VM_OC_NONE, /**< string concatenation */
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
// 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.
|
||||
|
||||
/* This test checks await expressions (nothing else). */
|
||||
|
||||
function check_syntax_error (code)
|
||||
{
|
||||
try {
|
||||
eval (code)
|
||||
assert (false)
|
||||
} catch (e) {
|
||||
assert (e instanceof SyntaxError)
|
||||
}
|
||||
}
|
||||
|
||||
check_syntax_error("(async function await() {})")
|
||||
check_syntax_error("(async function *await() {})")
|
||||
check_syntax_error("async function f(await) {}")
|
||||
check_syntax_error("(async function f(await) {})")
|
||||
check_syntax_error("async function f(a = await new Promise) {}")
|
||||
check_syntax_error("async function f() { function await() {} }")
|
||||
check_syntax_error("async await => 0");
|
||||
check_syntax_error("async (await) => 0");
|
||||
check_syntax_error("async function f() { await () => 0 }");
|
||||
check_syntax_error("async (a) => a\\u0077ait a");
|
||||
check_syntax_error("async (a) => { () => 0\na\\u0077ait a }");
|
||||
|
||||
// Valid uses of await
|
||||
|
||||
async a => await a
|
||||
async a => { await a }
|
||||
async (a) => await a
|
||||
async(a) => { await a }
|
||||
|
||||
// Nested async and non-async functions
|
||||
|
||||
async (a) => {
|
||||
() => await
|
||||
await a
|
||||
}
|
||||
|
||||
(a) => {
|
||||
await
|
||||
async (a) => await a
|
||||
await
|
||||
async (a) => await a
|
||||
a\u0077ait
|
||||
}
|
||||
|
||||
async function f1(a) {
|
||||
await a
|
||||
(function () { await ? async function(a) { await a } : await })
|
||||
await a
|
||||
}
|
||||
|
||||
async (a) => {
|
||||
await a;
|
||||
() => await ? async (a) => await a : await
|
||||
await a
|
||||
}
|
||||
|
||||
async (a) => {
|
||||
(a = () => await, [b] = (c))
|
||||
await a
|
||||
(a, b = () => await)
|
||||
await a
|
||||
}
|
||||
|
||||
// Object initializers
|
||||
|
||||
var o = {
|
||||
async await(a) {
|
||||
await a;
|
||||
() => await
|
||||
await a
|
||||
},
|
||||
|
||||
f(a) {
|
||||
await
|
||||
async (a) => await a
|
||||
await
|
||||
async (a) => await a
|
||||
a\u0077ait
|
||||
},
|
||||
|
||||
async ["g"] () {
|
||||
await a;
|
||||
() => await
|
||||
await a
|
||||
}
|
||||
}
|
||||
|
||||
async function f2(a) {
|
||||
var o = {
|
||||
[await a]() { await % await }
|
||||
}
|
||||
await a;
|
||||
}
|
||||
|
||||
class C {
|
||||
async await(a) {
|
||||
await a;
|
||||
() => await
|
||||
await a
|
||||
}
|
||||
|
||||
f(a) {
|
||||
await
|
||||
async (a) => await a
|
||||
await
|
||||
async (a) => await a
|
||||
a\u0077ait
|
||||
}
|
||||
|
||||
async ["g"] () {
|
||||
await a;
|
||||
() => await
|
||||
await a
|
||||
}
|
||||
}
|
||||
|
||||
async function f3(a) {
|
||||
class C {
|
||||
[await a]() { await % await }
|
||||
}
|
||||
await a;
|
||||
}
|
||||
@@ -43,7 +43,7 @@
|
||||
// Test %GeneratorPrototype% prototype chain
|
||||
(function () {
|
||||
function* g(){}
|
||||
var iterator = new g.constructor("a","b","c","yield a; yield b; yield c;")(1,2,3);
|
||||
var iterator = new g.constructor("a","b","c","() => yield\n yield a; yield b; yield c;")(1,2,3);
|
||||
|
||||
var item = iterator.next();
|
||||
assert(item.value === 1);
|
||||
|
||||
@@ -58,6 +58,7 @@ check_syntax_error("function *gen(){ (yield\n1) }");
|
||||
check_syntax_error("function *gen(){ function yield() {} }");
|
||||
check_syntax_error("function *gen(){ (yield)=>1 }");
|
||||
check_syntax_error("function *gen(){ yield => 1 }");
|
||||
check_syntax_error("function *gen(){ yi\\u0065ld 1 }");
|
||||
|
||||
function *gen4() {
|
||||
var f = function yield(i) {
|
||||
@@ -71,3 +72,15 @@ function *gen4() {
|
||||
}
|
||||
|
||||
assert(gen4().next().value === 39);
|
||||
|
||||
(function *() {
|
||||
() => yield
|
||||
yield 1;
|
||||
})
|
||||
|
||||
function *gen5() {
|
||||
var o = {
|
||||
["f"]() { yield % yield }
|
||||
}
|
||||
yield 1;
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ main (void)
|
||||
/* Check the snapshot data. Unused bytes should be filled with zeroes */
|
||||
const uint8_t expected_data[] =
|
||||
{
|
||||
0x4A, 0x52, 0x52, 0x59, 0x2B, 0x00, 0x00, 0x00,
|
||||
0x4A, 0x52, 0x52, 0x59, 0x2C, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x01, 0x00, 0x41, 0x00, 0x01, 0x00,
|
||||
|
||||
Reference in New Issue
Block a user