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:
Zoltan Herczeg
2019-11-18 14:15:36 +01:00
committed by Dániel Bátyai
parent 359643b5b2
commit 8bdb32cc88
19 changed files with 753 additions and 202 deletions
+6 -6
View File
@@ -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;
+2 -2
View File
@@ -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);
+1 -1
View File
@@ -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.
+14 -12
View File
@@ -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,
+34 -23
View File
@@ -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) */
+31 -14
View File
@@ -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 *)))
+62 -15
View File
@@ -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);
+32 -4
View File
@@ -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) */
/**
+181 -33
View File
@@ -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)
+147 -79
View File
@@ -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);
+36 -2
View File
@@ -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.
*/
+6
View File
@@ -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:
+21 -2
View File
@@ -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);
+93
View File
@@ -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)
+61
View File
@@ -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);
+5 -5
View File
@@ -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,