summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp4
-rw-r--r--Userland/Libraries/LibJS/Bytecode/Generator.h9
2 files changed, 11 insertions, 2 deletions
diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp
index c55caa9e06..8240d330f5 100644
--- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp
+++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp
@@ -45,7 +45,9 @@ Bytecode::CodeGenerationErrorOr<void> ScopeNode::generate_bytecode(Bytecode::Gen
auto is_constant_declaration = declaration.is_constant_declaration();
declaration.for_each_bound_name([&](auto const& name) {
auto index = generator.intern_identifier(name);
- if (is_constant_declaration || !generator.has_binding(index)) {
+ // NOTE: BlockDeclarationInstantiation takes as input the new lexical environment that was created and checks if there is a binding for the current name only in this new scope.
+ // For example: `{ let a = 1; { let a = 2; } }`. The second `a` will shadow the first `a` instead of re-initializing or setting it.
+ if (is_constant_declaration || !generator.has_binding_in_current_scope(index)) {
generator.register_binding(index);
generator.emit<Bytecode::Op::CreateVariable>(index, Bytecode::Op::EnvironmentMode::Lexical, is_constant_declaration);
}
diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.h b/Userland/Libraries/LibJS/Bytecode/Generator.h
index 6af3c9bfdb..5473e11ca8 100644
--- a/Userland/Libraries/LibJS/Bytecode/Generator.h
+++ b/Userland/Libraries/LibJS/Bytecode/Generator.h
@@ -138,7 +138,7 @@ public:
{
m_variable_scopes.last_matching([&](auto& x) { return x.mode == BindingMode::Global || x.mode == mode; })->known_bindings.set(identifier);
}
- bool has_binding(IdentifierTableIndex identifier, Optional<BindingMode> const& specific_binding_mode = {})
+ bool has_binding(IdentifierTableIndex identifier, Optional<BindingMode> const& specific_binding_mode = {}) const
{
for (auto index = m_variable_scopes.size(); index > 0; --index) {
auto& scope = m_variable_scopes[index - 1];
@@ -151,6 +151,13 @@ public:
}
return false;
}
+ bool has_binding_in_current_scope(IdentifierTableIndex identifier) const
+ {
+ if (m_variable_scopes.is_empty())
+ return false;
+
+ return m_variable_scopes.last().known_bindings.contains(identifier);
+ }
void begin_variable_scope(BindingMode mode = BindingMode::Lexical, SurroundingScopeKind kind = SurroundingScopeKind::Block);
void end_variable_scope();