Fix lexical scoping between scripts (#3558)
This change fixes the handling of lexical blocks when executing multiple scripts, and also fixes a few issues with module environments. After this change, all script files will run in the same context and will have access to lexically scoped global variables of previous scripts, and module environments will no longer have a bound global 'this' value. The REPL implementation in main-unix is also fixed to correctly handle lexically scoped variables. Fixes #3561. JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai@inf.u-szeged.hu
This commit is contained in:
@@ -470,21 +470,14 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
bool no_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_REG) != 0;
|
||||
bool search_arguments = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) == 0;
|
||||
bool arguments_required = (no_reg && search_arguments);
|
||||
|
||||
uint8_t no_reg_types = 0;
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
uint8_t no_var_flags = 0;
|
||||
|
||||
if (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_VAR_REG)
|
||||
if (!(context_p->status_flags & PARSER_IS_DIRECT_EVAL))
|
||||
{
|
||||
no_var_flags = SCANNER_LITERAL_IS_VAR;
|
||||
|
||||
if (!(context_p->status_flags & PARSER_IS_DIRECT_EVAL))
|
||||
{
|
||||
no_var_flags |= SCANNER_LITERAL_IS_FUNC;
|
||||
}
|
||||
no_reg_types |= SCANNER_LITERAL_IS_FUNC;
|
||||
}
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
uint8_t no_var_flags = 0;
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
#endif /* !ENABLED (JERRY_ES2015) */
|
||||
|
||||
if (no_reg && prev_literal_pool_p != NULL)
|
||||
{
|
||||
@@ -565,7 +558,7 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
no_declarations++;
|
||||
}
|
||||
|
||||
if (no_reg || (type & no_var_flags))
|
||||
if (no_reg || (type & no_reg_types))
|
||||
{
|
||||
type |= SCANNER_LITERAL_NO_REG;
|
||||
literal_p->type = type;
|
||||
@@ -1738,6 +1731,90 @@ scanner_create_unused_literal (parser_context_t *context_p, /**< context */
|
||||
context_p->literal_count++;
|
||||
} /* scanner_create_unused_literal */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
/**
|
||||
* Emit checks for redeclared bindings in the global lexical scope.
|
||||
*/
|
||||
void
|
||||
scanner_check_variables (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
scanner_info_t *info_p = context_p->next_scanner_info_p;
|
||||
const uint8_t *next_data_p = (const uint8_t *) (info_p + 1);
|
||||
lexer_lit_location_t literal;
|
||||
|
||||
JERRY_ASSERT (info_p->type == SCANNER_TYPE_FUNCTION);
|
||||
|
||||
literal.char_p = info_p->source_p - 1;
|
||||
|
||||
while (next_data_p[0] != SCANNER_STREAM_TYPE_END)
|
||||
{
|
||||
uint32_t type = next_data_p[0] & SCANNER_STREAM_TYPE_MASK;
|
||||
const uint8_t *data_p = next_data_p;
|
||||
|
||||
JERRY_ASSERT (type != SCANNER_STREAM_TYPE_HOLE
|
||||
&& !SCANNER_STREAM_TYPE_IS_ARG (type)
|
||||
&& !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type));
|
||||
JERRY_ASSERT (data_p[0] & SCANNER_STREAM_NO_REG);
|
||||
|
||||
if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF))
|
||||
{
|
||||
if (data_p[2] != 0)
|
||||
{
|
||||
literal.char_p += data_p[2];
|
||||
next_data_p += 2 + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (&literal.char_p, data_p + 2 + 1, sizeof (const uint8_t *));
|
||||
next_data_p += 2 + 1 + sizeof (const uint8_t *);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8;
|
||||
|
||||
if (diff <= UINT8_MAX)
|
||||
{
|
||||
diff = -diff;
|
||||
}
|
||||
|
||||
literal.char_p += diff;
|
||||
next_data_p += 2 + 2;
|
||||
}
|
||||
|
||||
literal.length = data_p[1];
|
||||
literal.type = LEXER_IDENT_LITERAL;
|
||||
literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0;
|
||||
|
||||
lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL);
|
||||
literal.char_p += data_p[1];
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
if (type == SCANNER_STREAM_TYPE_IMPORT)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED;
|
||||
|
||||
uint16_t opcode;
|
||||
if (type == SCANNER_STREAM_TYPE_VAR || type == SCANNER_STREAM_TYPE_FUNC)
|
||||
{
|
||||
opcode = CBC_CHECK_VAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
opcode = CBC_CHECK_LET;
|
||||
}
|
||||
|
||||
parser_emit_cbc_literal (context_p, opcode, context_p->lit_object.index);
|
||||
}
|
||||
|
||||
parser_flush_cbc (context_p);
|
||||
} /* scanner_check_variables */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
* Create and/or initialize var/let/const/function/etc. variables.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user