Initial implementation of class fields (#4191)
Missing features: - this binding in static fields are not supported - static field evaluation order is wrong - function names are not supported JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -27,7 +27,7 @@ JERRY_STATIC_ASSERT ((sizeof (cbc_uint16_arguments_t) % sizeof (jmem_cpointer_t)
|
||||
*/
|
||||
JERRY_STATIC_ASSERT (CBC_END == 238,
|
||||
number_of_cbc_opcodes_changed);
|
||||
JERRY_STATIC_ASSERT (CBC_EXT_END == 135,
|
||||
JERRY_STATIC_ASSERT (CBC_EXT_END == 140,
|
||||
number_of_cbc_ext_opcodes_changed);
|
||||
|
||||
#if ENABLED (JERRY_PARSER)
|
||||
|
||||
@@ -634,6 +634,8 @@
|
||||
VM_OC_SET_GETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK) \
|
||||
CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER, CBC_NO_FLAG, -2, \
|
||||
VM_OC_SET_SETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK) \
|
||||
CBC_OPCODE (CBC_EXT_SET_STATIC_PROPERTY, CBC_HAS_LITERAL_ARG, -1, \
|
||||
VM_OC_SET_PROPERTY | VM_OC_GET_STACK_LITERAL) \
|
||||
CBC_OPCODE (CBC_EXT_SET_STATIC_PROPERTY_LITERAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
|
||||
VM_OC_SET_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \
|
||||
CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_PROPERTY, CBC_NO_FLAG, -2, \
|
||||
@@ -648,6 +650,8 @@
|
||||
VM_OC_SET_SETTER | VM_OC_GET_STACK_STACK) \
|
||||
CBC_OPCODE (CBC_EXT_SET__PROTO__, CBC_NO_FLAG, -1, \
|
||||
VM_OC_SET__PROTO__ | VM_OC_GET_STACK) \
|
||||
CBC_OPCODE (CBC_EXT_ADD_COMPUTED_FIELD, CBC_NO_FLAG, -1, \
|
||||
VM_OC_ADD_COMPUTED_FIELD | VM_OC_GET_STACK) \
|
||||
\
|
||||
/* Class related opcodes. */ \
|
||||
CBC_OPCODE (CBC_EXT_PUSH_NAMED_CLASS_ENV, CBC_HAS_LITERAL_ARG, 1, \
|
||||
@@ -664,6 +668,12 @@
|
||||
VM_OC_FINALIZE_CLASS | VM_OC_GET_LITERAL) \
|
||||
CBC_OPCODE (CBC_EXT_FINALIZE_ANONYMOUS_CLASS, CBC_NO_FLAG, -2, \
|
||||
VM_OC_FINALIZE_CLASS) \
|
||||
CBC_OPCODE (CBC_EXT_SET_CLASS_FIELD_INIT, CBC_HAS_LITERAL_ARG, 0, \
|
||||
VM_OC_SET_CLASS_FIELD_INIT | VM_OC_GET_LITERAL) \
|
||||
CBC_OPCODE (CBC_EXT_RUN_CLASS_FIELD_INIT, CBC_NO_FLAG, 0, \
|
||||
VM_OC_RUN_CLASS_FIELD_INIT) \
|
||||
CBC_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD, CBC_NO_FLAG, -1, \
|
||||
VM_OC_SET_NEXT_COMPUTED_FIELD | VM_OC_PUT_REFERENCE) \
|
||||
CBC_OPCODE (CBC_EXT_PUSH_SUPER, CBC_NO_FLAG, 1, \
|
||||
VM_OC_NONE) \
|
||||
CBC_OPCODE (CBC_EXT_PUSH_SUPER_CONSTRUCTOR, CBC_NO_FLAG, 1, \
|
||||
|
||||
+115
-44
@@ -433,6 +433,7 @@ lexer_skip_spaces (parser_context_t *context_p) /**< context */
|
||||
} /* lexer_skip_spaces */
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
/**
|
||||
* Skip all the continuous empty statements.
|
||||
*/
|
||||
@@ -450,6 +451,22 @@ lexer_skip_empty_statements (parser_context_t *context_p) /**< context */
|
||||
|
||||
context_p->token.flags = (uint8_t) (context_p->token.flags | LEXER_NO_SKIP_SPACES);
|
||||
} /* lexer_skip_empty_statements */
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
/**
|
||||
* Checks whether the keyword has escape sequences.
|
||||
*/
|
||||
#define LEXER_CHECK_INVALID_KEYWORD(ident_start_p, buffer_p) \
|
||||
(JERRY_UNLIKELY ((ident_start_p) == (buffer_p)) \
|
||||
&& !(context_p->global_status_flags & ECMA_PARSE_INTERNAL_PRE_SCANNING))
|
||||
#else /* !ENABLED (JERRY_ESNEXT) */
|
||||
/**
|
||||
* Checks whether the keyword has escape sequences.
|
||||
*/
|
||||
#define LEXER_CHECK_INVALID_KEYWORD(ident_start_p, buffer_p) \
|
||||
(JERRY_UNLIKELY ((ident_start_p) == (buffer_p)))
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/**
|
||||
@@ -807,7 +824,6 @@ lexer_parse_identifier (parser_context_t *context_p, /**< context */
|
||||
JERRY_ASSERT (length > 0);
|
||||
|
||||
context_p->token.type = LEXER_LITERAL;
|
||||
context_p->token.keyword_type = LEXER_EOS;
|
||||
context_p->token.lit_location.type = LEXER_IDENT_LITERAL;
|
||||
context_p->token.lit_location.has_escape = has_escape;
|
||||
|
||||
@@ -865,7 +881,7 @@ lexer_parse_identifier (parser_context_t *context_p, /**< context */
|
||||
|
||||
if (context_p->status_flags & PARSER_DISALLOW_AWAIT_YIELD)
|
||||
{
|
||||
if (ident_start_p == buffer_p)
|
||||
if (LEXER_CHECK_INVALID_KEYWORD (ident_start_p, buffer_p))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD);
|
||||
}
|
||||
@@ -877,7 +893,7 @@ lexer_parse_identifier (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
if (ident_start_p == buffer_p)
|
||||
if (LEXER_CHECK_INVALID_KEYWORD (ident_start_p, buffer_p))
|
||||
{
|
||||
/* Escape sequences are not allowed in a keyword. */
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD);
|
||||
@@ -890,7 +906,7 @@ lexer_parse_identifier (parser_context_t *context_p, /**< context */
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (keyword_p->type == LEXER_KEYW_LET && (context_p->status_flags & PARSER_IS_STRICT))
|
||||
{
|
||||
if (ident_start_p == buffer_p)
|
||||
if (LEXER_CHECK_INVALID_KEYWORD (ident_start_p, buffer_p))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD);
|
||||
}
|
||||
@@ -903,7 +919,7 @@ lexer_parse_identifier (parser_context_t *context_p, /**< context */
|
||||
{
|
||||
if (context_p->status_flags & PARSER_DISALLOW_AWAIT_YIELD)
|
||||
{
|
||||
if (ident_start_p == buffer_p)
|
||||
if (LEXER_CHECK_INVALID_KEYWORD (ident_start_p, buffer_p))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_KEYWORD);
|
||||
}
|
||||
@@ -913,6 +929,11 @@ lexer_parse_identifier (parser_context_t *context_p, /**< context */
|
||||
context_p->token.type = (uint8_t) LEXER_KEYW_YIELD;
|
||||
break;
|
||||
}
|
||||
|
||||
if (keyword_p->type == LEXER_KEYW_ARGUMENTS && (context_p->status_flags & PARSER_INSIDE_CLASS_FIELD))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_ARGUMENTS_IN_CLASS_FIELD);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
if (keyword_p->type >= LEXER_FIRST_FUTURE_STRICT_RESERVED_WORD
|
||||
@@ -944,6 +965,8 @@ lexer_parse_identifier (parser_context_t *context_p, /**< context */
|
||||
return true;
|
||||
} /* lexer_parse_identifier */
|
||||
|
||||
#undef LEXER_CHECK_INVALID_KEYWORD
|
||||
|
||||
/**
|
||||
* Parse string.
|
||||
*/
|
||||
@@ -1118,9 +1141,6 @@ lexer_parse_string (parser_context_t *context_p, /**< context */
|
||||
uint32_t escape_length = (*source_p == LIT_CHAR_LOWERCASE_X) ? 3 : 5;
|
||||
lit_code_point_t code_point = UINT32_MAX;
|
||||
|
||||
context_p->token.line = line;
|
||||
context_p->token.column = (parser_line_counter_t) (column - 1);
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (source_p + 4 <= source_end_p
|
||||
&& source_p[0] == LIT_CHAR_LOWERCASE_U
|
||||
@@ -1142,6 +1162,8 @@ lexer_parse_string (parser_context_t *context_p, /**< context */
|
||||
|
||||
if (code_point == UINT32_MAX)
|
||||
{
|
||||
context_p->token.line = line;
|
||||
context_p->token.column = (parser_line_counter_t) (column - 1);
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_UNICODE_ESCAPE_SEQUENCE);
|
||||
}
|
||||
|
||||
@@ -1312,7 +1334,6 @@ lexer_parse_number (parser_context_t *context_p) /**< context */
|
||||
size_t length;
|
||||
|
||||
context_p->token.type = LEXER_LITERAL;
|
||||
context_p->token.keyword_type = LEXER_EOS;
|
||||
context_p->token.extra_value = LEXER_NUMBER_DECIMAL;
|
||||
context_p->token.lit_location.char_p = source_p;
|
||||
context_p->token.lit_location.type = LEXER_NUMBER_LITERAL;
|
||||
@@ -1571,6 +1592,7 @@ lexer_next_token (parser_context_t *context_p) /**< context */
|
||||
|
||||
lexer_skip_spaces (context_p);
|
||||
|
||||
context_p->token.keyword_type = LEXER_EOS;
|
||||
context_p->token.line = context_p->line;
|
||||
context_p->token.column = context_p->column;
|
||||
|
||||
@@ -2079,6 +2101,33 @@ lexer_consume_generator (parser_context_t *context_p) /**< context */
|
||||
return true;
|
||||
} /* lexer_consume_generator */
|
||||
|
||||
/**
|
||||
* Checks whether the next token is an equal sign and consumes it.
|
||||
*
|
||||
* @return true if the next token is an equal sign
|
||||
*/
|
||||
bool
|
||||
lexer_consume_assign (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
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_EQUALS
|
||||
|| (context_p->source_p + 1 < context_p->source_end_p
|
||||
&& (context_p->source_p[1] == LIT_CHAR_EQUALS || context_p->source_p[1] == LIT_CHAR_GREATER_THAN)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
lexer_consume_next_character (context_p);
|
||||
context_p->token.type = LEXER_ASSIGN;
|
||||
return true;
|
||||
} /* lexer_consume_assign */
|
||||
|
||||
/**
|
||||
* Update await / yield keywords after an arrow function with expression.
|
||||
*/
|
||||
@@ -2409,6 +2458,27 @@ lexer_convert_literal_to_chars (parser_context_t *context_p, /**< context */
|
||||
return destination_start_p;
|
||||
} /* lexer_convert_literal_to_chars */
|
||||
|
||||
/**
|
||||
* Construct an unused literal.
|
||||
*
|
||||
* @return a newly allocated literal
|
||||
*/
|
||||
lexer_literal_t *
|
||||
lexer_construct_unused_literal (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
lexer_literal_t *literal_p;
|
||||
|
||||
if (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
|
||||
}
|
||||
|
||||
literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
|
||||
literal_p->type = LEXER_UNUSED_LITERAL;
|
||||
literal_p->status_flags = 0;
|
||||
return literal_p;
|
||||
} /* lexer_construct_unused_literal */
|
||||
|
||||
/**
|
||||
* Construct a literal object from an identifier.
|
||||
*/
|
||||
@@ -2755,34 +2825,32 @@ lexer_construct_function_object (parser_context_t *context_p, /**< context */
|
||||
lexer_literal_t *literal_p;
|
||||
uint16_t result_index;
|
||||
|
||||
if (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
|
||||
}
|
||||
|
||||
parser_flush_cbc (context_p);
|
||||
|
||||
if (context_p->status_flags & PARSER_INSIDE_WITH)
|
||||
{
|
||||
extra_status_flags |= PARSER_INSIDE_WITH;
|
||||
}
|
||||
|
||||
literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
|
||||
literal_p->type = LEXER_UNUSED_LITERAL;
|
||||
literal_p->status_flags = 0;
|
||||
|
||||
literal_p = lexer_construct_unused_literal (context_p);
|
||||
result_index = context_p->literal_count;
|
||||
context_p->literal_count++;
|
||||
|
||||
parser_flush_cbc (context_p);
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (!(extra_status_flags & PARSER_IS_ARROW_FUNCTION))
|
||||
if (JERRY_LIKELY (!(extra_status_flags & PARSER_IS_ARROW_FUNCTION)))
|
||||
{
|
||||
compiled_code_p = parser_parse_function (context_p, extra_status_flags);
|
||||
}
|
||||
else
|
||||
else if (JERRY_LIKELY (!(extra_status_flags & PARSER_CLASS_CONSTRUCTOR)))
|
||||
{
|
||||
compiled_code_p = parser_parse_arrow_function (context_p, extra_status_flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Since PARSER_IS_ARROW_FUNCTION and PARSER_CLASS_CONSTRUCTOR bits cannot
|
||||
* be set at the same time, this bit combination triggers class field parsing. */
|
||||
compiled_code_p = parser_parse_class_fields (context_p);
|
||||
}
|
||||
#else /* !ENABLED (JERRY_ESNEXT) */
|
||||
compiled_code_p = parser_parse_function (context_p, extra_status_flags);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
@@ -3031,14 +3099,12 @@ lexer_construct_regexp_object (parser_context_t *context_p, /**< context */
|
||||
literal_p->type = literal_type;
|
||||
literal_p->prop.length = (prop_length_t) length;
|
||||
literal_p->status_flags = 0;
|
||||
context_p->literal_count++;
|
||||
|
||||
context_p->token.type = LEXER_LITERAL;
|
||||
context_p->token.keyword_type = LEXER_EOS;
|
||||
context_p->token.lit_location.type = LEXER_REGEXP_LITERAL;
|
||||
|
||||
context_p->lit_object.literal_p = literal_p;
|
||||
context_p->lit_object.index = (uint16_t) (context_p->literal_count - 1);
|
||||
context_p->lit_object.index = context_p->literal_count++;
|
||||
#else /* !ENABLED (JERRY_BUILTIN_REGEXP) */
|
||||
JERRY_UNUSED (parse_only);
|
||||
parser_raise_error (context_p, PARSER_ERR_UNSUPPORTED_REGEXP);
|
||||
@@ -3057,6 +3123,7 @@ lexer_expect_identifier (parser_context_t *context_p, /**< context */
|
||||
|| literal_type == LEXER_NEW_IDENT_LITERAL);
|
||||
|
||||
lexer_skip_spaces (context_p);
|
||||
context_p->token.keyword_type = LEXER_EOS;
|
||||
context_p->token.line = context_p->line;
|
||||
context_p->token.column = context_p->column;
|
||||
|
||||
@@ -3093,7 +3160,6 @@ lexer_expect_identifier (parser_context_t *context_p, /**< context */
|
||||
/* When parsing default exports for modules, it is not required by functions or classes to have identifiers.
|
||||
* In this case we use a synthetic name for them. */
|
||||
context_p->token.type = LEXER_LITERAL;
|
||||
context_p->token.keyword_type = LEXER_EOS;
|
||||
context_p->token.lit_location = lexer_default_literal;
|
||||
lexer_construct_literal_object (context_p, &context_p->token.lit_location, literal_type);
|
||||
context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_DEFAULT_CLASS_OR_FUNC);
|
||||
@@ -3128,16 +3194,14 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */
|
||||
parser_raise_error (context_p, PARSER_ERR_PROPERTY_IDENTIFIER_EXPECTED);
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
int is_class_method = ((ident_opts & LEXER_OBJ_IDENT_CLASS_METHOD)
|
||||
&& !(ident_opts & LEXER_OBJ_IDENT_ONLY_IDENTIFIERS)
|
||||
&& (context_p->token.type != LEXER_KEYW_STATIC));
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
context_p->token.keyword_type = LEXER_EOS;
|
||||
context_p->token.line = context_p->line;
|
||||
context_p->token.column = context_p->column;
|
||||
bool create_literal_object = false;
|
||||
|
||||
JERRY_ASSERT ((ident_opts & LEXER_OBJ_IDENT_CLASS_IDENTIFIER)
|
||||
|| !(ident_opts & LEXER_OBJ_IDENT_CLASS_NO_STATIC));
|
||||
|
||||
if (lexer_parse_identifier (context_p, LEXER_PARSE_NO_OPTS))
|
||||
{
|
||||
if (!(ident_opts & (LEXER_OBJ_IDENT_ONLY_IDENTIFIERS | LEXER_OBJ_IDENT_OBJECT_PATTERN)))
|
||||
@@ -3150,6 +3214,8 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */
|
||||
&& context_p->source_p[0] != LIT_CHAR_COMMA
|
||||
&& context_p->source_p[0] != LIT_CHAR_RIGHT_BRACE
|
||||
&& context_p->source_p[0] != LIT_CHAR_LEFT_PAREN
|
||||
&& context_p->source_p[0] != LIT_CHAR_SEMICOLON
|
||||
&& context_p->source_p[0] != LIT_CHAR_EQUALS
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
&& context_p->source_p[0] != LIT_CHAR_COLON)
|
||||
{
|
||||
@@ -3171,18 +3237,19 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */
|
||||
context_p->token.type = LEXER_KEYW_ASYNC;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ident_opts & LEXER_OBJ_IDENT_CLASS_NO_STATIC)
|
||||
{
|
||||
if (lexer_compare_literal_to_string (context_p, "static", 6))
|
||||
{
|
||||
context_p->token.type = LEXER_KEYW_STATIC;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (is_class_method && lexer_compare_literal_to_string (context_p, "static", 6))
|
||||
{
|
||||
context_p->token.type = LEXER_KEYW_STATIC;
|
||||
return;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
create_literal_object = true;
|
||||
}
|
||||
else
|
||||
@@ -3263,7 +3330,11 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */
|
||||
&& char_p[0] <= LIT_CHAR_9)
|
||||
{
|
||||
lexer_parse_number (context_p);
|
||||
lexer_construct_number_object (context_p, false, false);
|
||||
|
||||
if (!(ident_opts & LEXER_OBJ_IDENT_CLASS_IDENTIFIER))
|
||||
{
|
||||
lexer_construct_number_object (context_p, false, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -3274,10 +3345,8 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */
|
||||
if (create_literal_object)
|
||||
{
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (is_class_method && lexer_compare_literal_to_string (context_p, "constructor", 11))
|
||||
if (ident_opts & LEXER_OBJ_IDENT_CLASS_IDENTIFIER)
|
||||
{
|
||||
context_p->token.type = LEXER_CLASS_CONSTRUCTOR;
|
||||
context_p->token.flags &= (uint8_t) ~LEXER_NO_SKIP_SPACES;
|
||||
return;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
@@ -3300,6 +3369,7 @@ bool
|
||||
lexer_scan_identifier (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
lexer_skip_spaces (context_p);
|
||||
context_p->token.keyword_type = LEXER_EOS;
|
||||
context_p->token.line = context_p->line;
|
||||
context_p->token.column = context_p->column;
|
||||
|
||||
@@ -3309,6 +3379,7 @@ lexer_scan_identifier (parser_context_t *context_p) /**< context */
|
||||
return true;
|
||||
}
|
||||
|
||||
context_p->token.flags |= LEXER_NO_SKIP_SPACES;
|
||||
lexer_next_token (context_p);
|
||||
return false;
|
||||
} /* lexer_scan_identifier */
|
||||
|
||||
@@ -198,7 +198,6 @@ typedef enum
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
LEXER_ASSIGN_GROUP_EXPR, /**< indetifier for the assignment is located in a group expression */
|
||||
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 */
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
@@ -276,8 +275,9 @@ typedef enum
|
||||
{
|
||||
LEXER_OBJ_IDENT_NO_OPTS = (1u << 0), /**< no options */
|
||||
LEXER_OBJ_IDENT_ONLY_IDENTIFIERS = (1u << 1), /**< only identifiers are accepted */
|
||||
LEXER_OBJ_IDENT_CLASS_METHOD = (1u << 2), /**< expect identifier inside a class body */
|
||||
LEXER_OBJ_IDENT_OBJECT_PATTERN = (1u << 3), /**< parse "get"/"set" as string literal in object pattern */
|
||||
LEXER_OBJ_IDENT_CLASS_IDENTIFIER = (1u << 2), /**< expect identifier inside a class body */
|
||||
LEXER_OBJ_IDENT_CLASS_NO_STATIC = (1u << 3), /**< static keyword was not present before the identifier */
|
||||
LEXER_OBJ_IDENT_OBJECT_PATTERN = (1u << 4), /**< parse "get"/"set" as string literal in object pattern */
|
||||
} lexer_obj_ident_opts_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -491,22 +491,6 @@ parser_parse_array_initializer (parser_context_t *context_p, parser_pattern_flag
|
||||
static void
|
||||
parser_parse_object_initializer (parser_context_t *context_p, parser_pattern_flags_t flags);
|
||||
|
||||
/**
|
||||
* Description of "get" literal string.
|
||||
*/
|
||||
static const lexer_lit_location_t lexer_get_literal =
|
||||
{
|
||||
(const uint8_t *) "get", 3, LEXER_STRING_LITERAL, false
|
||||
};
|
||||
|
||||
/**
|
||||
* Description of "set" literal string.
|
||||
*/
|
||||
static const lexer_lit_location_t lexer_set_literal =
|
||||
{
|
||||
(const uint8_t *) "set", 3, LEXER_STRING_LITERAL, false
|
||||
};
|
||||
|
||||
/**
|
||||
* Class literal parsing options.
|
||||
*/
|
||||
@@ -517,6 +501,18 @@ typedef enum
|
||||
PARSER_CLASS_LITERAL_HERTIAGE_PRESENT = (1 << 1), /**< class heritage is present */
|
||||
} parser_class_literal_opts_t;
|
||||
|
||||
/**
|
||||
* Checks whether the current string or identifier literal is constructor
|
||||
*
|
||||
* @return true, if constructor and false otherwise
|
||||
*/
|
||||
static inline bool JERRY_ATTR_ALWAYS_INLINE
|
||||
parser_is_constructor_literal (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
return (LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type)
|
||||
&& lexer_compare_literal_to_string (context_p, "constructor", 11));
|
||||
} /* parser_is_constructor_literal */
|
||||
|
||||
/**
|
||||
* Parse class literal.
|
||||
*/
|
||||
@@ -526,20 +522,11 @@ parser_parse_class_literal (parser_context_t *context_p, /**< context */
|
||||
{
|
||||
JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE);
|
||||
|
||||
uint32_t status_flags = PARSER_FUNCTION_CLOSURE | PARSER_ALLOW_SUPER;
|
||||
|
||||
lexer_literal_t *ctor_literal_p = NULL;
|
||||
|
||||
if (opts & PARSER_CLASS_LITERAL_CTOR_PRESENT)
|
||||
{
|
||||
if (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
|
||||
}
|
||||
|
||||
ctor_literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
|
||||
ctor_literal_p->type = LEXER_UNUSED_LITERAL;
|
||||
ctor_literal_p->status_flags = 0;
|
||||
ctor_literal_p = lexer_construct_unused_literal (context_p);
|
||||
parser_emit_cbc_literal (context_p, CBC_PUSH_LITERAL, (uint16_t) (context_p->literal_count++));
|
||||
}
|
||||
else if (opts & PARSER_CLASS_LITERAL_HERTIAGE_PRESENT)
|
||||
@@ -554,6 +541,7 @@ parser_parse_class_literal (parser_context_t *context_p, /**< context */
|
||||
parser_emit_cbc_ext (context_p, CBC_EXT_INIT_CLASS);
|
||||
|
||||
bool is_static = false;
|
||||
size_t fields_size = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
@@ -562,17 +550,56 @@ parser_parse_class_literal (parser_context_t *context_p, /**< context */
|
||||
lexer_skip_empty_statements (context_p);
|
||||
}
|
||||
|
||||
lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_CLASS_METHOD);
|
||||
lexer_expect_object_literal_id (context_p, (LEXER_OBJ_IDENT_CLASS_IDENTIFIER
|
||||
| (is_static ? 0 : LEXER_OBJ_IDENT_CLASS_NO_STATIC)));
|
||||
|
||||
if (context_p->token.type == LEXER_RIGHT_BRACE)
|
||||
{
|
||||
if (JERRY_UNLIKELY (is_static))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
|
||||
}
|
||||
JERRY_ASSERT (!is_static);
|
||||
break;
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_KEYW_STATIC)
|
||||
{
|
||||
JERRY_ASSERT (!is_static);
|
||||
is_static = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_static && context_p->token.type == LEXER_LITERAL && parser_is_constructor_literal (context_p))
|
||||
{
|
||||
JERRY_ASSERT (!is_static);
|
||||
JERRY_ASSERT (opts & PARSER_CLASS_LITERAL_CTOR_PRESENT);
|
||||
JERRY_ASSERT (ctor_literal_p != NULL);
|
||||
|
||||
if (ctor_literal_p->type == LEXER_FUNCTION_LITERAL)
|
||||
{
|
||||
/* 14.5.1 */
|
||||
parser_raise_error (context_p, PARSER_ERR_MULTIPLE_CLASS_CONSTRUCTORS);
|
||||
}
|
||||
|
||||
uint32_t constructor_status_flags = (PARSER_FUNCTION_CLOSURE
|
||||
| PARSER_ALLOW_SUPER
|
||||
| PARSER_CLASS_CONSTRUCTOR
|
||||
| PARSER_LEXICAL_ENV_NEEDED);
|
||||
|
||||
if (opts & PARSER_CLASS_LITERAL_HERTIAGE_PRESENT)
|
||||
{
|
||||
constructor_status_flags |= PARSER_ALLOW_SUPER_CALL;
|
||||
}
|
||||
|
||||
if (context_p->status_flags & PARSER_INSIDE_WITH)
|
||||
{
|
||||
constructor_status_flags |= PARSER_INSIDE_WITH;
|
||||
}
|
||||
|
||||
parser_flush_cbc (context_p);
|
||||
ecma_compiled_code_t *compiled_code_p = parser_parse_function (context_p, constructor_status_flags);
|
||||
ctor_literal_p->u.bytecode_p = compiled_code_p;
|
||||
ctor_literal_p->type = LEXER_FUNCTION_LITERAL;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool is_computed = false;
|
||||
|
||||
if (context_p->token.type == LEXER_PROPERTY_GETTER || context_p->token.type == LEXER_PROPERTY_SETTER)
|
||||
@@ -580,28 +607,17 @@ parser_parse_class_literal (parser_context_t *context_p, /**< context */
|
||||
uint16_t literal_index, function_literal_index;
|
||||
bool is_getter = (context_p->token.type == LEXER_PROPERTY_GETTER);
|
||||
|
||||
if (lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN))
|
||||
{
|
||||
lexer_construct_literal_object (context_p,
|
||||
(is_getter ? (lexer_lit_location_t *) &lexer_get_literal
|
||||
: (lexer_lit_location_t *) &lexer_set_literal),
|
||||
LEXER_STRING_LITERAL);
|
||||
goto parse_class_method;
|
||||
}
|
||||
|
||||
uint32_t accessor_status_flags = status_flags;
|
||||
uint32_t accessor_status_flags = PARSER_FUNCTION_CLOSURE | PARSER_ALLOW_SUPER;
|
||||
accessor_status_flags |= (is_getter ? PARSER_IS_PROPERTY_GETTER : PARSER_IS_PROPERTY_SETTER);
|
||||
|
||||
lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_CLASS_METHOD | LEXER_OBJ_IDENT_ONLY_IDENTIFIERS);
|
||||
lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_ONLY_IDENTIFIERS);
|
||||
literal_index = context_p->lit_object.index;
|
||||
|
||||
if (context_p->token.type == LEXER_RIGHT_SQUARE)
|
||||
{
|
||||
is_computed = true;
|
||||
}
|
||||
else if (!is_static
|
||||
&& LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type)
|
||||
&& lexer_compare_literal_to_string (context_p, "constructor", 11))
|
||||
else if (!is_static && parser_is_constructor_literal (context_p))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_CLASS_CONSTRUCTOR_AS_ACCESSOR);
|
||||
}
|
||||
@@ -659,45 +675,7 @@ parser_parse_class_literal (parser_context_t *context_p, /**< context */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_static)
|
||||
{
|
||||
if (context_p->token.type == LEXER_KEYW_STATIC)
|
||||
{
|
||||
is_static = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_CLASS_CONSTRUCTOR)
|
||||
{
|
||||
JERRY_ASSERT (opts & PARSER_CLASS_LITERAL_CTOR_PRESENT);
|
||||
JERRY_ASSERT (ctor_literal_p != NULL);
|
||||
|
||||
if (ctor_literal_p->type == LEXER_FUNCTION_LITERAL)
|
||||
{
|
||||
/* 14.5.1 */
|
||||
parser_raise_error (context_p, PARSER_ERR_MULTIPLE_CLASS_CONSTRUCTORS);
|
||||
}
|
||||
|
||||
uint32_t constructor_status_flags = (status_flags
|
||||
| PARSER_CLASS_CONSTRUCTOR
|
||||
| PARSER_LEXICAL_ENV_NEEDED);
|
||||
|
||||
if (opts & PARSER_CLASS_LITERAL_HERTIAGE_PRESENT)
|
||||
{
|
||||
constructor_status_flags |= PARSER_ALLOW_SUPER_CALL;
|
||||
}
|
||||
|
||||
parser_flush_cbc (context_p);
|
||||
ecma_compiled_code_t *compiled_code_p = parser_parse_function (context_p, constructor_status_flags);
|
||||
ctor_literal_p->u.bytecode_p = compiled_code_p;
|
||||
ctor_literal_p->type = LEXER_FUNCTION_LITERAL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION
|
||||
| PARSER_IS_ASYNC_FUNCTION
|
||||
| PARSER_DISALLOW_AWAIT_YIELD);
|
||||
uint32_t status_flags = PARSER_FUNCTION_CLOSURE | PARSER_ALLOW_SUPER;
|
||||
|
||||
if (context_p->token.type == LEXER_KEYW_ASYNC)
|
||||
{
|
||||
@@ -728,15 +706,164 @@ parser_parse_class_literal (parser_context_t *context_p, /**< context */
|
||||
parser_raise_error (context_p, PARSER_ERR_CLASS_STATIC_PROTOTYPE);
|
||||
}
|
||||
}
|
||||
else if ((status_flags & PARSER_IS_GENERATOR_FUNCTION)
|
||||
else if ((status_flags & (PARSER_IS_ASYNC_FUNCTION | PARSER_IS_GENERATOR_FUNCTION))
|
||||
&& lexer_compare_literal_to_string (context_p, "constructor", 11))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_CLASS_CONSTRUCTOR_AS_GENERATOR);
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_CLASS_CONSTRUCTOR);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(status_flags & (PARSER_IS_ASYNC_FUNCTION | PARSER_IS_GENERATOR_FUNCTION)))
|
||||
{
|
||||
if (!is_static && !lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN))
|
||||
{
|
||||
/* Class field. */
|
||||
if (fields_size == 0)
|
||||
{
|
||||
parser_stack_push_uint8 (context_p, PARSER_CLASS_FIELD_END);
|
||||
}
|
||||
|
||||
scanner_range_t range;
|
||||
uint8_t class_field_type = 0;
|
||||
|
||||
if (!is_computed)
|
||||
{
|
||||
range.start_location.source_p = context_p->token.lit_location.char_p;
|
||||
range.start_location.line = context_p->token.line;
|
||||
range.start_location.column = context_p->token.column;
|
||||
class_field_type = PARSER_CLASS_FIELD_NORMAL;
|
||||
|
||||
if (context_p->token.lit_location.type == LEXER_STRING_LITERAL)
|
||||
{
|
||||
range.start_location.source_p--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parser_emit_cbc_ext (context_p, CBC_EXT_ADD_COMPUTED_FIELD);
|
||||
}
|
||||
|
||||
if (lexer_consume_assign (context_p))
|
||||
{
|
||||
class_field_type |= PARSER_CLASS_FIELD_INITIALIZED;
|
||||
|
||||
if (context_p->next_scanner_info_p->source_p != context_p->source_p)
|
||||
{
|
||||
lexer_next_token (context_p);
|
||||
parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
|
||||
parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED);
|
||||
}
|
||||
|
||||
if (is_computed)
|
||||
{
|
||||
scanner_get_location (&range.start_location, context_p);
|
||||
}
|
||||
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END);
|
||||
range.source_end_p = ((scanner_location_info_t *) context_p->next_scanner_info_p)->location.source_p;
|
||||
|
||||
scanner_set_location (context_p, &((scanner_location_info_t *) context_p->next_scanner_info_p)->location);
|
||||
scanner_release_next (context_p, sizeof (scanner_location_info_t));
|
||||
scanner_seek (context_p);
|
||||
|
||||
parser_stack_push (context_p, &range, sizeof (scanner_range_t));
|
||||
fields_size += sizeof (scanner_range_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(context_p->token.flags & LEXER_WAS_NEWLINE)
|
||||
&& !lexer_check_next_characters (context_p, LIT_CHAR_SEMICOLON, LIT_CHAR_RIGHT_BRACE))
|
||||
{
|
||||
lexer_next_token (context_p);
|
||||
parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED);
|
||||
}
|
||||
|
||||
if (!is_computed)
|
||||
{
|
||||
parser_stack_push (context_p, &range.start_location, sizeof (scanner_location_t));
|
||||
fields_size += sizeof (scanner_location_t);
|
||||
}
|
||||
}
|
||||
|
||||
parser_stack_push_uint8 (context_p, class_field_type);
|
||||
fields_size++;
|
||||
is_static = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_computed)
|
||||
{
|
||||
if (context_p->token.lit_location.type != LEXER_NUMBER_LITERAL)
|
||||
{
|
||||
JERRY_ASSERT (context_p->token.lit_location.type == LEXER_IDENT_LITERAL
|
||||
|| context_p->token.lit_location.type == LEXER_STRING_LITERAL);
|
||||
lexer_construct_literal_object (context_p,
|
||||
&context_p->token.lit_location,
|
||||
LEXER_STRING_LITERAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
lexer_construct_number_object (context_p, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_static && !lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN))
|
||||
{
|
||||
if (!is_computed && parser_is_constructor_literal (context_p))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIST_EXPECTED);
|
||||
}
|
||||
|
||||
uint16_t literal_index = context_p->lit_object.index;
|
||||
context_p->status_flags |= PARSER_INSIDE_CLASS_FIELD;
|
||||
|
||||
if (lexer_consume_assign (context_p))
|
||||
{
|
||||
if (context_p->next_scanner_info_p->source_p != context_p->source_p)
|
||||
{
|
||||
lexer_next_token (context_p);
|
||||
parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
|
||||
parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED);
|
||||
}
|
||||
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END);
|
||||
|
||||
/* Changing the source_end_p prevents the lexer to process the name of the next class field
|
||||
* as normal token which may cause issues if the name is also a keyword (e.g. var). */
|
||||
const uint8_t *source_end_p = context_p->source_end_p;
|
||||
context_p->source_end_p = ((scanner_location_info_t *) context_p->next_scanner_info_p)->location.source_p;
|
||||
scanner_release_next (context_p, sizeof (scanner_location_info_t));
|
||||
|
||||
lexer_next_token (context_p);
|
||||
parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
|
||||
|
||||
if (context_p->token.type != LEXER_EOS)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED);
|
||||
}
|
||||
|
||||
context_p->source_end_p = source_end_p;
|
||||
}
|
||||
else
|
||||
{
|
||||
parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED);
|
||||
}
|
||||
|
||||
if (!is_computed)
|
||||
{
|
||||
parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_STATIC_PROPERTY, literal_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
parser_emit_cbc_ext (context_p, CBC_EXT_SET_STATIC_COMPUTED_PROPERTY);
|
||||
}
|
||||
|
||||
context_p->status_flags &= (uint32_t) ~PARSER_INSIDE_CLASS_FIELD;
|
||||
is_static = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
parse_class_method:
|
||||
; /* Empty statement to make compiler happy. */
|
||||
uint16_t literal_index = context_p->lit_object.index;
|
||||
uint16_t function_literal_index = lexer_construct_function_object (context_p, status_flags | PARSER_IS_METHOD);
|
||||
|
||||
@@ -769,6 +896,17 @@ parse_class_method:
|
||||
context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY;
|
||||
}
|
||||
}
|
||||
|
||||
if (fields_size > 0)
|
||||
{
|
||||
parser_reverse_class_fields (context_p, fields_size);
|
||||
|
||||
/* Since PARSER_IS_ARROW_FUNCTION and PARSER_CLASS_CONSTRUCTOR bits cannot
|
||||
* be set at the same time, this bit combination triggers class field parsing. */
|
||||
uint16_t function_literal_index = lexer_construct_function_object (context_p, (PARSER_IS_ARROW_FUNCTION
|
||||
| PARSER_CLASS_CONSTRUCTOR));
|
||||
parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_FIELD_INIT, function_literal_index);
|
||||
}
|
||||
} /* parser_parse_class_literal */
|
||||
|
||||
/**
|
||||
@@ -1813,7 +1951,9 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
|
||||
|
||||
uint32_t arrow_status_flags = (PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION);
|
||||
uint32_t arrow_status_flags = (PARSER_IS_FUNCTION
|
||||
| PARSER_IS_ARROW_FUNCTION
|
||||
| (context_p->status_flags & PARSER_INSIDE_CLASS_FIELD));
|
||||
|
||||
if (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_ASYNC)
|
||||
{
|
||||
@@ -2073,7 +2213,10 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
|
||||
|
||||
parser_check_assignment_expr (context_p);
|
||||
|
||||
parser_parse_function_expression (context_p, PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION);
|
||||
uint32_t arrow_status_flags = (PARSER_IS_FUNCTION
|
||||
| PARSER_IS_ARROW_FUNCTION
|
||||
| (context_p->status_flags & PARSER_INSIDE_CLASS_FIELD));
|
||||
parser_parse_function_expression (context_p, arrow_status_flags);
|
||||
return parser_abort_parsing_after_assignment_expression (context_p);
|
||||
}
|
||||
case LEXER_KEYW_YIELD:
|
||||
@@ -3442,11 +3585,6 @@ parser_parse_object_initializer (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
|
||||
parser_reparse_as_common_identifier (context_p, start_line, start_column);
|
||||
lexer_next_token (context_p);
|
||||
|
||||
JERRY_ASSERT (context_p->token.type == LEXER_RIGHT_BRACE
|
||||
|| context_p->token.type == LEXER_ASSIGN
|
||||
|| context_p->token.type == LEXER_COMMA);
|
||||
|
||||
if (flags & PARSER_PATTERN_ARGUMENTS)
|
||||
{
|
||||
@@ -3462,6 +3600,12 @@ parser_parse_object_initializer (parser_context_t *context_p, /**< context */
|
||||
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
|
||||
|
||||
parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);
|
||||
|
||||
lexer_next_token (context_p);
|
||||
JERRY_ASSERT (context_p->token.type == LEXER_RIGHT_BRACE
|
||||
|| context_p->token.type == LEXER_ASSIGN
|
||||
|| context_p->token.type == LEXER_COMMA);
|
||||
|
||||
parser_pattern_form_assignment (context_p, flags, push_prop_opcode, prop_index, start_line);
|
||||
}
|
||||
|
||||
|
||||
@@ -69,16 +69,17 @@ typedef enum
|
||||
PARSER_FUNCTION_HAS_REST_PARAM = (1u << 19), /**< function has rest parameter */
|
||||
PARSER_CLASS_CONSTRUCTOR = (1u << 20), /**< a class constructor is parsed
|
||||
* Note: PARSER_ALLOW_SUPER must be present */
|
||||
/* These three status flags must be in this order. See PARSER_SAVED_FLAGS_OFFSET. */
|
||||
/* These four status flags must be in this order. See PARSER_SAVED_FLAGS_OFFSET. */
|
||||
PARSER_ALLOW_SUPER = (1u << 21), /**< allow super property access */
|
||||
PARSER_ALLOW_SUPER_CALL = (1u << 22), /**< allow super constructor call
|
||||
* Note: PARSER_CLASS_CONSTRUCTOR must be present */
|
||||
PARSER_ALLOW_NEW_TARGET = (1u << 23), /**< allow new.target parsing in the current context */
|
||||
PARSER_IS_METHOD = (1u << 24), /**< method is parsed */
|
||||
PARSER_INSIDE_CLASS_FIELD = (1u << 23), /**< a class field is being parsed */
|
||||
PARSER_ALLOW_NEW_TARGET = (1u << 24), /**< allow new.target parsing in the current context */
|
||||
PARSER_IS_METHOD = (1u << 25), /**< method is parsed */
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
#if ENABLED (JERRY_MODULE_SYSTEM)
|
||||
PARSER_MODULE_DEFAULT_CLASS_OR_FUNC = (1u << 25), /**< parsing a function or class default export */
|
||||
PARSER_MODULE_STORE_IDENT = (1u << 26), /**< store identifier of the current export statement */
|
||||
PARSER_MODULE_DEFAULT_CLASS_OR_FUNC = (1u << 26), /**< parsing a function or class default export */
|
||||
PARSER_MODULE_STORE_IDENT = (1u << 27), /**< store identifier of the current export statement */
|
||||
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
|
||||
PARSER_HAS_LATE_LIT_INIT = (1u << 30), /**< there are identifier or string literals which construction
|
||||
* is postponed after the local parser data is freed */
|
||||
@@ -129,6 +130,20 @@ typedef enum
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
} parser_check_context_type_t;
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
/**
|
||||
* Class field bits.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
PARSER_CLASS_FIELD_END = (1u << 0), /**< last class field */
|
||||
PARSER_CLASS_FIELD_NORMAL = (1u << 1), /**< normal (non-computed) class field */
|
||||
PARSER_CLASS_FIELD_INITIALIZED = (1u << 2), /**< class field is initialized */
|
||||
} parser_class_field_type_t;
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/**
|
||||
* Mask for strict mode code
|
||||
*/
|
||||
@@ -704,6 +719,10 @@ void parser_set_continues_to_current_position (parser_context_t *context_p, pars
|
||||
#define parser_emit_cbc_ext_backward_branch(context_p, opcode, offset) \
|
||||
parser_emit_cbc_backward_branch ((context_p), PARSER_TO_EXT_OPCODE (opcode), (offset))
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
void parser_reverse_class_fields (parser_context_t *context_p, size_t fields_size);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
@@ -725,6 +744,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);
|
||||
bool lexer_consume_assign (parser_context_t *context_p);
|
||||
void lexer_update_await_yield (parser_context_t *context_p, uint32_t status_flags);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
void lexer_parse_string (parser_context_t *context_p, lexer_string_options_t opts);
|
||||
@@ -736,7 +756,7 @@ void lexer_convert_ident_to_cesu8 (uint8_t *destination_p, const uint8_t *source
|
||||
const uint8_t *lexer_convert_literal_to_chars (parser_context_t *context_p, const lexer_lit_location_t *literal_p,
|
||||
uint8_t *local_byte_array_p, lexer_string_options_t opts);
|
||||
void lexer_expect_object_literal_id (parser_context_t *context_p, uint32_t ident_opts);
|
||||
uint16_t scanner_save_literal (parser_context_t *context_p, uint16_t ident_index);
|
||||
lexer_literal_t *lexer_construct_unused_literal (parser_context_t *context_p);
|
||||
void lexer_construct_literal_object (parser_context_t *context_p, const lexer_lit_location_t *lit_location_p,
|
||||
uint8_t literal_type);
|
||||
bool lexer_construct_number_object (parser_context_t *context_p, bool is_expr, bool is_negative_number);
|
||||
@@ -804,6 +824,7 @@ void scanner_get_location (scanner_location_t *location_p, parser_context_t *con
|
||||
void scanner_set_location (parser_context_t *context_p, scanner_location_t *location_p);
|
||||
uint16_t scanner_decode_map_to (parser_scope_stack_t *stack_item_p);
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
uint16_t scanner_save_literal (parser_context_t *context_p, uint16_t ident_index);
|
||||
bool scanner_literal_is_const_reg (parser_context_t *context_p, uint16_t literal_index);
|
||||
bool scanner_literal_is_created (parser_context_t *context_p, uint16_t literal_index);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
@@ -859,6 +880,7 @@ void parser_module_add_names_to_node (parser_context_t *context_p,
|
||||
ecma_compiled_code_t *parser_parse_function (parser_context_t *context_p, uint32_t status_flags);
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ecma_compiled_code_t *parser_parse_arrow_function (parser_context_t *context_p, uint32_t status_flags);
|
||||
ecma_compiled_code_t *parser_parse_class_fields (parser_context_t *context_p);
|
||||
void parser_set_function_name (parser_context_t *context_p, uint16_t function_literal_index, uint16_t name_index,
|
||||
uint32_t status_flags);
|
||||
void parser_compiled_code_set_function_name (parser_context_t *context_p, ecma_compiled_code_t *bytecode_p,
|
||||
|
||||
@@ -790,6 +790,78 @@ parser_set_continues_to_current_position (parser_context_t *context_p, /**< cont
|
||||
}
|
||||
} /* parser_set_continues_to_current_position */
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
/**
|
||||
* Reverse the field list of a class
|
||||
*/
|
||||
void
|
||||
parser_reverse_class_fields (parser_context_t *context_p, /**< context */
|
||||
size_t fields_size) /**< size of consumed memory */
|
||||
{
|
||||
uint8_t *data_p = (uint8_t *) parser_malloc (context_p, fields_size);
|
||||
uint8_t *data_end_p = data_p + fields_size;
|
||||
uint8_t *current_p = data_p;
|
||||
parser_stack_iterator_t iterator;
|
||||
|
||||
parser_stack_iterator_init (context_p, &iterator);
|
||||
|
||||
do
|
||||
{
|
||||
uint8_t class_field_type = parser_stack_iterator_read_uint8 (&iterator);
|
||||
parser_stack_iterator_skip (&iterator, 1);
|
||||
|
||||
if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED)
|
||||
{
|
||||
parser_stack_iterator_read (&iterator, current_p, sizeof (scanner_range_t));
|
||||
parser_stack_iterator_skip (&iterator, sizeof (scanner_range_t));
|
||||
current_p += sizeof (scanner_range_t);
|
||||
}
|
||||
else if (class_field_type & PARSER_CLASS_FIELD_NORMAL)
|
||||
{
|
||||
parser_stack_iterator_read (&iterator, current_p, sizeof (scanner_location_t));
|
||||
parser_stack_iterator_skip (&iterator, sizeof (scanner_location_t));
|
||||
current_p += sizeof (scanner_location_t);
|
||||
}
|
||||
|
||||
*current_p++ = class_field_type;
|
||||
}
|
||||
while (current_p < data_end_p);
|
||||
|
||||
parser_stack_iterator_init (context_p, &iterator);
|
||||
current_p = data_end_p;
|
||||
context_p->stack_top_uint8 = current_p[-1];
|
||||
|
||||
do
|
||||
{
|
||||
uint8_t class_field_type = current_p[-1];
|
||||
|
||||
if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED)
|
||||
{
|
||||
current_p -= sizeof (scanner_range_t) + 1;
|
||||
parser_stack_iterator_write (&iterator, current_p, sizeof (scanner_range_t) + 1);
|
||||
parser_stack_iterator_skip (&iterator, sizeof (scanner_range_t) + 1);
|
||||
}
|
||||
else if (class_field_type & PARSER_CLASS_FIELD_NORMAL)
|
||||
{
|
||||
current_p -= sizeof (scanner_location_t) + 1;
|
||||
parser_stack_iterator_write (&iterator, current_p, sizeof (scanner_location_t) + 1);
|
||||
parser_stack_iterator_skip (&iterator, sizeof (scanner_location_t) + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
current_p--;
|
||||
parser_stack_iterator_write (&iterator, current_p, 1);
|
||||
parser_stack_iterator_skip (&iterator, 1);
|
||||
}
|
||||
}
|
||||
while (current_p > data_p);
|
||||
|
||||
parser_free (data_p, fields_size);
|
||||
} /* parser_reverse_class_fields */
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#if ENABLED (JERRY_ERROR_MESSAGES)
|
||||
/**
|
||||
* Returns with the string representation of the error
|
||||
@@ -1170,9 +1242,9 @@ parser_error_to_string (parser_error_t error) /**< error code */
|
||||
{
|
||||
return "Class constructor may not be an accessor.";
|
||||
}
|
||||
case PARSER_ERR_CLASS_CONSTRUCTOR_AS_GENERATOR:
|
||||
case PARSER_ERR_INVALID_CLASS_CONSTRUCTOR:
|
||||
{
|
||||
return "Class constructor may not be a generator.";
|
||||
return "Class constructor may not be a generator or async function.";
|
||||
}
|
||||
case PARSER_ERR_CLASS_STATIC_PROTOTYPE:
|
||||
{
|
||||
@@ -1182,6 +1254,10 @@ parser_error_to_string (parser_error_t error) /**< error code */
|
||||
{
|
||||
return "Super is not allowed to be used here.";
|
||||
}
|
||||
case PARSER_ERR_ARGUMENTS_IN_CLASS_FIELD:
|
||||
{
|
||||
return "In class field declarations 'arguments' is not allowed.";
|
||||
}
|
||||
case PARSER_ERR_RIGHT_BRACE_EXPECTED:
|
||||
{
|
||||
return "Expected '}' token.";
|
||||
|
||||
@@ -2578,6 +2578,13 @@ parser_parse_function (parser_context_t *context_p, /**< context */
|
||||
parser_raise_error (context_p, PARSER_ERR_ONE_ARGUMENT_EXPECTED);
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if ((context_p->status_flags & (PARSER_CLASS_CONSTRUCTOR | PARSER_ALLOW_SUPER_CALL)) == PARSER_CLASS_CONSTRUCTOR)
|
||||
{
|
||||
parser_emit_cbc_ext (context_p, CBC_EXT_RUN_CLASS_FIELD_INIT);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
|
||||
if (context_p->is_show_opcodes
|
||||
&& (context_p->status_flags & PARSER_HAS_NON_STRICT_ARG))
|
||||
@@ -2712,6 +2719,152 @@ parser_parse_arrow_function (parser_context_t *context_p, /**< context */
|
||||
return compiled_code_p;
|
||||
} /* parser_parse_arrow_function */
|
||||
|
||||
/**
|
||||
* Parse class fields
|
||||
*
|
||||
* @return compiled code
|
||||
*/
|
||||
ecma_compiled_code_t *
|
||||
parser_parse_class_fields (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
parser_saved_context_t saved_context;
|
||||
ecma_compiled_code_t *compiled_code_p;
|
||||
|
||||
JERRY_ASSERT (context_p->token.type == LEXER_RIGHT_BRACE);
|
||||
parser_save_context (context_p, &saved_context);
|
||||
context_p->status_flags |= (PARSER_IS_FUNCTION
|
||||
| PARSER_ALLOW_SUPER
|
||||
| PARSER_INSIDE_CLASS_FIELD
|
||||
| PARSER_ALLOW_NEW_TARGET);
|
||||
|
||||
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
|
||||
if (context_p->is_show_opcodes)
|
||||
{
|
||||
JERRY_DEBUG_MSG ("\n--- Class fields parsing start ---\n\n");
|
||||
}
|
||||
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
|
||||
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
|
||||
{
|
||||
jerry_debugger_send_parse_function (context_p->token.line, context_p->token.column);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
|
||||
const uint8_t *source_end_p = context_p->source_end_p;
|
||||
bool first_computed_class_field = true;
|
||||
scanner_location_t end_location;
|
||||
scanner_get_location (&end_location, context_p);
|
||||
|
||||
do
|
||||
{
|
||||
uint8_t class_field_type = context_p->stack_top_uint8;
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
|
||||
scanner_range_t range;
|
||||
|
||||
if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED)
|
||||
{
|
||||
parser_stack_pop (context_p, &range, sizeof (scanner_range_t));
|
||||
}
|
||||
else if (class_field_type & PARSER_CLASS_FIELD_NORMAL)
|
||||
{
|
||||
parser_stack_pop (context_p, &range.start_location, sizeof (scanner_location_t));
|
||||
}
|
||||
|
||||
uint16_t literal_index = 0;
|
||||
|
||||
if (class_field_type & PARSER_CLASS_FIELD_NORMAL)
|
||||
{
|
||||
scanner_set_location (context_p, &range.start_location);
|
||||
context_p->source_end_p = source_end_p;
|
||||
scanner_seek (context_p);
|
||||
|
||||
lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_ONLY_IDENTIFIERS);
|
||||
|
||||
literal_index = context_p->lit_object.index;
|
||||
|
||||
if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED)
|
||||
{
|
||||
lexer_next_token (context_p);
|
||||
JERRY_ASSERT (context_p->token.type == LEXER_ASSIGN);
|
||||
}
|
||||
}
|
||||
else if (first_computed_class_field)
|
||||
{
|
||||
parser_emit_cbc (context_p, CBC_PUSH_NUMBER_0);
|
||||
first_computed_class_field = false;
|
||||
}
|
||||
|
||||
if (class_field_type & PARSER_CLASS_FIELD_INITIALIZED)
|
||||
{
|
||||
if (!(class_field_type & PARSER_CLASS_FIELD_NORMAL))
|
||||
{
|
||||
scanner_set_location (context_p, &range.start_location);
|
||||
scanner_seek (context_p);
|
||||
}
|
||||
|
||||
context_p->source_end_p = range.source_end_p;
|
||||
lexer_next_token (context_p);
|
||||
parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
|
||||
|
||||
if (context_p->token.type != LEXER_EOS)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_SEMICOLON_EXPECTED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED);
|
||||
}
|
||||
|
||||
if (class_field_type & PARSER_CLASS_FIELD_NORMAL)
|
||||
{
|
||||
parser_emit_cbc_literal (context_p, CBC_ASSIGN_PROP_THIS_LITERAL, literal_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
parser_flush_cbc (context_p);
|
||||
|
||||
/* The next opcode pushes two more temporary values onto the stack */
|
||||
if (context_p->stack_depth + 1 > context_p->stack_limit)
|
||||
{
|
||||
context_p->stack_limit = (uint16_t) (context_p->stack_depth + 1);
|
||||
if (context_p->stack_limit > PARSER_MAXIMUM_STACK_LIMIT)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED);
|
||||
}
|
||||
}
|
||||
|
||||
parser_emit_cbc_ext (context_p, CBC_EXT_SET_NEXT_COMPUTED_FIELD);
|
||||
}
|
||||
}
|
||||
while (context_p->stack_top_uint8 != PARSER_CLASS_FIELD_END);
|
||||
|
||||
if (!first_computed_class_field)
|
||||
{
|
||||
parser_emit_cbc (context_p, CBC_POP);
|
||||
}
|
||||
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
parser_flush_cbc (context_p);
|
||||
context_p->source_end_p = source_end_p;
|
||||
scanner_set_location (context_p, &end_location);
|
||||
|
||||
compiled_code_p = parser_post_processing (context_p);
|
||||
|
||||
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
|
||||
if (context_p->is_show_opcodes)
|
||||
{
|
||||
JERRY_DEBUG_MSG ("\n--- Class fields parsing end ---\n\n");
|
||||
}
|
||||
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
|
||||
|
||||
parser_restore_context (context_p, &saved_context);
|
||||
|
||||
return compiled_code_p;
|
||||
} /* parser_parse_class_fields */
|
||||
|
||||
/**
|
||||
* Check whether the last emitted cbc opcode was an anonymous function declaration
|
||||
*
|
||||
|
||||
@@ -142,9 +142,10 @@ typedef enum
|
||||
|
||||
PARSER_ERR_MULTIPLE_CLASS_CONSTRUCTORS, /**< multiple class constructor */
|
||||
PARSER_ERR_CLASS_CONSTRUCTOR_AS_ACCESSOR, /**< class constructor cannot be an accessor */
|
||||
PARSER_ERR_CLASS_CONSTRUCTOR_AS_GENERATOR, /**< class constructor cannot be a generator */
|
||||
PARSER_ERR_INVALID_CLASS_CONSTRUCTOR, /**< class constructor cannot be a generator or async function */
|
||||
PARSER_ERR_CLASS_STATIC_PROTOTYPE, /**< static method name 'prototype' is not allowed */
|
||||
PARSER_ERR_UNEXPECTED_SUPER_KEYWORD, /**< unexpected super keyword */
|
||||
PARSER_ERR_ARGUMENTS_IN_CLASS_FIELD, /**< arguments is not allowed in class fields */
|
||||
|
||||
PARSER_ERR_RIGHT_BRACE_EXPECTED, /**< right brace expected */
|
||||
PARSER_ERR_OF_EXPECTED, /**< of keyword expected */
|
||||
|
||||
@@ -45,7 +45,8 @@ typedef enum
|
||||
SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS, /**< continue scanning function arguments */
|
||||
SCAN_MODE_BINDING, /**< array or object binding */
|
||||
SCAN_MODE_CLASS_DECLARATION, /**< scanning class declaration */
|
||||
SCAN_MODE_CLASS_METHOD, /**< scanning class method */
|
||||
SCAN_MODE_CLASS_BODY, /**< scanning class body */
|
||||
SCAN_MODE_CLASS_BODY_NO_SCAN, /**< scanning class body without calling lexer_scan_identifier */
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
} scan_modes_t;
|
||||
|
||||
@@ -59,7 +60,7 @@ typedef enum
|
||||
SCAN_STACK_BLOCK_STATEMENT, /**< block statement group */
|
||||
SCAN_STACK_FUNCTION_STATEMENT, /**< function statement */
|
||||
SCAN_STACK_FUNCTION_EXPRESSION, /**< function expression */
|
||||
SCAN_STACK_FUNCTION_PROPERTY, /**< function expression in an object literal or class */
|
||||
SCAN_STACK_FUNCTION_PROPERTY, /**< function expression in an object literal */
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
SCAN_STACK_FUNCTION_ARROW, /**< arrow function expression */
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
@@ -113,6 +114,7 @@ typedef enum
|
||||
SCAN_STACK_CLASS_STATEMENT, /**< class statement */
|
||||
SCAN_STACK_CLASS_EXPRESSION, /**< class expression */
|
||||
SCAN_STACK_CLASS_EXTENDS, /**< class extends expression */
|
||||
SCAN_STACK_CLASS_FIELD_INITIALIZER, /**< class field initializer */
|
||||
SCAN_STACK_FUNCTION_PARAMETERS, /**< function parameter initializer */
|
||||
SCAN_STACK_FOR_START_PATTERN, /**< possible assignment pattern for "for" iterator */
|
||||
SCAN_STACK_USE_ASYNC, /**< an "async" identifier is used */
|
||||
@@ -387,6 +389,7 @@ void scanner_detect_eval_call (parser_context_t *context_p, scanner_context_t *s
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
void scanner_push_class_declaration (parser_context_t *context_p, scanner_context_t *scanner_context_p,
|
||||
uint8_t stack_mode);
|
||||
void scanner_push_class_field_initializer (parser_context_t *context_p, scanner_context_t *scanner_context_p);
|
||||
void scanner_push_destructuring_pattern (parser_context_t *context_p, scanner_context_t *scanner_context_p,
|
||||
uint8_t binding_type, bool is_nested);
|
||||
void scanner_pop_binding_list (scanner_context_t *scanner_context_p);
|
||||
|
||||
@@ -1494,6 +1494,21 @@ scanner_push_class_declaration (parser_context_t *context_p, /**< context */
|
||||
lexer_next_token (context_p);
|
||||
} /* scanner_push_class_declaration */
|
||||
|
||||
/**
|
||||
* Push the start of a class field initializer.
|
||||
*/
|
||||
void
|
||||
scanner_push_class_field_initializer (parser_context_t *context_p, /**< context */
|
||||
scanner_context_t *scanner_context_p) /* scanner context */
|
||||
{
|
||||
scanner_source_start_t source_start;
|
||||
source_start.source_p = context_p->source_p;
|
||||
|
||||
parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t));
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_FIELD_INITIALIZER);
|
||||
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
||||
} /* scanner_push_class_field_initializer */
|
||||
|
||||
/**
|
||||
* Push the values required for destructuring assignment or binding parsing.
|
||||
*/
|
||||
@@ -1658,6 +1673,7 @@ scanner_cleanup (parser_context_t *context_p) /**< context */
|
||||
case SCANNER_TYPE_CASE:
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
case SCANNER_TYPE_INITIALIZER:
|
||||
case SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END:
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
{
|
||||
size = sizeof (scanner_location_info_t);
|
||||
|
||||
@@ -430,6 +430,11 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
{
|
||||
break;
|
||||
}
|
||||
case SCAN_STACK_CLASS_FIELD_INITIALIZER:
|
||||
{
|
||||
scanner_raise_error (context_p);
|
||||
break;
|
||||
}
|
||||
case SCAN_STACK_FUNCTION_PARAMETERS:
|
||||
{
|
||||
scanner_context_p->mode = SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS;
|
||||
@@ -962,7 +967,7 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
break;
|
||||
}
|
||||
|
||||
lexer_next_token (context_p);
|
||||
lexer_scan_identifier (context_p);
|
||||
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
stack_top = (scan_stack_modes_t) context_p->stack_top_uint8;
|
||||
@@ -970,11 +975,33 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
if (stack_top == SCAN_STACK_FUNCTION_PROPERTY)
|
||||
{
|
||||
scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
|
||||
|
||||
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
|
||||
if (stack_top == SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR
|
||||
|| stack_top == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR)
|
||||
{
|
||||
if (context_p->token.type == LEXER_LEFT_PAREN)
|
||||
{
|
||||
scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
|
||||
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
|
||||
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_ASSIGN)
|
||||
{
|
||||
scanner_push_class_field_initializer (context_p, scanner_context_p);
|
||||
return SCAN_NEXT_TOKEN;
|
||||
}
|
||||
|
||||
scanner_context_p->mode = (context_p->token.type != LEXER_SEMICOLON ? SCAN_MODE_CLASS_BODY_NO_SCAN
|
||||
: SCAN_MODE_CLASS_BODY);
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (stack_top == SCAN_STACK_OBJECT_LITERAL
|
||||
|| stack_top == SCAN_STACK_OBJECT_LITERAL_WITH_SUPER);
|
||||
|
||||
@@ -1073,11 +1100,87 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
break;
|
||||
}
|
||||
|
||||
scanner_context_p->mode = SCAN_MODE_CLASS_METHOD;
|
||||
scanner_context_p->mode = SCAN_MODE_CLASS_BODY;
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
case SCAN_STACK_CLASS_FIELD_INITIALIZER:
|
||||
{
|
||||
scanner_source_start_t source_start;
|
||||
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t));
|
||||
|
||||
const uint8_t *source_p = NULL;
|
||||
|
||||
scanner_context_p->mode = SCAN_MODE_CLASS_BODY_NO_SCAN;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case LEXER_SEMICOLON:
|
||||
{
|
||||
source_p = context_p->source_p - 1;
|
||||
scanner_context_p->mode = SCAN_MODE_CLASS_BODY;
|
||||
break;
|
||||
}
|
||||
case LEXER_RIGHT_BRACE:
|
||||
{
|
||||
source_p = context_p->source_p - 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (!(context_p->token.flags & LEXER_WAS_NEWLINE))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == LEXER_LEFT_SQUARE)
|
||||
{
|
||||
source_p = context_p->source_p - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == LEXER_LITERAL)
|
||||
{
|
||||
if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL
|
||||
|| context_p->token.lit_location.type == LEXER_NUMBER_LITERAL)
|
||||
{
|
||||
source_p = context_p->token.lit_location.char_p;
|
||||
}
|
||||
else if (context_p->token.lit_location.type == LEXER_STRING_LITERAL)
|
||||
{
|
||||
source_p = context_p->token.lit_location.char_p - 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == context_p->token.keyword_type && type != LEXER_EOS)
|
||||
{
|
||||
/* Convert keyword to literal. */
|
||||
source_p = context_p->token.lit_location.char_p;
|
||||
context_p->token.type = LEXER_LITERAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (source_p == NULL))
|
||||
{
|
||||
scanner_raise_error (context_p);
|
||||
}
|
||||
|
||||
scanner_location_info_t *location_info_p;
|
||||
location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p,
|
||||
source_start.source_p,
|
||||
sizeof (scanner_location_info_t));
|
||||
location_info_p->info.type = SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END;
|
||||
location_info_p->location.source_p = source_p;
|
||||
location_info_p->location.line = context_p->token.line;
|
||||
location_info_p->location.column = context_p->token.column;
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
case SCAN_STACK_FUNCTION_PARAMETERS:
|
||||
{
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
@@ -2027,7 +2130,7 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
|
||||
if (context_p->stack_top_uint8 == SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR)
|
||||
{
|
||||
scanner_context_p->mode = SCAN_MODE_CLASS_METHOD;
|
||||
scanner_context_p->mode = SCAN_MODE_CLASS_BODY;
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
|
||||
@@ -2337,6 +2440,9 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
|
||||
/* This assignment must be here because of Apple compilers. */
|
||||
context_p->u.scanner_context_p = &scanner_context;
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
context_p->global_status_flags |= ECMA_PARSE_INTERNAL_PRE_SCANNING;
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
parser_stack_init (context_p);
|
||||
|
||||
@@ -2437,18 +2543,20 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
scanner_raise_error (context_p);
|
||||
}
|
||||
|
||||
scanner_context.mode = SCAN_MODE_CLASS_METHOD;
|
||||
scanner_context.mode = SCAN_MODE_CLASS_BODY;
|
||||
/* FALLTHRU */
|
||||
}
|
||||
case SCAN_MODE_CLASS_METHOD:
|
||||
case SCAN_MODE_CLASS_BODY:
|
||||
{
|
||||
lexer_skip_empty_statements (context_p);
|
||||
lexer_scan_identifier (context_p);
|
||||
/* FALLTHRU */
|
||||
}
|
||||
case SCAN_MODE_CLASS_BODY_NO_SCAN:
|
||||
{
|
||||
JERRY_ASSERT (stack_top == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR
|
||||
|| stack_top == SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR);
|
||||
|
||||
lexer_skip_empty_statements (context_p);
|
||||
|
||||
lexer_scan_identifier (context_p);
|
||||
|
||||
if (context_p->token.type == LEXER_RIGHT_BRACE)
|
||||
{
|
||||
scanner_source_start_t source_start;
|
||||
@@ -2476,6 +2584,8 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
break;
|
||||
}
|
||||
|
||||
bool identifier_found = false;
|
||||
|
||||
if (context_p->token.type == LEXER_LITERAL
|
||||
&& LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type)
|
||||
&& lexer_compare_literal_to_string (context_p, "constructor", 11))
|
||||
@@ -2491,13 +2601,12 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR);
|
||||
}
|
||||
}
|
||||
|
||||
if (lexer_token_is_identifier (context_p, "static", 6))
|
||||
else if (lexer_token_is_identifier (context_p, "static", 6))
|
||||
{
|
||||
lexer_scan_identifier (context_p);
|
||||
identifier_found = true;
|
||||
}
|
||||
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
|
||||
scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
|
||||
|
||||
uint16_t literal_pool_flags = SCANNER_LITERAL_POOL_FUNCTION;
|
||||
@@ -2506,9 +2615,11 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
|| lexer_token_is_identifier (context_p, "set", 3))
|
||||
{
|
||||
lexer_scan_identifier (context_p);
|
||||
identifier_found = true;
|
||||
|
||||
if (context_p->token.type == LEXER_LEFT_PAREN)
|
||||
{
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
|
||||
scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION);
|
||||
continue;
|
||||
}
|
||||
@@ -2516,19 +2627,24 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
else if (lexer_token_is_identifier (context_p, "async", 5))
|
||||
{
|
||||
lexer_scan_identifier (context_p);
|
||||
identifier_found = true;
|
||||
|
||||
if (context_p->token.type == LEXER_LEFT_PAREN)
|
||||
if (!(context_p->token.flags & LEXER_WAS_NEWLINE))
|
||||
{
|
||||
scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION);
|
||||
continue;
|
||||
}
|
||||
if (context_p->token.type == LEXER_LEFT_PAREN)
|
||||
{
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
|
||||
scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION);
|
||||
continue;
|
||||
}
|
||||
|
||||
literal_pool_flags |= SCANNER_LITERAL_POOL_ASYNC;
|
||||
literal_pool_flags |= SCANNER_LITERAL_POOL_ASYNC;
|
||||
|
||||
if (context_p->token.type == LEXER_MULTIPLY)
|
||||
{
|
||||
lexer_scan_identifier (context_p);
|
||||
literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR;
|
||||
if (context_p->token.type == LEXER_MULTIPLY)
|
||||
{
|
||||
lexer_scan_identifier (context_p);
|
||||
literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (context_p->token.type == LEXER_MULTIPLY)
|
||||
@@ -2539,23 +2655,63 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
|
||||
if (context_p->token.type == LEXER_LEFT_SQUARE)
|
||||
{
|
||||
if (literal_pool_flags != SCANNER_LITERAL_POOL_FUNCTION)
|
||||
{
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
|
||||
}
|
||||
|
||||
parser_stack_push_uint8 (context_p, SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (literal_pool_flags));
|
||||
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
||||
break;
|
||||
}
|
||||
|
||||
if (context_p->token.type != LEXER_LITERAL)
|
||||
if (context_p->token.type == LEXER_LITERAL)
|
||||
{
|
||||
lexer_scan_identifier (context_p);
|
||||
identifier_found = true;
|
||||
}
|
||||
|
||||
if (!identifier_found)
|
||||
{
|
||||
scanner_raise_error (context_p);
|
||||
}
|
||||
|
||||
if (literal_pool_flags & SCANNER_LITERAL_POOL_GENERATOR)
|
||||
if (context_p->token.type == LEXER_LEFT_PAREN)
|
||||
{
|
||||
context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION;
|
||||
if (literal_pool_flags & SCANNER_LITERAL_POOL_GENERATOR)
|
||||
{
|
||||
context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION;
|
||||
}
|
||||
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
|
||||
scanner_push_literal_pool (context_p, &scanner_context, literal_pool_flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
scanner_push_literal_pool (context_p, &scanner_context, literal_pool_flags);
|
||||
lexer_next_token (context_p);
|
||||
if (literal_pool_flags != SCANNER_LITERAL_POOL_FUNCTION)
|
||||
{
|
||||
scanner_raise_error (context_p);
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_ASSIGN)
|
||||
{
|
||||
scanner_push_class_field_initializer (context_p, &scanner_context);
|
||||
break;
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_SEMICOLON)
|
||||
{
|
||||
scanner_context.mode = SCAN_MODE_CLASS_BODY;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (context_p->token.type != LEXER_RIGHT_BRACE
|
||||
&& !(context_p->token.flags & LEXER_WAS_NEWLINE))
|
||||
{
|
||||
scanner_raise_error (context_p);
|
||||
}
|
||||
|
||||
scanner_context.mode = SCAN_MODE_CLASS_BODY_NO_SCAN;
|
||||
continue;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
@@ -3299,6 +3455,9 @@ scan_completed:
|
||||
PARSER_TRY_END
|
||||
|
||||
context_p->status_flags = scanner_context.context_status_flags;
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
context_p->global_status_flags &= (uint32_t) ~ECMA_PARSE_INTERNAL_PRE_SCANNING;
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
scanner_reverse_info_list (context_p);
|
||||
|
||||
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
|
||||
@@ -3549,6 +3708,12 @@ scan_completed:
|
||||
print_location = false;
|
||||
break;
|
||||
}
|
||||
case SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END:
|
||||
{
|
||||
name_p = "SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END";
|
||||
print_location = true;
|
||||
break;
|
||||
}
|
||||
case SCANNER_TYPE_LET_EXPRESSION:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" LET_EXPRESSION: source:%d\n",
|
||||
|
||||
@@ -48,6 +48,7 @@ typedef enum
|
||||
SCANNER_TYPE_INITIALIZER, /**< destructuring binding or assignment pattern with initializer */
|
||||
SCANNER_TYPE_FOR_PATTERN, /**< assignment pattern for for-in or for-of interators */
|
||||
SCANNER_TYPE_CLASS_CONSTRUCTOR, /**< class constructor */
|
||||
SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END, /**< class field initializer end */
|
||||
SCANNER_TYPE_LET_EXPRESSION, /**< let expression */
|
||||
SCANNER_TYPE_ERR_REDECLARED, /**< syntax error: a variable is redeclared */
|
||||
SCANNER_TYPE_ERR_ASYNC_FUNCTION, /**< an invalid async function follows */
|
||||
@@ -65,6 +66,15 @@ typedef struct
|
||||
parser_line_counter_t column; /**< token start column */
|
||||
} scanner_location_t;
|
||||
|
||||
/**
|
||||
* Source code range with its start and end position.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const uint8_t *source_end_p; /**< end position */
|
||||
scanner_location_t start_location; /**< start location */
|
||||
} scanner_range_t;
|
||||
|
||||
/**
|
||||
* Scanner info blocks which provides information for the parser.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user