diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index 6de37f0573..e54d2d4380 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -1440,6 +1440,16 @@ void SequenceExpression::dump(int indent) const expression->dump(indent + 1); } +bool ScopeNode::has_non_local_lexical_declarations() const +{ + bool result = false; + MUST(for_each_lexically_declared_identifier([&](Identifier const& identifier) { + if (!identifier.is_local()) + result = true; + })); + return result; +} + ThrowCompletionOr ScopeNode::for_each_lexically_scoped_declaration(ThrowCompletionOrVoidCallback&& callback) const { for (auto& declaration : m_lexical_declarations) diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h index c846f33262..1c7b74a380 100644 --- a/Userland/Libraries/LibJS/AST.h +++ b/Userland/Libraries/LibJS/AST.h @@ -306,6 +306,7 @@ public: void add_hoisted_function(NonnullRefPtr declaration); [[nodiscard]] bool has_lexical_declarations() const { return !m_lexical_declarations.is_empty(); } + [[nodiscard]] bool has_non_local_lexical_declarations() const; [[nodiscard]] bool has_var_declarations() const { return !m_var_declarations.is_empty(); } [[nodiscard]] size_t var_declaration_count() const { return m_var_declarations.size(); } diff --git a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp index 3b10104768..fa446943a1 100644 --- a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp @@ -308,7 +308,7 @@ ECMAScriptFunctionObject::ECMAScriptFunctionObject(DeprecatedFlyString name, Byt // 30. If strict is false, then if (!m_strict) { - bool can_elide_declarative_environment = !m_contains_direct_call_to_eval && (!scope_body || !scope_body->has_lexical_declarations()); + bool can_elide_declarative_environment = !m_contains_direct_call_to_eval && (!scope_body || !scope_body->has_non_local_lexical_declarations()); if (can_elide_declarative_environment) { lex_environment_size = var_environment_size; } else { @@ -870,7 +870,7 @@ ThrowCompletionOr ECMAScriptFunctionObject::function_declaration_instantia // Optimization: We avoid creating empty top-level declarative environments in non-strict mode, if both of these conditions are true: // 1. there is no direct call to eval() within this function // 2. there are no lexical declarations that would go into the environment - bool can_elide_declarative_environment = !m_contains_direct_call_to_eval && (!scope_body || !scope_body->has_lexical_declarations()); + bool can_elide_declarative_environment = !m_contains_direct_call_to_eval && (!scope_body || !scope_body->has_non_local_lexical_declarations()); if (can_elide_declarative_environment) { lex_environment = var_environment; } else {