mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Implement the core of let/const statement. (#3239)
This patch implements the core part of let/const statements. Redeclarations are correctly detected and separate contexts are correctly created for these statements. Register optimizations are also emplyed whenever possible. Lots of features are still missing: - checking the var statements in eval - const are treated as lets - single statement checks are missing - export declarations are exported as vars, let/const export is not supported JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
4b352758c1
commit
3d797b8836
@ -30,7 +30,7 @@ extern "C"
|
||||
/**
|
||||
* Jerry snapshot format version.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_VERSION (25u)
|
||||
#define JERRY_SNAPSHOT_VERSION (26u)
|
||||
|
||||
/**
|
||||
* Flags for jerry_generate_snapshot and jerry_generate_function_snapshot.
|
||||
|
||||
@ -192,6 +192,8 @@
|
||||
#define PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION 3
|
||||
/* PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION must be <= 4 */
|
||||
#define PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION 4
|
||||
/* PARSER_BLOCK_CONTEXT_STACK_ALLOCATION must be <= 3 */
|
||||
#define PARSER_BLOCK_CONTEXT_STACK_ALLOCATION 1
|
||||
/* PARSER_WITH_CONTEXT_STACK_ALLOCATION must be <= 4 */
|
||||
#define PARSER_WITH_CONTEXT_STACK_ALLOCATION 1
|
||||
/* PARSER_SUPER_CLASS_CONTEXT_STACK_ALLOCATION must be <= 4 */
|
||||
@ -244,6 +246,10 @@
|
||||
VM_OC_PUSH_ELISON | VM_OC_PUT_STACK) \
|
||||
CBC_FORWARD_BRANCH (CBC_BRANCH_IF_STRICT_EQUAL, -1, \
|
||||
VM_OC_BRANCH_IF_STRICT_EQUAL) \
|
||||
CBC_OPCODE (CBC_PUSH_NULL, CBC_NO_FLAG, 1, \
|
||||
VM_OC_PUSH_NULL | VM_OC_PUT_STACK) \
|
||||
CBC_FORWARD_BRANCH (CBC_BLOCK_CREATE_CONTEXT, \
|
||||
PARSER_BLOCK_CONTEXT_STACK_ALLOCATION, VM_OC_BLOCK_CREATE_CONTEXT) \
|
||||
\
|
||||
/* Basic opcodes. Note: These 4 opcodes must me in this order */ \
|
||||
CBC_OPCODE (CBC_PUSH_LITERAL, CBC_HAS_LITERAL_ARG, 1, \
|
||||
@ -260,8 +266,6 @@
|
||||
VM_OC_PUSH_TRUE | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_PUSH_FALSE, CBC_NO_FLAG, 1, \
|
||||
VM_OC_PUSH_FALSE | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_PUSH_NULL, CBC_NO_FLAG, 1, \
|
||||
VM_OC_PUSH_NULL | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_PUSH_THIS, CBC_NO_FLAG, 1, \
|
||||
VM_OC_PUSH_THIS | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_PUSH_NUMBER_0, CBC_NO_FLAG, 1, \
|
||||
@ -302,6 +306,10 @@
|
||||
VM_OC_NONE) \
|
||||
CBC_OPCODE (CBC_INIT_LOCAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
|
||||
VM_OC_NONE) \
|
||||
CBC_OPCODE (CBC_CREATE_VAR_FUNC, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
|
||||
VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \
|
||||
CBC_OPCODE (CBC_SET_VAR_FUNC, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
|
||||
VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \
|
||||
CBC_OPCODE (CBC_SET_BYTECODE_PTR, CBC_NO_FLAG, 0, \
|
||||
VM_OC_NONE) \
|
||||
CBC_OPCODE (CBC_RETURN, CBC_NO_FLAG, -1, \
|
||||
@ -508,8 +516,8 @@
|
||||
VM_OC_SET_SETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL) \
|
||||
CBC_FORWARD_BRANCH (CBC_EXT_TRY_CREATE_CONTEXT, PARSER_TRY_CONTEXT_STACK_ALLOCATION, \
|
||||
VM_OC_TRY) \
|
||||
CBC_OPCODE (CBC_EXT_THROW_REFERENCE_ERROR, CBC_NO_FLAG, 1, \
|
||||
VM_OC_THROW_REFERENCE_ERROR) \
|
||||
CBC_OPCODE (CBC_EXT_TRY_CREATE_ENV, CBC_NO_FLAG, 0, \
|
||||
VM_OC_BLOCK_CREATE_CONTEXT) \
|
||||
CBC_FORWARD_BRANCH (CBC_EXT_CATCH, 1, \
|
||||
VM_OC_CATCH) \
|
||||
CBC_OPCODE (CBC_EXT_PUSH_UNDEFINED_BASE, CBC_NO_FLAG, 1, \
|
||||
@ -554,6 +562,8 @@
|
||||
VM_OC_SET_SETTER | VM_OC_GET_STACK_LITERAL) \
|
||||
CBC_OPCODE (CBC_EXT_RESOLVE_BASE, CBC_NO_FLAG, 0, \
|
||||
VM_OC_RESOLVE_BASE_FOR_CALL) \
|
||||
CBC_OPCODE (CBC_EXT_THROW_REFERENCE_ERROR, CBC_NO_FLAG, 1, \
|
||||
VM_OC_THROW_REFERENCE_ERROR) \
|
||||
\
|
||||
/* Class opcodes */ \
|
||||
CBC_OPCODE (CBC_EXT_INHERIT_AND_SET_CONSTRUCTOR, CBC_NO_FLAG, 0, \
|
||||
|
||||
@ -74,6 +74,9 @@ typedef enum
|
||||
LEXER_FLAG_SOURCE_PTR = (1 << 2), /**< the literal is directly referenced in the source code
|
||||
* (no need to allocate memory) */
|
||||
LEXER_FLAG_LATE_INIT = (1 << 3), /**< initialize this variable after the byte code is freed */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
LEXER_FLAG_GLOBAL = (1 << 4), /**< this local identifier is not a let or const declaration */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
} lexer_literal_status_flags_t;
|
||||
|
||||
/**
|
||||
|
||||
@ -1476,7 +1476,14 @@ lexer_process_char_literal (parser_context_t *context_p, /**< context */
|
||||
{
|
||||
scope_stack_p--;
|
||||
|
||||
if (scope_stack_p->map_from == literal_index)
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
bool cond = (scope_stack_p->map_from == literal_index
|
||||
&& scope_stack_p->map_to != PARSER_SCOPE_STACK_FUNC);
|
||||
#else /* ENABLED (JERRY_ES2015) */
|
||||
bool cond = (scope_stack_p->map_from == literal_index);
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (cond)
|
||||
{
|
||||
JERRY_ASSERT (scope_stack_p->map_to >= PARSER_REGISTER_START
|
||||
|| (literal_p->status_flags & LEXER_FLAG_USED));
|
||||
@ -2322,7 +2329,7 @@ lexer_expect_identifier (parser_context_t *context_p, /**< context */
|
||||
context_p->token.literal_is_reserved = false;
|
||||
context_p->token.lit_location.type = LEXER_IDENT_LITERAL;
|
||||
context_p->token.lit_location.has_escape = false;
|
||||
lexer_construct_literal_object (context_p, &lexer_default_literal, lexer_default_literal.type);
|
||||
lexer_construct_literal_object (context_p, &lexer_default_literal, literal_type);
|
||||
context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_DEFAULT_CLASS_OR_FUNC);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -151,10 +151,6 @@ typedef enum
|
||||
LEXER_COMMA_SEP_LIST, /**< comma separated bracketed expression list */
|
||||
LEXER_SCAN_SWITCH, /**< special value for switch pre-scan */
|
||||
LEXER_CLASS_CONSTRUCTOR, /**< special value for class constructor method */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
LEXER_FOR_IN_OF, /**< special value during for in/of statmenet scanning */
|
||||
LEXER_LITERAL_OF, /**< 'of' literal */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
#if !ENABLED (JERRY_ES2015)
|
||||
/* Future reserved words: these keywords
|
||||
@ -164,6 +160,9 @@ typedef enum
|
||||
LEXER_KEYW_CLASS, /**< class */
|
||||
LEXER_KEYW_EXTENDS, /**< extends */
|
||||
LEXER_KEYW_SUPER, /**< super */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
LEXER_KEYW_LET, /**< let */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
LEXER_KEYW_CONST, /**< const */
|
||||
LEXER_KEYW_EXPORT, /**< export */
|
||||
LEXER_KEYW_IMPORT, /**< import */
|
||||
@ -190,25 +189,13 @@ typedef enum
|
||||
LEXER_KEYW_PACKAGE, /**< package */
|
||||
LEXER_KEYW_PROTECTED, /**< protected */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
/* Context dependent strict reserved words:
|
||||
* See also: ECMA-262 v6, 11.6.2.1 */
|
||||
#define LEXER_FIRST_CONTEXT_DEPENDENT_RESERVED_WORD LEXER_KEYW_STATIC
|
||||
LEXER_KEYW_STATIC, /**< static */
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
/* Context dependent strict reserved words:
|
||||
* See also: ECMA-262 v6, 11.6.2.1 */
|
||||
#define LEXER_FIRST_CONTEXT_DEPENDENT_RESERVED_WORD
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/* Context dependent future strict reserved words:
|
||||
* See also: ECMA-262 v6, 11.6.2.1 */
|
||||
#define LEXER_FIRST_CONTEXT_DEPENDENT_FUTURE_RESERVED_WORD LEXER_KEYW_LET
|
||||
LEXER_KEYW_LET, /**< let */
|
||||
LEXER_KEYW_YIELD, /**< yield */
|
||||
#if !ENABLED (JERRY_ES2015)
|
||||
LEXER_KEYW_STATIC, /**< static */
|
||||
LEXER_KEYW_LET, /**< let */
|
||||
#endif /* !ENABLED (JERRY_ES2015) */
|
||||
LEXER_KEYW_YIELD, /**< yield */
|
||||
LEXER_KEYW_STATIC, /**< static */
|
||||
} lexer_token_type_t;
|
||||
|
||||
#define LEXER_NEWLINE_LS_PS_BYTE_1 0xe2
|
||||
|
||||
@ -595,6 +595,14 @@ parser_parse_class (parser_context_t *context_p, /**< context */
|
||||
JERRY_ASSERT (context_p->token.type == LEXER_LITERAL
|
||||
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
|
||||
parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
class_ident_index = context_p->lit_object.index;
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
|
||||
@ -64,9 +64,10 @@ typedef enum
|
||||
PARSER_DEBUGGER_BREAKPOINT_APPENDED = (1u << 15), /**< pending (unsent) breakpoint
|
||||
* info is available */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
PARSER_FUNCTION_HAS_REST_PARAM = (1u << 16), /**< function has rest parameter */
|
||||
PARSER_IS_ARROW_FUNCTION = (1u << 18), /**< an arrow function is parsed */
|
||||
PARSER_ARROW_PARSE_ARGS = (1u << 19), /**< parse the argument list of an arrow function */
|
||||
PARSER_INSIDE_BLOCK = (1u << 16), /**< script has a lexical environment for let and const */
|
||||
PARSER_IS_ARROW_FUNCTION = (1u << 17), /**< an arrow function is parsed */
|
||||
PARSER_ARROW_PARSE_ARGS = (1u << 18), /**< parse the argument list of an arrow function */
|
||||
PARSER_FUNCTION_HAS_REST_PARAM = (1u << 19), /**< function has rest parameter */
|
||||
/* These four status flags must be in this order. See PARSER_CLASS_PARSE_OPTS_OFFSET. */
|
||||
PARSER_CLASS_CONSTRUCTOR = (1u << 20), /**< a class constructor is parsed (this value must be kept in
|
||||
* in sync with ECMA_PARSE_CLASS_CONSTRUCTOR) */
|
||||
@ -371,8 +372,11 @@ typedef struct parser_saved_context_t
|
||||
parser_mem_data_t literal_pool_data; /**< literal list */
|
||||
parser_scope_stack *scope_stack_p; /**< scope stack */
|
||||
uint16_t scope_stack_size; /**< size of scope stack */
|
||||
uint16_t scope_stack_top; /**< current top of scope stack */
|
||||
uint16_t scope_stack_reg_top; /**< current top register of scope stack */
|
||||
uint16_t scope_stack_top; /**< preserved top of scope stack */
|
||||
uint16_t scope_stack_reg_top; /**< preserved top register of scope stack */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
uint16_t scope_stack_global_end; /**< end of global declarations of a function */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
uint16_t context_stack_depth; /**< current context stack depth */
|
||||
@ -440,6 +444,9 @@ typedef struct
|
||||
uint16_t scope_stack_size; /**< size of scope stack */
|
||||
uint16_t scope_stack_top; /**< current top of scope stack */
|
||||
uint16_t scope_stack_reg_top; /**< current top register of scope stack */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
uint16_t scope_stack_global_end; /**< end of global declarations of a function */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
uint8_t stack_top_uint8; /**< top byte stored on the stack */
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
@ -615,10 +622,6 @@ void parser_parse_super_class_context_end (parser_context_t *context_p, bool is_
|
||||
* @{
|
||||
*/
|
||||
|
||||
void scanner_raise_error (parser_context_t *context_p);
|
||||
void *scanner_malloc (parser_context_t *context_p, size_t size);
|
||||
void scanner_free (void *ptr, size_t size);
|
||||
|
||||
void scanner_release_next (parser_context_t *context_p, size_t size);
|
||||
void scanner_set_active (parser_context_t *context_p);
|
||||
void scanner_release_active (parser_context_t *context_p, size_t size);
|
||||
@ -627,6 +630,7 @@ void scanner_seek (parser_context_t *context_p);
|
||||
void scanner_reverse_info_list (parser_context_t *context_p);
|
||||
void scanner_cleanup (parser_context_t *context_p);
|
||||
|
||||
bool scanner_is_context_needed (parser_context_t *context_p);
|
||||
void scanner_create_variables (parser_context_t *context_p, size_t size);
|
||||
|
||||
void scanner_get_location (scanner_location_t *location_p, parser_context_t *context_p);
|
||||
|
||||
@ -438,7 +438,7 @@ parser_module_parse_import_clause (parser_context_t *context_p) /**< parser cont
|
||||
ecma_string_t *import_name_p = NULL;
|
||||
ecma_string_t *local_name_p = NULL;
|
||||
|
||||
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
|
||||
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL);
|
||||
|
||||
uint16_t import_name_index = context_p->lit_object.index;
|
||||
uint16_t local_name_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS;
|
||||
@ -454,7 +454,7 @@ parser_module_parse_import_clause (parser_context_t *context_p) /**< parser cont
|
||||
parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
|
||||
}
|
||||
|
||||
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
|
||||
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL);
|
||||
|
||||
local_name_index = context_p->lit_object.index;
|
||||
|
||||
|
||||
@ -57,12 +57,18 @@ typedef enum
|
||||
{
|
||||
PARSER_STATEMENT_START,
|
||||
PARSER_STATEMENT_BLOCK,
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
PARSER_STATEMENT_BLOCK_CONTEXT,
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
PARSER_STATEMENT_LABEL,
|
||||
PARSER_STATEMENT_IF,
|
||||
PARSER_STATEMENT_ELSE,
|
||||
/* From switch -> for-in : break target statements */
|
||||
PARSER_STATEMENT_SWITCH,
|
||||
PARSER_STATEMENT_SWITCH_NO_DEFAULT,
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
PARSER_STATEMENT_SWITCH_BLOCK_CONTEXT,
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
/* From do-while -> for->in : continue target statements */
|
||||
PARSER_STATEMENT_DO_WHILE,
|
||||
PARSER_STATEMENT_WHILE,
|
||||
@ -78,6 +84,40 @@ typedef enum
|
||||
PARSER_STATEMENT_TRY,
|
||||
} parser_statement_type_t;
|
||||
|
||||
#if !ENABLED (JERRY_ES2015)
|
||||
|
||||
/**
|
||||
* Get the expected depth of a function call.
|
||||
*/
|
||||
#define JERRY_GET_EXPECTED_DEPTH(context_p) 0
|
||||
|
||||
#else /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
* Get the expected depth of a function call.
|
||||
*/
|
||||
#define JERRY_GET_EXPECTED_DEPTH(context_p) \
|
||||
(((context_p)->status_flags & PARSER_INSIDE_BLOCK) ? PARSER_BLOCK_CONTEXT_STACK_ALLOCATION : 0)
|
||||
|
||||
/**
|
||||
* Block statement.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t scope_stack_top; /**< preserved top of scope stack */
|
||||
uint16_t scope_stack_reg_top; /**< preserved top register of scope stack */
|
||||
} parser_block_statement_t;
|
||||
|
||||
/**
|
||||
* Context of block statement.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
parser_branch_t branch; /**< branch to the end */
|
||||
} parser_block_context_t;
|
||||
|
||||
#endif /* !ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
* Loop statement.
|
||||
*/
|
||||
@ -110,6 +150,10 @@ typedef struct
|
||||
{
|
||||
parser_branch_t default_branch; /**< branch to the default case */
|
||||
parser_branch_node_t *branch_list_p; /**< branches of case statements */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
uint16_t scope_stack_top; /**< preserved top of scope stack */
|
||||
uint16_t scope_stack_reg_top; /**< preserved top register of scope stack */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
} parser_switch_statement_t;
|
||||
|
||||
/**
|
||||
@ -190,8 +234,15 @@ parser_statement_length (uint8_t type) /**< type of statement */
|
||||
{
|
||||
static const uint8_t statement_lengths[] =
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
/* PARSER_STATEMENT_BLOCK */
|
||||
(uint8_t) (sizeof (parser_block_statement_t) + 1),
|
||||
/* PARSER_STATEMENT_BLOCK_CONTEXT */
|
||||
(uint8_t) (sizeof (parser_block_statement_t) + sizeof (parser_block_context_t) + 1),
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
/* PARSER_STATEMENT_BLOCK */
|
||||
1,
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
/* PARSER_STATEMENT_LABEL */
|
||||
(uint8_t) (sizeof (parser_label_statement_t) + 1),
|
||||
/* PARSER_STATEMENT_IF */
|
||||
@ -202,6 +253,10 @@ parser_statement_length (uint8_t type) /**< type of statement */
|
||||
(uint8_t) (sizeof (parser_switch_statement_t) + sizeof (parser_loop_statement_t) + 1),
|
||||
/* PARSER_STATEMENT_SWITCH_NO_DEFAULT */
|
||||
(uint8_t) (sizeof (parser_switch_statement_t) + sizeof (parser_loop_statement_t) + 1),
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
/* PARSER_STATEMENT_SWITCH_BLOCK_CONTEXT */
|
||||
(uint8_t) (sizeof (parser_block_context_t) + 1),
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
/* PARSER_STATEMENT_DO_WHILE */
|
||||
(uint8_t) (sizeof (parser_do_while_statement_t) + sizeof (parser_loop_statement_t) + 1),
|
||||
/* PARSER_STATEMENT_WHILE */
|
||||
@ -293,7 +348,9 @@ parser_parse_enclosed_expr (parser_context_t *context_p) /**< context */
|
||||
static void
|
||||
parser_parse_var_statement (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_VAR);
|
||||
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_VAR
|
||||
|| context_p->token.type == LEXER_KEYW_LET
|
||||
|| context_p->token.type == LEXER_KEYW_CONST);
|
||||
|
||||
while (true)
|
||||
{
|
||||
@ -313,6 +370,14 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
|
||||
parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
lexer_next_token (context_p);
|
||||
|
||||
if (context_p->token.type == LEXER_ASSIGN)
|
||||
@ -368,6 +433,14 @@ parser_parse_function_statement (parser_context_t *context_p) /**< context */
|
||||
JERRY_ASSERT (context_p->token.type == LEXER_LITERAL
|
||||
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
|
||||
parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (context_p->lit_object.type == LEXER_LITERAL_OBJECT_ARGUMENTS)
|
||||
{
|
||||
context_p->status_flags |= PARSER_ARGUMENTS_NOT_NEEDED;
|
||||
@ -1185,6 +1258,33 @@ parser_parse_switch_statement_start (parser_context_t *context_p) /**< context *
|
||||
parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED);
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
switch_statement.scope_stack_top = context_p->scope_stack_top;
|
||||
switch_statement.scope_stack_reg_top = context_p->scope_stack_reg_top;
|
||||
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p - 1)
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK);
|
||||
|
||||
if (scanner_is_context_needed (context_p))
|
||||
{
|
||||
parser_block_context_t block_context;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
parser_emit_cbc_forward_branch (context_p,
|
||||
CBC_BLOCK_CREATE_CONTEXT,
|
||||
&block_context.branch);
|
||||
parser_stack_push (context_p, &block_context, sizeof (parser_block_context_t));
|
||||
parser_stack_push_uint8 (context_p, PARSER_STATEMENT_SWITCH_BLOCK_CONTEXT);
|
||||
}
|
||||
|
||||
scanner_create_variables (context_p, sizeof (scanner_info_t));
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->source_p == context_p->source_p
|
||||
&& context_p->next_scanner_info_p->type == SCANNER_TYPE_SWITCH);
|
||||
|
||||
@ -1201,6 +1301,14 @@ parser_parse_switch_statement_start (parser_context_t *context_p) /**< context *
|
||||
|
||||
parser_emit_cbc (context_p, CBC_POP);
|
||||
parser_flush_cbc (context_p);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
parser_block_statement_t block_statement;
|
||||
block_statement.scope_stack_top = context_p->scope_stack_top;
|
||||
block_statement.scope_stack_reg_top = context_p->scope_stack_reg_top;
|
||||
parser_stack_push (context_p, &block_statement, sizeof (parser_block_statement_t));
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
parser_stack_push_uint8 (context_p, PARSER_STATEMENT_BLOCK);
|
||||
parser_stack_iterator_init (context_p, &context_p->last_statement);
|
||||
return;
|
||||
@ -1349,6 +1457,11 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
|
||||
parser_stack_iterator_skip (&iterator, 1);
|
||||
parser_stack_iterator_read (&iterator, &try_statement, sizeof (parser_try_statement_t));
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
context_p->scope_stack_top = try_statement.scope_stack_top;
|
||||
context_p->scope_stack_reg_top = try_statement.scope_stack_reg_top;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
lexer_next_token (context_p);
|
||||
|
||||
if (try_statement.type == parser_finally_block)
|
||||
@ -1368,8 +1481,10 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
|
||||
|
||||
if (try_statement.type == parser_catch_block)
|
||||
{
|
||||
#if !ENABLED (JERRY_ES2015)
|
||||
context_p->scope_stack_top = try_statement.scope_stack_top;
|
||||
context_p->scope_stack_reg_top = try_statement.scope_stack_reg_top;
|
||||
#endif /* !ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (context_p->token.type != LEXER_KEYW_FINALLY)
|
||||
{
|
||||
@ -1423,12 +1538,18 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
|
||||
bool block_found = false;
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p
|
||||
&& context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK)
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK);
|
||||
#ifndef JERRY_NDEBUG
|
||||
block_found = true;
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
if (scanner_is_context_needed (context_p))
|
||||
{
|
||||
parser_emit_cbc_ext (context_p, CBC_EXT_TRY_CREATE_ENV);
|
||||
}
|
||||
|
||||
scanner_create_variables (context_p, sizeof (scanner_info_t));
|
||||
}
|
||||
|
||||
@ -1474,6 +1595,20 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
|
||||
parser_emit_cbc_ext_forward_branch (context_p,
|
||||
CBC_EXT_FINALLY,
|
||||
&try_statement.branch);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK);
|
||||
|
||||
if (scanner_is_context_needed (context_p))
|
||||
{
|
||||
parser_emit_cbc_ext (context_p, CBC_EXT_TRY_CREATE_ENV);
|
||||
}
|
||||
|
||||
scanner_create_variables (context_p, sizeof (scanner_info_t));
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
}
|
||||
|
||||
lexer_next_token (context_p);
|
||||
@ -1585,6 +1720,9 @@ parser_parse_break_statement (parser_context_t *context_p) /**< context */
|
||||
|| type == PARSER_STATEMENT_FOR_OF
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|| type == PARSER_STATEMENT_WITH
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|| type == PARSER_STATEMENT_BLOCK_CONTEXT
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|| type == PARSER_STATEMENT_TRY)
|
||||
{
|
||||
opcode = CBC_JUMP_FORWARD_EXIT_CONTEXT;
|
||||
@ -1629,6 +1767,9 @@ parser_parse_break_statement (parser_context_t *context_p) /**< context */
|
||||
|| type == PARSER_STATEMENT_FOR_OF
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|| type == PARSER_STATEMENT_WITH
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|| type == PARSER_STATEMENT_BLOCK_CONTEXT
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|| type == PARSER_STATEMENT_TRY)
|
||||
{
|
||||
opcode = CBC_JUMP_FORWARD_EXIT_CONTEXT;
|
||||
@ -1723,6 +1864,9 @@ parser_parse_continue_statement (parser_context_t *context_p) /**< context */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (type == PARSER_STATEMENT_WITH
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|| type == PARSER_STATEMENT_BLOCK_CONTEXT
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|| type == PARSER_STATEMENT_TRY
|
||||
|| for_in_of_was_seen)
|
||||
{
|
||||
@ -1782,6 +1926,9 @@ parser_parse_continue_statement (parser_context_t *context_p) /**< context */
|
||||
}
|
||||
|
||||
if (type == PARSER_STATEMENT_WITH
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|| type == PARSER_STATEMENT_BLOCK_CONTEXT
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|| type == PARSER_STATEMENT_TRY)
|
||||
{
|
||||
opcode = CBC_JUMP_FORWARD_EXIT_CONTEXT;
|
||||
@ -1993,6 +2140,10 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */
|
||||
break;
|
||||
}
|
||||
case LEXER_KEYW_VAR:
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case LEXER_KEYW_LET:
|
||||
case LEXER_KEYW_CONST:
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
{
|
||||
context_p->status_flags |= PARSER_MODULE_STORE_IDENT;
|
||||
parser_parse_var_statement (context_p);
|
||||
@ -2151,7 +2302,10 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
|
||||
lexer_lit_location_t lit_location;
|
||||
uint32_t status_flags = context_p->status_flags;
|
||||
|
||||
JERRY_ASSERT (context_p->stack_depth == 0);
|
||||
JERRY_ASSERT (context_p->stack_depth == JERRY_GET_EXPECTED_DEPTH (context_p));
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (context_p->context_stack_depth == context_p->stack_depth);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
lit_location = context_p->token.lit_location;
|
||||
|
||||
@ -2246,6 +2400,8 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
|
||||
&& context_p->token.type != LEXER_LEFT_BRACE
|
||||
&& context_p->token.type != LEXER_RIGHT_BRACE
|
||||
&& context_p->token.type != LEXER_KEYW_VAR
|
||||
&& context_p->token.type != LEXER_KEYW_LET
|
||||
&& context_p->token.type != LEXER_KEYW_CONST
|
||||
&& context_p->token.type != LEXER_KEYW_FUNCTION
|
||||
&& context_p->token.type != LEXER_KEYW_CASE
|
||||
&& context_p->token.type != LEXER_KEYW_DEFAULT)
|
||||
@ -2265,6 +2421,8 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
|
||||
&& context_p->token.type != LEXER_LEFT_BRACE
|
||||
&& context_p->token.type != LEXER_RIGHT_BRACE
|
||||
&& context_p->token.type != LEXER_KEYW_VAR
|
||||
&& context_p->token.type != LEXER_KEYW_LET
|
||||
&& context_p->token.type != LEXER_KEYW_CONST
|
||||
&& context_p->token.type != LEXER_KEYW_FUNCTION
|
||||
&& context_p->token.type != LEXER_KEYW_CASE
|
||||
&& context_p->token.type != LEXER_KEYW_DEFAULT)
|
||||
@ -2301,13 +2459,49 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
|
||||
|
||||
case LEXER_LEFT_BRACE:
|
||||
{
|
||||
parser_stack_push_uint8 (context_p, PARSER_STATEMENT_BLOCK);
|
||||
uint8_t block_type = PARSER_STATEMENT_BLOCK;
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
parser_block_statement_t block_statement;
|
||||
block_statement.scope_stack_top = context_p->scope_stack_top;
|
||||
block_statement.scope_stack_reg_top = context_p->scope_stack_reg_top;
|
||||
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK);
|
||||
|
||||
if (scanner_is_context_needed (context_p))
|
||||
{
|
||||
parser_block_context_t block_context;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
PARSER_PLUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
parser_emit_cbc_forward_branch (context_p,
|
||||
CBC_BLOCK_CREATE_CONTEXT,
|
||||
&block_context.branch);
|
||||
parser_stack_push (context_p, &block_context, sizeof (parser_block_context_t));
|
||||
block_type = PARSER_STATEMENT_BLOCK_CONTEXT;
|
||||
}
|
||||
|
||||
scanner_create_variables (context_p, sizeof (scanner_info_t));
|
||||
}
|
||||
|
||||
parser_stack_push (context_p, &block_statement, sizeof (parser_block_statement_t));
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
parser_stack_push_uint8 (context_p, block_type);
|
||||
parser_stack_iterator_init (context_p, &context_p->last_statement);
|
||||
lexer_next_token (context_p);
|
||||
continue;
|
||||
}
|
||||
|
||||
case LEXER_KEYW_VAR:
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case LEXER_KEYW_LET:
|
||||
case LEXER_KEYW_CONST:
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
{
|
||||
parser_parse_var_statement (context_p);
|
||||
break;
|
||||
@ -2409,6 +2603,23 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
|
||||
CBC_EXT_TRY_CREATE_CONTEXT,
|
||||
&try_statement.branch);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
try_statement.scope_stack_top = context_p->scope_stack_top;
|
||||
try_statement.scope_stack_reg_top = context_p->scope_stack_reg_top;
|
||||
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK);
|
||||
|
||||
if (scanner_is_context_needed (context_p))
|
||||
{
|
||||
parser_emit_cbc_ext (context_p, CBC_EXT_TRY_CREATE_ENV);
|
||||
}
|
||||
|
||||
scanner_create_variables (context_p, sizeof (scanner_info_t));
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
parser_stack_push (context_p, &try_statement, sizeof (parser_try_statement_t));
|
||||
parser_stack_push_uint8 (context_p, PARSER_STATEMENT_TRY);
|
||||
parser_stack_iterator_init (context_p, &context_p->last_statement);
|
||||
@ -2575,9 +2786,43 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
|
||||
if (context_p->stack_top_uint8 == PARSER_STATEMENT_BLOCK)
|
||||
{
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
parser_block_statement_t block_statement;
|
||||
|
||||
parser_stack_pop (context_p, &block_statement, sizeof (parser_block_statement_t));
|
||||
context_p->scope_stack_top = block_statement.scope_stack_top;
|
||||
context_p->scope_stack_reg_top = block_statement.scope_stack_reg_top;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
parser_stack_iterator_init (context_p, &context_p->last_statement);
|
||||
lexer_next_token (context_p);
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
else if (context_p->stack_top_uint8 == PARSER_STATEMENT_BLOCK_CONTEXT)
|
||||
{
|
||||
parser_block_statement_t block_statement;
|
||||
parser_block_context_t block_context;
|
||||
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
parser_stack_pop (context_p, &block_statement, sizeof (parser_block_statement_t));
|
||||
parser_stack_pop (context_p, &block_context, sizeof (parser_block_context_t));
|
||||
|
||||
context_p->scope_stack_top = block_statement.scope_stack_top;
|
||||
context_p->scope_stack_reg_top = block_statement.scope_stack_reg_top;
|
||||
|
||||
PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
|
||||
#ifndef JERRY_NDEBUG
|
||||
PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
parser_emit_cbc (context_p, CBC_CONTEXT_END);
|
||||
parser_set_branch_to_current_position (context_p, &block_context.branch);
|
||||
|
||||
parser_stack_iterator_init (context_p, &context_p->last_statement);
|
||||
lexer_next_token (context_p);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
else if (context_p->stack_top_uint8 == PARSER_STATEMENT_SWITCH
|
||||
|| context_p->stack_top_uint8 == PARSER_STATEMENT_SWITCH_NO_DEFAULT)
|
||||
{
|
||||
@ -2590,6 +2835,11 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
|
||||
parser_stack_pop (context_p, &switch_statement, sizeof (parser_switch_statement_t));
|
||||
parser_stack_iterator_init (context_p, &context_p->last_statement);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
context_p->scope_stack_top = switch_statement.scope_stack_top;
|
||||
context_p->scope_stack_reg_top = switch_statement.scope_stack_reg_top;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
JERRY_ASSERT (switch_statement.branch_list_p == NULL);
|
||||
|
||||
if (!has_default)
|
||||
@ -2599,6 +2849,26 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
|
||||
|
||||
parser_set_breaks_to_current_position (context_p, loop.branch_list_p);
|
||||
lexer_next_token (context_p);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (context_p->stack_top_uint8 == PARSER_STATEMENT_SWITCH_BLOCK_CONTEXT)
|
||||
{
|
||||
parser_block_context_t block_context;
|
||||
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
parser_stack_pop (context_p, &block_context, sizeof (parser_block_context_t));
|
||||
|
||||
PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
|
||||
#ifndef JERRY_NDEBUG
|
||||
PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
parser_emit_cbc (context_p, CBC_CONTEXT_END);
|
||||
parser_set_branch_to_current_position (context_p, &block_context.branch);
|
||||
|
||||
parser_stack_iterator_init (context_p, &context_p->last_statement);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
}
|
||||
else if (context_p->stack_top_uint8 == PARSER_STATEMENT_TRY)
|
||||
{
|
||||
@ -2762,9 +3032,9 @@ consume_last_statement:
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_ASSERT (context_p->stack_depth == 0);
|
||||
JERRY_ASSERT (context_p->stack_depth == JERRY_GET_EXPECTED_DEPTH (context_p));
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (context_p->context_stack_depth == 0);
|
||||
JERRY_ASSERT (context_p->context_stack_depth == context_p->stack_depth);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
|
||||
@ -1117,6 +1117,10 @@ parser_error_to_string (parser_error_t error) /**< error code */
|
||||
{
|
||||
return "Rest parameter may not have a default initializer.";
|
||||
}
|
||||
case PARSER_ERR_VARIABLE_REDECLARED:
|
||||
{
|
||||
return "Local variable is redeclared.";
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
case PARSER_ERR_FILE_NOT_FOUND:
|
||||
|
||||
@ -1813,6 +1813,9 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
|
||||
context.scope_stack_size = 0;
|
||||
context.scope_stack_top = 0;
|
||||
context.scope_stack_reg_top = 0;
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
context.scope_stack_global_end = 0;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
context.context_stack_depth = 0;
|
||||
@ -1896,12 +1899,51 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (context.next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
|
||||
JERRY_ASSERT (context.next_scanner_info_p->source_p == source_p - 1
|
||||
&& context.next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
|
||||
scanner_create_variables (&context, sizeof (scanner_function_info_t));
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (context.next_scanner_info_p->source_p == source_p)
|
||||
{
|
||||
JERRY_ASSERT (context.next_scanner_info_p->type == SCANNER_TYPE_BLOCK);
|
||||
|
||||
if (scanner_is_context_needed (&context))
|
||||
{
|
||||
parser_branch_t branch;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
PARSER_PLUS_EQUAL_U16 (context.context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
parser_emit_cbc_forward_branch (&context,
|
||||
CBC_BLOCK_CREATE_CONTEXT,
|
||||
&branch);
|
||||
|
||||
parser_stack_push (&context, &branch, sizeof (parser_branch_t));
|
||||
context.status_flags |= PARSER_INSIDE_BLOCK;
|
||||
}
|
||||
|
||||
scanner_create_variables (&context, sizeof (scanner_info_t));
|
||||
context.scope_stack_global_end = context.scope_stack_top;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
}
|
||||
|
||||
parser_parse_statements (&context);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (context.status_flags & PARSER_INSIDE_BLOCK)
|
||||
{
|
||||
parser_branch_t branch;
|
||||
parser_stack_pop (&context, &branch, sizeof (parser_branch_t));
|
||||
|
||||
parser_emit_cbc (&context, CBC_CONTEXT_END);
|
||||
parser_set_branch_to_current_position (&context, &branch);
|
||||
parser_flush_cbc (&context);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/* When the parsing is successful, only the
|
||||
* dummy value can be remained on the stack. */
|
||||
JERRY_ASSERT (context.stack_top_uint8 == CBC_MAXIMUM_BYTE_VALUE
|
||||
@ -2022,6 +2064,9 @@ parser_save_context (parser_context_t *context_p, /**< context */
|
||||
saved_context_p->scope_stack_size = context_p->scope_stack_size;
|
||||
saved_context_p->scope_stack_top = context_p->scope_stack_top;
|
||||
saved_context_p->scope_stack_reg_top = context_p->scope_stack_reg_top;
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
saved_context_p->scope_stack_global_end = context_p->scope_stack_global_end;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
saved_context_p->context_stack_depth = context_p->context_stack_depth;
|
||||
@ -2046,6 +2091,9 @@ parser_save_context (parser_context_t *context_p, /**< context */
|
||||
context_p->scope_stack_size = 0;
|
||||
context_p->scope_stack_top = 0;
|
||||
context_p->scope_stack_reg_top = 0;
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
context_p->scope_stack_global_end = 0;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
context_p->context_stack_depth = 0;
|
||||
@ -2087,6 +2135,9 @@ parser_restore_context (parser_context_t *context_p, /**< context */
|
||||
context_p->scope_stack_size = saved_context_p->scope_stack_size;
|
||||
context_p->scope_stack_top = saved_context_p->scope_stack_top;
|
||||
context_p->scope_stack_reg_top = saved_context_p->scope_stack_reg_top;
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
context_p->scope_stack_global_end = saved_context_p->scope_stack_global_end;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
context_p->context_stack_depth = saved_context_p->context_stack_depth;
|
||||
|
||||
@ -112,6 +112,9 @@ typedef enum
|
||||
PARSER_ERR_INVALID_RIGHT_SQUARE, /**< right square must terminate a block */
|
||||
PARSER_ERR_DUPLICATED_LABEL, /**< duplicated label */
|
||||
PARSER_ERR_OBJECT_PROPERTY_REDEFINED, /**< property of object literal redefined */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
PARSER_ERR_VARIABLE_REDECLARED, /**< a variable redeclared */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
PARSER_ERR_MULTIPLE_CLASS_CONSTRUCTORS, /**< multiple class constructor */
|
||||
|
||||
@ -45,8 +45,28 @@ typedef enum
|
||||
SCANNER_LITERAL_IS_VAR = (1 << 2), /**< literal is var */
|
||||
SCANNER_LITERAL_IS_FUNC = (1 << 3), /**< literal is function */
|
||||
SCANNER_LITERAL_NO_REG = (1 << 4), /**< literal cannot be stored in register */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
SCANNER_LITERAL_IS_LET = (1 << 5), /**< literal is let */
|
||||
SCANNER_LITERAL_IS_CONST = (1 << 6), /**< literal is const */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
} scanner_literal_type_flags_t;
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|
||||
/**
|
||||
* Tells whether the literal is let or const declaration.
|
||||
*/
|
||||
#define SCANNER_LITERAL_IS_LET_OR_CONST (SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_IS_CONST)
|
||||
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
* No literal is let or const declaration in ECMAScript 5.1.
|
||||
*/
|
||||
#define SCANNER_LITERAL_IS_LET_OR_CONST 0
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
* For statement descriptor.
|
||||
*/
|
||||
@ -112,6 +132,14 @@ struct scanner_context_t
|
||||
scanner_info_t *end_arguments_p; /**< position of end arguments */
|
||||
};
|
||||
|
||||
void scanner_raise_error (parser_context_t *context_p);
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
void scanner_raise_redeclaration_error (parser_context_t *context_p);
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
void *scanner_malloc (parser_context_t *context_p, size_t size);
|
||||
void scanner_free (void *ptr, size_t size);
|
||||
|
||||
size_t scanner_get_stream_size (scanner_info_t *info_p, size_t size);
|
||||
scanner_info_t *scanner_insert_info (parser_context_t *context_p, const uint8_t *source_p, size_t size);
|
||||
scanner_info_t *scanner_insert_info_before (parser_context_t *context_p, const uint8_t *source_p,
|
||||
@ -119,14 +147,22 @@ scanner_info_t *scanner_insert_info_before (parser_context_t *context_p, const u
|
||||
scanner_literal_pool_t *scanner_push_literal_pool (parser_context_t *context_p, scanner_context_t *scanner_context_p,
|
||||
uint16_t status_flags);
|
||||
void scanner_pop_literal_pool (parser_context_t *context_p, scanner_context_t *scanner_context_p);
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
void scanner_construct_global_block (parser_context_t *context_p, scanner_context_t *scanner_context_p);
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
void scanner_filter_arguments (parser_context_t *context_p, scanner_context_t *scanner_context_p);
|
||||
lexer_lit_location_t *scanner_add_custom_literal (parser_context_t *context_p, scanner_literal_pool_t *literal_pool_p,
|
||||
const lexer_lit_location_t *literal_location_p);
|
||||
lexer_lit_location_t *scanner_add_literal (parser_context_t *context_p, scanner_context_t *scanner_context_p);
|
||||
void scanner_add_reference (parser_context_t *context_p, scanner_context_t *scanner_context_p);
|
||||
void scanner_append_argument (parser_context_t *context_p, scanner_context_t *scanner_context_p);
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
void scanner_detect_invalid_var (parser_context_t *context_p, scanner_context_t *scanner_context_p,
|
||||
lexer_lit_location_t *var_literal_p);
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
void scanner_detect_eval_call (parser_context_t *context_p, scanner_context_t *scanner_context_p);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@ -43,6 +43,22 @@ scanner_raise_error (parser_context_t *context_p) /**< context */
|
||||
JERRY_ASSERT (0);
|
||||
} /* scanner_raise_error */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|
||||
/**
|
||||
* Raise a variable redeclaration error.
|
||||
*/
|
||||
void
|
||||
scanner_raise_redeclaration_error (parser_context_t *context_p)
|
||||
{
|
||||
scanner_info_t *info_p = scanner_insert_info (context_p, context_p->source_p, sizeof (scanner_info_t));
|
||||
info_p->type = SCANNER_TYPE_ERR_REDECLARED;
|
||||
|
||||
scanner_raise_error (context_p);
|
||||
} /* scanner_raise_redeclaration_error */
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
* Allocate memory for scanner.
|
||||
*
|
||||
@ -94,10 +110,17 @@ scanner_get_stream_size (scanner_info_t *info_p, /**< scanner info block */
|
||||
{
|
||||
switch (data_p[0] & SCANNER_STREAM_TYPE_MASK)
|
||||
{
|
||||
case SCANNER_STREAM_TYPE_VAR:
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case SCANNER_STREAM_TYPE_LET:
|
||||
case SCANNER_STREAM_TYPE_CONST:
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
case SCANNER_STREAM_TYPE_ARG:
|
||||
case SCANNER_STREAM_TYPE_ARG_FUNC:
|
||||
case SCANNER_STREAM_TYPE_VAR:
|
||||
case SCANNER_STREAM_TYPE_FUNC:
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case SCANNER_STREAM_TYPE_VAR_FUNC:
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -404,7 +427,7 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
{
|
||||
search_arguments = false;
|
||||
|
||||
if (type & (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_FUNC))
|
||||
if (type & (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET_OR_CONST))
|
||||
{
|
||||
arguments_required = false;
|
||||
}
|
||||
@ -416,8 +439,16 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
}
|
||||
|
||||
if (((type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG)) && is_function)
|
||||
|| (type & SCANNER_LITERAL_IS_LOCAL))
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (is_function && (type & (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET)) == SCANNER_LITERAL_IS_FUNC)
|
||||
{
|
||||
type = (uint8_t) ((type & ~SCANNER_LITERAL_IS_FUNC) | SCANNER_LITERAL_IS_VAR);
|
||||
literal_p->type = type;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if ((is_function && (type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG)))
|
||||
|| (type & (SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_IS_LET_OR_CONST)))
|
||||
{
|
||||
JERRY_ASSERT (is_function || !(literal_p->type & SCANNER_LITERAL_IS_ARG));
|
||||
|
||||
@ -457,7 +488,7 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
|
||||
prev_source_p = literal_p->char_p + literal_p->length;
|
||||
|
||||
if (is_function || !(type & SCANNER_LITERAL_IS_VAR))
|
||||
if (is_function || !(type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -475,7 +506,15 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
literal_location_p->type |= SCANNER_LITERAL_NO_REG;
|
||||
}
|
||||
|
||||
type = (type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC));
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (literal_location_p->type & SCANNER_LITERAL_IS_LET_OR_CONST)
|
||||
{
|
||||
JERRY_ASSERT (!(type & SCANNER_LITERAL_IS_VAR));
|
||||
type = 0;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
type = (uint8_t) (type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC));
|
||||
JERRY_ASSERT (type == 0 || !is_function);
|
||||
|
||||
literal_location_p->type = (uint8_t) (literal_location_p->type | type);
|
||||
@ -532,21 +571,17 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
data_p += sizeof (scanner_info_t);
|
||||
|
||||
JERRY_ASSERT (prev_literal_pool_p != NULL);
|
||||
if (prev_literal_pool_p->no_declarations < no_declarations)
|
||||
{
|
||||
prev_literal_pool_p->no_declarations = (uint16_t) no_declarations;
|
||||
}
|
||||
}
|
||||
|
||||
parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
|
||||
prev_source_p = literal_pool_p->source_p - 1;
|
||||
no_declarations = 0;
|
||||
no_declarations = literal_pool_p->no_declarations;
|
||||
|
||||
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
|
||||
{
|
||||
if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
|
||||
|| (!((literal_p->type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG)) && is_function)
|
||||
&& !(literal_p->type & SCANNER_LITERAL_IS_LOCAL)))
|
||||
|| (!(is_function && (literal_p->type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG)))
|
||||
&& !(literal_p->type & (SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_IS_LET_OR_CONST))))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -575,6 +610,16 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
{
|
||||
type = SCANNER_STREAM_TYPE_ARG;
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
else if (literal_p->type & SCANNER_LITERAL_IS_LET)
|
||||
{
|
||||
type = SCANNER_STREAM_TYPE_LET;
|
||||
}
|
||||
else if (literal_p->type & SCANNER_LITERAL_IS_CONST)
|
||||
{
|
||||
type = SCANNER_STREAM_TYPE_CONST;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (literal_p->has_escape)
|
||||
{
|
||||
@ -624,12 +669,192 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
JERRY_ASSERT (((uint8_t *) info_p) + compressed_size == data_p + 1);
|
||||
}
|
||||
|
||||
if (!is_function && prev_literal_pool_p->no_declarations < no_declarations)
|
||||
{
|
||||
prev_literal_pool_p->no_declarations = (uint16_t) no_declarations;
|
||||
}
|
||||
|
||||
scanner_context_p->active_literal_pool_p = literal_pool_p->prev_p;
|
||||
|
||||
parser_list_free (&literal_pool_p->literal_pool);
|
||||
scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t));
|
||||
} /* scanner_pop_literal_pool */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|
||||
/**
|
||||
* Extract certain (e.g. let/const) global declarations and construct a scanner info structure from them.
|
||||
*/
|
||||
void
|
||||
scanner_construct_global_block (parser_context_t *context_p, /**< context */
|
||||
scanner_context_t *scanner_context_p) /**< scanner context */
|
||||
{
|
||||
scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
|
||||
|
||||
parser_list_iterator_t literal_iterator;
|
||||
lexer_lit_location_t *literal_p;
|
||||
bool no_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_REG) != 0;
|
||||
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
if (scanner_context_p->debugger_enabled)
|
||||
{
|
||||
/* When debugger is enabled, identifiers are not stored in registers. However,
|
||||
* this does not affect 'eval' detection, so 'arguments' object is not created. */
|
||||
no_reg = true;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
|
||||
JERRY_ASSERT (literal_pool_p->prev_p == NULL);
|
||||
|
||||
parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
|
||||
|
||||
const uint8_t *prev_source_p = literal_pool_p->source_p;
|
||||
size_t compressed_size = 1;
|
||||
uint32_t no_declarations = literal_pool_p->no_declarations;
|
||||
|
||||
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
|
||||
{
|
||||
uint8_t type = literal_p->type;
|
||||
|
||||
if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
|
||||
|| !(type & SCANNER_LITERAL_IS_LET_OR_CONST))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
no_declarations++;
|
||||
|
||||
if (type & SCANNER_LITERAL_IS_FUNC)
|
||||
{
|
||||
JERRY_ASSERT (type & SCANNER_LITERAL_IS_LET);
|
||||
|
||||
no_declarations++;
|
||||
|
||||
type |= SCANNER_LITERAL_NO_REG;
|
||||
literal_p->type = type;
|
||||
}
|
||||
else if (no_reg)
|
||||
{
|
||||
type |= SCANNER_LITERAL_NO_REG;
|
||||
literal_p->type = type;
|
||||
}
|
||||
|
||||
intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p);
|
||||
|
||||
if (diff >= 1 && diff <= UINT8_MAX)
|
||||
{
|
||||
compressed_size += 2 + 1;
|
||||
}
|
||||
else if (diff >= -UINT8_MAX && diff <= UINT16_MAX)
|
||||
{
|
||||
compressed_size += 2 + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
compressed_size += 2 + 1 + sizeof (const uint8_t *);
|
||||
}
|
||||
|
||||
prev_source_p = literal_p->char_p + literal_p->length;
|
||||
}
|
||||
|
||||
if (compressed_size <= 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
scanner_info_t *info_p;
|
||||
|
||||
compressed_size += sizeof (scanner_info_t);
|
||||
|
||||
info_p = scanner_insert_info (context_p, literal_pool_p->source_p + 1, compressed_size);
|
||||
info_p->type = SCANNER_TYPE_BLOCK;
|
||||
|
||||
uint8_t *data_p = ((uint8_t *) info_p) + sizeof (scanner_info_t);
|
||||
|
||||
parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
|
||||
prev_source_p = literal_pool_p->source_p;
|
||||
no_declarations = literal_pool_p->no_declarations;
|
||||
|
||||
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
|
||||
{
|
||||
if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
|
||||
|| !(literal_p->type & SCANNER_LITERAL_IS_LET_OR_CONST))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
no_declarations++;
|
||||
|
||||
uint8_t type = SCANNER_STREAM_TYPE_LET;
|
||||
|
||||
if (literal_p->type & SCANNER_LITERAL_IS_CONST)
|
||||
{
|
||||
type = SCANNER_STREAM_TYPE_CONST;
|
||||
}
|
||||
else if (literal_p->type & SCANNER_LITERAL_IS_FUNC)
|
||||
{
|
||||
type = SCANNER_STREAM_TYPE_VAR_FUNC;
|
||||
no_declarations++;
|
||||
}
|
||||
|
||||
if (literal_p->has_escape)
|
||||
{
|
||||
type |= SCANNER_STREAM_HAS_ESCAPE;
|
||||
}
|
||||
|
||||
if (literal_p->type & SCANNER_LITERAL_NO_REG)
|
||||
{
|
||||
type |= SCANNER_STREAM_NO_REG;
|
||||
}
|
||||
|
||||
literal_p->type = 0;
|
||||
|
||||
data_p[0] = type;
|
||||
data_p[1] = (uint8_t) literal_p->length;
|
||||
data_p += 3;
|
||||
|
||||
intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p);
|
||||
|
||||
if (diff >= 1 && diff <= UINT8_MAX)
|
||||
{
|
||||
data_p[-1] = (uint8_t) diff;
|
||||
}
|
||||
else if (diff >= -UINT8_MAX && diff <= UINT16_MAX)
|
||||
{
|
||||
if (diff < 0)
|
||||
{
|
||||
diff = -diff;
|
||||
}
|
||||
|
||||
data_p[-3] |= SCANNER_STREAM_UINT16_DIFF;
|
||||
data_p[-1] = (uint8_t) diff;
|
||||
data_p[0] = (uint8_t) (diff >> 8);
|
||||
data_p += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
data_p[-1] = 0;
|
||||
memcpy (data_p, &literal_p->char_p, sizeof (const uint8_t *));
|
||||
data_p += sizeof (const uint8_t *);
|
||||
}
|
||||
|
||||
prev_source_p = literal_p->char_p + literal_p->length;
|
||||
}
|
||||
|
||||
data_p[0] = SCANNER_STREAM_TYPE_END;
|
||||
|
||||
JERRY_ASSERT (((uint8_t *) info_p) + compressed_size == data_p + 1);
|
||||
|
||||
if (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
|
||||
{
|
||||
no_declarations = PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK;
|
||||
}
|
||||
|
||||
literal_pool_p->no_declarations = (uint16_t) no_declarations;
|
||||
} /* scanner_construct_global_block */
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
* Filter out the arguments from a literal pool.
|
||||
*/
|
||||
@ -883,6 +1108,75 @@ scanner_detect_eval_call (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
} /* scanner_detect_eval_call */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|
||||
/**
|
||||
* Throws an error for invalid var statements.
|
||||
*/
|
||||
void
|
||||
scanner_detect_invalid_var (parser_context_t *context_p, /**< context */
|
||||
scanner_context_t *scanner_context_p, /**< scanner context */
|
||||
lexer_lit_location_t *var_literal_p) /**< literal */
|
||||
{
|
||||
if (var_literal_p->type & (SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_IS_CONST)
|
||||
&& !(var_literal_p->type & SCANNER_LITERAL_IS_FUNC))
|
||||
{
|
||||
scanner_raise_redeclaration_error (context_p);
|
||||
}
|
||||
|
||||
scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
|
||||
const uint8_t *char_p = var_literal_p->char_p;
|
||||
prop_length_t length = var_literal_p->length;
|
||||
|
||||
while (!(literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION))
|
||||
{
|
||||
literal_pool_p = literal_pool_p->prev_p;
|
||||
|
||||
parser_list_iterator_t literal_iterator;
|
||||
parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
|
||||
lexer_lit_location_t *literal_p;
|
||||
|
||||
if (JERRY_LIKELY (!context_p->token.lit_location.has_escape))
|
||||
{
|
||||
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
|
||||
{
|
||||
if (literal_p->type & (SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_IS_CONST)
|
||||
&& literal_p->length == length)
|
||||
{
|
||||
if (JERRY_LIKELY (!literal_p->has_escape))
|
||||
{
|
||||
if (memcmp (literal_p->char_p, char_p, length) == 0)
|
||||
{
|
||||
scanner_raise_redeclaration_error (context_p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (lexer_compare_identifiers (literal_p->char_p, char_p, length))
|
||||
{
|
||||
scanner_raise_redeclaration_error (context_p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
|
||||
{
|
||||
if (literal_p->type & (SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_IS_CONST)
|
||||
&& literal_p->length == length
|
||||
&& lexer_compare_identifiers (literal_p->char_p, char_p, length))
|
||||
{
|
||||
scanner_raise_redeclaration_error (context_p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* scanner_detect_invalid_var */
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
* Reverse the scanner info chain after the scanning is completed.
|
||||
*/
|
||||
@ -973,7 +1267,12 @@ scanner_cleanup (parser_context_t *context_p) /**< context */
|
||||
}
|
||||
default:
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS
|
||||
|| scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS);
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -986,6 +1285,158 @@ scanner_cleanup (parser_context_t *context_p) /**< context */
|
||||
context_p->active_scanner_info_p = NULL;
|
||||
} /* scanner_cleanup */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|
||||
/**
|
||||
* Finds the literal id of a function if its target is a var declaration
|
||||
*
|
||||
* @return function id - if the target of a function is a var declaration,
|
||||
* negative value - otherwise
|
||||
*/
|
||||
static int32_t
|
||||
scanner_get_function_target (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
uint16_t literal_index = context_p->lit_object.index;
|
||||
parser_scope_stack *scope_stack_start_p = context_p->scope_stack_p;
|
||||
parser_scope_stack *scope_stack_p = scope_stack_start_p + context_p->scope_stack_top;
|
||||
|
||||
while (scope_stack_p > scope_stack_start_p)
|
||||
{
|
||||
scope_stack_p--;
|
||||
|
||||
if (scope_stack_p->map_from == literal_index
|
||||
&& scope_stack_p->map_to != PARSER_SCOPE_STACK_FUNC)
|
||||
{
|
||||
if ((scope_stack_p - scope_stack_start_p) >= context_p->scope_stack_global_end
|
||||
|| !(context_p->lit_object.literal_p->status_flags & LEXER_FLAG_GLOBAL))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return scope_stack_p->map_to;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
} /* scanner_get_function_target */
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
* Checks whether a context needs to be created for a block.
|
||||
*
|
||||
* @return true - if context is needed,
|
||||
* false - otherwise
|
||||
*/
|
||||
bool
|
||||
scanner_is_context_needed (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
scanner_info_t *info_p = context_p->next_scanner_info_p;
|
||||
const uint8_t *data_p = ((const uint8_t *) info_p) + sizeof (scanner_info_t);
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
lexer_lit_location_t literal;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
JERRY_ASSERT (info_p->type == SCANNER_TYPE_BLOCK);
|
||||
|
||||
uint32_t scope_stack_reg_top = context_p->scope_stack_reg_top;
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
literal.char_p = info_p->source_p - 1;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
while (data_p[0] != SCANNER_STREAM_TYPE_END)
|
||||
{
|
||||
uint32_t type = data_p[0] & SCANNER_STREAM_TYPE_MASK;
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR
|
||||
|| type == SCANNER_STREAM_TYPE_LET
|
||||
|| type == SCANNER_STREAM_TYPE_CONST
|
||||
|| type == SCANNER_STREAM_TYPE_FUNC
|
||||
|| type == SCANNER_STREAM_TYPE_VAR_FUNC);
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR);
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
size_t length;
|
||||
|
||||
if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF))
|
||||
{
|
||||
if (data_p[2] != 0)
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
literal.char_p += data_p[2];
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
length = 2 + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
memcpy (&literal.char_p, data_p + 2 + 1, sizeof (const uint8_t *));
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
length = 2 + 1 + sizeof (const uint8_t *);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8;
|
||||
|
||||
if (diff <= UINT8_MAX)
|
||||
{
|
||||
diff = -diff;
|
||||
}
|
||||
|
||||
literal.char_p += diff;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
length = 2 + 2;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (type == SCANNER_STREAM_TYPE_FUNC)
|
||||
{
|
||||
literal.length = data_p[1];
|
||||
literal.type = LEXER_IDENT_LITERAL;
|
||||
literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0;
|
||||
|
||||
lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL);
|
||||
|
||||
if (scanner_get_function_target (context_p) >= 0)
|
||||
{
|
||||
literal.char_p += data_p[1];
|
||||
data_p += length;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (!(data_p[0] & SCANNER_STREAM_NO_REG)
|
||||
&& scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
|
||||
{
|
||||
scope_stack_reg_top++;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (type != SCANNER_STREAM_TYPE_VAR_FUNC)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
return true;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
literal.char_p += data_p[1];
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
data_p += length;
|
||||
}
|
||||
|
||||
return false;
|
||||
} /* scanner_is_context_needed */
|
||||
|
||||
/**
|
||||
* Description of "arguments" literal string.
|
||||
*/
|
||||
@ -1111,64 +1562,124 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
|
||||
lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL);
|
||||
|
||||
scope_stack_p->map_from = context_p->lit_object.index;
|
||||
|
||||
uint16_t map_to;
|
||||
uint16_t func_init_opcode = CBC_INIT_LOCAL;
|
||||
|
||||
if (!(data_p[0] & SCANNER_STREAM_NO_REG)
|
||||
&& scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (info_type == SCANNER_TYPE_FUNCTION)
|
||||
{
|
||||
map_to = (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top);
|
||||
|
||||
scope_stack_p->map_from = context_p->lit_object.index;
|
||||
scope_stack_p->map_to = map_to;
|
||||
scope_stack_reg_top++;
|
||||
if (type != SCANNER_STREAM_TYPE_LET
|
||||
&& type != SCANNER_STREAM_TYPE_CONST)
|
||||
{
|
||||
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_GLOBAL;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (type == SCANNER_STREAM_TYPE_FUNC)
|
||||
{
|
||||
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED;
|
||||
map_to = context_p->lit_object.index;
|
||||
int32_t target_id = scanner_get_function_target (context_p);
|
||||
|
||||
scope_stack_p->map_from = map_to;
|
||||
scope_stack_p->map_to = map_to;
|
||||
|
||||
if (info_type == SCANNER_TYPE_FUNCTION)
|
||||
if (target_id >= 0)
|
||||
{
|
||||
context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED;
|
||||
map_to = (uint16_t) target_id;
|
||||
|
||||
scope_stack_p->map_to = PARSER_SCOPE_STACK_FUNC;
|
||||
func_init_opcode = CBC_SET_VAR_FUNC;
|
||||
}
|
||||
}
|
||||
else if (type == SCANNER_STREAM_TYPE_VAR_FUNC)
|
||||
{
|
||||
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_GLOBAL;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (type == SCANNER_STREAM_TYPE_VAR)
|
||||
if (func_init_opcode == CBC_INIT_LOCAL)
|
||||
{
|
||||
if (!(data_p[0] & SCANNER_STREAM_NO_REG)
|
||||
&& scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
|
||||
{
|
||||
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
|
||||
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
|
||||
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
|
||||
map_to = (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top);
|
||||
|
||||
parser_emit_cbc_literal (context_p, CBC_CREATE_VAR, map_to);
|
||||
scope_stack_p->map_to = map_to;
|
||||
scope_stack_reg_top++;
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
func_init_opcode = CBC_SET_VAR_FUNC;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
}
|
||||
else if (type == SCANNER_STREAM_TYPE_ARG || type == SCANNER_STREAM_TYPE_ARG_FUNC)
|
||||
else
|
||||
{
|
||||
if (type == SCANNER_STREAM_TYPE_ARG)
|
||||
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED;
|
||||
map_to = context_p->lit_object.index;
|
||||
|
||||
scope_stack_p->map_to = map_to;
|
||||
|
||||
if (info_type == SCANNER_TYPE_FUNCTION)
|
||||
{
|
||||
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
|
||||
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
|
||||
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
|
||||
|
||||
parser_emit_cbc_literal_value (context_p,
|
||||
CBC_INIT_LOCAL,
|
||||
(uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top),
|
||||
map_to);
|
||||
context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED;
|
||||
}
|
||||
|
||||
if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
|
||||
switch (type)
|
||||
{
|
||||
scope_stack_reg_top++;
|
||||
case SCANNER_STREAM_TYPE_VAR:
|
||||
{
|
||||
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
|
||||
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
|
||||
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
|
||||
|
||||
parser_emit_cbc_literal (context_p, CBC_CREATE_VAR, map_to);
|
||||
break;
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case SCANNER_STREAM_TYPE_LET:
|
||||
case SCANNER_STREAM_TYPE_CONST:
|
||||
{
|
||||
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
|
||||
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
|
||||
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
|
||||
|
||||
/* FIXME: introduce CBC_CREATE_LET / CBC_CREATE_CONST. */
|
||||
parser_emit_cbc_literal (context_p, CBC_CREATE_VAR, map_to);
|
||||
break;
|
||||
}
|
||||
case SCANNER_STREAM_TYPE_VAR_FUNC:
|
||||
{
|
||||
if (context_p->status_flags & PARSER_INSIDE_BLOCK)
|
||||
{
|
||||
func_init_opcode = CBC_CREATE_VAR_FUNC;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
case SCANNER_STREAM_TYPE_ARG:
|
||||
{
|
||||
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
|
||||
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
|
||||
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
|
||||
|
||||
parser_emit_cbc_literal_value (context_p,
|
||||
CBC_INIT_LOCAL,
|
||||
(uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top),
|
||||
map_to);
|
||||
/* FALLTHRU */
|
||||
}
|
||||
case SCANNER_STREAM_TYPE_ARG_FUNC:
|
||||
{
|
||||
if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
|
||||
{
|
||||
scope_stack_reg_top++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scope_stack_p++;
|
||||
|
||||
literal.char_p += data_p[1];
|
||||
data_p += length;
|
||||
|
||||
if (type != SCANNER_STREAM_TYPE_ARG_FUNC && type != SCANNER_STREAM_TYPE_FUNC)
|
||||
if (!SCANNER_STREAM_TYPE_IS_FUNCTION (type))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -1188,7 +1699,7 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
|
||||
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
|
||||
|
||||
parser_emit_cbc_literal_value (context_p, CBC_INIT_LOCAL, context_p->literal_count, map_to);
|
||||
parser_emit_cbc_literal_value (context_p, func_init_opcode, context_p->literal_count, map_to);
|
||||
|
||||
scope_stack_p->map_from = PARSER_SCOPE_STACK_FUNC;
|
||||
scope_stack_p->map_to = context_p->literal_count;
|
||||
@ -1222,6 +1733,13 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
|
||||
context_p->scope_stack_reg_top = (uint16_t) scope_stack_reg_top;
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (info_type == SCANNER_TYPE_FUNCTION)
|
||||
{
|
||||
context_p->scope_stack_global_end = context_p->scope_stack_top;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (context_p->register_count < scope_stack_reg_top)
|
||||
{
|
||||
context_p->register_count = (uint16_t) scope_stack_reg_top;
|
||||
|
||||
@ -72,6 +72,10 @@ typedef enum
|
||||
SCAN_STACK_WHILE_EXPRESSION, /**< expression part of "while" iterator */
|
||||
SCAN_STACK_PAREN_EXPRESSION, /**< expression in brackets */
|
||||
SCAN_STACK_STATEMENT_WITH_EXPR, /**< statement which starts with expression enclosed in brackets */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
SCAN_STACK_LET, /**< let statement */
|
||||
SCAN_STACK_CONST, /**< const statement */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
/* The SCANNER_IS_FOR_START macro needs to be updated when the following constants are reordered. */
|
||||
SCAN_STACK_VAR, /**< var statement */
|
||||
SCAN_STACK_FOR_VAR_START, /**< start of "for" iterator with var statement */
|
||||
@ -504,6 +508,10 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
case SCAN_STACK_VAR:
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case SCAN_STACK_LET:
|
||||
case SCAN_STACK_CONST:
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
case SCAN_STACK_FOR_VAR_START:
|
||||
{
|
||||
scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
|
||||
@ -628,6 +636,10 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
return SCAN_NEXT_TOKEN;
|
||||
}
|
||||
case SCAN_STACK_VAR:
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case SCAN_STACK_LET:
|
||||
case SCAN_STACK_CONST:
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
{
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
return SCAN_KEEP_TOKEN;
|
||||
@ -752,6 +764,12 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
break;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
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 - 1;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
|
||||
scanner_switch_statement_t switch_statement = scanner_context_p->active_switch_statement;
|
||||
@ -966,6 +984,14 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
case LEXER_LEFT_BRACE:
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
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;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT);
|
||||
return SCAN_NEXT_TOKEN;
|
||||
@ -985,6 +1011,14 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
|
||||
scanner_raise_error (context_p);
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
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;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_TRY_STATEMENT);
|
||||
return SCAN_NEXT_TOKEN;
|
||||
@ -1081,6 +1115,20 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_VAR);
|
||||
return SCAN_NEXT_TOKEN;
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case LEXER_KEYW_LET:
|
||||
{
|
||||
scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_LET);
|
||||
return SCAN_NEXT_TOKEN;
|
||||
}
|
||||
case LEXER_KEYW_CONST:
|
||||
{
|
||||
scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_CONST);
|
||||
return SCAN_NEXT_TOKEN;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
case LEXER_KEYW_THROW:
|
||||
{
|
||||
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
||||
@ -1164,7 +1212,18 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
|
||||
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (location_p->type & SCANNER_LITERAL_IS_LET_OR_CONST
|
||||
&& !(location_p->type & SCANNER_LITERAL_IS_FUNC))
|
||||
{
|
||||
scanner_raise_redeclaration_error (context_p);
|
||||
}
|
||||
|
||||
location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET;
|
||||
#else
|
||||
location_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
|
||||
|
||||
@ -1182,8 +1241,22 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
|
||||
scanner_raise_error (context_p);
|
||||
}
|
||||
|
||||
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
|
||||
location_p->type |= SCANNER_LITERAL_IS_VAR;
|
||||
lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p);
|
||||
|
||||
if (literal_p->type & (SCANNER_LITERAL_IS_ARG
|
||||
| SCANNER_LITERAL_IS_LOCAL
|
||||
| SCANNER_LITERAL_IS_VAR
|
||||
| SCANNER_LITERAL_IS_LET_OR_CONST))
|
||||
{
|
||||
scanner_raise_redeclaration_error (context_p);
|
||||
}
|
||||
|
||||
if (literal_p->type & SCANNER_LITERAL_IS_FUNC)
|
||||
{
|
||||
literal_p->type = (uint8_t) (literal_p->type & ~SCANNER_LITERAL_IS_FUNC);
|
||||
}
|
||||
|
||||
literal_p->type |= SCANNER_LITERAL_IS_LET;
|
||||
|
||||
scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION;
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_STATEMENT);
|
||||
@ -1339,7 +1412,17 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
|
||||
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
|
||||
{
|
||||
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (location_p->type & SCANNER_LITERAL_IS_LET_OR_CONST
|
||||
&& !(location_p->type & SCANNER_LITERAL_IS_FUNC))
|
||||
{
|
||||
scanner_raise_redeclaration_error (context_p);
|
||||
}
|
||||
location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET;
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
location_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
lexer_next_token (context_p);
|
||||
}
|
||||
@ -1349,7 +1432,11 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
|
||||
location_p = scanner_add_custom_literal (context_p,
|
||||
scanner_context_p->active_literal_pool_p,
|
||||
&lexer_default_literal);
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET;
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
location_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
}
|
||||
|
||||
scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
|
||||
@ -1478,6 +1565,26 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
|
||||
return SCAN_NEXT_TOKEN;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (context_p->token.type == LEXER_KEYW_CLASS)
|
||||
{
|
||||
/* FIXME: classes should be let declarations. */
|
||||
scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION;
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_STATEMENT);
|
||||
|
||||
lexer_next_token (context_p);
|
||||
|
||||
if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
|
||||
{
|
||||
scanner_raise_error (context_p);
|
||||
}
|
||||
|
||||
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
|
||||
location_p->type |= SCANNER_LITERAL_IS_VAR;
|
||||
return SCAN_NEXT_TOKEN;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
scanner_context_p->mode = SCAN_MODE_STATEMENT;
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
@ -1566,10 +1673,17 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
|
||||
break;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (context_p->stack_top_uint8 != SCAN_STACK_CLASS_STATEMENT)
|
||||
{
|
||||
scanner_pop_literal_pool (context_p, scanner_context_p);
|
||||
}
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
if (context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_STATEMENT)
|
||||
{
|
||||
scanner_pop_literal_pool (context_p, scanner_context_p);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
terminator_found = true;
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
@ -1640,6 +1754,10 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
|
||||
|
||||
scanner_context_p->active_switch_statement = switch_statement;
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
scanner_pop_literal_pool (context_p, scanner_context_p);
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
terminator_found = true;
|
||||
lexer_next_token (context_p);
|
||||
continue;
|
||||
@ -1712,10 +1830,14 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
lexer_next_token (context_p);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
scanner_pop_literal_pool (context_p, scanner_context_p);
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
if (stack_top == SCAN_STACK_CATCH_STATEMENT)
|
||||
{
|
||||
scanner_pop_literal_pool (context_p, scanner_context_p);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/* A finally statement is optional after a try or catch statement. */
|
||||
if (context_p->token.type == LEXER_KEYW_FINALLY)
|
||||
@ -1727,6 +1849,14 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
|
||||
scanner_raise_error (context_p);
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
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;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT);
|
||||
scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
|
||||
return SCAN_NEXT_TOKEN;
|
||||
@ -1839,9 +1969,14 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
context_p->source_p = source_p;
|
||||
context_p->source_end_p = source_end_p;
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS;
|
||||
#else /* !ENABLED (JERRY_DEBUGGER) */
|
||||
uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS | SCANNER_LITERAL_POOL_NO_REG;
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
|
||||
scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, &scanner_context, status_flags);
|
||||
literal_pool_p->source_p = source_p;
|
||||
literal_pool_p->source_p = source_p - 1;
|
||||
|
||||
scanner_context.mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_SCRIPT);
|
||||
@ -2011,12 +2146,45 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
scanner_raise_error (context_p);
|
||||
}
|
||||
|
||||
lexer_lit_location_t *location_p = scanner_add_literal (context_p, &scanner_context);
|
||||
location_p->type |= SCANNER_LITERAL_IS_VAR;
|
||||
lexer_lit_location_t *literal_p = scanner_add_literal (context_p, &scanner_context);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (stack_top == SCAN_STACK_LET || stack_top == SCAN_STACK_CONST)
|
||||
{
|
||||
if (literal_p->type & (SCANNER_LITERAL_IS_ARG
|
||||
| SCANNER_LITERAL_IS_LOCAL
|
||||
| SCANNER_LITERAL_IS_VAR
|
||||
| SCANNER_LITERAL_IS_LET_OR_CONST))
|
||||
{
|
||||
scanner_raise_redeclaration_error (context_p);
|
||||
}
|
||||
|
||||
if (literal_p->type & SCANNER_LITERAL_IS_FUNC)
|
||||
{
|
||||
literal_p->type = (uint8_t) (literal_p->type & ~SCANNER_LITERAL_IS_FUNC);
|
||||
}
|
||||
|
||||
if (stack_top == SCAN_STACK_LET)
|
||||
{
|
||||
literal_p->type |= SCANNER_LITERAL_IS_LET;
|
||||
}
|
||||
else
|
||||
{
|
||||
literal_p->type |= SCANNER_LITERAL_IS_CONST;
|
||||
}
|
||||
}
|
||||
else if (!(literal_p->type & SCANNER_LITERAL_IS_VAR))
|
||||
{
|
||||
scanner_detect_invalid_var (context_p, &scanner_context, literal_p);
|
||||
literal_p->type |= SCANNER_LITERAL_IS_VAR;
|
||||
}
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
literal_p->type |= SCANNER_LITERAL_IS_VAR;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
|
||||
{
|
||||
location_p->type |= SCANNER_LITERAL_NO_REG;
|
||||
literal_p->type |= SCANNER_LITERAL_NO_REG;
|
||||
}
|
||||
|
||||
lexer_next_token (context_p);
|
||||
@ -2048,7 +2216,11 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
continue;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
JERRY_ASSERT (stack_top == SCAN_STACK_VAR || stack_top == SCAN_STACK_LET || stack_top == SCAN_STACK_CONST);
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
JERRY_ASSERT (stack_top == SCAN_STACK_VAR);
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
scanner_context.mode = SCAN_MODE_STATEMENT_END;
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
@ -2275,6 +2447,14 @@ scan_completed:
|
||||
scanner_raise_error (context_p);
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (arg_list_p == NULL)
|
||||
{
|
||||
scanner_construct_global_block (context_p, &scanner_context);
|
||||
scanner_context.active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_NO_REG;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
scanner_pop_literal_pool (context_p, &scanner_context);
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
@ -2364,6 +2544,23 @@ scan_completed:
|
||||
{
|
||||
switch (data_p[0] & SCANNER_STREAM_TYPE_MASK)
|
||||
{
|
||||
case SCANNER_STREAM_TYPE_VAR:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" VAR ");
|
||||
break;
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case SCANNER_STREAM_TYPE_LET:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" LET ");
|
||||
break;
|
||||
}
|
||||
case SCANNER_STREAM_TYPE_CONST:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" CONST ");
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
case SCANNER_STREAM_TYPE_ARG:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" ARG ");
|
||||
@ -2374,16 +2571,18 @@ scan_completed:
|
||||
JERRY_DEBUG_MSG (" ARG_FUNC ");
|
||||
break;
|
||||
}
|
||||
case SCANNER_STREAM_TYPE_VAR:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" VAR ");
|
||||
break;
|
||||
}
|
||||
case SCANNER_STREAM_TYPE_FUNC:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" FUNC ");
|
||||
break;
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case SCANNER_STREAM_TYPE_VAR_FUNC:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" VAR_FUNC ");
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
default:
|
||||
{
|
||||
JERRY_ASSERT ((data_p[0] & SCANNER_STREAM_TYPE_MASK) == SCANNER_STREAM_TYPE_HOLE);
|
||||
|
||||
@ -44,6 +44,9 @@ typedef enum
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
SCANNER_TYPE_SWITCH, /**< switch statement */
|
||||
SCANNER_TYPE_CASE, /**< case statement */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
SCANNER_TYPE_ERR_REDECLARED, /**< syntax error: a variable is redeclared */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
} scanner_info_type_t;
|
||||
|
||||
/**
|
||||
@ -127,6 +130,7 @@ typedef enum
|
||||
SCANNER_STREAM_UINT16_DIFF = (1 << 7), /**< relative distance is between -256 and 65535 */
|
||||
SCANNER_STREAM_HAS_ESCAPE = (1 << 6), /**< literal has escape */
|
||||
SCANNER_STREAM_NO_REG = (1 << 5), /**< identifier cannot be stored in register */
|
||||
/* Update SCANNER_STREAM_TYPE_MASK macro if more bits are added. */
|
||||
} scanner_compressed_stream_flags_t;
|
||||
|
||||
/**
|
||||
@ -136,10 +140,18 @@ typedef enum
|
||||
{
|
||||
SCANNER_STREAM_TYPE_END, /**< end of scanner data */
|
||||
SCANNER_STREAM_TYPE_HOLE, /**< no name is assigned to this argument */
|
||||
SCANNER_STREAM_TYPE_ARG, /**< argument declaration */
|
||||
SCANNER_STREAM_TYPE_ARG_FUNC, /**< argument declaration which is later initialized with a function */
|
||||
SCANNER_STREAM_TYPE_VAR, /**< var declaration */
|
||||
SCANNER_STREAM_TYPE_FUNC, /**< function declaration */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
SCANNER_STREAM_TYPE_LET, /**< let declaration */
|
||||
SCANNER_STREAM_TYPE_CONST, /**< const declaration */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
SCANNER_STREAM_TYPE_ARG, /**< argument declaration */
|
||||
/* Function types should be at the end. See the SCANNER_STREAM_TYPE_IS_FUNCTION macro. */
|
||||
SCANNER_STREAM_TYPE_ARG_FUNC, /**< argument declaration which is later initialized with a function */
|
||||
SCANNER_STREAM_TYPE_FUNC, /**< local function declaration */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
SCANNER_STREAM_TYPE_VAR_FUNC, /**< var function declaration */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
} scanner_compressed_stream_types_t;
|
||||
|
||||
/**
|
||||
@ -147,6 +159,11 @@ typedef enum
|
||||
*/
|
||||
#define SCANNER_STREAM_TYPE_MASK 0xf
|
||||
|
||||
/**
|
||||
* Mask for decoding the type from the compressed stream.
|
||||
*/
|
||||
#define SCANNER_STREAM_TYPE_IS_FUNCTION(type) ((type) >= SCANNER_STREAM_TYPE_ARG_FUNC)
|
||||
|
||||
/**
|
||||
* Constants for u8_arg flags in scanner_function_info_t.
|
||||
*/
|
||||
|
||||
@ -26,6 +26,8 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
JERRY_STATIC_ASSERT (PARSER_WITH_CONTEXT_STACK_ALLOCATION == PARSER_BLOCK_CONTEXT_STACK_ALLOCATION,
|
||||
parser_with_context_stack_allocation_must_be_equal_to_parser_block_context_stack_allocation);
|
||||
JERRY_STATIC_ASSERT (PARSER_WITH_CONTEXT_STACK_ALLOCATION == PARSER_SUPER_CLASS_CONTEXT_STACK_ALLOCATION,
|
||||
parser_with_context_stack_allocation_must_be_equal_to_parser_super_class_context_stack_allocation);
|
||||
|
||||
@ -38,7 +40,17 @@ ecma_value_t *
|
||||
vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
ecma_value_t *vm_stack_top_p) /**< current stack top */
|
||||
{
|
||||
switch (VM_GET_CONTEXT_TYPE (vm_stack_top_p[-1]))
|
||||
ecma_value_t context_info = vm_stack_top_p[-1];
|
||||
|
||||
if (context_info & VM_CONTEXT_HAS_LEX_ENV)
|
||||
{
|
||||
ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p;
|
||||
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
|
||||
frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
|
||||
ecma_deref_object (lex_env_p);
|
||||
}
|
||||
|
||||
switch (VM_GET_CONTEXT_TYPE (context_info))
|
||||
{
|
||||
case VM_CONTEXT_FINALLY_THROW:
|
||||
case VM_CONTEXT_FINALLY_RETURN:
|
||||
@ -66,16 +78,14 @@ vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
vm_stack_top_p -= size_diff;
|
||||
/* FALLTHRU */
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case VM_CONTEXT_BLOCK:
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
case VM_CONTEXT_WITH:
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case VM_CONTEXT_SUPER_CLASS:
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
{
|
||||
ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p;
|
||||
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
|
||||
frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
|
||||
ecma_deref_object (lex_env_p);
|
||||
|
||||
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_WITH_CONTEXT_STACK_ALLOCATION);
|
||||
vm_stack_top_p -= PARSER_WITH_CONTEXT_STACK_ALLOCATION;
|
||||
break;
|
||||
@ -194,6 +204,16 @@ vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
return false;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (vm_stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV)
|
||||
{
|
||||
ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p;
|
||||
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
|
||||
frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
|
||||
ecma_deref_object (lex_env_p);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
byte_code_p = frame_ctx_p->byte_code_start_p + context_end;
|
||||
|
||||
if (context_type == VM_CONTEXT_TRY)
|
||||
@ -232,10 +252,15 @@ vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p;
|
||||
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
|
||||
frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
|
||||
ecma_deref_object (lex_env_p);
|
||||
#if !ENABLED (JERRY_ES2015)
|
||||
if (vm_stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV)
|
||||
{
|
||||
ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p;
|
||||
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
|
||||
frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
|
||||
ecma_deref_object (lex_env_p);
|
||||
}
|
||||
#endif /* !ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (byte_code_p[0] == CBC_CONTEXT_END)
|
||||
{
|
||||
|
||||
@ -25,20 +25,46 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define VM_CREATE_CONTEXT(type, end_offset) ((ecma_value_t) ((type) | (end_offset) << 4))
|
||||
#define VM_GET_CONTEXT_TYPE(value) ((vm_stack_context_type_t) ((value) & 0xf))
|
||||
#define VM_GET_CONTEXT_END(value) ((value) >> 4)
|
||||
/**
|
||||
* Create context on the vm stack.
|
||||
*/
|
||||
#define VM_CREATE_CONTEXT(type, end_offset) ((ecma_value_t) ((type) | ((end_offset) << 6)))
|
||||
|
||||
/**
|
||||
* Create context on the vm stack with environment.
|
||||
*/
|
||||
#define VM_CREATE_CONTEXT_WITH_ENV(type, end_offset) \
|
||||
((ecma_value_t) ((type) | ((end_offset) << 6) | VM_CONTEXT_HAS_LEX_ENV))
|
||||
|
||||
/**
|
||||
* Get type of a vm context.
|
||||
*/
|
||||
#define VM_GET_CONTEXT_TYPE(value) ((vm_stack_context_type_t) ((value) & 0x1f))
|
||||
|
||||
/**
|
||||
* Get the end position of a vm context.
|
||||
*/
|
||||
#define VM_GET_CONTEXT_END(value) ((value) >> 6)
|
||||
|
||||
/**
|
||||
* This flag is set if the context has a lexical environment.
|
||||
*/
|
||||
#define VM_CONTEXT_HAS_LEX_ENV 0x20
|
||||
|
||||
/**
|
||||
* Context types for the vm stack.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/* Update VM_CONTEXT_IS_FINALLY macro if the following three values are changed. */
|
||||
VM_CONTEXT_FINALLY_JUMP, /**< finally context with a jump */
|
||||
VM_CONTEXT_FINALLY_THROW, /**< finally context with a throw */
|
||||
VM_CONTEXT_FINALLY_RETURN, /**< finally context with a return */
|
||||
VM_CONTEXT_TRY, /**< try context */
|
||||
VM_CONTEXT_CATCH, /**< catch context */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
VM_CONTEXT_BLOCK, /**< block context */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
VM_CONTEXT_WITH, /**< with context */
|
||||
VM_CONTEXT_FOR_IN, /**< for-in context */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
@ -47,6 +73,12 @@ typedef enum
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
} vm_stack_context_type_t;
|
||||
|
||||
/**
|
||||
* Checks whether the context type is a finally type.
|
||||
*/
|
||||
#define VM_CONTEXT_IS_FINALLY(context_type) \
|
||||
((context_type) <= VM_CONTEXT_FINALLY_RETURN)
|
||||
|
||||
ecma_value_t *vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, ecma_value_t *vm_stack_top_p);
|
||||
bool vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, ecma_value_t **vm_stack_top_ref_p,
|
||||
vm_stack_context_type_t finally_type, uint32_t search_limit);
|
||||
|
||||
@ -835,35 +835,99 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
{
|
||||
ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]);
|
||||
frame_ctx_p->registers_p[literal_index] = lit_value;
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
||||
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
|
||||
|
||||
vm_var_decl (frame_ctx_p, name_p);
|
||||
|
||||
ecma_value_t put_value_result = ecma_op_put_value_lex_env_base (frame_ctx_p->lex_env_p,
|
||||
name_p,
|
||||
is_strict,
|
||||
lit_value);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_boolean (put_value_result)
|
||||
|| ecma_is_value_empty (put_value_result)
|
||||
|| ECMA_IS_VALUE_ERROR (put_value_result));
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (put_value_result))
|
||||
{
|
||||
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
|
||||
ecma_free_value (JERRY_CONTEXT (error_value));
|
||||
}
|
||||
|
||||
vm_var_decl (frame_ctx_p, name_p);
|
||||
|
||||
ecma_value_t put_value_result = ecma_op_put_value_lex_env_base (frame_ctx_p->lex_env_p,
|
||||
name_p,
|
||||
is_strict,
|
||||
lit_value);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_boolean (put_value_result)
|
||||
|| ecma_is_value_empty (put_value_result)
|
||||
|| ECMA_IS_VALUE_ERROR (put_value_result));
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (put_value_result))
|
||||
{
|
||||
ecma_free_value (JERRY_CONTEXT (error_value));
|
||||
}
|
||||
|
||||
if (value_index >= register_end)
|
||||
{
|
||||
ecma_free_value (lit_value);
|
||||
}
|
||||
if (value_index >= register_end)
|
||||
{
|
||||
ecma_free_value (lit_value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case CBC_CREATE_VAR_FUNC:
|
||||
case CBC_SET_VAR_FUNC:
|
||||
{
|
||||
uint8_t type = *byte_code_p;
|
||||
uint32_t literal_index, value_index;
|
||||
ecma_value_t lit_value;
|
||||
|
||||
byte_code_p++;
|
||||
READ_LITERAL_INDEX (value_index);
|
||||
READ_LITERAL_INDEX (literal_index);
|
||||
|
||||
JERRY_ASSERT (value_index != literal_index && value_index >= register_end);
|
||||
|
||||
lit_value = vm_construct_literal_object (frame_ctx_p,
|
||||
literal_start_p[value_index]);
|
||||
|
||||
if (literal_index < register_end)
|
||||
{
|
||||
JERRY_ASSERT (type == CBC_SET_VAR_FUNC);
|
||||
|
||||
ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]);
|
||||
frame_ctx_p->registers_p[literal_index] = lit_value;
|
||||
break;
|
||||
}
|
||||
|
||||
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
|
||||
ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p;
|
||||
|
||||
if (type == CBC_CREATE_VAR_FUNC)
|
||||
{
|
||||
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
|
||||
lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
|
||||
|
||||
if (!ecma_op_has_binding (lex_env_p, name_p))
|
||||
{
|
||||
const bool is_configurable_bindings = frame_ctx_p->is_eval_code;
|
||||
|
||||
ecma_value_t completion_value = ecma_op_create_mutable_binding (lex_env_p,
|
||||
name_p,
|
||||
is_configurable_bindings);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_empty (completion_value));
|
||||
}
|
||||
}
|
||||
|
||||
ecma_value_t put_value_result = ecma_op_put_value_lex_env_base (lex_env_p,
|
||||
name_p,
|
||||
is_strict,
|
||||
lit_value);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_boolean (put_value_result)
|
||||
|| ecma_is_value_empty (put_value_result)
|
||||
|| ECMA_IS_VALUE_ERROR (put_value_result));
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (put_value_result))
|
||||
{
|
||||
ecma_free_value (JERRY_CONTEXT (error_value));
|
||||
}
|
||||
|
||||
ecma_free_value (lit_value);
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
||||
case CBC_SET_BYTECODE_PTR:
|
||||
{
|
||||
@ -1364,7 +1428,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_SUPER_CLASS_CONTEXT_STACK_ALLOCATION);
|
||||
stack_top_p += PARSER_SUPER_CLASS_CONTEXT_STACK_ALLOCATION;
|
||||
|
||||
stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_SUPER_CLASS, branch_offset);
|
||||
stack_top_p[-1] = VM_CREATE_CONTEXT_WITH_ENV (VM_CONTEXT_SUPER_CLASS, branch_offset);
|
||||
|
||||
frame_ctx_p->lex_env_p = super_env_p;
|
||||
|
||||
@ -2818,6 +2882,58 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
*stack_top_p++ = result;
|
||||
goto free_both_values;
|
||||
}
|
||||
case VM_OC_BLOCK_CREATE_CONTEXT:
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
ecma_value_t *stack_context_top_p = frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth;
|
||||
JERRY_ASSERT (stack_context_top_p == stack_top_p || stack_context_top_p == stack_top_p - 1);
|
||||
|
||||
if (byte_code_start_p[0] != CBC_EXT_OPCODE)
|
||||
{
|
||||
branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p);
|
||||
|
||||
if (stack_context_top_p != stack_top_p)
|
||||
{
|
||||
/* Preserve the value of switch statement. */
|
||||
stack_context_top_p[1] = stack_context_top_p[0];
|
||||
}
|
||||
|
||||
stack_context_top_p[0] = VM_CREATE_CONTEXT_WITH_ENV (VM_CONTEXT_BLOCK, branch_offset);
|
||||
|
||||
VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
|
||||
stack_top_p += PARSER_BLOCK_CONTEXT_STACK_ALLOCATION;
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (byte_code_start_p[1] == CBC_EXT_TRY_CREATE_ENV);
|
||||
|
||||
JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_TRY
|
||||
|| VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_CATCH
|
||||
|| VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_FINALLY_JUMP
|
||||
|| VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_FINALLY_THROW
|
||||
|| VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_FINALLY_RETURN);
|
||||
|
||||
JERRY_ASSERT (!(stack_context_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV));
|
||||
|
||||
stack_context_top_p[-1] |= VM_CONTEXT_HAS_LEX_ENV;
|
||||
}
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-2]) == VM_CONTEXT_CATCH
|
||||
&& !(stack_top_p[-2] & VM_CONTEXT_HAS_LEX_ENV));
|
||||
|
||||
stack_top_p[-2] |= VM_CONTEXT_HAS_LEX_ENV;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
frame_ctx_p->lex_env_p = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p);
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
frame_ctx_p->lex_env_p->type_flags_refs |= (uint16_t) ECMA_OBJECT_FLAG_NON_CLOSURE;
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
|
||||
frame_ctx_p->byte_code_p = byte_code_p;
|
||||
vm_init_loop (frame_ctx_p);
|
||||
byte_code_p = frame_ctx_p->byte_code_p;
|
||||
continue;
|
||||
}
|
||||
case VM_OC_WITH:
|
||||
{
|
||||
ecma_value_t value = *(--stack_top_p);
|
||||
@ -2846,7 +2962,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_WITH_CONTEXT_STACK_ALLOCATION);
|
||||
stack_top_p += PARSER_WITH_CONTEXT_STACK_ALLOCATION;
|
||||
|
||||
stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_WITH, branch_offset);
|
||||
stack_top_p[-1] = VM_CREATE_CONTEXT_WITH_ENV (VM_CONTEXT_WITH, branch_offset);
|
||||
|
||||
frame_ctx_p->lex_env_p = with_env_p;
|
||||
continue;
|
||||
@ -2872,7 +2988,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
|
||||
VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION);
|
||||
stack_top_p += PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION;
|
||||
stack_top_p[-1] = (ecma_value_t) VM_CREATE_CONTEXT (VM_CONTEXT_FOR_IN, branch_offset);
|
||||
stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_FOR_IN, branch_offset);
|
||||
ECMA_SET_INTERNAL_VALUE_ANY_POINTER (stack_top_p[-2], prop_names_p);
|
||||
stack_top_p[-3] = 0;
|
||||
stack_top_p[-4] = expr_obj_value;
|
||||
@ -2972,7 +3088,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
|
||||
VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION);
|
||||
stack_top_p += PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION;
|
||||
stack_top_p[-1] = (ecma_value_t) VM_CREATE_CONTEXT (VM_CONTEXT_FOR_OF, branch_offset);
|
||||
stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_FOR_OF, branch_offset);
|
||||
stack_top_p[-2] = iterator_step;
|
||||
stack_top_p[-3] = iterator;
|
||||
|
||||
@ -3032,7 +3148,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
|
||||
stack_top_p += PARSER_TRY_CONTEXT_STACK_ALLOCATION;
|
||||
|
||||
stack_top_p[-1] = (ecma_value_t) VM_CREATE_CONTEXT (VM_CONTEXT_TRY, branch_offset);
|
||||
stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_TRY, branch_offset);
|
||||
continue;
|
||||
}
|
||||
case VM_OC_CATCH:
|
||||
@ -3053,15 +3169,17 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_TRY
|
||||
|| VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_CATCH);
|
||||
|
||||
if (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_CATCH)
|
||||
if (stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV)
|
||||
{
|
||||
ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p;
|
||||
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
|
||||
frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
|
||||
ecma_deref_object (lex_env_p);
|
||||
|
||||
stack_top_p[-1] &= (ecma_value_t) ~VM_CONTEXT_HAS_LEX_ENV;
|
||||
}
|
||||
|
||||
stack_top_p[-1] = (ecma_value_t) VM_CREATE_CONTEXT (VM_CONTEXT_FINALLY_JUMP, branch_offset);
|
||||
stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_FINALLY_JUMP, branch_offset);
|
||||
stack_top_p[-2] = (ecma_value_t) branch_offset;
|
||||
continue;
|
||||
}
|
||||
@ -3069,59 +3187,64 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
{
|
||||
JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p);
|
||||
|
||||
switch (VM_GET_CONTEXT_TYPE (stack_top_p[-1]))
|
||||
ecma_value_t context_type = VM_GET_CONTEXT_TYPE (stack_top_p[-1]);
|
||||
|
||||
if (!VM_CONTEXT_IS_FINALLY (context_type))
|
||||
{
|
||||
case VM_CONTEXT_FINALLY_JUMP:
|
||||
{
|
||||
uint32_t jump_target = stack_top_p[-2];
|
||||
stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p);
|
||||
|
||||
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth,
|
||||
PARSER_TRY_CONTEXT_STACK_ALLOCATION);
|
||||
stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
|
||||
JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vm_stack_find_finally (frame_ctx_p,
|
||||
&stack_top_p,
|
||||
VM_CONTEXT_FINALLY_JUMP,
|
||||
jump_target))
|
||||
{
|
||||
JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_JUMP);
|
||||
byte_code_p = frame_ctx_p->byte_code_p;
|
||||
stack_top_p[-2] = jump_target;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte_code_p = frame_ctx_p->byte_code_start_p + jump_target;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VM_CONTEXT_FINALLY_THROW:
|
||||
{
|
||||
JERRY_CONTEXT (error_value) = stack_top_p[-2];
|
||||
JERRY_CONTEXT (status_flags) |= ECMA_STATUS_EXCEPTION;
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV)
|
||||
{
|
||||
ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p;
|
||||
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
|
||||
frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
|
||||
ecma_deref_object (lex_env_p);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth,
|
||||
PARSER_TRY_CONTEXT_STACK_ALLOCATION);
|
||||
stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
|
||||
result = ECMA_VALUE_ERROR;
|
||||
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth,
|
||||
PARSER_TRY_CONTEXT_STACK_ALLOCATION);
|
||||
stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
|
||||
|
||||
if (context_type == VM_CONTEXT_FINALLY_RETURN)
|
||||
{
|
||||
result = *stack_top_p;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (context_type == VM_CONTEXT_FINALLY_THROW)
|
||||
{
|
||||
JERRY_CONTEXT (error_value) = *stack_top_p;
|
||||
JERRY_CONTEXT (status_flags) |= ECMA_STATUS_EXCEPTION;
|
||||
result = ECMA_VALUE_ERROR;
|
||||
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN);
|
||||
JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN);
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
goto error;
|
||||
}
|
||||
case VM_CONTEXT_FINALLY_RETURN:
|
||||
{
|
||||
result = stack_top_p[-2];
|
||||
goto error;
|
||||
}
|
||||
|
||||
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth,
|
||||
PARSER_TRY_CONTEXT_STACK_ALLOCATION);
|
||||
stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
|
||||
goto error;
|
||||
}
|
||||
default:
|
||||
{
|
||||
stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p);
|
||||
}
|
||||
JERRY_ASSERT (context_type == VM_CONTEXT_FINALLY_JUMP);
|
||||
|
||||
uint32_t jump_target = *stack_top_p;
|
||||
|
||||
if (vm_stack_find_finally (frame_ctx_p,
|
||||
&stack_top_p,
|
||||
VM_CONTEXT_FINALLY_JUMP,
|
||||
jump_target))
|
||||
{
|
||||
JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_JUMP);
|
||||
byte_code_p = frame_ctx_p->byte_code_p;
|
||||
stack_top_p[-2] = jump_target;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte_code_p = frame_ctx_p->byte_code_start_p + jump_target;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p);
|
||||
@ -3466,31 +3589,23 @@ error:
|
||||
0))
|
||||
{
|
||||
JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p);
|
||||
JERRY_ASSERT (!(stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV));
|
||||
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN);
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
|
||||
if (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_CATCH)
|
||||
{
|
||||
*stack_top_p++ = JERRY_CONTEXT (error_value);
|
||||
|
||||
ecma_object_t *catch_env_p = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p);
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
catch_env_p->type_flags_refs |= (uint16_t) ECMA_OBJECT_FLAG_NON_CLOSURE;
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
|
||||
frame_ctx_p->lex_env_p = catch_env_p;
|
||||
|
||||
vm_init_loop (frame_ctx_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_THROW);
|
||||
stack_top_p[-2] = JERRY_CONTEXT (error_value);
|
||||
}
|
||||
|
||||
byte_code_p = frame_ctx_p->byte_code_p;
|
||||
|
||||
if (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_THROW)
|
||||
{
|
||||
stack_top_p[-2] = JERRY_CONTEXT (error_value);
|
||||
continue;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_CATCH);
|
||||
|
||||
*stack_top_p++ = JERRY_CONTEXT (error_value);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,6 +202,9 @@ typedef enum
|
||||
VM_OC_RIGHT_SHIFT, /**< right shift */
|
||||
VM_OC_UNS_RIGHT_SHIFT, /**< unsigned right shift */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
VM_OC_BLOCK_CREATE_CONTEXT, /**< create lexical environment for blocks enclosed in braces */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
VM_OC_WITH, /**< with */
|
||||
VM_OC_FOR_IN_CREATE_CONTEXT, /**< for in create context */
|
||||
VM_OC_FOR_IN_GET_NEXT, /**< get next */
|
||||
@ -260,6 +263,7 @@ typedef enum
|
||||
#endif /* !ENABLED (JERRY_LINE_INFO) */
|
||||
#if !ENABLED (JERRY_ES2015)
|
||||
VM_OC_SET_COMPUTED_PROPERTY = VM_OC_NONE, /**< set computed property is unused */
|
||||
VM_OC_BLOCK_CREATE_CONTEXT = VM_OC_NONE, /**< create context for blocks enclosed in braces */
|
||||
|
||||
VM_OC_FOR_OF_CREATE_CONTEXT = VM_OC_NONE, /**< for of create context */
|
||||
VM_OC_FOR_OF_GET_NEXT = VM_OC_NONE, /**< get next */
|
||||
|
||||
@ -12,4 +12,4 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
var let = 1;
|
||||
var package = 1;
|
||||
|
||||
42
tests/jerry/es2015/let1.js
Normal file
42
tests/jerry/es2015/let1.js
Normal file
@ -0,0 +1,42 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
var a = 5;
|
||||
var a = 6;
|
||||
let b = 7;
|
||||
|
||||
assert (a === 6);
|
||||
assert (this.a === 6);
|
||||
assert (b === 7);
|
||||
assert (this.b === undefined);
|
||||
|
||||
{
|
||||
let c;
|
||||
c = 8;
|
||||
|
||||
{
|
||||
let c = 9;
|
||||
assert (c === 9);
|
||||
}
|
||||
|
||||
{
|
||||
function c() { return 10 }
|
||||
assert (c() === 10);
|
||||
}
|
||||
|
||||
assert (c === 8);
|
||||
}
|
||||
assert (typeof c === "undefined");
|
||||
|
||||
44
tests/jerry/es2015/let2.js
Normal file
44
tests/jerry/es2015/let2.js
Normal file
@ -0,0 +1,44 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function check_syntax_error (code)
|
||||
{
|
||||
try {
|
||||
eval (code);
|
||||
assert (false);
|
||||
} catch (e) {
|
||||
assert (e instanceof SyntaxError);
|
||||
}
|
||||
}
|
||||
|
||||
check_syntax_error ("let a; let b; let a");
|
||||
check_syntax_error ("let a, b, a");
|
||||
check_syntax_error ("var a; let a;");
|
||||
check_syntax_error ("var a; const a = 3;");
|
||||
check_syntax_error ("let a; var a;");
|
||||
check_syntax_error ("const a = 3; var x, y, a;");
|
||||
check_syntax_error ("let a; { let b; { var a; } }");
|
||||
check_syntax_error ("{ { var a = 4; } }; let a = 3");
|
||||
check_syntax_error ("function a() {}; let a;");
|
||||
check_syntax_error ("let a; function a() {};");
|
||||
check_syntax_error ("{ { function a() {}; let a; } }");
|
||||
check_syntax_error ("{ { let a; function a() {}; } }");
|
||||
check_syntax_error ("let a = 1; const b = 5; const a = 2;");
|
||||
check_syntax_error ("try {} catch (e) { let e; }");
|
||||
check_syntax_error ("try {} catch (e) { const e = 1; }");
|
||||
check_syntax_error ("let A; class A {}");
|
||||
check_syntax_error ("const A; class A {}");
|
||||
check_syntax_error ("class A {}; let A");
|
||||
check_syntax_error ("class A {}; const A");
|
||||
68
tests/jerry/es2015/let3.js
Normal file
68
tests/jerry/es2015/let3.js
Normal file
@ -0,0 +1,68 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
var g = -1;
|
||||
|
||||
function f1() {
|
||||
/* Function hoisted as var. */
|
||||
assert (g === undefined);
|
||||
|
||||
{
|
||||
assert (g() === 1);
|
||||
|
||||
{
|
||||
assert (g() === 2);
|
||||
|
||||
function g() { return 2 };
|
||||
}
|
||||
|
||||
function g() { return 1 };
|
||||
|
||||
assert (g() === 2);
|
||||
}
|
||||
|
||||
assert (g() === 2);
|
||||
}
|
||||
f1();
|
||||
|
||||
function f2() {
|
||||
/* Function hoisted as let. */
|
||||
assert (g === -1);
|
||||
|
||||
{
|
||||
let g = 1;
|
||||
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
assert (g() === 2);
|
||||
|
||||
if (true)
|
||||
{
|
||||
assert (g() === 2);
|
||||
}
|
||||
|
||||
function g() { return 2 };
|
||||
}
|
||||
|
||||
assert (g === 1);
|
||||
}
|
||||
|
||||
assert (g === 1);
|
||||
}
|
||||
|
||||
assert (g === -1);
|
||||
}
|
||||
f2();
|
||||
68
tests/jerry/es2015/let4.js
Normal file
68
tests/jerry/es2015/let4.js
Normal file
@ -0,0 +1,68 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
var g = -1;
|
||||
|
||||
function f1() {
|
||||
/* Function hoisted as var. */
|
||||
assert (g === undefined);
|
||||
|
||||
{
|
||||
assert (g() === 1);
|
||||
|
||||
{
|
||||
eval("assert (g() === 2)");
|
||||
|
||||
function g() { return 2 };
|
||||
}
|
||||
|
||||
function g() { return 1 };
|
||||
|
||||
assert (g() === 2);
|
||||
}
|
||||
|
||||
assert (g() === 2);
|
||||
}
|
||||
f1();
|
||||
|
||||
function f2() {
|
||||
/* Function hoisted as let. */
|
||||
assert (g === -1);
|
||||
|
||||
{
|
||||
let g = 1;
|
||||
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
assert (g() === 2);
|
||||
|
||||
if (true)
|
||||
{
|
||||
eval("assert (g() === 2)");
|
||||
}
|
||||
|
||||
function g() { return 2 };
|
||||
}
|
||||
|
||||
assert (g === 1);
|
||||
}
|
||||
|
||||
assert (g === 1);
|
||||
}
|
||||
|
||||
assert (g === -1);
|
||||
}
|
||||
f2();
|
||||
35
tests/jerry/es2015/let5.js
Normal file
35
tests/jerry/es2015/let5.js
Normal file
@ -0,0 +1,35 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
let arr = [];
|
||||
|
||||
for (var a = 0; a < 10; a++)
|
||||
{
|
||||
let j = a;
|
||||
var f;
|
||||
|
||||
{
|
||||
f = function () { return j; }
|
||||
|
||||
let j = (a & 0x1) ? a + 10 : a + 100;
|
||||
}
|
||||
|
||||
arr[j] = f;
|
||||
}
|
||||
|
||||
for (var a = 0; a < 10; a++)
|
||||
{
|
||||
assert (arr[a]() == ((a & 0x1) ? a + 10 : a + 100))
|
||||
}
|
||||
79
tests/jerry/es2015/let6.js
Normal file
79
tests/jerry/es2015/let6.js
Normal file
@ -0,0 +1,79 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
try {
|
||||
let a = 1;
|
||||
eval ("assert(a === 1)");
|
||||
} catch (e) {
|
||||
assert (false);
|
||||
}
|
||||
|
||||
assert (typeof a === "undefined");
|
||||
|
||||
try {
|
||||
let a = 2;
|
||||
eval ("assert(a === 2)");
|
||||
|
||||
assert (typeof b === "undefined");
|
||||
throw 3;
|
||||
} catch (e) {
|
||||
let b = e;
|
||||
eval ("assert(b === 3)");
|
||||
|
||||
assert (typeof a === "undefined");
|
||||
}
|
||||
|
||||
assert (typeof a === "undefined");
|
||||
assert (typeof b === "undefined");
|
||||
|
||||
try {
|
||||
let a = 4;
|
||||
eval ("assert(a === 4)");
|
||||
|
||||
assert (typeof b === "undefined");
|
||||
} finally {
|
||||
let b = 5;
|
||||
eval ("assert(b === 5)");
|
||||
|
||||
assert (typeof a === "undefined");
|
||||
}
|
||||
|
||||
assert (typeof a === "undefined");
|
||||
assert (typeof b === "undefined");
|
||||
|
||||
try {
|
||||
let a = 6;
|
||||
eval ("assert(a === 6)");
|
||||
|
||||
assert (typeof b === "undefined");
|
||||
assert (typeof c === "undefined");
|
||||
throw 7;
|
||||
} catch (e) {
|
||||
let b = e;
|
||||
eval ("assert(b === 7)");
|
||||
|
||||
assert (typeof a === "undefined");
|
||||
assert (typeof c === "undefined");
|
||||
} finally {
|
||||
let c = 8;
|
||||
eval ("assert(c === 8)");
|
||||
|
||||
assert (typeof a === "undefined");
|
||||
assert (typeof b === "undefined");
|
||||
}
|
||||
|
||||
assert (typeof a === "undefined");
|
||||
assert (typeof b === "undefined");
|
||||
assert (typeof c === "undefined");
|
||||
68
tests/jerry/es2015/let7.js
Normal file
68
tests/jerry/es2015/let7.js
Normal file
@ -0,0 +1,68 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
|
||||
assert (typeof f === "undefined");
|
||||
|
||||
function g() { return 6; }
|
||||
|
||||
switch (g()) {
|
||||
case f():
|
||||
|
||||
let g = 9;
|
||||
|
||||
assert (g === 9);
|
||||
|
||||
function f() { return 6; }
|
||||
break;
|
||||
|
||||
default:
|
||||
assert (false);
|
||||
}
|
||||
|
||||
assert (f() === 6);
|
||||
|
||||
switch (g()) {
|
||||
case f() - 2:
|
||||
|
||||
let g = 9;
|
||||
|
||||
assert ((function() { return g + f(); })() === 17);
|
||||
|
||||
function f() { return 8; }
|
||||
break;
|
||||
|
||||
default:
|
||||
assert (false);
|
||||
}
|
||||
|
||||
assert (f() === 8);
|
||||
|
||||
switch (g()) {
|
||||
case g() * 2:
|
||||
|
||||
{
|
||||
let g = 4;
|
||||
assert (g == 4);
|
||||
}
|
||||
|
||||
function g() { return 3; }
|
||||
break;
|
||||
|
||||
default:
|
||||
assert (false);
|
||||
}
|
||||
|
||||
assert (g() === 3);
|
||||
58
tests/jerry/es2015/let8.js
Normal file
58
tests/jerry/es2015/let8.js
Normal file
@ -0,0 +1,58 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
assert (typeof A === "undefined");
|
||||
|
||||
{
|
||||
class A {};
|
||||
|
||||
{
|
||||
let A = 6;
|
||||
|
||||
assert (A === 6);
|
||||
}
|
||||
|
||||
assert (typeof A === "function");
|
||||
}
|
||||
|
||||
assert (typeof A === "undefined");
|
||||
|
||||
{
|
||||
let A = 5;
|
||||
{
|
||||
{
|
||||
class A {};
|
||||
|
||||
assert (typeof A === "function");
|
||||
}
|
||||
|
||||
assert (A === 5);
|
||||
}
|
||||
}
|
||||
|
||||
assert (typeof A === "undefined");
|
||||
|
||||
{
|
||||
let A = 5;
|
||||
{
|
||||
{
|
||||
class A {};
|
||||
|
||||
eval ('assert (typeof A === "function")');
|
||||
}
|
||||
|
||||
eval ('assert (A === 5)');
|
||||
}
|
||||
}
|
||||
25
tests/jerry/es5.1/func-decl.js
Normal file
25
tests/jerry/es5.1/func-decl.js
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright JS Foundation and other contributors, http://js.foundation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
function f() {
|
||||
return 'foo';
|
||||
}
|
||||
assert ((function() {
|
||||
if (1 === 0) {
|
||||
function f() {
|
||||
return 'bar';
|
||||
}
|
||||
}
|
||||
return f();
|
||||
})() === 'bar');
|
||||
@ -16,7 +16,7 @@ function f() {
|
||||
return 'foo';
|
||||
}
|
||||
assert ((function() {
|
||||
if (1 === 0) {
|
||||
if (1 === 1) {
|
||||
function f() {
|
||||
return 'bar';
|
||||
}
|
||||
|
||||
@ -223,15 +223,15 @@ main (void)
|
||||
/* Check the snapshot data. Unused bytes should be filled with zeroes */
|
||||
const uint8_t expected_data[] =
|
||||
{
|
||||
0x4A, 0x52, 0x52, 0x59, 0x19, 0x00, 0x00, 0x00,
|
||||
0x4A, 0x52, 0x52, 0x59, 0x1A, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x01, 0x00, 0x21, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00,
|
||||
0x28, 0x00, 0xB7, 0x45, 0x00, 0x00, 0x00, 0x00,
|
||||
0x2C, 0x00, 0xBC, 0x4A, 0x00, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x01, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x00,
|
||||
0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
|
||||
0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x73, 0x6E,
|
||||
0x61, 0x70, 0x73, 0x68, 0x6F, 0x74,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user