Implement function destructuring argument support. (#3322)
Furthermore create unmapped arguments objects if a function has a non-simple argument. A few destructuring pattern issues were fixed as well. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
committed by
Dániel Bátyai
parent
359643b5b2
commit
8bdb32cc88
@@ -417,7 +417,7 @@ static_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< c
|
||||
}
|
||||
}
|
||||
|
||||
if (CBC_NON_STRICT_ARGUMENTS_NEEDED (compiled_code_p))
|
||||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
|
||||
{
|
||||
buffer_p += ((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG;
|
||||
literal_start_p = ((ecma_value_t *) buffer_p) - argument_end;
|
||||
@@ -489,7 +489,7 @@ jerry_snapshot_set_offsets (uint32_t *buffer_p, /**< buffer */
|
||||
}
|
||||
}
|
||||
|
||||
if (CBC_NON_STRICT_ARGUMENTS_NEEDED (bytecode_p))
|
||||
if (bytecode_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
|
||||
{
|
||||
uint8_t *byte_p = (uint8_t *) bytecode_p;
|
||||
byte_p += ((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG;
|
||||
@@ -582,7 +582,7 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th
|
||||
uint8_t *byte_p = (uint8_t *) bytecode_p;
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) byte_p;
|
||||
|
||||
if (CBC_NON_STRICT_ARGUMENTS_NEEDED (bytecode_p))
|
||||
if (bytecode_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
|
||||
{
|
||||
argument_end = args_p->argument_end;
|
||||
}
|
||||
@@ -596,7 +596,7 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th
|
||||
uint8_t *byte_p = (uint8_t *) bytecode_p;
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) byte_p;
|
||||
|
||||
if (CBC_NON_STRICT_ARGUMENTS_NEEDED (bytecode_p))
|
||||
if (bytecode_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
|
||||
{
|
||||
argument_end = args_p->argument_end;
|
||||
}
|
||||
@@ -1092,7 +1092,7 @@ scan_snapshot_functions (const uint8_t *buffer_p, /**< snapshot buffer start */
|
||||
}
|
||||
}
|
||||
|
||||
if (CBC_NON_STRICT_ARGUMENTS_NEEDED (bytecode_p))
|
||||
if (bytecode_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
|
||||
{
|
||||
uint8_t *byte_p = (uint8_t *) bytecode_p;
|
||||
byte_p += ((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG;
|
||||
@@ -1170,7 +1170,7 @@ update_literal_offsets (uint8_t *buffer_p, /**< [in,out] snapshot buffer start *
|
||||
}
|
||||
}
|
||||
|
||||
if (CBC_NON_STRICT_ARGUMENTS_NEEDED (bytecode_p))
|
||||
if (bytecode_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
|
||||
{
|
||||
uint8_t *byte_p = (uint8_t *) bytecode_p;
|
||||
byte_p += ((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG;
|
||||
|
||||
@@ -346,7 +346,7 @@ ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_
|
||||
const_literal_end = args_p->const_literal_end - register_end;
|
||||
literal_end = args_p->literal_end - register_end;
|
||||
|
||||
if (CBC_NON_STRICT_ARGUMENTS_NEEDED (compiled_code_p))
|
||||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
|
||||
{
|
||||
argument_end = args_p->argument_end;
|
||||
}
|
||||
@@ -361,7 +361,7 @@ ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_
|
||||
const_literal_end = args_p->const_literal_end - register_end;
|
||||
literal_end = args_p->literal_end - register_end;
|
||||
|
||||
if (CBC_NON_STRICT_ARGUMENTS_NEEDED (compiled_code_p))
|
||||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
|
||||
{
|
||||
argument_end = args_p->argument_end;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ ecma_op_resource_name (const ecma_compiled_code_t *bytecode_header_p)
|
||||
|
||||
ecma_length_t formal_params_number = 0;
|
||||
|
||||
if (CBC_NON_STRICT_ARGUMENTS_NEEDED (bytecode_header_p))
|
||||
if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
|
||||
{
|
||||
if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
{
|
||||
@@ -832,7 +832,7 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
|
||||
else
|
||||
{
|
||||
local_env_p = ecma_create_decl_lex_env (scope_p);
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_ARGUMENTS_NEEDED)
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_IS_ARGUMENTS_NEEDED)
|
||||
{
|
||||
ecma_op_create_arguments_object (func_obj_p,
|
||||
local_env_p,
|
||||
@@ -908,7 +908,7 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
|
||||
{
|
||||
local_env_p = ecma_create_decl_lex_env (scope_p);
|
||||
|
||||
JERRY_ASSERT (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_ARGUMENTS_NEEDED));
|
||||
JERRY_ASSERT (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_IS_ARGUMENTS_NEEDED));
|
||||
}
|
||||
|
||||
ecma_value_t ret_value = vm_run (bytecode_data_p,
|
||||
|
||||
@@ -68,7 +68,9 @@ ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function
|
||||
|
||||
ecma_object_t *obj_p;
|
||||
|
||||
if (!is_strict && arguments_number > 0 && formal_params_number > 0)
|
||||
if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
|
||||
&& arguments_number > 0
|
||||
&& formal_params_number > 0)
|
||||
{
|
||||
size_t formal_params_size = formal_params_number * sizeof (ecma_value_t);
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ extern "C"
|
||||
/**
|
||||
* Jerry snapshot format version.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_VERSION (29u)
|
||||
#define JERRY_SNAPSHOT_VERSION (30u)
|
||||
|
||||
/**
|
||||
* Flags for jerry_generate_snapshot and jerry_generate_function_snapshot.
|
||||
|
||||
@@ -308,6 +308,8 @@
|
||||
VM_OC_INIT_LOCALS) \
|
||||
CBC_OPCODE (CBC_CREATE_CONST, CBC_HAS_LITERAL_ARG, 0, \
|
||||
VM_OC_INIT_LOCALS) \
|
||||
CBC_OPCODE (CBC_CREATE_DESTRUCTURED_ARG, CBC_HAS_LITERAL_ARG, 0, \
|
||||
VM_OC_NONE) \
|
||||
CBC_OPCODE (CBC_INIT_LOCAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
|
||||
VM_OC_INIT_LOCALS) \
|
||||
CBC_OPCODE (CBC_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0, \
|
||||
@@ -538,7 +540,7 @@
|
||||
-1 + PARSER_SUPER_CLASS_CONTEXT_STACK_ALLOCATION, VM_OC_CLASS_HERITAGE) \
|
||||
CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP, CBC_NO_FLAG, 0, \
|
||||
VM_OC_INITIALIZER_PUSH_PROP | VM_OC_GET_STACK) \
|
||||
CBC_FORWARD_BRANCH (CBC_EXT_DEFAULT_INITIALIZER, 0, \
|
||||
CBC_FORWARD_BRANCH (CBC_EXT_DEFAULT_INITIALIZER, -1, \
|
||||
VM_OC_DEFAULT_INITIALIZER) \
|
||||
\
|
||||
/* Basic opcodes. */ \
|
||||
@@ -712,21 +714,21 @@ typedef enum
|
||||
CBC_CODE_FLAGS_FULL_LITERAL_ENCODING = (1u << 1), /**< full literal encoding mode is enabled */
|
||||
CBC_CODE_FLAGS_UINT16_ARGUMENTS = (1u << 2), /**< compiled code data is cbc_uint16_arguments_t */
|
||||
CBC_CODE_FLAGS_STRICT_MODE = (1u << 3), /**< strict mode is enabled */
|
||||
CBC_CODE_FLAGS_ARGUMENTS_NEEDED = (1u << 4), /**< arguments object must be constructed */
|
||||
CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED = (1u << 5), /**< no need to create a lexical environment */
|
||||
CBC_CODE_FLAGS_ARROW_FUNCTION = (1u << 6), /**< this function is an arrow function */
|
||||
CBC_CODE_FLAGS_STATIC_FUNCTION = (1u << 7), /**< this function is a static snapshot function */
|
||||
CBC_CODE_FLAGS_DEBUGGER_IGNORE = (1u << 8), /**< this function should be ignored by debugger */
|
||||
CBC_CODE_FLAGS_CONSTRUCTOR = (1u << 9), /**< this function is a constructor */
|
||||
CBC_CODE_FLAGS_REST_PARAMETER = (1u << 10), /**< this function has rest parameter */
|
||||
CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED = (1u << 4), /**< mapped arguments object must be constructed */
|
||||
CBC_CODE_FLAGS_UNMAPPED_ARGUMENTS_NEEDED = (1u << 5), /**< mapped arguments object must be constructed */
|
||||
CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED = (1u << 6), /**< no need to create a lexical environment */
|
||||
CBC_CODE_FLAGS_ARROW_FUNCTION = (1u << 7), /**< this function is an arrow function */
|
||||
CBC_CODE_FLAGS_STATIC_FUNCTION = (1u << 8), /**< this function is a static snapshot function */
|
||||
CBC_CODE_FLAGS_DEBUGGER_IGNORE = (1u << 9), /**< this function should be ignored by debugger */
|
||||
CBC_CODE_FLAGS_CONSTRUCTOR = (1u << 10), /**< this function is a constructor */
|
||||
CBC_CODE_FLAGS_REST_PARAMETER = (1u << 11), /**< this function has rest parameter */
|
||||
} cbc_code_flags;
|
||||
|
||||
/**
|
||||
* Non-strict arguments object must be constructed
|
||||
* Any arguments object is needed
|
||||
*/
|
||||
#define CBC_NON_STRICT_ARGUMENTS_NEEDED(compiled_code_p) \
|
||||
(((compiled_code_p)->status_flags & CBC_CODE_FLAGS_ARGUMENTS_NEEDED) \
|
||||
&& !((compiled_code_p)->status_flags & CBC_CODE_FLAGS_STRICT_MODE))
|
||||
#define CBC_CODE_FLAGS_IS_ARGUMENTS_NEEDED \
|
||||
(CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED | CBC_CODE_FLAGS_UNMAPPED_ARGUMENTS_NEEDED)
|
||||
|
||||
#define CBC_OPCODE(arg1, arg2, arg3, arg4) arg1,
|
||||
|
||||
|
||||
@@ -388,18 +388,14 @@ parser_append_object_literal_item (parser_context_t *context_p, /**< context */
|
||||
#endif /* !ENABLED (JERRY_ES2015) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
/**
|
||||
* Definition of parse object initializer.
|
||||
*/
|
||||
static void
|
||||
parser_parse_object_initializer (parser_context_t *context_p, parser_pattern_flags_t flags);
|
||||
|
||||
/**
|
||||
* Definition of parse array initializer.
|
||||
*/
|
||||
/** Forward definition of parse array initializer. */
|
||||
static void
|
||||
parser_parse_array_initializer (parser_context_t *context_p, parser_pattern_flags_t flags);
|
||||
|
||||
/** Forward definition of parse object initializer. */
|
||||
static void
|
||||
parser_parse_object_initializer (parser_context_t *context_p, parser_pattern_flags_t flags);
|
||||
|
||||
/**
|
||||
* Description of "get" literal string.
|
||||
*/
|
||||
@@ -2111,7 +2107,6 @@ parser_pattern_get_target (parser_context_t *context_p, /**< context */
|
||||
JERRY_ASSERT (flags & PARSER_PATTERN_TARGET_ON_STACK);
|
||||
|
||||
parser_emit_cbc_forward_branch (context_p, PARSER_TO_EXT_OPCODE (CBC_EXT_DEFAULT_INITIALIZER), &skip_init);
|
||||
parser_emit_cbc (context_p, CBC_POP);
|
||||
}
|
||||
|
||||
if ((flags & (PARSER_PATTERN_TARGET_ON_STACK | PARSER_PATTERN_TARGET_DEFAULT)) != PARSER_PATTERN_TARGET_ON_STACK)
|
||||
@@ -2177,8 +2172,7 @@ parser_pattern_finalize (parser_context_t *context_p, /**< context */
|
||||
lexer_next_token (context_p);
|
||||
}
|
||||
|
||||
if ((flags & PARSER_PATTERN_BINDING)
|
||||
&& !(flags & PARSER_PATTERN_NESTED_PATTERN))
|
||||
if ((flags & (PARSER_PATTERN_BINDING | PARSER_PATTERN_NESTED_PATTERN)) == PARSER_PATTERN_BINDING)
|
||||
{
|
||||
/* Pop the result of the expression. */
|
||||
parser_emit_cbc (context_p, CBC_POP);
|
||||
@@ -2235,9 +2229,8 @@ parser_pattern_form_assignment (parser_context_t *context_p, /**< context */
|
||||
parser_branch_t skip_init;
|
||||
lexer_next_token (context_p);
|
||||
parser_emit_cbc_forward_branch (context_p, PARSER_TO_EXT_OPCODE (CBC_EXT_DEFAULT_INITIALIZER), &skip_init);
|
||||
parser_emit_cbc (context_p, CBC_POP);
|
||||
|
||||
parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA | PARSE_EXPR_LEFT_HAND_SIDE);
|
||||
parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
|
||||
parser_set_branch_to_current_position (context_p, &skip_init);
|
||||
}
|
||||
|
||||
@@ -2336,6 +2329,15 @@ parser_pattern_process_assignment (parser_context_t *context_p, /**< context */
|
||||
parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
|
||||
}
|
||||
|
||||
if (flags & PARSER_PATTERN_ARGUMENTS)
|
||||
{
|
||||
if (context_p->lit_object.literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
|
||||
}
|
||||
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_FUNCTION_ARGUMENT;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
parser_module_append_export_name (context_p);
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
@@ -2461,15 +2463,6 @@ parser_parse_object_initializer (parser_context_t *context_p, /**< context */
|
||||
|
||||
lexer_next_token (context_p);
|
||||
|
||||
if (push_prop_opcode != CBC_EXT_INITIALIZER_PUSH_PROP
|
||||
&& (context_p->token.type == LEXER_RIGHT_BRACE
|
||||
|| context_p->token.type == LEXER_ASSIGN
|
||||
|| context_p->token.type == LEXER_COMMA))
|
||||
{
|
||||
parser_reparse_as_common_identifier (context_p, start_line, start_column);
|
||||
lexer_next_token (context_p);
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_COLON)
|
||||
{
|
||||
lexer_next_token (context_p);
|
||||
@@ -2477,6 +2470,24 @@ parser_parse_object_initializer (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (push_prop_opcode != CBC_EXT_INITIALIZER_PUSH_PROP
|
||||
&& (context_p->token.type == LEXER_RIGHT_BRACE
|
||||
|| context_p->token.type == LEXER_ASSIGN
|
||||
|| context_p->token.type == LEXER_COMMA))
|
||||
{
|
||||
parser_reparse_as_common_identifier (context_p, start_line, start_column);
|
||||
lexer_next_token (context_p);
|
||||
}
|
||||
|
||||
if (flags & PARSER_PATTERN_ARGUMENTS)
|
||||
{
|
||||
if (context_p->lit_object.literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
|
||||
}
|
||||
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_FUNCTION_ARGUMENT;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
parser_module_append_export_name (context_p);
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
@@ -51,21 +51,22 @@ typedef enum
|
||||
PARSER_HAS_NON_STRICT_ARG = (1u << 6), /**< the function has arguments which
|
||||
* are not supported in strict mode */
|
||||
PARSER_ARGUMENTS_NEEDED = (1u << 7), /**< arguments object must be created */
|
||||
PARSER_LEXICAL_ENV_NEEDED = (1u << 9), /**< lexical environment object must be created */
|
||||
PARSER_INSIDE_WITH = (1u << 10), /**< code block is inside a with statement */
|
||||
PARSER_RESOLVE_BASE_FOR_CALLS = (1u << 11), /**< the this object must be resolved when
|
||||
PARSER_LEXICAL_ENV_NEEDED = (1u << 8), /**< lexical environment object must be created */
|
||||
PARSER_INSIDE_WITH = (1u << 9), /**< code block is inside a with statement */
|
||||
PARSER_RESOLVE_BASE_FOR_CALLS = (1u << 10), /**< the this object must be resolved when
|
||||
* a function without a base object is called */
|
||||
PARSER_HAS_INITIALIZED_VARS = (1u << 12), /**< a CBC_INITIALIZE_VARS instruction must be emitted */
|
||||
PARSER_HAS_LATE_LIT_INIT = (1u << 13), /**< allocate memory for this string after
|
||||
PARSER_HAS_INITIALIZED_VARS = (1u << 11), /**< a CBC_INITIALIZE_VARS instruction must be emitted */
|
||||
PARSER_HAS_LATE_LIT_INIT = (1u << 12), /**< allocate memory for this string after
|
||||
* the local parser data is freed */
|
||||
PARSER_NO_END_LABEL = (1u << 14), /**< return instruction must be inserted
|
||||
PARSER_NO_END_LABEL = (1u << 13), /**< return instruction must be inserted
|
||||
* after the last byte code */
|
||||
PARSER_DEBUGGER_BREAKPOINT_APPENDED = (1u << 15), /**< pending (unsent) breakpoint
|
||||
PARSER_DEBUGGER_BREAKPOINT_APPENDED = (1u << 14), /**< pending (unsent) breakpoint
|
||||
* info is available */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
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_INSIDE_BLOCK = (1u << 15), /**< script has a lexical environment for let and const */
|
||||
PARSER_IS_ARROW_FUNCTION = (1u << 16), /**< an arrow function is parsed */
|
||||
PARSER_ARROW_PARSE_ARGS = (1u << 17), /**< parse the argument list of an arrow function */
|
||||
PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM = (1u << 18), /**< function has a non simple parameter */
|
||||
PARSER_FUNCTION_HAS_REST_PARAM = (1u << 19), /**< function has rest parameter */
|
||||
/* 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
|
||||
@@ -107,10 +108,11 @@ typedef enum
|
||||
PARSER_PATTERN_NO_OPTS = 0, /**< parse the expression after '=' */
|
||||
PARSER_PATTERN_BINDING = (1u << 0), /**< parse BindingPattern */
|
||||
PARSER_PATTERN_TARGET_ON_STACK = (1u << 1), /**< assignment target is the topmost element on the stack */
|
||||
PARSER_PATTERN_TARGET_DEFAULT = (1u << 3), /**< perform default value comparison for assignment target */
|
||||
PARSER_PATTERN_NESTED_PATTERN = (1u << 4), /**< parse patter inside a pattern */
|
||||
PARSER_PATTERN_LEXICAL = (1u << 5), /**< pattern is a lexical (let/const) declaration */
|
||||
PARSER_PATTERN_REST_ELEMENT = (1u << 6), /**< parse rest array initializer */
|
||||
PARSER_PATTERN_TARGET_DEFAULT = (1u << 2), /**< perform default value comparison for assignment target */
|
||||
PARSER_PATTERN_NESTED_PATTERN = (1u << 3), /**< parse patter inside a pattern */
|
||||
PARSER_PATTERN_LEXICAL = (1u << 4), /**< pattern is a lexical (let/const) declaration */
|
||||
PARSER_PATTERN_REST_ELEMENT = (1u << 5), /**< parse rest array initializer */
|
||||
PARSER_PATTERN_ARGUMENTS = (1u << 6), /**< parse arguments binding */
|
||||
} parser_pattern_flags_t;
|
||||
|
||||
/**
|
||||
@@ -159,8 +161,23 @@ typedef enum
|
||||
*/
|
||||
#define PARSER_IS_CLASS_CONSTRUCTOR_SUPER(flag) \
|
||||
(((flag) & PARSER_CLASS_CONSTRUCTOR_SUPER) == PARSER_CLASS_CONSTRUCTOR_SUPER)
|
||||
|
||||
/* All flags that affect exotic arguments object creation. */
|
||||
#define PARSER_ARGUMENTS_RELATED_FLAGS \
|
||||
(PARSER_ARGUMENTS_NEEDED | PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM | PARSER_IS_STRICT)
|
||||
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
|
||||
/* All flags that affect exotic arguments object creation. */
|
||||
#define PARSER_ARGUMENTS_RELATED_FLAGS \
|
||||
(PARSER_ARGUMENTS_NEEDED | PARSER_IS_STRICT)
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/* Checks whether unmapped arguments are needed. */
|
||||
#define PARSER_NEEDS_MAPPED_ARGUMENTS(status_flags) \
|
||||
(((status_flags) & PARSER_ARGUMENTS_RELATED_FLAGS) == PARSER_ARGUMENTS_NEEDED)
|
||||
|
||||
/* The maximum of PARSER_CBC_STREAM_PAGE_SIZE is 127. */
|
||||
#define PARSER_CBC_STREAM_PAGE_SIZE \
|
||||
((uint32_t) (64 - sizeof (void *)))
|
||||
|
||||
@@ -654,9 +654,14 @@ parse_print_final_cbc (ecma_compiled_code_t *compiled_code_p, /**< compiled code
|
||||
JERRY_DEBUG_MSG (",strict_mode");
|
||||
}
|
||||
|
||||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_ARGUMENTS_NEEDED)
|
||||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
|
||||
{
|
||||
JERRY_DEBUG_MSG (",arguments_needed");
|
||||
JERRY_DEBUG_MSG (",mapped_arguments_needed");
|
||||
}
|
||||
|
||||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UNMAPPED_ARGUMENTS_NEEDED)
|
||||
{
|
||||
JERRY_DEBUG_MSG (",unmapped_arguments_needed");
|
||||
}
|
||||
|
||||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED)
|
||||
@@ -1148,8 +1153,7 @@ parser_post_processing (parser_context_t *context_p) /**< context */
|
||||
|
||||
total_size += literal_length + length;
|
||||
|
||||
if ((context_p->status_flags & PARSER_ARGUMENTS_NEEDED)
|
||||
&& !(context_p->status_flags & PARSER_IS_STRICT))
|
||||
if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags))
|
||||
{
|
||||
total_size += context_p->argument_count * sizeof (ecma_value_t);
|
||||
}
|
||||
@@ -1243,7 +1247,14 @@ parser_post_processing (parser_context_t *context_p) /**< context */
|
||||
|
||||
if (context_p->status_flags & PARSER_ARGUMENTS_NEEDED)
|
||||
{
|
||||
compiled_code_p->status_flags |= CBC_CODE_FLAGS_ARGUMENTS_NEEDED;
|
||||
if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags))
|
||||
{
|
||||
compiled_code_p->status_flags |= CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED;
|
||||
}
|
||||
else
|
||||
{
|
||||
compiled_code_p->status_flags |= CBC_CODE_FLAGS_UNMAPPED_ARGUMENTS_NEEDED;
|
||||
}
|
||||
|
||||
/* Arguments is stored in the lexical environment. */
|
||||
context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED;
|
||||
@@ -1513,8 +1524,7 @@ parser_post_processing (parser_context_t *context_p) /**< context */
|
||||
}
|
||||
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
|
||||
|
||||
if ((context_p->status_flags & PARSER_ARGUMENTS_NEEDED)
|
||||
&& !(context_p->status_flags & PARSER_IS_STRICT))
|
||||
if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags))
|
||||
{
|
||||
parser_list_iterator_t literal_iterator;
|
||||
uint16_t argument_count = 0;
|
||||
@@ -1557,8 +1567,7 @@ parser_post_processing (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
ecma_value_t *resource_name_p = (ecma_value_t *) (((uint8_t *) compiled_code_p) + total_size);
|
||||
|
||||
if ((context_p->status_flags & PARSER_ARGUMENTS_NEEDED)
|
||||
&& !(context_p->status_flags & PARSER_IS_STRICT))
|
||||
if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags))
|
||||
{
|
||||
resource_name_p -= context_p->argument_count;
|
||||
}
|
||||
@@ -1607,7 +1616,6 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
bool duplicated_argument_names = false;
|
||||
bool initializer_found = false;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
|
||||
@@ -1637,7 +1645,47 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */
|
||||
parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES);
|
||||
}
|
||||
|
||||
context_p->status_flags |= PARSER_FUNCTION_HAS_REST_PARAM;
|
||||
context_p->status_flags |= PARSER_FUNCTION_HAS_REST_PARAM | PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM;
|
||||
}
|
||||
else if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE)
|
||||
{
|
||||
if (duplicated_argument_names)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES);
|
||||
}
|
||||
|
||||
context_p->status_flags |= PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM;
|
||||
|
||||
parser_emit_cbc_literal (context_p,
|
||||
CBC_PUSH_LITERAL,
|
||||
(uint16_t) (PARSER_REGISTER_START + context_p->argument_count));
|
||||
|
||||
uint32_t flags = (PARSER_PATTERN_BINDING
|
||||
| PARSER_PATTERN_TARGET_ON_STACK
|
||||
| PARSER_PATTERN_LEXICAL
|
||||
| PARSER_PATTERN_ARGUMENTS);
|
||||
|
||||
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
|
||||
{
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER);
|
||||
flags |= PARSER_PATTERN_TARGET_DEFAULT;
|
||||
}
|
||||
|
||||
parser_parse_initializer (context_p, (parser_pattern_flags_t) flags);
|
||||
|
||||
context_p->argument_count++;
|
||||
if (context_p->argument_count >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED);
|
||||
}
|
||||
|
||||
if (context_p->token.type != LEXER_COMMA)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
lexer_next_token (context_p);
|
||||
continue;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
@@ -1660,12 +1708,10 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */
|
||||
if (JERRY_UNLIKELY (context_p->lit_object.literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT))
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (initializer_found)
|
||||
if (context_p->status_flags & PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
duplicated_argument_names = true;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
@@ -1698,7 +1744,8 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES);
|
||||
}
|
||||
initializer_found = true;
|
||||
|
||||
context_p->status_flags |= PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM;
|
||||
|
||||
/* LEXER_ASSIGN does not overwrite lit_object. */
|
||||
parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED);
|
||||
|
||||
@@ -49,11 +49,27 @@ typedef enum
|
||||
{
|
||||
SCANNER_LITERAL_IS_ARG = (1 << 0), /**< literal is argument */
|
||||
SCANNER_LITERAL_IS_VAR = (1 << 1), /**< literal is var */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
/** literal is a destructured argument binding of a possible arrow function */
|
||||
SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG = SCANNER_LITERAL_IS_VAR,
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
SCANNER_LITERAL_IS_FUNC = (1 << 2), /**< literal is function */
|
||||
SCANNER_LITERAL_NO_REG = (1 << 3), /**< literal cannot be stored in register */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
/** a destructured argument binding of a possible arrow function cannot be stored in a register */
|
||||
SCANNER_LITERAL_ARROW_DESTRUCTURED_ARG_NO_REG = SCANNER_LITERAL_IS_FUNC,
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
SCANNER_LITERAL_NO_REG = (1 << 3), /**< literal cannot be stored in a register */
|
||||
SCANNER_LITERAL_IS_LET = (1 << 4), /**< literal is let */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
/** literal is a function declared in this block (prevents declaring let/const with the same name) */
|
||||
SCANNER_LITERAL_IS_FUNC_DECLARATION = SCANNER_LITERAL_IS_LET,
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
SCANNER_LITERAL_IS_CONST = (1 << 5), /**< literal is const */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
/** literal is a destructured argument binding */
|
||||
SCANNER_LITERAL_IS_DESTRUCTURED_ARG = SCANNER_LITERAL_IS_CONST,
|
||||
/** literal is a local function */
|
||||
SCANNER_LITERAL_IS_FUNC_LOCAL = SCANNER_LITERAL_IS_CONST,
|
||||
SCANNER_LITERAL_IS_USED = (1 << 6), /**< literal is used */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
} scanner_literal_type_flags_t;
|
||||
@@ -61,9 +77,18 @@ typedef enum
|
||||
/*
|
||||
* Known combinations:
|
||||
*
|
||||
* SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET : function declared in this block, might be let or var
|
||||
* SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_CONST : function declared in this block, must be let
|
||||
* SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_IS_CONST : module import on global scope, catch block variable otherwise
|
||||
* SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_FUNC_DECLARATION :
|
||||
* function declared in this block, might be let or var
|
||||
* SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_FUNC_LOCAL :
|
||||
* function is visible only in this block
|
||||
* SCANNER_LITERAL_IS_LOCAL :
|
||||
* module import on global scope, catch block variable otherwise
|
||||
* SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_FUNC :
|
||||
* a function argument which is reassigned to a function later
|
||||
* SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG :
|
||||
* destructured binding argument
|
||||
* SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG | SCANNER_LITERAL_IS_FUNC :
|
||||
* destructured binding argument which is reassigned to a function later
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -104,6 +129,8 @@ typedef enum
|
||||
SCANNER_BINDING_VAR, /**< destructuring var binding */
|
||||
SCANNER_BINDING_LET, /**< destructuring let binding */
|
||||
SCANNER_BINDING_CONST, /**< destructuring const binding */
|
||||
SCANNER_BINDING_ARG, /**< destructuring arg binding */
|
||||
SCANNER_BINDING_ARROW_ARG, /**< possible destructuring arg binding of an arrow function */
|
||||
} scanner_binding_type_t;
|
||||
|
||||
/**
|
||||
@@ -222,6 +249,7 @@ void scanner_detect_eval_call (parser_context_t *context_p, scanner_context_t *s
|
||||
void scanner_push_destructuring_pattern (parser_context_t *context_p, scanner_context_t *scanner_context_p,
|
||||
uint8_t binding_type, bool is_nested);
|
||||
void scanner_pop_binding_list (scanner_context_t *scanner_context_p);
|
||||
void scanner_append_hole (parser_context_t *context_p, scanner_context_t *scanner_context_p);
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,6 +34,31 @@
|
||||
JERRY_STATIC_ASSERT (PARSER_MAXIMUM_NUMBER_OF_LITERALS + PARSER_MAXIMUM_NUMBER_OF_REGISTERS < PARSER_REGISTER_START,
|
||||
maximum_number_of_literals_plus_registers_must_be_less_than_register_start);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|
||||
JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG & SCANNER_LITERAL_IS_LOCAL) == 0,
|
||||
is_arrow_arg_binding_flag_must_not_use_local_flags);
|
||||
|
||||
JERRY_STATIC_ASSERT ((SCANNER_LITERAL_ARROW_DESTRUCTURED_ARG_NO_REG & SCANNER_LITERAL_IS_LOCAL) == 0,
|
||||
arrow_arg_binding_no_reg_flag_must_not_use_local_flags);
|
||||
|
||||
JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_LET & SCANNER_LITERAL_IS_LOCAL) != 0,
|
||||
is_let_flag_must_use_local_flags);
|
||||
|
||||
JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_CONST & SCANNER_LITERAL_IS_LOCAL) != 0,
|
||||
is_const_flag_must_use_local_flags);
|
||||
|
||||
JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_FUNC_DECLARATION & SCANNER_LITERAL_IS_LOCAL) != 0,
|
||||
is_func_declaration_flag_must_use_local_flags);
|
||||
|
||||
JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_DESTRUCTURED_ARG & SCANNER_LITERAL_IS_LOCAL) != 0,
|
||||
is_arg_binding_flag_must_use_local_flags);
|
||||
|
||||
JERRY_STATIC_ASSERT (SCANNER_LITERAL_IS_FUNC_DECLARATION != SCANNER_LITERAL_IS_DESTRUCTURED_ARG,
|
||||
is_func_declaration_must_be_different_from_is_arg_binding);
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
* Raise a scanner error.
|
||||
*/
|
||||
@@ -116,9 +141,13 @@ scanner_get_stream_size (scanner_info_t *info_p, /**< scanner info block */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case SCANNER_STREAM_TYPE_LET:
|
||||
case SCANNER_STREAM_TYPE_CONST:
|
||||
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
case SCANNER_STREAM_TYPE_ARG:
|
||||
case SCANNER_STREAM_TYPE_ARG_FUNC:
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
case SCANNER_STREAM_TYPE_FUNC:
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case SCANNER_STREAM_TYPE_FUNC_LOCAL:
|
||||
@@ -395,6 +424,16 @@ scanner_push_literal_pool (parser_context_t *context_p, /**< context */
|
||||
JERRY_STATIC_ASSERT (PARSER_MAXIMUM_IDENT_LENGTH <= UINT8_MAX,
|
||||
maximum_ident_length_must_fit_in_a_byte);
|
||||
|
||||
/**
|
||||
* Checks whether a literal is equal to "arguments".
|
||||
*/
|
||||
static inline bool JERRY_ATTR_ALWAYS_INLINE
|
||||
scanner_literal_is_arguments (lexer_lit_location_t *literal_p) /**< literal */
|
||||
{
|
||||
return (literal_p->length == 9
|
||||
&& lexer_compare_identifiers (literal_p->char_p, (const uint8_t *) "arguments", 9));
|
||||
} /* scanner_literal_is_arguments */
|
||||
|
||||
/**
|
||||
* Pop the last literal pool from the end.
|
||||
*/
|
||||
@@ -445,9 +484,7 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (search_arguments
|
||||
&& literal_p->length == 9
|
||||
&& lexer_compare_identifiers (literal_p->char_p, (const uint8_t *) "arguments", 9))
|
||||
if (search_arguments && scanner_literal_is_arguments (literal_p))
|
||||
{
|
||||
search_arguments = false;
|
||||
|
||||
@@ -542,10 +579,12 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
extended_type |= SCANNER_LITERAL_IS_USED;
|
||||
|
||||
if (literal_location_p->type & SCANNER_LITERAL_IS_LOCAL)
|
||||
if ((type & SCANNER_LITERAL_IS_ARG)
|
||||
|| (!(literal_location_p->type & SCANNER_LITERAL_IS_ARG)
|
||||
&& (literal_location_p->type & SCANNER_LITERAL_IS_LOCAL)))
|
||||
{
|
||||
JERRY_ASSERT (!(type & SCANNER_LITERAL_IS_VAR));
|
||||
/* Clears the SCANNER_LITERAL_IS_FUNC flag. */
|
||||
/* Clears the SCANNER_LITERAL_IS_VAR and SCANNER_LITERAL_IS_FUNC flags
|
||||
* for speculative arrow paramters and local (non-var) functions. */
|
||||
type = 0;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
@@ -637,9 +676,16 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
if (literal_p->type & SCANNER_LITERAL_IS_ARG)
|
||||
{
|
||||
type = SCANNER_STREAM_TYPE_ARG_FUNC;
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (literal_p->type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG)
|
||||
{
|
||||
type = SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
else if (literal_p->type & SCANNER_LITERAL_IS_CONST)
|
||||
else if (literal_p->type & SCANNER_LITERAL_IS_FUNC_LOCAL)
|
||||
{
|
||||
type = SCANNER_STREAM_TYPE_FUNC_LOCAL;
|
||||
}
|
||||
@@ -648,6 +694,13 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
else if (literal_p->type & SCANNER_LITERAL_IS_ARG)
|
||||
{
|
||||
type = SCANNER_STREAM_TYPE_ARG;
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (literal_p->type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG)
|
||||
{
|
||||
type = SCANNER_STREAM_TYPE_DESTRUCTURED_ARG;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
else if (literal_p->type & SCANNER_LITERAL_IS_LET)
|
||||
@@ -759,10 +812,19 @@ scanner_filter_arguments (parser_context_t *context_p, /**< context */
|
||||
literal_p->type |= SCANNER_LITERAL_NO_REG;
|
||||
}
|
||||
|
||||
if (!(literal_p->type & SCANNER_LITERAL_IS_ARG))
|
||||
uint8_t type = literal_p->type;
|
||||
|
||||
if (!(type & SCANNER_LITERAL_IS_ARG) && !(has_arguments && scanner_literal_is_arguments (literal_p)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (type & (SCANNER_LITERAL_IS_DESTRUCTURED_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG))
|
||||
{
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
}
|
||||
|
||||
if (literal_p == NULL)
|
||||
@@ -784,21 +846,49 @@ scanner_filter_arguments (parser_context_t *context_p, /**< context */
|
||||
|
||||
parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
/* Destructured args are placed after the other arguments because of register assignments. */
|
||||
bool has_destructured_arg = false;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
|
||||
{
|
||||
if ((literal_p->type & SCANNER_LITERAL_IS_ARG)
|
||||
|| (has_arguments
|
||||
&& literal_p->length == 9
|
||||
&& lexer_compare_identifiers (literal_p->char_p, (const uint8_t *) "arguments", 9)))
|
||||
uint8_t type = literal_p->type;
|
||||
|
||||
if ((type & SCANNER_LITERAL_IS_ARG) || (has_arguments && scanner_literal_is_arguments (literal_p)))
|
||||
{
|
||||
if (no_reg)
|
||||
{
|
||||
literal_p->type |= SCANNER_LITERAL_NO_REG;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (type & (SCANNER_LITERAL_IS_DESTRUCTURED_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG))
|
||||
{
|
||||
has_destructured_arg = true;
|
||||
|
||||
if (type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
type &= (uint8_t) ~SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG;
|
||||
type |= SCANNER_LITERAL_IS_DESTRUCTURED_ARG;
|
||||
|
||||
if (type & SCANNER_LITERAL_ARROW_DESTRUCTURED_ARG_NO_REG)
|
||||
{
|
||||
type &= (uint8_t) ~SCANNER_LITERAL_ARROW_DESTRUCTURED_ARG_NO_REG;
|
||||
type |= SCANNER_LITERAL_NO_REG;
|
||||
}
|
||||
|
||||
literal_p->type = type;
|
||||
continue;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
lexer_lit_location_t *new_literal_p;
|
||||
new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool);
|
||||
*new_literal_p = *literal_p;
|
||||
|
||||
if (no_reg)
|
||||
{
|
||||
new_literal_p->type |= SCANNER_LITERAL_NO_REG;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -806,12 +896,37 @@ scanner_filter_arguments (parser_context_t *context_p, /**< context */
|
||||
lexer_lit_location_t *literal_location_p = scanner_add_custom_literal (context_p,
|
||||
prev_literal_pool_p,
|
||||
literal_p);
|
||||
if (literal_p->type & SCANNER_LITERAL_NO_REG)
|
||||
if (type & SCANNER_LITERAL_NO_REG)
|
||||
{
|
||||
literal_location_p->type |= SCANNER_LITERAL_NO_REG;
|
||||
type |= SCANNER_LITERAL_NO_REG;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
type |= SCANNER_LITERAL_IS_USED;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
literal_location_p->type |= type;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (has_destructured_arg)
|
||||
{
|
||||
parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
|
||||
|
||||
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
|
||||
{
|
||||
const uint8_t expected_flags = SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG;
|
||||
|
||||
if ((literal_p->type & expected_flags) == expected_flags)
|
||||
{
|
||||
lexer_lit_location_t *new_literal_p;
|
||||
new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool);
|
||||
*new_literal_p = *literal_p;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
new_literal_pool_p->prev_p = prev_literal_pool_p;
|
||||
|
||||
@@ -1059,7 +1174,7 @@ scanner_detect_invalid_var (parser_context_t *context_p, /**< context */
|
||||
lexer_lit_location_t *var_literal_p) /**< var literal */
|
||||
{
|
||||
if (var_literal_p->type & SCANNER_LITERAL_IS_LOCAL
|
||||
&& !(var_literal_p->type & SCANNER_LITERAL_IS_FUNC)
|
||||
&& !(var_literal_p->type & (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_ARG))
|
||||
&& (var_literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL)
|
||||
{
|
||||
scanner_raise_redeclaration_error (context_p);
|
||||
@@ -1082,6 +1197,7 @@ scanner_detect_invalid_var (parser_context_t *context_p, /**< context */
|
||||
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
|
||||
{
|
||||
if (literal_p->type & SCANNER_LITERAL_IS_LOCAL
|
||||
&& !(literal_p->type & SCANNER_LITERAL_IS_ARG)
|
||||
&& (literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL
|
||||
&& literal_p->length == length)
|
||||
{
|
||||
@@ -1106,6 +1222,7 @@ scanner_detect_invalid_var (parser_context_t *context_p, /**< context */
|
||||
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
|
||||
{
|
||||
if (literal_p->type & SCANNER_LITERAL_IS_LOCAL
|
||||
&& !(literal_p->type & SCANNER_LITERAL_IS_ARG)
|
||||
&& (literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL
|
||||
&& literal_p->length == length
|
||||
&& lexer_compare_identifiers (literal_p->char_p, char_p, length))
|
||||
@@ -1197,7 +1314,7 @@ scanner_pop_binding_list (scanner_context_t *scanner_context_p) /**< scanner con
|
||||
{
|
||||
scanner_binding_item_t *next_p = item_p->next_p;
|
||||
|
||||
JERRY_ASSERT (item_p->literal_p->type & SCANNER_LITERAL_IS_LOCAL);
|
||||
JERRY_ASSERT (item_p->literal_p->type & (SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_IS_ARG));
|
||||
|
||||
scanner_free (item_p, sizeof (scanner_binding_item_t));
|
||||
item_p = next_p;
|
||||
@@ -1218,6 +1335,23 @@ scanner_pop_binding_list (scanner_context_t *scanner_context_p) /**< scanner con
|
||||
}
|
||||
} /* scanner_pop_binding_list */
|
||||
|
||||
/**
|
||||
* Append a hole into the literal pool.
|
||||
*/
|
||||
void
|
||||
scanner_append_hole (parser_context_t *context_p, scanner_context_t *scanner_context_p)
|
||||
{
|
||||
scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
|
||||
|
||||
lexer_lit_location_t *literal_p;
|
||||
literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool);
|
||||
|
||||
literal_p->char_p = NULL;
|
||||
literal_p->length = 0;
|
||||
literal_p->type = SCANNER_LITERAL_IS_ARG;
|
||||
literal_p->has_escape = 0;
|
||||
} /* scanner_append_hole */
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
@@ -1635,8 +1769,9 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
|
||||
JERRY_ASSERT ((option_flags & (SCANNER_CREATE_VARS_IS_FUNCTION_BODY | SCANNER_CREATE_VARS_IS_FUNCTION_ARGS))
|
||||
|| (type != SCANNER_STREAM_TYPE_HOLE
|
||||
&& type != SCANNER_STREAM_TYPE_ARG
|
||||
&& type != SCANNER_STREAM_TYPE_ARG_FUNC));
|
||||
&& !SCANNER_STREAM_TYPE_IS_ARG (type)
|
||||
&& !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type)));
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
JERRY_ASSERT (type != SCANNER_STREAM_TYPE_IMPORT || (data_p[0] & SCANNER_STREAM_NO_REG));
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
@@ -1688,7 +1823,7 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
next_data_p += 2 + 2;
|
||||
}
|
||||
|
||||
if (type == SCANNER_STREAM_TYPE_ARG)
|
||||
if (SCANNER_STREAM_TYPE_IS_ARG (type))
|
||||
{
|
||||
if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
|
||||
{
|
||||
@@ -1697,7 +1832,7 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
}
|
||||
else if ((option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)
|
||||
&& type != SCANNER_STREAM_TYPE_ARG_FUNC)
|
||||
&& !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type))
|
||||
{
|
||||
/* Function arguments must come first. */
|
||||
break;
|
||||
@@ -1710,7 +1845,7 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL);
|
||||
literal.char_p += data_p[1];
|
||||
|
||||
if (type == SCANNER_STREAM_TYPE_ARG_FUNC && (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY))
|
||||
if (SCANNER_STREAM_TYPE_IS_ARG_FUNC (type) && (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY))
|
||||
{
|
||||
JERRY_ASSERT (scope_stack_p >= context_p->scope_stack_p + 2);
|
||||
|
||||
@@ -1798,6 +1933,8 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case SCANNER_STREAM_TYPE_LET:
|
||||
case SCANNER_STREAM_TYPE_CONST:
|
||||
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
|
||||
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
{
|
||||
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
|
||||
@@ -1812,13 +1949,24 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (type == SCANNER_STREAM_TYPE_LET)
|
||||
switch (type)
|
||||
{
|
||||
opcode = CBC_CREATE_LET;
|
||||
}
|
||||
else if (type == SCANNER_STREAM_TYPE_CONST)
|
||||
{
|
||||
opcode = CBC_CREATE_CONST;
|
||||
case SCANNER_STREAM_TYPE_LET:
|
||||
{
|
||||
opcode = CBC_CREATE_LET;
|
||||
break;
|
||||
}
|
||||
case SCANNER_STREAM_TYPE_CONST:
|
||||
{
|
||||
opcode = CBC_CREATE_CONST;
|
||||
break;
|
||||
}
|
||||
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
|
||||
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
|
||||
{
|
||||
opcode = CBC_CREATE_DESTRUCTURED_ARG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
@@ -1864,7 +2012,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) */
|
||||
|
||||
if (type != SCANNER_STREAM_TYPE_ARG_FUNC)
|
||||
if (!SCANNER_STREAM_TYPE_IS_ARG_FUNC (type))
|
||||
{
|
||||
if (func_init_opcode == CBC_INIT_LOCAL
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|
||||
@@ -255,6 +255,23 @@ scanner_process_arrow_arg (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE)
|
||||
{
|
||||
scanner_append_hole (context_p, scanner_context_p);
|
||||
scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_ARROW_ARG, false);
|
||||
|
||||
if (context_p->token.type == LEXER_LEFT_BRACE)
|
||||
{
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
|
||||
scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
|
||||
return;
|
||||
}
|
||||
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL);
|
||||
scanner_context_p->mode = SCAN_MODE_BINDING;
|
||||
lexer_next_token (context_p);
|
||||
return;
|
||||
}
|
||||
|
||||
scanner_pop_literal_pool (context_p, scanner_context_p);
|
||||
|
||||
@@ -551,31 +568,9 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case SCAN_STACK_BINDING_INIT:
|
||||
case SCAN_STACK_BINDING_LIST_INIT:
|
||||
{
|
||||
scanner_binding_literal_t binding_literal;
|
||||
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
parser_stack_pop (context_p, &binding_literal, sizeof (scanner_binding_literal_t));
|
||||
|
||||
if (binding_literal.literal_p->type & SCANNER_LITERAL_IS_USED)
|
||||
{
|
||||
binding_literal.literal_p->type |= SCANNER_LITERAL_NO_REG;
|
||||
}
|
||||
|
||||
if (context_p->stack_top_uint8 == SCAN_STACK_ARRAY_LITERAL
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL)
|
||||
{
|
||||
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_LET
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_CONST
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_FOR_LET_START
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_FOR_CONST_START);
|
||||
|
||||
scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
|
||||
return SCAN_NEXT_TOKEN;
|
||||
break;
|
||||
}
|
||||
case SCAN_STACK_ARROW_ARGUMENTS:
|
||||
{
|
||||
@@ -713,15 +708,25 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARRAY_LITERAL
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_LET
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_CONST);
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_CONST
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_FOR_LET_START
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_FOR_CONST_START
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_PARAMETERS
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS);
|
||||
|
||||
scanner_binding_item_t *item_p = scanner_context_p->active_binding_list_p->items_p;
|
||||
|
||||
uint8_t flag = SCANNER_LITERAL_NO_REG;
|
||||
if (scanner_context_p->binding_type == SCANNER_BINDING_ARROW_ARG)
|
||||
{
|
||||
flag = SCANNER_LITERAL_ARROW_DESTRUCTURED_ARG_NO_REG;
|
||||
}
|
||||
|
||||
while (item_p != NULL)
|
||||
{
|
||||
if (item_p->literal_p->type & SCANNER_LITERAL_IS_USED)
|
||||
{
|
||||
item_p->literal_p->type |= SCANNER_LITERAL_NO_REG;
|
||||
item_p->literal_p->type |= flag;
|
||||
}
|
||||
item_p = item_p->next_p;
|
||||
}
|
||||
@@ -737,28 +742,31 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
parser_stack_pop_uint8 (context_p);
|
||||
parser_stack_pop (context_p, &binding_literal, sizeof (scanner_binding_literal_t));
|
||||
|
||||
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARRAY_LITERAL
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_LET
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_CONST
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_FOR_LET_START
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_FOR_CONST_START
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS);
|
||||
|
||||
if (binding_literal.literal_p->type & SCANNER_LITERAL_IS_USED)
|
||||
{
|
||||
binding_literal.literal_p->type |= SCANNER_LITERAL_NO_REG;
|
||||
stack_top = (scan_stack_modes_t) context_p->stack_top_uint8;
|
||||
|
||||
if ((stack_top == SCAN_STACK_ARRAY_LITERAL || stack_top == SCAN_STACK_OBJECT_LITERAL)
|
||||
&& (scanner_context_p->binding_type == SCANNER_BINDING_ARROW_ARG))
|
||||
{
|
||||
binding_literal.literal_p->type |= SCANNER_LITERAL_ARROW_DESTRUCTURED_ARG_NO_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
binding_literal.literal_p->type |= SCANNER_LITERAL_NO_REG;
|
||||
}
|
||||
}
|
||||
|
||||
if (context_p->stack_top_uint8 == SCAN_STACK_ARRAY_LITERAL
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL)
|
||||
{
|
||||
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
|
||||
if (context_p->stack_top_uint8 == SCAN_STACK_FOR_LET_START
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_FOR_CONST_START)
|
||||
{
|
||||
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_LET
|
||||
|| context_p->stack_top_uint8 == SCAN_STACK_CONST);
|
||||
/* FALLTHRU */
|
||||
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
case SCAN_STACK_VAR:
|
||||
@@ -1004,6 +1012,11 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
|
||||
}
|
||||
|
||||
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
||||
|
||||
if (context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_PARAMETERS)
|
||||
{
|
||||
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
||||
}
|
||||
return SCAN_KEEP_TOKEN;
|
||||
}
|
||||
|
||||
@@ -1441,7 +1454,7 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (literal_p->type & SCANNER_LITERAL_IS_LOCAL
|
||||
&& !(literal_p->type & SCANNER_LITERAL_IS_FUNC))
|
||||
&& !(literal_p->type & (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_ARG)))
|
||||
{
|
||||
scanner_raise_redeclaration_error (context_p);
|
||||
}
|
||||
@@ -1449,11 +1462,11 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
|
||||
if ((context_p->status_flags & PARSER_IS_EVAL)
|
||||
&& scanner_scope_find_let_declaration (context_p, literal_p))
|
||||
{
|
||||
literal_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_CONST;
|
||||
literal_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_FUNC_LOCAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
literal_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET;
|
||||
literal_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_FUNC_DECLARATION;
|
||||
}
|
||||
#else
|
||||
literal_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC;
|
||||
@@ -2589,6 +2602,8 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
case SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS:
|
||||
{
|
||||
bool is_destructuring_binding = false;
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (context_p->token.type != LEXER_RIGHT_PAREN && context_p->token.type != LEXER_EOS)
|
||||
@@ -2600,6 +2615,12 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
{
|
||||
lexer_next_token (context_p);
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE)
|
||||
{
|
||||
is_destructuring_binding = true;
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (context_p->token.type != LEXER_LITERAL
|
||||
@@ -2621,6 +2642,24 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (is_destructuring_binding)
|
||||
{
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PARAMETERS);
|
||||
scanner_append_hole (context_p, &scanner_context);
|
||||
scanner_push_destructuring_pattern (context_p, &scanner_context, SCANNER_BINDING_ARG, false);
|
||||
|
||||
if (context_p->token.type == LEXER_LEFT_SQUARE)
|
||||
{
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL);
|
||||
scanner_context.mode = SCAN_MODE_BINDING;
|
||||
break;
|
||||
}
|
||||
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
|
||||
scanner_context.mode = SCAN_MODE_PROPERTY_NAME;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_ASSIGN)
|
||||
{
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PARAMETERS);
|
||||
@@ -2792,7 +2831,9 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
{
|
||||
JERRY_ASSERT (scanner_context.binding_type == SCANNER_BINDING_VAR
|
||||
|| scanner_context.binding_type == SCANNER_BINDING_LET
|
||||
|| scanner_context.binding_type == SCANNER_BINDING_CONST);
|
||||
|| scanner_context.binding_type == SCANNER_BINDING_CONST
|
||||
|| scanner_context.binding_type == SCANNER_BINDING_ARG
|
||||
|| scanner_context.binding_type == SCANNER_BINDING_ARROW_ARG);
|
||||
|
||||
if (type == LEXER_THREE_DOTS)
|
||||
{
|
||||
@@ -2837,6 +2878,18 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
literal_p->type |= SCANNER_LITERAL_NO_REG;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (scanner_context.binding_type == SCANNER_BINDING_ARROW_ARG)
|
||||
{
|
||||
literal_p->type |= SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG;
|
||||
|
||||
if (literal_p->type & SCANNER_LITERAL_IS_USED)
|
||||
{
|
||||
literal_p->type |= SCANNER_LITERAL_ARROW_DESTRUCTURED_ARG_NO_REG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2849,38 +2902,41 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
|
||||
else
|
||||
{
|
||||
literal_p->type |= SCANNER_LITERAL_IS_CONST;
|
||||
|
||||
if (scanner_context.binding_type == SCANNER_BINDING_ARG)
|
||||
{
|
||||
literal_p->type |= SCANNER_LITERAL_IS_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (literal_p->type & SCANNER_LITERAL_IS_USED)
|
||||
{
|
||||
literal_p->type |= SCANNER_LITERAL_NO_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
scanner_binding_item_t *binding_item_p;
|
||||
binding_item_p = (scanner_binding_item_t *) scanner_malloc (context_p, sizeof (scanner_binding_item_t));
|
||||
|
||||
binding_item_p->next_p = scanner_context.active_binding_list_p->items_p;
|
||||
binding_item_p->literal_p = literal_p;
|
||||
|
||||
scanner_context.active_binding_list_p->items_p = binding_item_p;
|
||||
|
||||
lexer_next_token (context_p);
|
||||
if (context_p->token.type != LEXER_ASSIGN)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
scanner_binding_literal_t binding_literal;
|
||||
binding_literal.literal_p = literal_p;
|
||||
|
||||
parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t));
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT);
|
||||
|
||||
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
scanner_binding_item_t *binding_item_p;
|
||||
binding_item_p = (scanner_binding_item_t *) scanner_malloc (context_p, sizeof (scanner_binding_item_t));
|
||||
|
||||
binding_item_p->next_p = scanner_context.active_binding_list_p->items_p;
|
||||
binding_item_p->literal_p = literal_p;
|
||||
|
||||
scanner_context.active_binding_list_p->items_p = binding_item_p;
|
||||
|
||||
lexer_next_token (context_p);
|
||||
if (context_p->token.type != LEXER_ASSIGN)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
scanner_binding_literal_t binding_literal;
|
||||
binding_literal.literal_p = literal_p;
|
||||
|
||||
parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t));
|
||||
parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT);
|
||||
|
||||
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
@@ -3012,7 +3068,19 @@ scan_completed:
|
||||
JERRY_DEBUG_MSG (" CONST ");
|
||||
break;
|
||||
}
|
||||
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" DESTRUCTURED_ARG ");
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
case SCANNER_STREAM_TYPE_IMPORT:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" IMPORT ");
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
case SCANNER_STREAM_TYPE_ARG:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" ARG ");
|
||||
@@ -3023,6 +3091,13 @@ scan_completed:
|
||||
JERRY_DEBUG_MSG (" ARG_FUNC ");
|
||||
break;
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" DESTRUCTURED_ARG_FUNC ");
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
case SCANNER_STREAM_TYPE_FUNC:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" FUNC ");
|
||||
@@ -3035,13 +3110,6 @@ scan_completed:
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
case SCANNER_STREAM_TYPE_IMPORT:
|
||||
{
|
||||
JERRY_DEBUG_MSG (" IMPORT ");
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
default:
|
||||
{
|
||||
JERRY_ASSERT ((data_p[0] & SCANNER_STREAM_TYPE_MASK) == SCANNER_STREAM_TYPE_HOLE);
|
||||
|
||||
@@ -145,13 +145,19 @@ typedef enum
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
SCANNER_STREAM_TYPE_LET, /**< let declaration */
|
||||
SCANNER_STREAM_TYPE_CONST, /**< const declaration */
|
||||
SCANNER_STREAM_TYPE_DESTRUCTURED_ARG, /**< destructuring argument declaration */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
SCANNER_STREAM_TYPE_IMPORT, /**< module import */
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
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_ARG_FUNC, /**< argument declaration which
|
||||
* is later initialized with a function */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC, /**< destructuring argument declaration which
|
||||
* is later initialized with a function */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
SCANNER_STREAM_TYPE_FUNC, /**< local or global function declaration */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
SCANNER_STREAM_TYPE_FUNC_LOCAL, /**< always local function declaration */
|
||||
@@ -164,10 +170,38 @@ typedef enum
|
||||
#define SCANNER_STREAM_TYPE_MASK 0xf
|
||||
|
||||
/**
|
||||
* Mask for decoding the type from the compressed stream.
|
||||
* Checks whether the decoded type represents a function declaration.
|
||||
*/
|
||||
#define SCANNER_STREAM_TYPE_IS_FUNCTION(type) ((type) >= SCANNER_STREAM_TYPE_ARG_FUNC)
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|
||||
/**
|
||||
* Checks whether the decoded type represents a function argument.
|
||||
*/
|
||||
#define SCANNER_STREAM_TYPE_IS_ARG(type) \
|
||||
((type) == SCANNER_STREAM_TYPE_ARG || (type) == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG)
|
||||
|
||||
/**
|
||||
* Checks whether the decoded type represents both a function argument and a function declaration.
|
||||
*/
|
||||
#define SCANNER_STREAM_TYPE_IS_ARG_FUNC(type) \
|
||||
((type) == SCANNER_STREAM_TYPE_ARG_FUNC || (type) == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC)
|
||||
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
* Checks whether the decoded type represents a function argument.
|
||||
*/
|
||||
#define SCANNER_STREAM_TYPE_IS_ARG(type) ((type) == SCANNER_STREAM_TYPE_ARG)
|
||||
|
||||
/**
|
||||
* Checks whether the decoded type represents both a function argument and a function declaration.
|
||||
*/
|
||||
#define SCANNER_STREAM_TYPE_IS_ARG_FUNC(type) ((type) == SCANNER_STREAM_TYPE_ARG_FUNC)
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
* Constants for u8_arg flags in scanner_function_info_t.
|
||||
*/
|
||||
|
||||
@@ -806,6 +806,7 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case CBC_CREATE_LET:
|
||||
case CBC_CREATE_CONST:
|
||||
case CBC_CREATE_DESTRUCTURED_ARG:
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
{
|
||||
uint32_t literal_index;
|
||||
@@ -1832,10 +1833,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
}
|
||||
case VM_OC_DEFAULT_INITIALIZER:
|
||||
{
|
||||
JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end);
|
||||
|
||||
if (stack_top_p[-1] != ECMA_VALUE_UNDEFINED)
|
||||
{
|
||||
byte_code_p = byte_code_start_p + branch_offset;
|
||||
continue;
|
||||
}
|
||||
|
||||
stack_top_p--;
|
||||
continue;
|
||||
}
|
||||
case VM_OC_REST_INITIALIZER:
|
||||
|
||||
@@ -61,6 +61,8 @@ var arguments = 10;
|
||||
function j(a = arguments[1])
|
||||
{
|
||||
assert(a === 2);
|
||||
a = 3;
|
||||
assert(arguments[0] === undefined)
|
||||
}
|
||||
j(undefined,2);
|
||||
|
||||
@@ -72,10 +74,27 @@ function k(a = 2)
|
||||
}
|
||||
k();
|
||||
|
||||
function i(a = 3)
|
||||
function l(a = 3)
|
||||
{
|
||||
const d = 6;
|
||||
assert(d === 6);
|
||||
eval("assert(a === 3)");
|
||||
}
|
||||
i();
|
||||
l();
|
||||
|
||||
function m(a, b = 2)
|
||||
{
|
||||
assert(a === 1);
|
||||
assert(arguments[0] === 1);
|
||||
assert(b === 2);
|
||||
assert(arguments[1] === undefined);
|
||||
|
||||
a = 8;
|
||||
b = 9;
|
||||
|
||||
assert(a === 8);
|
||||
assert(arguments[0] === 1);
|
||||
assert(b === 9);
|
||||
assert(arguments[1] === undefined);
|
||||
}
|
||||
m(1);
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// 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 must_throw (str, type = SyntaxError)
|
||||
{
|
||||
try
|
||||
{
|
||||
eval (str);
|
||||
assert (false);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
assert (e instanceof type)
|
||||
}
|
||||
}
|
||||
|
||||
must_throw ("function f(a, [a]) {}");
|
||||
must_throw ("function f([a], a) {}");
|
||||
must_throw ("function f(a = b, [b]) {}; f()", ReferenceError);
|
||||
must_throw ("function f([a+b]) {}");
|
||||
must_throw ("function f([a().b]) {}");
|
||||
|
||||
function a1([a,b]) {
|
||||
var a, b;
|
||||
|
||||
assert(a === 1);
|
||||
assert(b === undefined);
|
||||
|
||||
var a = 3;
|
||||
assert(a === 3);
|
||||
}
|
||||
a1([1]);
|
||||
|
||||
function a2([a,b]) {
|
||||
eval("var a, b");
|
||||
assert(a === 1);
|
||||
assert(b === undefined);
|
||||
|
||||
eval("var a = 3");
|
||||
assert(a === 3);
|
||||
}
|
||||
a2([1]);
|
||||
|
||||
function f1(a, [b], c, [d], e)
|
||||
{
|
||||
assert (a === 1);
|
||||
assert (b === 2);
|
||||
assert (c === 3);
|
||||
assert (d === 4);
|
||||
assert (e === 5);
|
||||
}
|
||||
f1(1, [2], 3, [4], 5)
|
||||
|
||||
function f2(a, [b], c, [d], e)
|
||||
{
|
||||
eval("");
|
||||
assert (a === 1);
|
||||
assert (b === 2);
|
||||
assert (c === 3);
|
||||
assert (d === 4);
|
||||
assert (e === 5);
|
||||
}
|
||||
f2(1, [2], 3, [4], 5)
|
||||
|
||||
var g1 = (a, [b], c, [d], e) => {
|
||||
assert (a === 1);
|
||||
assert (b === 2);
|
||||
assert (c === 3);
|
||||
assert (d === 4);
|
||||
assert (e === 5);
|
||||
}
|
||||
g1(1, [2], 3, [4], 5)
|
||||
|
||||
var g2 = (a, [b], c, [d], e) => {
|
||||
eval("");
|
||||
assert (a === 1);
|
||||
assert (b === 2);
|
||||
assert (c === 3);
|
||||
assert (d === 4);
|
||||
assert (e === 5);
|
||||
}
|
||||
g2(1, [2], 3, [4], 5)
|
||||
@@ -0,0 +1,61 @@
|
||||
// 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((function([a], b, {c}) {}).length === 3);
|
||||
|
||||
function f([a = "x", b = "y", c = "z"])
|
||||
{
|
||||
assert(a === "a");
|
||||
assert(b === "b");
|
||||
assert(c === "z");
|
||||
}
|
||||
f("ab")
|
||||
|
||||
function g({ ["x" + "y"]: { a = 4, b = 5 }, })
|
||||
{
|
||||
assert(a === 1);
|
||||
assert(b === 5);
|
||||
}
|
||||
g({ xy: { a:1 } });
|
||||
|
||||
function h([,,a,,b,,])
|
||||
{
|
||||
assert(a === 3);
|
||||
assert(b === 5);
|
||||
}
|
||||
h([1,2,3,4,5,6,7,8])
|
||||
|
||||
function i([a] = [42], b = a)
|
||||
{
|
||||
assert(a === 42);
|
||||
assert(b === 42);
|
||||
}
|
||||
i();
|
||||
|
||||
function j(a, [[b = a, [c] = [b], { d } = { d:eval("c") }], e = d + 1] = [[]])
|
||||
{
|
||||
assert(a === 8);
|
||||
assert(b === 8);
|
||||
assert(c === 8);
|
||||
assert(d === 8);
|
||||
assert(e === 9);
|
||||
}
|
||||
j(8);
|
||||
|
||||
function k([a = function() { return a; }])
|
||||
{
|
||||
assert(typeof a === "function");
|
||||
assert(a() === a);
|
||||
}
|
||||
k([]);
|
||||
@@ -78,3 +78,18 @@ assert (g2 () === 11);
|
||||
assert (g2 (1) === 3);
|
||||
assert (g2 (1, 2) === 3);
|
||||
assert (g2 (1, 2, 3) === 4);
|
||||
|
||||
function args(a, ...b)
|
||||
{
|
||||
assert(a === 1);
|
||||
assert(arguments[0] === 1);
|
||||
|
||||
a = 5;
|
||||
|
||||
assert(a === 5);
|
||||
assert(arguments[0] === 1);
|
||||
|
||||
assert(arguments[1] === 2);
|
||||
assert(b[0] === 2)
|
||||
}
|
||||
args(1, 2);
|
||||
|
||||
@@ -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, 0x1D, 0x00, 0x00, 0x00,
|
||||
0x4A, 0x52, 0x52, 0x59, 0x1E, 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,
|
||||
0x03, 0x00, 0x01, 0x00, 0x41, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00,
|
||||
0x2C, 0x00, 0xBF, 0x4D, 0x00, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x01, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||
0x2C, 0x00, 0xC0, 0x4E, 0x00, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x01, 0x00, 0x41, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x00,
|
||||
0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x4F, 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,
|
||||
|
||||
Reference in New Issue
Block a user