Bladeren bron

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.
Andreas Kling 2 jaren geleden
bovenliggende
commit
61148bce5f
1 gewijzigde bestanden met toevoegingen van 22 en 2 verwijderingen
  1. 22 2
      Userland/Libraries/LibJS/Bytecode/Op.cpp

+ 22 - 2
Userland/Libraries/LibJS/Bytecode/Op.cpp

@@ -489,8 +489,28 @@ ThrowCompletionOr<void> SetVariable::execute_impl(Bytecode::Interpreter& interpr
 ThrowCompletionOr<void> 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<Object> 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 {};
 }