diff --git a/Userland/Libraries/LibJS/Parser.cpp b/Userland/Libraries/LibJS/Parser.cpp index 4a07074748d..36143737d41 100644 --- a/Userland/Libraries/LibJS/Parser.cpp +++ b/Userland/Libraries/LibJS/Parser.cpp @@ -77,9 +77,15 @@ public: { ScopePusher scope_pusher(parser, &function_body, ScopeLevel::FunctionTopLevel, ScopeType::Function); scope_pusher.m_function_parameters = parameters; + + auto has_parameters_with_default_values = false; for (auto& parameter : parameters) { parameter.binding.visit( [&](Identifier const& identifier) { + if (parameter.default_value) + has_parameters_with_default_values = true; + scope_pusher.register_identifier(identifier); + scope_pusher.m_function_parameters_candidates_for_local_variables.set(identifier.string()); scope_pusher.m_forbidden_lexical_names.set(identifier.string()); }, [&](NonnullRefPtr const& binding_pattern) { @@ -89,6 +95,11 @@ public: })); }); } + + if (has_parameters_with_default_values) { + scope_pusher.m_function_parameters_candidates_for_local_variables.clear(); + } + return scope_pusher; } @@ -313,6 +324,10 @@ public: scope_has_declaration = false; } + if (m_type == ScopeType::Function && !m_contains_access_to_arguments_object && m_function_parameters_candidates_for_local_variables.contains(identifier_group_name)) { + scope_has_declaration = true; + } + if (scope_has_declaration) { if (function_declaration) continue; @@ -413,6 +428,7 @@ private: Vector> m_functions_to_hoist; HashTable m_bound_names; + HashTable m_function_parameters_candidates_for_local_variables; struct IdentifierGroup { bool captured_by_nested_function { false }; diff --git a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp index ef31371a07e..3ba4f3ba348 100644 --- a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp @@ -479,12 +479,18 @@ ThrowCompletionOr ECMAScriptFunctionObject::function_declaration_instantia Environment* used_environment = has_duplicates ? nullptr : environment; if constexpr (IsSame const&, decltype(param)>) { - Reference reference = TRY(vm.resolve_binding(param->string(), used_environment)); - // Here the difference from hasDuplicates is important - if (has_duplicates) - return reference.put_value(vm, argument_value); - else - return reference.initialize_referenced_binding(vm, argument_value); + if (vm.bytecode_interpreter_if_exists() && param->is_local()) { + // NOTE: Local variables are supported only in bytecode interpreter + callee_context.local_variables[param->local_variable_index()] = argument_value; + return {}; + } else { + Reference reference = TRY(vm.resolve_binding(param->string(), used_environment)); + // Here the difference from hasDuplicates is important + if (has_duplicates) + return reference.put_value(vm, argument_value); + else + return reference.initialize_referenced_binding(vm, argument_value); + } } if constexpr (IsSame const&, decltype(param)>) { // Here the difference from hasDuplicates is important