diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index 8fdc2d7eaa4..47a0efbe121 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -44,8 +44,7 @@ Bytecode::CodeGenerationErrorOr> ScopeNode::generate_byt if (is(*this)) { if (has_lexical_declarations()) { - generator.block_declaration_instantiation(*this); - did_create_lexical_environment = true; + did_create_lexical_environment = generator.emit_block_declaration_instantiation(*this); } } else if (is(*this)) { // GlobalDeclarationInstantiation is handled by the C++ AO. @@ -2655,9 +2654,9 @@ Bytecode::CodeGenerationErrorOr> SwitchStatement::genera Bytecode::BasicBlock* entry_block_for_default { nullptr }; Bytecode::BasicBlock* next_test_block = &generator.make_block(); - auto has_lexical_declarations = this->has_lexical_declarations(); - if (has_lexical_declarations) - generator.block_declaration_instantiation(*this); + bool did_create_lexical_environment = false; + if (has_lexical_declarations()) + did_create_lexical_environment = generator.emit_block_declaration_instantiation(*this); generator.emit(Bytecode::Label { *next_test_block }); @@ -2721,7 +2720,7 @@ Bytecode::CodeGenerationErrorOr> SwitchStatement::genera generator.switch_to_basic_block(end_block); - if (has_lexical_declarations) + if (did_create_lexical_environment) generator.end_variable_scope(); return dst; diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.cpp b/Userland/Libraries/LibJS/Bytecode/Generator.cpp index f7b6b5b4f23..246e68bbbea 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Generator.cpp @@ -448,10 +448,28 @@ Label Generator::nearest_continuable_scope() const return m_continuable_scopes.last().bytecode_target; } -void Generator::block_declaration_instantiation(ScopeNode const& scope_node) +bool Generator::emit_block_declaration_instantiation(ScopeNode const& scope_node) { + bool needs_block_declaration_instantiation = false; + MUST(scope_node.for_each_lexically_scoped_declaration([&](Declaration const& declaration) { + if (declaration.is_function_declaration()) { + needs_block_declaration_instantiation = true; + return; + } + MUST(declaration.for_each_bound_identifier([&](auto const& id) { + if (!id.is_local()) + needs_block_declaration_instantiation = true; + })); + })); + + if (!needs_block_declaration_instantiation) + return false; + + // FIXME: Generate the actual bytecode for block declaration instantiation + // and get rid of the BlockDeclarationInstantiation instruction. start_boundary(BlockBoundaryType::LeaveLexicalEnvironment); emit(scope_node); + return true; } void Generator::begin_variable_scope() diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.h b/Userland/Libraries/LibJS/Bytecode/Generator.h index f1e54fa2a04..5ef5b1d49ee 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.h +++ b/Userland/Libraries/LibJS/Bytecode/Generator.h @@ -213,7 +213,8 @@ public: SurroundingScopeKind kind; }; - void block_declaration_instantiation(ScopeNode const&); + // Returns true if a lexical environment was created. + bool emit_block_declaration_instantiation(ScopeNode const&); void begin_variable_scope(); void end_variable_scope();