mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Fix var and function declaration in eval (#4360)
Fixes #4149 JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
fe29bf7390
commit
29be24f056
@ -823,7 +823,6 @@ void scanner_cleanup (parser_context_t *context_p);
|
||||
|
||||
bool scanner_is_context_needed (parser_context_t *context_p, parser_check_context_type_t check_type);
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
bool scanner_scope_find_let_declaration (parser_context_t *context_p, lexer_lit_location_t *literal_p);
|
||||
bool scanner_try_scan_new_target (parser_context_t *context_p);
|
||||
void scanner_check_variables (parser_context_t *context_p);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
@ -1992,7 +1992,7 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
|
||||
context.status_flags |= PARSER_LEXICAL_BLOCK_NEEDED;
|
||||
}
|
||||
|
||||
if ((parse_opts & ECMA_PARSE_EVAL) == 0)
|
||||
if (!(parse_opts & ECMA_PARSE_EVAL))
|
||||
{
|
||||
scanner_check_variables (&context);
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-lex-env.h"
|
||||
#include "jcontext.h"
|
||||
#include "js-parser-internal.h"
|
||||
#include "js-scanner-internal.h"
|
||||
@ -385,6 +386,85 @@ scanner_seek (parser_context_t *context_p) /**< context */
|
||||
context_p->next_scanner_info_p = prev_p->next_p;
|
||||
} /* scanner_seek */
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
/**
|
||||
* Find any let/const declaration of a given literal.
|
||||
*
|
||||
* @return true - if the literal is found, false - otherwise
|
||||
*/
|
||||
static bool
|
||||
scanner_scope_find_lexical_declaration (parser_context_t *context_p, /**< context */
|
||||
lexer_lit_location_t *literal_p) /**< literal */
|
||||
{
|
||||
ecma_string_t *name_p;
|
||||
uint32_t flags = context_p->global_status_flags;
|
||||
|
||||
if (!(flags & ECMA_PARSE_EVAL)
|
||||
|| (!(flags & ECMA_PARSE_DIRECT_EVAL) && (context_p->status_flags & PARSER_IS_STRICT)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (JERRY_LIKELY (!literal_p->has_escape))
|
||||
{
|
||||
name_p = ecma_new_ecma_string_from_utf8 (literal_p->char_p, literal_p->length);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t *destination_p = (uint8_t *) scanner_malloc (context_p, literal_p->length);
|
||||
|
||||
lexer_convert_ident_to_cesu8 (destination_p, literal_p->char_p, literal_p->length);
|
||||
|
||||
name_p = ecma_new_ecma_string_from_utf8 (destination_p, literal_p->length);
|
||||
scanner_free (destination_p, literal_p->length);
|
||||
}
|
||||
|
||||
ecma_object_t *lex_env_p;
|
||||
|
||||
if (flags & ECMA_PARSE_DIRECT_EVAL)
|
||||
{
|
||||
lex_env_p = JERRY_CONTEXT (vm_top_context_p)->lex_env_p;
|
||||
|
||||
while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK)
|
||||
{
|
||||
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||
{
|
||||
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
|
||||
|
||||
if (property_p != NULL && ecma_is_property_enumerable (*property_p))
|
||||
{
|
||||
ecma_deref_ecma_string (name_p);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
|
||||
lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lex_env_p = ecma_get_global_scope (ecma_builtin_get_global ());
|
||||
}
|
||||
|
||||
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||
{
|
||||
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
|
||||
|
||||
if (property_p != NULL && ecma_is_property_enumerable (*property_p))
|
||||
{
|
||||
ecma_deref_ecma_string (name_p);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ecma_deref_ecma_string (name_p);
|
||||
return false;
|
||||
} /* scanner_scope_find_lexical_declaration */
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/**
|
||||
* Push a new literal pool.
|
||||
*
|
||||
@ -694,9 +774,7 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
|
||||
if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION)
|
||||
&& (type & SCANNER_LITERAL_IS_LOCAL_FUNC) == SCANNER_LITERAL_IS_FUNC)
|
||||
{
|
||||
if (prev_literal_pool_p == NULL
|
||||
&& (context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL)
|
||||
&& scanner_scope_find_let_declaration (context_p, literal_p))
|
||||
if (prev_literal_pool_p == NULL && scanner_scope_find_lexical_declaration (context_p, literal_p))
|
||||
{
|
||||
literal_p->type = 0;
|
||||
continue;
|
||||
@ -1504,65 +1582,6 @@ scanner_detect_eval_call (parser_context_t *context_p, /**< context */
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
/**
|
||||
* Find a let/const declaration of a given literal.
|
||||
*
|
||||
* @return true - if the literal is found, false - otherwise
|
||||
*/
|
||||
bool
|
||||
scanner_scope_find_let_declaration (parser_context_t *context_p, /**< context */
|
||||
lexer_lit_location_t *literal_p) /**< literal */
|
||||
{
|
||||
ecma_string_t *name_p;
|
||||
|
||||
if (JERRY_LIKELY (!literal_p->has_escape))
|
||||
{
|
||||
name_p = ecma_new_ecma_string_from_utf8 (literal_p->char_p, literal_p->length);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t *destination_p = (uint8_t *) scanner_malloc (context_p, literal_p->length);
|
||||
|
||||
lexer_convert_ident_to_cesu8 (destination_p, literal_p->char_p, literal_p->length);
|
||||
|
||||
name_p = ecma_new_ecma_string_from_utf8 (destination_p, literal_p->length);
|
||||
scanner_free (destination_p, literal_p->length);
|
||||
}
|
||||
|
||||
ecma_object_t *lex_env_p = JERRY_CONTEXT (vm_top_context_p)->lex_env_p;
|
||||
|
||||
while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK)
|
||||
{
|
||||
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||
{
|
||||
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
|
||||
|
||||
if (property_p != NULL && ecma_is_property_enumerable (*property_p))
|
||||
{
|
||||
ecma_deref_ecma_string (name_p);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
|
||||
lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
|
||||
}
|
||||
|
||||
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||
{
|
||||
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
|
||||
|
||||
if (property_p != NULL && ecma_is_property_enumerable (*property_p))
|
||||
{
|
||||
ecma_deref_ecma_string (name_p);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ecma_deref_ecma_string (name_p);
|
||||
return false;
|
||||
} /* scanner_scope_find_let_declaration */
|
||||
|
||||
/**
|
||||
* Throws an error for invalid var statements.
|
||||
*/
|
||||
@ -1642,8 +1661,7 @@ scanner_detect_invalid_var (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
}
|
||||
|
||||
if ((context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL)
|
||||
&& scanner_scope_find_let_declaration (context_p, var_literal_p))
|
||||
if (scanner_scope_find_lexical_declaration (context_p, var_literal_p))
|
||||
{
|
||||
scanner_raise_redeclaration_error (context_p);
|
||||
}
|
||||
@ -2072,7 +2090,7 @@ scanner_is_context_needed (parser_context_t *context_p, /**< context */
|
||||
|
||||
if (JERRY_UNLIKELY (check_type == PARSER_CHECK_GLOBAL_CONTEXT)
|
||||
&& (type == SCANNER_STREAM_TYPE_VAR
|
||||
|| (type == SCANNER_STREAM_TYPE_FUNC && !(context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL))
|
||||
|| (type == SCANNER_STREAM_TYPE_FUNC && !(context_p->global_status_flags & ECMA_PARSE_EVAL))
|
||||
|| is_import))
|
||||
{
|
||||
continue;
|
||||
@ -2768,8 +2786,8 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
|
||||
{
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
literal.char_p -= data_p[1];
|
||||
if (!(context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL)
|
||||
|| !scanner_scope_find_let_declaration (context_p, &literal))
|
||||
|
||||
if (!scanner_scope_find_lexical_declaration (context_p, &literal))
|
||||
{
|
||||
func_init_opcode = CBC_CREATE_VAR_FUNC_EVAL;
|
||||
|
||||
|
||||
24
tests/jerry/es.next/regression-test-issue-4149.js
Normal file
24
tests/jerry/es.next/regression-test-issue-4149.js
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright JS Foundation and other contributors, http://js.foundation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
let x;
|
||||
try {
|
||||
(0,eval)('var x');
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof SyntaxError)
|
||||
}
|
||||
|
||||
(0,eval)('function x() {};');
|
||||
|
||||
@ -390,7 +390,6 @@
|
||||
<test id="language/eval-code/indirect/non-definable-global-var.js"><reason></reason></test>
|
||||
<test id="language/eval-code/indirect/var-env-func-init-global-new.js"><reason></reason></test>
|
||||
<test id="language/eval-code/indirect/var-env-func-init-global-update-configurable.js"><reason></reason></test>
|
||||
<test id="language/eval-code/indirect/var-env-global-lex-non-strict.js"><reason></reason></test>
|
||||
<test id="language/eval-code/indirect/var-env-var-init-global-new.js"><reason></reason></test>
|
||||
<test id="language/expressions/arrow-function/dstr/ary-init-iter-no-close.js"><reason></reason></test>
|
||||
<test id="language/expressions/arrow-function/dstr/dflt-ary-init-iter-no-close.js"><reason></reason></test>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user