Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Rework export default parsing
- Remove SCANNER_LITERAL_POOL_DEFAULT_CLASS_NAME workaround
- Add async and generator function support
- Fix auto semicolon insertion after export statement
- fixes #4150.

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik [email protected]
  • Loading branch information
rerobika committed Jan 19, 2021
commit cb175b568c73975debb6222fca220ea4ec55f8ba
27 changes: 25 additions & 2 deletions jerry-core/parser/js/js-parser-statm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2535,8 +2535,11 @@ parser_parse_import_statement (parser_context_t *context_p) /**< parser context

/**
* Parse export statement.
*
* @return true - if function of class statement was found
* false - otherwise
*/
static void
static bool
parser_parse_export_statement (parser_context_t *context_p) /**< context */
{
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_EXPORT);
Expand All @@ -2545,6 +2548,8 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */

context_p->module_current_node_p = parser_module_create_module_node (context_p);

bool consume_last_statement = false;

lexer_next_token (context_p);
switch (context_p->token.type)
{
Expand All @@ -2556,15 +2561,26 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */
context_p->status_flags |= PARSER_MODULE_STORE_IDENT;

lexer_next_token (context_p);

if (context_p->token.type == LEXER_LITERAL
&& lexer_token_is_async (context_p)
&& context_p->next_scanner_info_p->source_p == context_p->source_p
&& context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION)
{
lexer_next_token (context_p);
}

if (context_p->token.type == LEXER_KEYW_CLASS)
{
context_p->status_flags |= PARSER_MODULE_DEFAULT_CLASS_OR_FUNC;
parser_parse_class (context_p, true);
consume_last_statement = true;
}
else if (context_p->token.type == LEXER_KEYW_FUNCTION)
{
context_p->status_flags |= PARSER_MODULE_DEFAULT_CLASS_OR_FUNC;
parser_parse_function_statement (context_p);
consume_last_statement = true;
}
else
{
Expand Down Expand Up @@ -2627,12 +2643,14 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */
{
context_p->status_flags |= PARSER_MODULE_STORE_IDENT;
parser_parse_class (context_p, true);
consume_last_statement = true;
break;
}
case LEXER_KEYW_FUNCTION:
{
context_p->status_flags |= PARSER_MODULE_STORE_IDENT;
parser_parse_function_statement (context_p);
consume_last_statement = true;
break;
}
case LEXER_LEFT_BRACE:
Expand All @@ -2656,6 +2674,8 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */
context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_DEFAULT_CLASS_OR_FUNC | PARSER_MODULE_STORE_IDENT);
parser_module_finalize_export_node (context_p);
context_p->module_current_node_p = NULL;

return consume_last_statement;
} /* parser_parse_export_statement */
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */

Expand Down Expand Up @@ -2948,7 +2968,10 @@ parser_parse_statements (parser_context_t *context_p) /**< context */

case LEXER_KEYW_EXPORT:
{
parser_parse_export_statement (context_p);
if (parser_parse_export_statement (context_p))
{
goto consume_last_statement;
}
break;
}
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
Expand Down
8 changes: 3 additions & 5 deletions jerry-core/parser/js/js-scanner-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ typedef enum
SCAN_STACK_FOR_START_PATTERN, /**< possible assignment pattern for "for" iterator */
SCAN_STACK_USE_ASYNC, /**< an "async" identifier is used */
#endif /* ENABLED (JERRY_ESNEXT) */
#if ENABLED (JERRY_MODULE_SYSTEM)
SCAN_STACK_EXPORT_DEFAULT, /**< scan primary expression after export default */
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
} scan_stack_modes_t;

/**
Expand Down Expand Up @@ -337,11 +340,6 @@ typedef enum
#define SCANNER_LITERAL_POOL_MAY_HAVE_ARGUMENTS(status_flags) \
(!((status_flags) & (SCANNER_LITERAL_POOL_CLASS_NAME | SCANNER_LITERAL_POOL_CLASS_FIELD)))

/**
* The class name is the *default* class name
*/
#define SCANNER_LITERAL_POOL_DEFAULT_CLASS_NAME SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE

#else /* !ENABLED (JERRY_ESNEXT) */

/**
Expand Down
55 changes: 40 additions & 15 deletions jerry-core/parser/js/js-scanner-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -640,19 +640,6 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */

parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);

#if ENABLED (JERRY_ESNEXT)
if (JERRY_UNLIKELY (status_flags & SCANNER_LITERAL_POOL_CLASS_NAME))
{
literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator);

if ((literal_p != NULL || (status_flags & SCANNER_LITERAL_POOL_DEFAULT_CLASS_NAME))
&& no_declarations < PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
{
no_declarations++;
}
}
#endif /* ENABLED (JERRY_ESNEXT) */

uint8_t arguments_stream_type = SCANNER_STREAM_TYPE_ARGUMENTS;
const uint8_t *prev_source_p = literal_pool_p->source_p - 1;
lexer_lit_location_t *last_argument_p = NULL;
Expand Down Expand Up @@ -1702,23 +1689,61 @@ scanner_push_class_declaration (parser_context_t *context_p, /**< context */
const uint8_t *source_p = context_p->source_p;
lexer_lit_location_t *literal_p = NULL;

#if ENABLED (JERRY_MODULE_SYSTEM)
bool is_export_default = context_p->stack_top_uint8 == SCAN_STACK_EXPORT_DEFAULT;
JERRY_ASSERT (!is_export_default || stack_mode == SCAN_STACK_CLASS_EXPRESSION);
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */

parser_stack_push_uint8 (context_p, stack_mode);
lexer_next_token (context_p);

bool class_has_name = (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL);

if (stack_mode == SCAN_STACK_CLASS_STATEMENT && class_has_name)
if (class_has_name)
{
literal_p = scanner_add_literal (context_p, scanner_context_p);
if (stack_mode == SCAN_STACK_CLASS_STATEMENT)
{
literal_p = scanner_add_literal (context_p, scanner_context_p);
scanner_context_p->active_literal_pool_p->no_declarations++;
}
#if ENABLED (JERRY_MODULE_SYSTEM)
else if (is_export_default)
{
literal_p = scanner_add_literal (context_p, scanner_context_p);
scanner_context_p->active_literal_pool_p->no_declarations++;

scanner_detect_invalid_let (context_p, literal_p);

if (literal_p->type & SCANNER_LITERAL_IS_USED)
{
literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
}

literal_p->type |= SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_NO_REG;
}
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
}

scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0);

if (class_has_name)
{
scanner_add_literal (context_p, scanner_context_p);
scanner_context_p->active_literal_pool_p->no_declarations++;
}
#if ENABLED (JERRY_MODULE_SYSTEM)
else if (is_export_default)
{
lexer_lit_location_t *name_literal_p;
name_literal_p = scanner_add_custom_literal (context_p,
scanner_context_p->active_literal_pool_p->prev_p,
&lexer_default_literal);

name_literal_p->type |= SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_NO_REG;
scanner_context_p->active_literal_pool_p->no_declarations++;
}
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */

literal_pool_p->source_p = source_p;
literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CLASS_NAME;
Expand Down
149 changes: 71 additions & 78 deletions jerry-core/parser/js/js-scanner.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
case LEXER_KEYW_FUNCTION:
{
uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION;
#if ENABLED (JERRY_MODULE_SYSTEM)
bool is_export_default = stack_top == SCAN_STACK_EXPORT_DEFAULT;
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */

#if ENABLED (JERRY_ESNEXT)
if (scanner_context_p->async_source_p != NULL)
Expand All @@ -121,8 +124,30 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
if (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
{
#if ENABLED (JERRY_MODULE_SYSTEM)
if (is_export_default)
{
lexer_lit_location_t *location_p;
location_p = scanner_add_custom_literal (context_p,
scanner_context_p->active_literal_pool_p->prev_p,
&context_p->token.lit_location);

scanner_detect_invalid_let (context_p, location_p);
location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET;
}
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
lexer_next_token (context_p);
}
#if ENABLED (JERRY_MODULE_SYSTEM)
else if (is_export_default)
{
lexer_lit_location_t *location_p;
location_p = scanner_add_custom_literal (context_p,
scanner_context_p->active_literal_pool_p->prev_p,
&lexer_default_literal);
location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET;
}
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */

parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_EXPRESSION);
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
Expand Down Expand Up @@ -179,7 +204,8 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
scanner_scan_simple_arrow (context_p, scanner_context_p, source_p);
return SCAN_KEEP_TOKEN;
}
else if (JERRY_UNLIKELY (lexer_token_is_async (context_p)))

if (JERRY_UNLIKELY (lexer_token_is_async (context_p)))
{
scanner_context_p->async_source_p = source_p;
scanner_check_async_function (context_p, scanner_context_p);
Expand All @@ -189,6 +215,17 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */

if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
{
#if ENABLED (JERRY_MODULE_SYSTEM)
if (stack_top == SCAN_STACK_EXPORT_DEFAULT)
{
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
location_p->type |= (SCANNER_LITERAL_IS_USED | SCANNER_LITERAL_IS_VAR);
scanner_detect_eval_call (context_p, scanner_context_p);
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
break;
}
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */

scanner_add_reference (context_p, scanner_context_p);
}
/* FALLTHRU */
Expand Down Expand Up @@ -1804,84 +1841,9 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
if (context_p->token.type == LEXER_KEYW_DEFAULT)
{
lexer_next_token (context_p);

if (context_p->token.type == LEXER_KEYW_FUNCTION)
{
lexer_next_token (context_p);
if (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
{
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);

if (location_p->type & SCANNER_LITERAL_IS_LOCAL
&& !(location_p->type & SCANNER_LITERAL_IS_FUNC))
{
scanner_raise_redeclaration_error (context_p);
}
location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET;

lexer_next_token (context_p);
}
else
{
lexer_lit_location_t *location_p;
location_p = scanner_add_custom_literal (context_p,
scanner_context_p->active_literal_pool_p,
&lexer_default_literal);
location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET;
}

scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);

parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_STATEMENT);
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
return SCAN_KEEP_TOKEN;
}

if (context_p->token.type == LEXER_KEYW_CLASS)
{
lexer_lit_location_t *literal_p;
literal_p = scanner_push_class_declaration (context_p, scanner_context_p, SCAN_STACK_CLASS_STATEMENT);

if (literal_p != NULL)
{
scanner_detect_invalid_let (context_p, literal_p);

if (literal_p->type & SCANNER_LITERAL_IS_USED)
{
literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
}

literal_p->type |= SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_NO_REG;
return SCAN_NEXT_TOKEN;
}

literal_p = scanner_add_custom_literal (context_p,
scanner_context_p->active_literal_pool_p,
&lexer_default_literal);

literal_p->type |= SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_NO_REG;
scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_DEFAULT_CLASS_NAME;
return SCAN_KEEP_TOKEN;
}

/* Assignment expression. */
lexer_lit_location_t *location_p;
location_p = scanner_add_custom_literal (context_p,
scanner_context_p->active_literal_pool_p,
&lexer_default_literal);
location_p->type |= SCANNER_LITERAL_IS_VAR;
parser_stack_push_uint8 (context_p, SCAN_STACK_EXPORT_DEFAULT);
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;

if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
{
return SCAN_KEEP_TOKEN;
}

location_p = scanner_add_literal (context_p, scanner_context_p);
location_p->type |= SCANNER_LITERAL_IS_VAR;
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
return SCAN_NEXT_TOKEN;
return SCAN_KEEP_TOKEN;
}

scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
Expand Down Expand Up @@ -2152,6 +2114,16 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */

scanner_pop_literal_pool (context_p, scanner_context_p);
parser_stack_pop_uint8 (context_p);

#if ENABLED (JERRY_MODULE_SYSTEM)
if (context_p->stack_top_uint8 == SCAN_STACK_EXPORT_DEFAULT)
{
terminator_found = true;
parser_stack_pop_uint8 (context_p);
lexer_next_token (context_p);
continue;
}
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
return SCAN_NEXT_TOKEN;
}
case SCAN_STACK_FUNCTION_PROPERTY:
Expand Down Expand Up @@ -2306,6 +2278,17 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
continue;
}
#endif /* ENABLED (JERRY_ESNEXT) */
#if ENABLED (JERRY_MODULE_SYSTEM)
case SCAN_STACK_EXPORT_DEFAULT:
{
parser_stack_pop_uint8 (context_p);
lexer_lit_location_t *location_p = scanner_add_custom_literal (context_p,
scanner_context_p->active_literal_pool_p,
&lexer_default_literal);
location_p->type |= SCANNER_LITERAL_IS_VAR;
continue;
}
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
default:
{
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_TRY_STATEMENT
Expand Down Expand Up @@ -2617,6 +2600,16 @@ scanner_scan_all (parser_context_t *context_p, /**< context */

scanner_context.mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
parser_stack_pop_uint8 (context_p);

#if ENABLED (JERRY_MODULE_SYSTEM)
if (context_p->stack_top_uint8 == SCAN_STACK_EXPORT_DEFAULT)
{
/* The token is kept to disallow consuming a semicolon after it. */
parser_stack_change_last_uint8 (context_p, SCAN_STACK_CLASS_STATEMENT);
scanner_context.mode = SCAN_MODE_STATEMENT_END;
continue;
}
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
break;
}

Expand Down
Loading