diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.cpp b/Userland/Libraries/LibJS/Bytecode/Generator.cpp index cc79dde9440..31e1a4fe611 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Generator.cpp @@ -76,6 +76,33 @@ Label Generator::nearest_continuable_scope() const return m_continuable_scopes.last(); } +void Generator::begin_variable_scope(BindingMode mode, SurroundingScopeKind kind) +{ + m_variable_scopes.append({ kind, mode, {} }); + if (mode != BindingMode::Global) { + start_boundary(mode == BindingMode::Lexical ? BlockBoundaryType::LeaveLexicalEnvironment : BlockBoundaryType::LeaveVariableEnvironment); + emit( + mode == BindingMode::Lexical + ? Bytecode::Op::EnvironmentMode::Lexical + : Bytecode::Op::EnvironmentMode::Var); + } +} + +void Generator::end_variable_scope() +{ + auto mode = m_variable_scopes.take_last().mode; + if (mode != BindingMode::Global) { + end_boundary(mode == BindingMode::Lexical ? BlockBoundaryType::LeaveLexicalEnvironment : BlockBoundaryType::LeaveVariableEnvironment); + + if (!m_current_basic_block->is_terminated()) { + emit( + mode == BindingMode::Lexical + ? Bytecode::Op::EnvironmentMode::Lexical + : Bytecode::Op::EnvironmentMode::Var); + } + } +} + void Generator::begin_continuable_scope(Label continue_target) { m_continuable_scopes.append(continue_target); diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.h b/Userland/Libraries/LibJS/Bytecode/Generator.h index 80db80d34f6..91662a9aea7 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.h +++ b/Userland/Libraries/LibJS/Bytecode/Generator.h @@ -150,31 +150,16 @@ public: } return false; } - void begin_variable_scope(BindingMode mode = BindingMode::Lexical, SurroundingScopeKind kind = SurroundingScopeKind::Block) - { - m_variable_scopes.append({ kind, mode, {} }); - if (mode != BindingMode::Global) { - emit( - mode == BindingMode::Lexical - ? Bytecode::Op::EnvironmentMode::Lexical - : Bytecode::Op::EnvironmentMode::Var); - } - } - void end_variable_scope() - { - auto mode = m_variable_scopes.take_last().mode; - if (mode != BindingMode::Global && !m_current_basic_block->is_terminated()) { - emit( - mode == BindingMode::Lexical - ? Bytecode::Op::EnvironmentMode::Lexical - : Bytecode::Op::EnvironmentMode::Var); - } - } + + void begin_variable_scope(BindingMode mode = BindingMode::Lexical, SurroundingScopeKind kind = SurroundingScopeKind::Block); + void end_variable_scope(); enum class BlockBoundaryType { Break, Continue, Unwind, + LeaveLexicalEnvironment, + LeaveVariableEnvironment, }; template void perform_needed_unwinds(bool is_break_node = false) requires(OpType::IsTerminator) @@ -191,6 +176,10 @@ public: break; if (boundary == BlockBoundaryType::Unwind) emit(); + else if (boundary == BlockBoundaryType::LeaveLexicalEnvironment) + emit(Bytecode::Op::EnvironmentMode::Lexical); + else if (boundary == BlockBoundaryType::LeaveVariableEnvironment) + emit(Bytecode::Op::EnvironmentMode::Var); } }