diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index 9de1d768bdc..2004d776d74 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -1379,6 +1379,25 @@ ThrowCompletionOr CreateArguments::execute_impl(Bytecode::Interpreter& int ThrowCompletionOr SetVariable::execute_impl(Bytecode::Interpreter& interpreter) const { auto& vm = interpreter.vm(); + + if (m_cache.is_valid()) { + auto* environment = m_mode == EnvironmentMode::Lexical + ? interpreter.running_execution_context().lexical_environment.ptr() + : interpreter.running_execution_context().variable_environment.ptr(); + for (size_t i = 0; i < m_cache.hops; ++i) + environment = environment->outer_environment(); + if (!environment->is_permanently_screwed_by_eval()) { + auto value = interpreter.get(src()); + if (m_initialization_mode == InitializationMode::Initialize) { + TRY(static_cast(*environment).initialize_binding_direct(vm, m_cache.index, value, Environment::InitializeBindingHint::Normal)); + return {}; + } + TRY(static_cast(*environment).set_mutable_binding_direct(vm, m_cache.index, value, vm.in_strict_mode())); + return {}; + } + m_cache = {}; + } + auto const& name = interpreter.current_executable().get_identifier(m_identifier); TRY(set_variable(vm, name, diff --git a/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.cpp b/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.cpp index 8e30f69bbf0..3cd0072912c 100644 --- a/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.cpp +++ b/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.cpp @@ -110,9 +110,12 @@ ThrowCompletionOr DeclarativeEnvironment::create_immutable_binding(VM&, De // 4.1.1.1.1 InitializeBinding ( N, V, hint ), https://tc39.es/proposal-explicit-resource-management/#sec-declarative-environment-records ThrowCompletionOr DeclarativeEnvironment::initialize_binding(VM& vm, DeprecatedFlyString const& name, Value value, Environment::InitializeBindingHint hint) { - auto binding_and_index = find_binding_and_index(name); - VERIFY(binding_and_index.has_value()); - auto& binding = binding_and_index->binding(); + return initialize_binding_direct(vm, find_binding_and_index(name)->index().value(), value, hint); +} + +ThrowCompletionOr DeclarativeEnvironment::initialize_binding_direct(VM& vm, size_t index, Value value, Environment::InitializeBindingHint hint) +{ + auto& binding = m_bindings.at(index); // 1. Assert: envRec must have an uninitialized binding for N. VERIFY(binding.initialized == false); diff --git a/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.h b/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.h index dea181b219b..25b425bc3d5 100644 --- a/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.h +++ b/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.h @@ -56,6 +56,7 @@ public: return names; } + ThrowCompletionOr initialize_binding_direct(VM&, size_t index, Value, InitializeBindingHint); ThrowCompletionOr set_mutable_binding_direct(VM&, size_t index, Value, bool strict); ThrowCompletionOr get_binding_value_direct(VM&, size_t index) const;