diff --git a/Userland/Libraries/LibJS/Runtime/Value.cpp b/Userland/Libraries/LibJS/Runtime/Value.cpp index 1ba8e52750..ceaa9a0f4f 100644 --- a/Userland/Libraries/LibJS/Runtime/Value.cpp +++ b/Userland/Libraries/LibJS/Runtime/Value.cpp @@ -466,31 +466,51 @@ bool Value::to_boolean() const // 7.1.1 ToPrimitive ( input [ , preferredType ] ), https://tc39.es/ecma262/#sec-toprimitive ThrowCompletionOr Value::to_primitive(VM& vm, PreferredType preferred_type) const { - auto get_hint_for_preferred_type = [&]() -> DeprecatedString { - switch (preferred_type) { - case PreferredType::Default: - return "default"; - case PreferredType::String: - return "string"; - case PreferredType::Number: - return "number"; - default: - VERIFY_NOT_REACHED(); - } - }; + // 1. If input is an Object, then if (is_object()) { - auto to_primitive_method = TRY(get_method(vm, *vm.well_known_symbol_to_primitive())); - if (to_primitive_method) { - auto hint = get_hint_for_preferred_type(); - auto result = TRY(call(vm, *to_primitive_method, *this, PrimitiveString::create(vm, hint))); + // a. Let exoticToPrim be ? GetMethod(input, @@toPrimitive). + auto* exotic_to_primitive = TRY(get_method(vm, *vm.well_known_symbol_to_primitive())); + + // b. If exoticToPrim is not undefined, then + if (exotic_to_primitive) { + auto hint = [&]() -> DeprecatedString { + switch (preferred_type) { + // i. If preferredType is not present, let hint be "default". + case PreferredType::Default: + return "default"; + // ii. Else if preferredType is string, let hint be "string". + case PreferredType::String: + return "string"; + // iii. Else, + // 1. Assert: preferredType is number. + // 2. Let hint be "number". + case PreferredType::Number: + return "number"; + default: + VERIFY_NOT_REACHED(); + } + }(); + + // iv. Let result be ? Call(exoticToPrim, input, « hint »). + auto result = TRY(call(vm, *exotic_to_primitive, *this, PrimitiveString::create(vm, hint))); + + // v. If result is not an Object, return result. if (!result.is_object()) return result; + + // vi. Throw a TypeError exception. return vm.throw_completion(ErrorType::ToPrimitiveReturnedObject, to_string_without_side_effects(), hint); } + + // c. If preferredType is not present, let preferredType be number. if (preferred_type == PreferredType::Default) preferred_type = PreferredType::Number; + + // d. Return ? OrdinaryToPrimitive(input, preferredType). return as_object().ordinary_to_primitive(preferred_type); } + + // 2. Return input. return *this; }