summaryrefslogtreecommitdiff
path: root/deps/v8/src/ast/scopes.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/ast/scopes.cc')
-rw-r--r--deps/v8/src/ast/scopes.cc39
1 files changed, 36 insertions, 3 deletions
diff --git a/deps/v8/src/ast/scopes.cc b/deps/v8/src/ast/scopes.cc
index a66e4ea93f..cd8be1caec 100644
--- a/deps/v8/src/ast/scopes.cc
+++ b/deps/v8/src/ast/scopes.cc
@@ -632,7 +632,8 @@ void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
// scope and we terminate the iteration there anyway.
do {
Variable* var = query_scope->LookupInScopeOrScopeInfo(name, query_scope);
- if (var != nullptr && IsLexicalVariableMode(var->mode())) {
+ if (var != nullptr && IsLexicalVariableMode(var->mode()) &&
+ !var->is_sloppy_block_function()) {
should_hoist = false;
break;
}
@@ -649,6 +650,19 @@ void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
auto declaration = factory->NewVariableDeclaration(pos);
// Based on the preceding checks, it doesn't matter what we pass as
// sloppy_mode_block_scope_function_redefinition.
+ //
+ // This synthesized var for Annex B functions-in-block (FiB) may be
+ // declared multiple times for the same var scope, such as in the case of
+ // shadowed functions-in-block like the following:
+ //
+ // {
+ // function f() {}
+ // { function f() {} }
+ // }
+ //
+ // Redeclarations for vars do not create new bindings, but the
+ // redeclarations' initializers are still run. That is, shadowed FiB will
+ // result in multiple assignments to the same synthesized var.
Variable* var = DeclareVariable(
declaration, name, pos, VariableMode::kVar, NORMAL_VARIABLE,
Variable::DefaultInitializationFlag(VariableMode::kVar), &was_added,
@@ -1263,8 +1277,9 @@ Declaration* DeclarationScope::CheckConflictingVarDeclarations(
if (decl->IsVariableDeclaration() &&
decl->AsVariableDeclaration()->AsNested() != nullptr) {
Scope* current = decl->AsVariableDeclaration()->AsNested()->scope();
- DCHECK(decl->var()->mode() == VariableMode::kVar ||
- decl->var()->mode() == VariableMode::kDynamic);
+ if (decl->var()->mode() != VariableMode::kVar &&
+ decl->var()->mode() != VariableMode::kDynamic)
+ continue;
// Iterate through all scopes until the declaration scope.
do {
// There is a conflict if there exists a non-VAR binding.
@@ -1796,6 +1811,8 @@ const char* Header(ScopeType scope_type, FunctionKind function_kind,
case CLASS_SCOPE:
return "class";
case WITH_SCOPE: return "with";
+ case SHADOW_REALM_SCOPE:
+ return "shadowrealm";
}
UNREACHABLE();
}
@@ -2058,6 +2075,15 @@ Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
return var;
}
+void Scope::ForceDynamicLookup(VariableProxy* proxy) {
+ // At the moment this is only used for looking up private names dynamically
+ // in debug-evaluate from top-level scope.
+ DCHECK(proxy->IsPrivateName());
+ DCHECK(is_script_scope() || is_module_scope() || is_eval_scope());
+ Variable* dynamic = NonLocal(proxy->raw_name(), VariableMode::kDynamic);
+ proxy->BindTo(dynamic);
+}
+
// static
template <Scope::ScopeLookupMode mode>
Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope,
@@ -3109,6 +3135,13 @@ void PrivateNameScopeIterator::AddUnresolvedPrivateName(VariableProxy* proxy) {
// be new.
DCHECK(!proxy->is_resolved());
DCHECK(proxy->IsPrivateName());
+
+ // Use dynamic lookup for top-level scopes in debug-evaluate.
+ if (Done()) {
+ start_scope_->ForceDynamicLookup(proxy);
+ return;
+ }
+
GetScope()->EnsureRareData()->unresolved_private_names.Add(proxy);
// Any closure scope that contain uses of private names that skips over a
// class scope due to heritage expressions need private name context chain