From 61148bce5ff8672db3f940654e27156b7d56a45b Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 16 Jun 2023 18:36:42 +0200 Subject: [PATCH] LibJS/Bytecode: Use the correct `this` value in GetById The fix for this was to port the "don't create unnecessary FooObject for property access on primitives" optimization from Reference, which also brings us the correct behavior. --- Userland/Libraries/LibJS/Bytecode/Op.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index c33ecb421d..99bfdf58b6 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -489,8 +489,28 @@ ThrowCompletionOr SetVariable::execute_impl(Bytecode::Interpreter& interpr ThrowCompletionOr GetById::execute_impl(Bytecode::Interpreter& interpreter) const { auto& vm = interpreter.vm(); - auto object = TRY(interpreter.accumulator().to_object(vm)); - interpreter.accumulator() = TRY(object->get(interpreter.current_executable().get_identifier(m_property))); + + auto const& name = interpreter.current_executable().get_identifier(m_property); + auto base_value = interpreter.accumulator(); + + // OPTIMIZATION: For various primitives we can avoid actually creating a new object for them. + GCPtr base_obj; + if (base_value.is_string()) { + auto string_value = TRY(base_value.as_string().get(vm, name)); + if (string_value.has_value()) { + interpreter.accumulator() = *string_value; + return {}; + } + base_obj = vm.current_realm()->intrinsics().string_prototype(); + } else if (base_value.is_number()) { + base_obj = vm.current_realm()->intrinsics().number_prototype(); + } else if (base_value.is_boolean()) { + base_obj = vm.current_realm()->intrinsics().boolean_prototype(); + } else { + base_obj = TRY(base_value.to_object(vm)); + } + + interpreter.accumulator() = TRY(base_obj->internal_get(name, base_value)); return {}; }