diff options
-rw-r--r-- | Userland/Libraries/LibJS/AST.cpp | 18 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/AST.h | 3 |
2 files changed, 16 insertions, 5 deletions
diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index 5cd3a2d7c9..8b2bdfe7cb 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -122,13 +122,21 @@ Value BlockStatement::execute(Interpreter& interpreter, GlobalObject& global_obj InterpreterNodeScope node_scope { interpreter, *this }; auto& vm = interpreter.vm(); - Environment* old_environment = vm.running_execution_context().lexical_environment; - ScopeGuard restore_environment = [&] { + + Environment* old_environment { nullptr }; + ArmedScopeGuard restore_environment = [&] { vm.running_execution_context().lexical_environment = old_environment; }; - auto* block_environment = new_declarative_environment(*old_environment); - block_declaration_instantiation(global_object, block_environment); - vm.running_execution_context().lexical_environment = block_environment; + + // Optimization: We only need a new lexical environment if there are any lexical declarations. :^) + if (has_lexical_declarations()) { + old_environment = vm.running_execution_context().lexical_environment; + auto* block_environment = new_declarative_environment(*old_environment); + block_declaration_instantiation(global_object, block_environment); + vm.running_execution_context().lexical_environment = block_environment; + } else { + restore_environment.disarm(); + } auto block_value = evaluate_statements(interpreter, global_object); if (!labels().is_empty() && vm.should_unwind_until(ScopeType::Breakable, labels())) diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h index f44c44a991..2baab6fda3 100644 --- a/Userland/Libraries/LibJS/AST.h +++ b/Userland/Libraries/LibJS/AST.h @@ -183,6 +183,9 @@ public: void add_lexical_declaration(NonnullRefPtr<Declaration> variables); void add_hoisted_function(NonnullRefPtr<FunctionDeclaration> declaration); + [[nodiscard]] bool has_lexical_declarations() const { return !m_lexical_declarations.is_empty(); } + [[nodiscard]] bool has_var_declarations() const { return !m_var_declarations.is_empty(); } + void for_each_lexically_scoped_declaration(IteratorOrVoidFunction<Declaration const&>&& callback) const; void for_each_lexically_declared_name(IteratorOrVoidFunction<FlyString const&>&& callback) const; |