mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
The "async" identifier processing is delayed until it is detected that it cannot be part of an arrow expression. The "async" identifier should be processed at this point, but it was not happened in this case. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
597 lines
18 KiB
C
597 lines
18 KiB
C
/* 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.
|
|
*/
|
|
|
|
#include "js-parser-internal.h"
|
|
#include "js-scanner-internal.h"
|
|
#include "lit-char-helpers.h"
|
|
|
|
#if ENABLED (JERRY_PARSER)
|
|
|
|
/** \addtogroup parser Parser
|
|
* @{
|
|
*
|
|
* \addtogroup jsparser JavaScript
|
|
* @{
|
|
*
|
|
* \addtogroup jsparser_scanner Scanner
|
|
* @{
|
|
*/
|
|
|
|
#if ENABLED (JERRY_ESNEXT)
|
|
|
|
/**
|
|
* Add the "async" literal to the literal pool.
|
|
*/
|
|
void
|
|
scanner_add_async_literal (parser_context_t *context_p, /**< context */
|
|
scanner_context_t *scanner_context_p) /**< scanner context */
|
|
{
|
|
lexer_lit_location_t async_literal;
|
|
|
|
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC);
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
parser_stack_pop (context_p, &async_literal, sizeof (lexer_lit_location_t));
|
|
|
|
lexer_lit_location_t *lit_location_p = scanner_add_custom_literal (context_p,
|
|
scanner_context_p->active_literal_pool_p,
|
|
&async_literal);
|
|
|
|
lit_location_p->type |= SCANNER_LITERAL_IS_USED;
|
|
|
|
if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
|
|
{
|
|
lit_location_p->type |= SCANNER_LITERAL_NO_REG;
|
|
}
|
|
} /* scanner_add_async_literal */
|
|
|
|
/**
|
|
* Init scanning the body of an arrow function.
|
|
*/
|
|
static void
|
|
scanner_check_arrow_body (parser_context_t *context_p, /**< context */
|
|
scanner_context_t *scanner_context_p) /**< scanner context */
|
|
{
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_LEFT_BRACE)
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_ARROW_EXPRESSION);
|
|
return;
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_ARROW);
|
|
scanner_check_directives (context_p, scanner_context_p);
|
|
} /* scanner_check_arrow_body */
|
|
|
|
/**
|
|
* Process arrow function with argument list.
|
|
*/
|
|
void
|
|
scanner_check_arrow (parser_context_t *context_p, /**< context */
|
|
scanner_context_t *scanner_context_p) /**< scanner context */
|
|
{
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_ARROW
|
|
|| (context_p->token.flags & LEXER_WAS_NEWLINE))
|
|
{
|
|
if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC)
|
|
{
|
|
scanner_add_async_literal (context_p, scanner_context_p);
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
scanner_pop_literal_pool (context_p, scanner_context_p);
|
|
return;
|
|
}
|
|
|
|
if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC)
|
|
{
|
|
parser_stack_pop (context_p, NULL, sizeof (lexer_lit_location_t) + 1);
|
|
}
|
|
|
|
scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
|
|
uint16_t status_flags = literal_pool_p->status_flags;
|
|
|
|
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 | 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 */
|
|
|
|
/**
|
|
* Process arrow function with a single argument.
|
|
*/
|
|
void
|
|
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 */
|
|
{
|
|
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);
|
|
location_p->type |= SCANNER_LITERAL_IS_ARG;
|
|
|
|
/* Skip the => token, which size is two. */
|
|
context_p->source_p += 2;
|
|
PARSER_PLUS_EQUAL_LC (context_p->column, 2);
|
|
context_p->token.flags = (uint8_t) (context_p->token.flags & ~LEXER_NO_SKIP_SPACES);
|
|
|
|
scanner_check_arrow_body (context_p, scanner_context_p);
|
|
} /* scanner_scan_simple_arrow */
|
|
|
|
/**
|
|
* Process the next argument of a might-be arrow function.
|
|
*/
|
|
void
|
|
scanner_check_arrow_arg (parser_context_t *context_p, /**< context */
|
|
scanner_context_t *scanner_context_p) /**< scanner context */
|
|
{
|
|
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS);
|
|
|
|
const uint8_t *source_p = context_p->source_p;
|
|
bool process_arrow = false;
|
|
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
|
|
if (context_p->token.type == LEXER_THREE_DOTS)
|
|
{
|
|
lexer_next_token (context_p);
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_LITERAL
|
|
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
|
|
if (lexer_check_arrow (context_p))
|
|
{
|
|
process_arrow = true;
|
|
}
|
|
else
|
|
{
|
|
lexer_lit_location_t *argument_literal_p = scanner_append_argument (context_p, scanner_context_p);
|
|
|
|
scanner_detect_eval_call (context_p, scanner_context_p);
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type == LEXER_ASSIGN)
|
|
{
|
|
if (argument_literal_p->type & SCANNER_LITERAL_IS_USED)
|
|
{
|
|
JERRY_ASSERT (argument_literal_p->type & SCANNER_LITERAL_EARLY_CREATE);
|
|
return;
|
|
}
|
|
|
|
scanner_binding_literal_t binding_literal;
|
|
binding_literal.literal_p = argument_literal_p;
|
|
|
|
parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t));
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT);
|
|
return;
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_COMMA || context_p->token.type == LEXER_RIGHT_PAREN)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE)
|
|
{
|
|
scanner_append_hole (context_p, scanner_context_p);
|
|
scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_ARROW_ARG, false);
|
|
|
|
if (context_p->token.type == LEXER_LEFT_BRACE)
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
|
|
scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
|
|
return;
|
|
}
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL);
|
|
scanner_context_p->mode = SCAN_MODE_BINDING;
|
|
lexer_next_token (context_p);
|
|
return;
|
|
}
|
|
|
|
scanner_pop_literal_pool (context_p, scanner_context_p);
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC)
|
|
{
|
|
scanner_add_async_literal (context_p, scanner_context_p);
|
|
}
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_PAREN_EXPRESSION);
|
|
|
|
if (process_arrow)
|
|
{
|
|
scanner_scan_simple_arrow (context_p, scanner_context_p, source_p);
|
|
}
|
|
} /* scanner_check_arrow_arg */
|
|
|
|
/**
|
|
* Detect async functions.
|
|
*
|
|
* @return true, if async is followed by a function keyword, false otherwise
|
|
*/
|
|
bool
|
|
scanner_check_async_function (parser_context_t *context_p, /**< context */
|
|
scanner_context_t *scanner_context_p) /**< scanner context */
|
|
{
|
|
JERRY_ASSERT (lexer_token_is_async (context_p));
|
|
JERRY_ASSERT (scanner_context_p->mode == SCAN_MODE_PRIMARY_EXPRESSION
|
|
|| scanner_context_p->mode == SCAN_MODE_PRIMARY_EXPRESSION_AFTER_NEW);
|
|
JERRY_ASSERT (scanner_context_p->async_source_p != NULL);
|
|
|
|
lexer_lit_location_t async_literal = context_p->token.lit_location;
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (!(context_p->token.flags & LEXER_WAS_NEWLINE))
|
|
{
|
|
if (context_p->token.type == LEXER_KEYW_FUNCTION)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_LITERAL
|
|
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
|
|
{
|
|
if (!lexer_check_arrow (context_p))
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_scan_simple_arrow (context_p, scanner_context_p, scanner_context_p->async_source_p);
|
|
scanner_context_p->async_source_p = NULL;
|
|
return false;
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_LEFT_PAREN)
|
|
{
|
|
parser_stack_push (context_p, &async_literal, sizeof (lexer_lit_location_t));
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_USE_ASYNC);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
lexer_lit_location_t *lit_location_p = scanner_add_custom_literal (context_p,
|
|
scanner_context_p->active_literal_pool_p,
|
|
&async_literal);
|
|
lit_location_p->type |= SCANNER_LITERAL_IS_USED;
|
|
|
|
if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
|
|
{
|
|
lit_location_p->type |= SCANNER_LITERAL_NO_REG;
|
|
}
|
|
|
|
scanner_context_p->async_source_p = NULL;
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
return false;
|
|
} /* scanner_check_async_function */
|
|
|
|
/**
|
|
* Check whether the statement of an if/else construct is a function statement.
|
|
*/
|
|
void
|
|
scanner_check_function_after_if (parser_context_t *context_p, /**< context */
|
|
scanner_context_t *scanner_context_p) /**< scanner context */
|
|
{
|
|
lexer_next_token (context_p);
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT;
|
|
|
|
if (JERRY_UNLIKELY (context_p->token.type == LEXER_KEYW_FUNCTION))
|
|
{
|
|
scanner_literal_pool_t *literal_pool_p;
|
|
literal_pool_p = scanner_push_literal_pool (context_p,
|
|
scanner_context_p,
|
|
SCANNER_LITERAL_POOL_BLOCK);
|
|
|
|
literal_pool_p->source_p = context_p->source_p;
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_PRIVATE_BLOCK);
|
|
}
|
|
} /* scanner_check_function_after_if */
|
|
|
|
/**
|
|
* Arrow types for scanner_scan_bracket() function.
|
|
*/
|
|
typedef enum
|
|
{
|
|
SCANNER_SCAN_BRACKET_NO_ARROW, /**< not an arrow function */
|
|
SCANNER_SCAN_BRACKET_SIMPLE_ARROW, /**< simple arrow function */
|
|
SCANNER_SCAN_BRACKET_ARROW_WITH_ONE_ARG, /**< arrow function with one argument */
|
|
} scanner_scan_bracket_arrow_type_t;
|
|
|
|
#endif /* ENABLED (JERRY_ESNEXT) */
|
|
|
|
/**
|
|
* Scan bracketed expressions.
|
|
*/
|
|
void
|
|
scanner_scan_bracket (parser_context_t *context_p, /**< context */
|
|
scanner_context_t *scanner_context_p) /**< scanner context */
|
|
{
|
|
size_t depth = 0;
|
|
#if ENABLED (JERRY_ESNEXT)
|
|
const uint8_t *arrow_source_p;
|
|
const uint8_t *async_source_p = NULL;
|
|
scanner_scan_bracket_arrow_type_t arrow_type = SCANNER_SCAN_BRACKET_NO_ARROW;
|
|
#endif /* ENABLED (JERRY_ESNEXT) */
|
|
|
|
JERRY_ASSERT (context_p->token.type == LEXER_LEFT_PAREN);
|
|
|
|
do
|
|
{
|
|
#if ENABLED (JERRY_ESNEXT)
|
|
arrow_source_p = context_p->source_p;
|
|
#endif /* ENABLED (JERRY_ESNEXT) */
|
|
depth++;
|
|
lexer_next_token (context_p);
|
|
}
|
|
while (context_p->token.type == LEXER_LEFT_PAREN);
|
|
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
|
|
switch (context_p->token.type)
|
|
{
|
|
case LEXER_LITERAL:
|
|
{
|
|
if (context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
|
|
{
|
|
#if ENABLED (JERRY_ESNEXT)
|
|
arrow_source_p = NULL;
|
|
#endif /* ENABLED (JERRY_ESNEXT) */
|
|
break;
|
|
}
|
|
|
|
#if ENABLED (JERRY_ESNEXT)
|
|
const uint8_t *source_p = context_p->source_p;
|
|
|
|
if (lexer_check_arrow (context_p))
|
|
{
|
|
arrow_source_p = source_p;
|
|
arrow_type = SCANNER_SCAN_BRACKET_SIMPLE_ARROW;
|
|
break;
|
|
}
|
|
|
|
size_t total_depth = depth;
|
|
#endif /* ENABLED (JERRY_ESNEXT) */
|
|
|
|
while (depth > 0 && lexer_check_next_character (context_p, LIT_CHAR_RIGHT_PAREN))
|
|
{
|
|
lexer_consume_next_character (context_p);
|
|
depth--;
|
|
}
|
|
|
|
if (context_p->token.keyword_type == LEXER_KEYW_EVAL
|
|
&& lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN))
|
|
{
|
|
#if ENABLED (JERRY_ESNEXT)
|
|
/* A function call cannot be an eval function. */
|
|
arrow_source_p = NULL;
|
|
#endif /* ENABLED (JERRY_ESNEXT) */
|
|
|
|
scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL;
|
|
break;
|
|
}
|
|
|
|
#if ENABLED (JERRY_ESNEXT)
|
|
if (total_depth == depth)
|
|
{
|
|
if (lexer_check_arrow_param (context_p))
|
|
{
|
|
JERRY_ASSERT (depth > 0);
|
|
depth--;
|
|
break;
|
|
}
|
|
|
|
if (JERRY_UNLIKELY (lexer_token_is_async (context_p)))
|
|
{
|
|
async_source_p = source_p;
|
|
}
|
|
}
|
|
else if (depth == total_depth - 1)
|
|
{
|
|
if (lexer_check_arrow (context_p))
|
|
{
|
|
arrow_type = SCANNER_SCAN_BRACKET_ARROW_WITH_ONE_ARG;
|
|
break;
|
|
}
|
|
|
|
if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC)
|
|
{
|
|
scanner_add_async_literal (context_p, scanner_context_p);
|
|
}
|
|
}
|
|
|
|
arrow_source_p = NULL;
|
|
#endif /* ENABLED (JERRY_ESNEXT) */
|
|
break;
|
|
}
|
|
#if ENABLED (JERRY_ESNEXT)
|
|
case LEXER_THREE_DOTS:
|
|
case LEXER_LEFT_SQUARE:
|
|
case LEXER_LEFT_BRACE:
|
|
case LEXER_RIGHT_PAREN:
|
|
{
|
|
JERRY_ASSERT (depth > 0);
|
|
depth--;
|
|
break;
|
|
}
|
|
#endif /* ENABLED (JERRY_ESNEXT) */
|
|
default:
|
|
{
|
|
#if ENABLED (JERRY_ESNEXT)
|
|
arrow_source_p = NULL;
|
|
#endif /* ENABLED (JERRY_ESNEXT) */
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if ENABLED (JERRY_ESNEXT)
|
|
if (JERRY_UNLIKELY (scanner_context_p->async_source_p != NULL)
|
|
&& (arrow_source_p == NULL || depth > 0))
|
|
{
|
|
scanner_context_p->async_source_p = NULL;
|
|
}
|
|
#endif /* ENABLED (JERRY_ESNEXT) */
|
|
|
|
while (depth > 0)
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_PAREN_EXPRESSION);
|
|
depth--;
|
|
}
|
|
|
|
#if ENABLED (JERRY_ESNEXT)
|
|
if (arrow_source_p != NULL)
|
|
{
|
|
JERRY_ASSERT (async_source_p == NULL);
|
|
|
|
if (arrow_type == SCANNER_SCAN_BRACKET_SIMPLE_ARROW)
|
|
{
|
|
scanner_scan_simple_arrow (context_p, scanner_context_p, arrow_source_p);
|
|
return;
|
|
}
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_ARROW_ARGUMENTS);
|
|
|
|
uint16_t status_flags = 0;
|
|
|
|
if (JERRY_UNLIKELY (scanner_context_p->async_source_p != NULL))
|
|
{
|
|
status_flags |= SCANNER_LITERAL_POOL_ASYNC_ARROW;
|
|
arrow_source_p = scanner_context_p->async_source_p;
|
|
scanner_context_p->async_source_p = NULL;
|
|
}
|
|
|
|
scanner_literal_pool_t *literal_pool_p;
|
|
literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, status_flags);
|
|
literal_pool_p->source_p = arrow_source_p;
|
|
|
|
if (arrow_type == SCANNER_SCAN_BRACKET_ARROW_WITH_ONE_ARG)
|
|
{
|
|
scanner_append_argument (context_p, scanner_context_p);
|
|
scanner_detect_eval_call (context_p, scanner_context_p);
|
|
|
|
context_p->token.type = LEXER_RIGHT_PAREN;
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
|
}
|
|
else if (context_p->token.type == LEXER_RIGHT_PAREN)
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
|
}
|
|
else
|
|
{
|
|
scanner_check_arrow_arg (context_p, scanner_context_p);
|
|
}
|
|
}
|
|
else if (JERRY_UNLIKELY (async_source_p != NULL))
|
|
{
|
|
scanner_context_p->async_source_p = async_source_p;
|
|
scanner_check_async_function (context_p, scanner_context_p);
|
|
}
|
|
#endif /* ENABLED (JERRY_ESNEXT) */
|
|
} /* scanner_scan_bracket */
|
|
|
|
/**
|
|
* Check directives before a source block.
|
|
*/
|
|
void
|
|
scanner_check_directives (parser_context_t *context_p, /**< context */
|
|
scanner_context_t *scanner_context_p) /**< scanner context */
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
|
|
|
|
while (context_p->token.type == LEXER_LITERAL
|
|
&& context_p->token.lit_location.type == LEXER_STRING_LITERAL)
|
|
{
|
|
bool is_use_strict = false;
|
|
|
|
if (lexer_string_is_use_strict (context_p)
|
|
&& !(context_p->status_flags & PARSER_IS_STRICT))
|
|
{
|
|
is_use_strict = true;
|
|
context_p->status_flags |= PARSER_IS_STRICT;
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (!lexer_string_is_directive (context_p))
|
|
{
|
|
if (is_use_strict)
|
|
{
|
|
context_p->status_flags &= (uint32_t) ~PARSER_IS_STRICT;
|
|
}
|
|
|
|
/* The string is part of an expression statement. */
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
break;
|
|
}
|
|
|
|
if (is_use_strict)
|
|
{
|
|
scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_IS_STRICT;
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_SEMICOLON)
|
|
{
|
|
lexer_next_token (context_p);
|
|
}
|
|
}
|
|
} /* scanner_check_directives */
|
|
|
|
/**
|
|
* @}
|
|
* @}
|
|
* @}
|
|
*/
|
|
|
|
#endif /* ENABLED (JERRY_PARSER) */
|