From 0bdb29326234a4cc89b2e14e3a2f83eb63ffb321 Mon Sep 17 00:00:00 2001 From: Idan Horowitz Date: Sun, 20 Feb 2022 19:53:50 +0200 Subject: [PATCH] LibJS: Add an initial implementation of Collator Compare Functions This commit adds an initial implementation (without any real locale support) of Collator Compare Functions, as well as the matching CompareStrings AO. These two are used to implement the ECMA402 version of String.localeCompare() and Int.Collator.compare(). --- Userland/Libraries/LibJS/CMakeLists.txt | 1 + .../Runtime/Intl/CollatorCompareFunction.cpp | 75 +++++++++++++++++++ .../Runtime/Intl/CollatorCompareFunction.h | 33 ++++++++ 3 files changed, 109 insertions(+) create mode 100644 Userland/Libraries/LibJS/Runtime/Intl/CollatorCompareFunction.cpp create mode 100644 Userland/Libraries/LibJS/Runtime/Intl/CollatorCompareFunction.h diff --git a/Userland/Libraries/LibJS/CMakeLists.txt b/Userland/Libraries/LibJS/CMakeLists.txt index 9e92ef1343..c90d83b957 100644 --- a/Userland/Libraries/LibJS/CMakeLists.txt +++ b/Userland/Libraries/LibJS/CMakeLists.txt @@ -88,6 +88,7 @@ set(SOURCES Runtime/IndexedProperties.cpp Runtime/Intl/AbstractOperations.cpp Runtime/Intl/Collator.cpp + Runtime/Intl/CollatorCompareFunction.cpp Runtime/Intl/CollatorConstructor.cpp Runtime/Intl/CollatorPrototype.cpp Runtime/Intl/DateTimeFormat.cpp diff --git a/Userland/Libraries/LibJS/Runtime/Intl/CollatorCompareFunction.cpp b/Userland/Libraries/LibJS/Runtime/Intl/CollatorCompareFunction.cpp new file mode 100644 index 0000000000..6c8240470d --- /dev/null +++ b/Userland/Libraries/LibJS/Runtime/Intl/CollatorCompareFunction.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2022, Idan Horowitz + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +namespace JS::Intl { + +CollatorCompareFunction* CollatorCompareFunction::create(GlobalObject& global_object, Collator& collator) +{ + return global_object.heap().allocate(global_object, global_object, collator); +} + +CollatorCompareFunction::CollatorCompareFunction(GlobalObject& global_object, Collator& collator) + : NativeFunction(*global_object.function_prototype()) + , m_collator(collator) +{ +} + +void CollatorCompareFunction::initialize(GlobalObject& global_object) +{ + auto& vm = global_object.vm(); + define_direct_property(vm.names.length, Value(2), Attribute::Configurable); +} + +// 10.3.3.2 CompareStrings ( collator, x, y ), https://tc39.es/ecma402/#sec-collator-comparestrings +double compare_strings(Collator& collator, Utf8View const& x, Utf8View const& y) +{ + // FIXME: Implement https://unicode.org/reports/tr10 + (void)collator; + auto x_iterator = x.begin(); + auto y_iterator = y.begin(); + for (; x_iterator != x.end() && y_iterator != y.end(); ++x_iterator, ++y_iterator) { + if (*x_iterator != *y_iterator) + return static_cast(*x_iterator) - static_cast(*y_iterator); + } + if (x_iterator != x.end()) + return 1.0; + if (y_iterator != y.end()) + return -1.0; + return 0.0; +} + +// 10.3.3.1 Collator Compare Functions, https://tc39.es/ecma402/#sec-collator-compare-functions +ThrowCompletionOr CollatorCompareFunction::call() +{ + auto& vm = this->vm(); + auto& global_object = this->global_object(); + + // 1. Let collator be F.[[Collator]]. + // 2. Assert: Type(collator) is Object and collator has an [[InitializedCollator]] internal slot. + // 3. If x is not provided, let x be undefined. + // 4. If y is not provided, let y be undefined. + + // 5. Let X be ? ToString(x). + auto x = TRY(vm.argument(0).to_string(global_object)); + // 6. Let Y be ? ToString(y). + auto y = TRY(vm.argument(1).to_string(global_object)); + + // 7. Return CompareStrings(collator, X, Y). + return compare_strings(m_collator, Utf8View(x), Utf8View(y)); +} + +void CollatorCompareFunction::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(&m_collator); +} + +} diff --git a/Userland/Libraries/LibJS/Runtime/Intl/CollatorCompareFunction.h b/Userland/Libraries/LibJS/Runtime/Intl/CollatorCompareFunction.h new file mode 100644 index 0000000000..a1540bc92b --- /dev/null +++ b/Userland/Libraries/LibJS/Runtime/Intl/CollatorCompareFunction.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022, Idan Horowitz + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace JS::Intl { + +class CollatorCompareFunction : public NativeFunction { + JS_OBJECT(CollatorCompareFunction, NativeFunction); + +public: + static CollatorCompareFunction* create(GlobalObject&, Collator&); + + explicit CollatorCompareFunction(GlobalObject&, Collator&); + virtual void initialize(GlobalObject&) override; + virtual ~CollatorCompareFunction() override = default; + + virtual ThrowCompletionOr call() override; + +private: + virtual void visit_edges(Visitor&) override; + + Collator& m_collator; // [[Collator]] +}; + +double compare_strings(Collator&, Utf8View const& x, Utf8View const& y); + +}