瀏覽代碼

LibJS: Implement the CompareArrayElements AO

Linus Groh 3 年之前
父節點
當前提交
5ddf0b0c99
共有 2 個文件被更改,包括 60 次插入0 次删除
  1. 57 0
      Userland/Libraries/LibJS/Runtime/Array.cpp
  2. 3 0
      Userland/Libraries/LibJS/Runtime/Array.h

+ 57 - 0
Userland/Libraries/LibJS/Runtime/Array.cpp

@@ -6,6 +6,7 @@
  */
 
 #include <AK/Function.h>
+#include <LibJS/Runtime/AbstractOperations.h>
 #include <LibJS/Runtime/Array.h>
 #include <LibJS/Runtime/Completion.h>
 #include <LibJS/Runtime/Error.h>
@@ -142,6 +143,62 @@ ThrowCompletionOr<bool> 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<double> 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<Optional<PropertyDescriptor>> Array::internal_get_own_property(PropertyKey const& property_key) const
 {

+ 3 - 0
Userland/Libraries/LibJS/Runtime/Array.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
  *
  * SPDX-License-Identifier: BSD-2-Clause
  */
@@ -50,4 +51,6 @@ private:
     bool m_length_writable { true };
 };
 
+ThrowCompletionOr<double> compare_array_elements(GlobalObject&, Value x, Value y, FunctionObject* comparefn);
+
 }