mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Delay the variable construction in the function body. (#3289)
Local variables inside the function body should be constructed after the parameters are initialized. Furthermore arguments should be available during parameter initialization. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
923fd128b5
commit
e1fc90db0e
@ -320,6 +320,14 @@ typedef struct
|
||||
|
||||
/**
|
||||
* This item represents a function literal in the scope stack.
|
||||
*
|
||||
* When map_from == PARSER_SCOPE_STACK_FUNC:
|
||||
* map_to represents the literal reserved for a function literal
|
||||
* Note: the name of the function is the previous value in the scope stack
|
||||
*
|
||||
* When map_to == PARSER_SCOPE_STACK_FUNC:
|
||||
* map_from represents the name of the function literal following this literal
|
||||
* Note: only the name, the real mapping is somewhere else in the scope stack
|
||||
*/
|
||||
#define PARSER_SCOPE_STACK_FUNC 0xffff
|
||||
|
||||
@ -626,6 +634,7 @@ void parser_parse_super_class_context_end (parser_context_t *context_p);
|
||||
|
||||
void scanner_release_next (parser_context_t *context_p, size_t size);
|
||||
void scanner_set_active (parser_context_t *context_p);
|
||||
void scanner_revert_active (parser_context_t *context_p);
|
||||
void scanner_release_active (parser_context_t *context_p, size_t size);
|
||||
void scanner_release_switch_cases (scanner_case_info_t *case_p);
|
||||
void scanner_seek (parser_context_t *context_p);
|
||||
|
||||
@ -1617,13 +1617,16 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
|
||||
scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS);
|
||||
|
||||
if (context_p->token.type == end_type)
|
||||
{
|
||||
scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS);
|
||||
return;
|
||||
}
|
||||
|
||||
scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_ARGS);
|
||||
scanner_set_active (context_p);
|
||||
|
||||
while (true)
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
@ -1730,6 +1733,9 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */
|
||||
|
||||
parser_raise_error (context_p, error);
|
||||
}
|
||||
|
||||
scanner_revert_active (context_p);
|
||||
scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_BODY);
|
||||
} /* parser_parse_function_arguments */
|
||||
|
||||
/**
|
||||
|
||||
@ -258,6 +258,19 @@ scanner_set_active (parser_context_t *context_p) /**< context */
|
||||
context_p->active_scanner_info_p = scanner_info_p;
|
||||
} /* scanner_set_active */
|
||||
|
||||
/**
|
||||
* Set the next scanner info to the active scanner info.
|
||||
*/
|
||||
inline void JERRY_ATTR_ALWAYS_INLINE
|
||||
scanner_revert_active (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
scanner_info_t *scanner_info_p = context_p->active_scanner_info_p;
|
||||
|
||||
context_p->active_scanner_info_p = scanner_info_p->next_p;
|
||||
scanner_info_p->next_p = context_p->next_scanner_info_p;
|
||||
context_p->next_scanner_info_p = scanner_info_p;
|
||||
} /* scanner_revert_active */
|
||||
|
||||
/**
|
||||
* Release the active scanner info.
|
||||
*/
|
||||
@ -394,7 +407,7 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
lexer_lit_location_t *literal_p;
|
||||
bool is_function = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION) != 0;
|
||||
bool no_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_REG) != 0;
|
||||
bool search_arguments = is_function && (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) == 0;
|
||||
bool search_arguments = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) == 0;
|
||||
bool arguments_required = (no_reg && search_arguments);
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
bool no_var_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_VAR_REG) != 0;
|
||||
@ -545,7 +558,7 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
|
||||
if (is_function || (compressed_size > 1))
|
||||
{
|
||||
compressed_size += is_function ? sizeof (scanner_function_info_t) : sizeof (scanner_info_t);
|
||||
compressed_size += sizeof (scanner_info_t);
|
||||
|
||||
scanner_info_t *info_p;
|
||||
|
||||
@ -564,14 +577,12 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
no_declarations = PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK;
|
||||
}
|
||||
|
||||
uint8_t *data_p = (uint8_t *) info_p;
|
||||
uint8_t *data_p = (uint8_t *) (info_p + 1);
|
||||
|
||||
if (is_function)
|
||||
{
|
||||
info_p->type = SCANNER_TYPE_FUNCTION;
|
||||
data_p += sizeof (scanner_function_info_t);
|
||||
|
||||
scanner_function_info_t *function_info_p = (scanner_function_info_t *) info_p;
|
||||
uint8_t status_flags = 0;
|
||||
|
||||
if (arguments_required)
|
||||
@ -584,13 +595,12 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
}
|
||||
|
||||
function_info_p->info.u8_arg = status_flags;
|
||||
function_info_p->info.u16_arg = (uint16_t) no_declarations;
|
||||
info_p->u8_arg = status_flags;
|
||||
info_p->u16_arg = (uint16_t) no_declarations;
|
||||
}
|
||||
else
|
||||
{
|
||||
info_p->type = SCANNER_TYPE_BLOCK;
|
||||
data_p += sizeof (scanner_info_t);
|
||||
|
||||
JERRY_ASSERT (prev_literal_pool_p != NULL);
|
||||
}
|
||||
@ -730,6 +740,7 @@ scanner_filter_arguments (parser_context_t *context_p, /**< context */
|
||||
parser_list_iterator_t literal_iterator;
|
||||
lexer_lit_location_t *literal_p;
|
||||
bool no_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_REG) != 0;
|
||||
bool has_arguments = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) == 0;
|
||||
|
||||
if (no_reg && prev_literal_pool_p != NULL)
|
||||
{
|
||||
@ -774,7 +785,10 @@ scanner_filter_arguments (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_ARG)
|
||||
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)))
|
||||
{
|
||||
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);
|
||||
@ -1189,10 +1203,6 @@ scanner_cleanup (parser_context_t *context_p) /**< context */
|
||||
continue;
|
||||
}
|
||||
case SCANNER_TYPE_FUNCTION:
|
||||
{
|
||||
size = scanner_get_stream_size (scanner_info_p, sizeof (scanner_function_info_t));
|
||||
break;
|
||||
}
|
||||
case SCANNER_TYPE_BLOCK:
|
||||
{
|
||||
size = scanner_get_stream_size (scanner_info_p, sizeof (scanner_info_t));
|
||||
@ -1396,7 +1406,7 @@ bool
|
||||
scanner_is_global_context_needed (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
scanner_info_t *info_p = context_p->next_scanner_info_p;
|
||||
const uint8_t *data_p = ((const uint8_t *) info_p) + sizeof (scanner_function_info_t);
|
||||
const uint8_t *data_p = (const uint8_t *) (info_p + 1);
|
||||
uint32_t scope_stack_reg_top = 0;
|
||||
|
||||
JERRY_ASSERT (info_p->type == SCANNER_TYPE_FUNCTION);
|
||||
@ -1467,6 +1477,26 @@ const lexer_lit_location_t lexer_arguments_literal =
|
||||
(const uint8_t *) "arguments", 9, LEXER_IDENT_LITERAL, false
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an unused literal.
|
||||
*/
|
||||
static void
|
||||
scanner_create_unused_literal (parser_context_t *context_p, /**< context */
|
||||
uint8_t status_flags) /**< initial status flags */
|
||||
{
|
||||
if (JERRY_UNLIKELY (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
|
||||
}
|
||||
|
||||
lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
|
||||
|
||||
literal_p->type = LEXER_UNUSED_LITERAL;
|
||||
literal_p->status_flags = status_flags;
|
||||
|
||||
context_p->literal_count++;
|
||||
} /* scanner_create_unused_literal */
|
||||
|
||||
/**
|
||||
* Create and/or initialize var/let/const/function/etc. variables.
|
||||
*/
|
||||
@ -1475,15 +1505,19 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
uint32_t option_flags) /**< combination of scanner_create_variables_flags_t bits */
|
||||
{
|
||||
scanner_info_t *info_p = context_p->next_scanner_info_p;
|
||||
const uint8_t *data_p;
|
||||
const uint8_t *next_data_p = (const uint8_t *) (info_p + 1);
|
||||
uint8_t info_type = info_p->type;
|
||||
lexer_lit_location_t literal;
|
||||
parser_scope_stack *scope_stack_p;
|
||||
parser_scope_stack *scope_stack_end_p;
|
||||
|
||||
JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION || info_type == SCANNER_TYPE_BLOCK);
|
||||
JERRY_ASSERT (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)
|
||||
|| !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY));
|
||||
JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION
|
||||
|| !(option_flags & (SCANNER_CREATE_VARS_IS_FUNCTION_ARGS | SCANNER_CREATE_VARS_IS_FUNCTION_BODY)));
|
||||
|
||||
if (info_type == SCANNER_TYPE_FUNCTION)
|
||||
if (info_type == SCANNER_TYPE_FUNCTION && !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY))
|
||||
{
|
||||
JERRY_ASSERT (context_p->scope_stack_p == NULL);
|
||||
|
||||
@ -1492,59 +1526,55 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
|
||||
if (stack_size == 0)
|
||||
{
|
||||
scanner_release_next (context_p, sizeof (scanner_function_info_t) + 1);
|
||||
if (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS))
|
||||
{
|
||||
scanner_release_next (context_p, sizeof (scanner_info_t) + 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
scope_stack_p = (parser_scope_stack *) parser_malloc (context_p, stack_size);
|
||||
context_p->scope_stack_p = scope_stack_p;
|
||||
scope_stack_end_p = scope_stack_p + context_p->scope_stack_size;
|
||||
|
||||
data_p = ((const uint8_t *) info_p) + sizeof (scanner_function_info_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (context_p->scope_stack_p != NULL);
|
||||
|
||||
scope_stack_p = context_p->scope_stack_p;
|
||||
scope_stack_end_p = scope_stack_p + context_p->scope_stack_size;
|
||||
scope_stack_p += context_p->scope_stack_top;
|
||||
|
||||
data_p = ((const uint8_t *) info_p) + sizeof (scanner_info_t);
|
||||
}
|
||||
|
||||
uint32_t scope_stack_reg_top = context_p->scope_stack_reg_top;
|
||||
|
||||
literal.char_p = info_p->source_p - 1;
|
||||
|
||||
while (data_p[0] != SCANNER_STREAM_TYPE_END)
|
||||
while (next_data_p[0] != SCANNER_STREAM_TYPE_END)
|
||||
{
|
||||
uint32_t type = data_p[0] & SCANNER_STREAM_TYPE_MASK;
|
||||
uint32_t type = next_data_p[0] & SCANNER_STREAM_TYPE_MASK;
|
||||
const uint8_t *data_p = next_data_p;
|
||||
|
||||
if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
|
||||
{
|
||||
JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
|
||||
parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
|
||||
}
|
||||
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));
|
||||
#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) */
|
||||
|
||||
if (type == SCANNER_STREAM_TYPE_HOLE)
|
||||
{
|
||||
data_p++;
|
||||
next_data_p++;
|
||||
|
||||
JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION);
|
||||
if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (info_p->u8_arg & SCANNER_FUNCTION_ARGUMENTS_NEEDED)
|
||||
{
|
||||
if (JERRY_UNLIKELY (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
|
||||
}
|
||||
|
||||
lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
|
||||
|
||||
literal_p->type = LEXER_UNUSED_LITERAL;
|
||||
literal_p->status_flags = LEXER_FLAG_FUNCTION_ARGUMENT;
|
||||
|
||||
context_p->literal_count++;
|
||||
scanner_create_unused_literal (context_p, LEXER_FLAG_FUNCTION_ARGUMENT);
|
||||
}
|
||||
|
||||
if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
|
||||
@ -1554,19 +1584,17 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t length;
|
||||
|
||||
if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF))
|
||||
{
|
||||
if (data_p[2] != 0)
|
||||
{
|
||||
literal.char_p += data_p[2];
|
||||
length = 2 + 1;
|
||||
next_data_p += 2 + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (&literal.char_p, data_p + 2 + 1, sizeof (const uint8_t *));
|
||||
length = 2 + 1 + sizeof (const uint8_t *);
|
||||
next_data_p += 2 + 1 + sizeof (const uint8_t *);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1579,7 +1607,22 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
|
||||
literal.char_p += diff;
|
||||
length = 2 + 2;
|
||||
next_data_p += 2 + 2;
|
||||
}
|
||||
|
||||
if (type == SCANNER_STREAM_TYPE_ARG)
|
||||
{
|
||||
if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
|
||||
{
|
||||
literal.char_p += data_p[1];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if ((option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)
|
||||
&& type != SCANNER_STREAM_TYPE_ARG_FUNC)
|
||||
{
|
||||
/* Function arguments must come first. */
|
||||
break;
|
||||
}
|
||||
|
||||
literal.length = data_p[1];
|
||||
@ -1587,16 +1630,39 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0;
|
||||
|
||||
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))
|
||||
{
|
||||
JERRY_ASSERT (scope_stack_p >= context_p->scope_stack_p + 2);
|
||||
|
||||
parser_scope_stack *function_map_p = scope_stack_p - 2;
|
||||
uint16_t literal_index = context_p->lit_object.index;
|
||||
|
||||
while (literal_index != function_map_p->map_from)
|
||||
{
|
||||
function_map_p--;
|
||||
|
||||
JERRY_ASSERT (function_map_p >= context_p->scope_stack_p);
|
||||
}
|
||||
|
||||
JERRY_ASSERT (function_map_p[1].map_from == PARSER_SCOPE_STACK_FUNC);
|
||||
|
||||
parser_emit_cbc_literal_value (context_p, CBC_SET_VAR_FUNC, function_map_p[1].map_to, function_map_p[0].map_to);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
|
||||
{
|
||||
JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
|
||||
parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
|
||||
}
|
||||
|
||||
scope_stack_p->map_from = context_p->lit_object.index;
|
||||
|
||||
uint16_t map_to;
|
||||
uint16_t func_init_opcode = CBC_INIT_LOCAL;
|
||||
|
||||
#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) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (info_type == SCANNER_TYPE_FUNCTION)
|
||||
{
|
||||
@ -1682,6 +1748,7 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
break;
|
||||
}
|
||||
case SCANNER_STREAM_TYPE_ARG:
|
||||
case SCANNER_STREAM_TYPE_ARG_FUNC:
|
||||
{
|
||||
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
|
||||
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
|
||||
@ -1691,14 +1758,12 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
CBC_INIT_LOCAL,
|
||||
(uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top),
|
||||
map_to);
|
||||
/* FALLTHRU */
|
||||
}
|
||||
case SCANNER_STREAM_TYPE_ARG_FUNC:
|
||||
{
|
||||
|
||||
if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
|
||||
{
|
||||
scope_stack_reg_top++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1706,9 +1771,6 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
|
||||
scope_stack_p++;
|
||||
|
||||
literal.char_p += data_p[1];
|
||||
data_p += length;
|
||||
|
||||
if (!SCANNER_STREAM_TYPE_IS_FUNCTION (type))
|
||||
{
|
||||
continue;
|
||||
@ -1720,37 +1782,34 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
|
||||
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
|
||||
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
|
||||
|
||||
if (func_init_opcode == CBC_INIT_LOCAL
|
||||
&& (option_flags & SCANNER_CREATE_VARS_IS_EVAL))
|
||||
if (type != SCANNER_STREAM_TYPE_ARG_FUNC)
|
||||
{
|
||||
func_init_opcode = CBC_CREATE_VAR_FUNC_EVAL;
|
||||
}
|
||||
if (func_init_opcode == CBC_INIT_LOCAL
|
||||
&& (option_flags & SCANNER_CREATE_VARS_IS_EVAL))
|
||||
{
|
||||
func_init_opcode = CBC_CREATE_VAR_FUNC_EVAL;
|
||||
}
|
||||
|
||||
parser_emit_cbc_literal_value (context_p, func_init_opcode, context_p->literal_count, map_to);
|
||||
parser_emit_cbc_literal_value (context_p, func_init_opcode, context_p->literal_count, map_to);
|
||||
}
|
||||
|
||||
scope_stack_p->map_from = PARSER_SCOPE_STACK_FUNC;
|
||||
scope_stack_p->map_to = context_p->literal_count;
|
||||
scope_stack_p++;
|
||||
|
||||
lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
|
||||
|
||||
literal_p->type = LEXER_UNUSED_LITERAL;
|
||||
literal_p->status_flags = 0;
|
||||
|
||||
context_p->literal_count++;
|
||||
scanner_create_unused_literal (context_p, 0);
|
||||
}
|
||||
|
||||
if (info_type == SCANNER_TYPE_FUNCTION && (info_p->u8_arg & SCANNER_FUNCTION_ARGUMENTS_NEEDED))
|
||||
if (info_type == SCANNER_TYPE_FUNCTION
|
||||
&& !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
|
||||
&& (info_p->u8_arg & SCANNER_FUNCTION_ARGUMENTS_NEEDED))
|
||||
{
|
||||
JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION);
|
||||
|
||||
if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
|
||||
{
|
||||
JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
|
||||
@ -1781,7 +1840,10 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
context_p->register_count = (uint16_t) scope_stack_reg_top;
|
||||
}
|
||||
|
||||
scanner_release_next (context_p, (size_t) (data_p + 1 - ((const uint8_t *) info_p)));
|
||||
if (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS))
|
||||
{
|
||||
scanner_release_next (context_p, (size_t) (next_data_p + 1 - ((const uint8_t *) info_p)));
|
||||
}
|
||||
parser_flush_cbc (context_p);
|
||||
} /* scanner_create_variables */
|
||||
|
||||
|
||||
@ -2632,12 +2632,11 @@ scan_completed:
|
||||
|
||||
if (info_p->type == SCANNER_TYPE_FUNCTION)
|
||||
{
|
||||
scanner_function_info_t *function_info_p = (scanner_function_info_t *) info_p;
|
||||
data_p = (const uint8_t *) (function_info_p + 1);
|
||||
data_p = (const uint8_t *) (info_p + 1);
|
||||
|
||||
JERRY_DEBUG_MSG (" FUNCTION: flags: 0x%x declarations: %d",
|
||||
(int) function_info_p->info.u8_arg,
|
||||
(int) function_info_p->info.u16_arg);
|
||||
(int) info_p->u8_arg,
|
||||
(int) info_p->u16_arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -175,14 +175,6 @@ typedef enum
|
||||
SCANNER_FUNCTION_ARGUMENTS_NEEDED = (1 << 0), /**< arguments object needs to be created */
|
||||
} scanner_function_flags_t;
|
||||
|
||||
/**
|
||||
* Scanner info for function statements.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
scanner_info_t info; /**< header */
|
||||
} scanner_function_info_t;
|
||||
|
||||
/**
|
||||
* Option bits for scanner_create_variables function.
|
||||
*/
|
||||
@ -190,6 +182,8 @@ typedef enum
|
||||
{
|
||||
SCANNER_CREATE_VARS_NO_OPTS = 0, /**< no options */
|
||||
SCANNER_CREATE_VARS_IS_EVAL = (1 << 0), /**< create variables for script / direct eval */
|
||||
SCANNER_CREATE_VARS_IS_FUNCTION_ARGS = (1 << 1), /**< create variables for function arguments */
|
||||
SCANNER_CREATE_VARS_IS_FUNCTION_BODY = (1 << 2), /**< create variables for function body */
|
||||
} scanner_create_variables_flags_t;
|
||||
|
||||
/**
|
||||
|
||||
@ -949,7 +949,6 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
break;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case CBC_SET_VAR_FUNC:
|
||||
{
|
||||
uint32_t literal_index, value_index;
|
||||
@ -966,8 +965,6 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
|
||||
if (literal_index < register_end)
|
||||
{
|
||||
JERRY_ASSERT (type == CBC_SET_VAR_FUNC);
|
||||
|
||||
ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]);
|
||||
frame_ctx_p->registers_p[literal_index] = lit_value;
|
||||
break;
|
||||
@ -978,7 +975,6 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
vm_set_var (frame_ctx_p->lex_env_p, name_p, is_strict, lit_value);
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
||||
case CBC_SET_BYTECODE_PTR:
|
||||
|
||||
65
tests/jerry/es2015/function-param-init2.js
Normal file
65
tests/jerry/es2015/function-param-init2.js
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright JS Foundation and other contributors, http://js.foundation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
function f(a, b = a)
|
||||
{
|
||||
function a() { return 2; }
|
||||
|
||||
assert(a() === 2);
|
||||
assert(b === 1)
|
||||
}
|
||||
f(1);
|
||||
|
||||
function g(a, b = a)
|
||||
{
|
||||
function a() { return 2; }
|
||||
|
||||
eval("assert(a() === 2)");
|
||||
eval("assert(b === 1)");
|
||||
}
|
||||
g(1);
|
||||
|
||||
var x = 1;
|
||||
function h(a = x) {
|
||||
assert(x === undefined);
|
||||
var x = 2;
|
||||
assert(a === 1);
|
||||
assert(x === 2);
|
||||
}
|
||||
h();
|
||||
|
||||
x = function() { return 4; }
|
||||
let y = 6;
|
||||
|
||||
function i(a = x() / 2, b = (y) + 2, c = typeof z) {
|
||||
let y = 10;
|
||||
let z = 11;
|
||||
|
||||
function x() { return 5; }
|
||||
|
||||
assert(a === 2);
|
||||
assert(x() === 5);
|
||||
assert(b === 8);
|
||||
assert(c === "undefined");
|
||||
assert(y === 10);
|
||||
assert(z === 11);
|
||||
}
|
||||
i();
|
||||
|
||||
var arguments = 10;
|
||||
function j(a = arguments[1])
|
||||
{
|
||||
assert(a === 2);
|
||||
}
|
||||
j(undefined,2);
|
||||
Loading…
x
Reference in New Issue
Block a user