From 5ddf0b0c99be1dc6a67129e9a7cc7c751e9ed629 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Mon, 13 Jun 2022 07:53:58 +0100 Subject: [PATCH] LibJS: Implement the CompareArrayElements AO --- Userland/Libraries/LibJS/Runtime/Array.cpp | 57 ++++++++++++++++++++++ Userland/Libraries/LibJS/Runtime/Array.h | 3 ++ 2 files changed, 60 insertions(+) diff --git a/Userland/Libraries/LibJS/Runtime/Array.cpp b/Userland/Libraries/LibJS/Runtime/Array.cpp index 20a36917fe..2de9a8e83d 100644 --- a/Userland/Libraries/LibJS/Runtime/Array.cpp +++ b/Userland/Libraries/LibJS/Runtime/Array.cpp @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -142,6 +143,62 @@ ThrowCompletionOr Array::set_length(PropertyDescriptor const& property_des return true; } +// 1.1.1.2 CompareArrayElements ( x, y, comparefn ), https://tc39.es/proposal-change-array-by-copy/#sec-comparearrayelements +ThrowCompletionOr compare_array_elements(GlobalObject& global_object, Value x, Value y, FunctionObject* comparefn) +{ + auto& vm = global_object.vm(); + + // 1. If x and y are both undefined, return +0๐”ฝ. + if (x.is_undefined() && y.is_undefined()) + return 0; + + // 2. If x is undefined, return 1๐”ฝ. + if (x.is_undefined()) + return 1; + + // 3. If y is undefined, return -1๐”ฝ. + if (y.is_undefined()) + return -1; + + // 4. If comparefn is not undefined, then + if (comparefn != nullptr) { + // a. Let v be ? ToNumber(? Call(comparefn, undefined, ยซ x, y ยป)). + auto value = TRY(call(global_object, comparefn, js_undefined(), x, y)); + auto value_number = TRY(value.to_number(global_object)); + + // b. If v is NaN, return +0๐”ฝ. + if (value_number.is_nan()) + return 0; + + // c. Return v. + return value_number.as_double(); + } + + // 5. Let xString be ? ToString(x). + auto* x_string = js_string(vm, TRY(x.to_string(global_object))); + + // 6. Let yString be ? ToString(y). + auto* y_string = js_string(vm, TRY(y.to_string(global_object))); + + // 7. Let xSmaller be ! IsLessThan(xString, yString, true). + // FIXME: Update order of parameters in our is_less_than() impl. + auto x_smaller = MUST(is_less_than(global_object, true, x_string, y_string)); + + // 8. If xSmaller is true, return -1๐”ฝ. + if (x_smaller == TriState::True) + return -1; + + // 9. Let ySmaller be ! IsLessThan(yString, xString, true). + auto y_smaller = MUST(is_less_than(global_object, true, y_string, x_string)); + + // 10. If ySmaller is true, return 1๐”ฝ. + if (y_smaller == TriState::True) + return 1; + + // 11. Return +0๐”ฝ. + return 0; +} + // NON-STANDARD: Used to return the value of the ephemeral length property ThrowCompletionOr> Array::internal_get_own_property(PropertyKey const& property_key) const { diff --git a/Userland/Libraries/LibJS/Runtime/Array.h b/Userland/Libraries/LibJS/Runtime/Array.h index 981fd26b01..a7c158963c 100644 --- a/Userland/Libraries/LibJS/Runtime/Array.h +++ b/Userland/Libraries/LibJS/Runtime/Array.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, Andreas Kling + * Copyright (c) 2020-2022, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ @@ -50,4 +51,6 @@ private: bool m_length_writable { true }; }; +ThrowCompletionOr compare_array_elements(GlobalObject&, Value x, Value y, FunctionObject* comparefn); + }