diff --git a/Userland/Libraries/LibJS/Runtime/Intl/CollatorConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Intl/CollatorConstructor.cpp index 6e0d4712391..f6b6856d90b 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/CollatorConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/CollatorConstructor.cpp @@ -171,14 +171,16 @@ ThrowCompletionOr> CollatorConstructor::construct(FunctionO // 34. Set collator.[[Sensitivity]] to sensitivity. collator->set_sensitivity(sensitivity.as_string().utf8_string_view()); - // FIXME: 35. Let defaultIgnorePunctuation be resolvedLocaleData.[[ignorePunctuation]]. - auto default_ignore_punctuation = false; + // 35. Let defaultIgnorePunctuation be resolvedLocaleData.[[ignorePunctuation]]. + // NOTE: We do not acquire the default [[ignorePunctuation]] here. Instead, we default the option to null, + // and let LibUnicode fill in the default value if an override was not provided here. // 36. Let ignorePunctuation be ? GetOption(options, "ignorePunctuation", boolean, empty, defaultIgnorePunctuation). - auto ignore_punctuation = TRY(get_option(vm, *options, vm.names.ignorePunctuation, OptionType::Boolean, {}, default_ignore_punctuation)); + auto ignore_punctuation_value = TRY(get_option(vm, *options, vm.names.ignorePunctuation, OptionType::Boolean, {}, Empty {})); - // 37. Set collator.[[IgnorePunctuation]] to ignorePunctuation. - collator->set_ignore_punctuation(ignore_punctuation.as_bool()); + Optional ignore_punctuation; + if (!ignore_punctuation_value.is_undefined()) + ignore_punctuation = ignore_punctuation_value.as_bool(); // Non-standard, create an ICU collator for this Intl object. auto icu_collator = Unicode::Collator::create( @@ -188,9 +190,12 @@ ThrowCompletionOr> CollatorConstructor::construct(FunctionO collator->sensitivity(), collator->case_first(), collator->numeric(), - collator->ignore_punctuation()); + ignore_punctuation); collator->set_collator(move(icu_collator)); + // 37. Set collator.[[IgnorePunctuation]] to ignorePunctuation. + collator->set_ignore_punctuation(collator->collator().ignore_punctuation()); + // 38. Return collator. return collator; } diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/Collator/Collator.prototype.resolvedOptions.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/Collator/Collator.prototype.resolvedOptions.js index 88578388f6e..e34b2f91720 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Intl/Collator/Collator.prototype.resolvedOptions.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/Collator/Collator.prototype.resolvedOptions.js @@ -38,9 +38,15 @@ describe("correct behavior", () => { const en1 = new Intl.Collator("en"); expect(en1.resolvedOptions().ignorePunctuation).toBeFalse(); + const th1 = new Intl.Collator("th"); + expect(th1.resolvedOptions().ignorePunctuation).toBeTrue(); + [true, false].forEach(ignorePunctuation => { const en2 = new Intl.Collator("en", { ignorePunctuation: ignorePunctuation }); expect(en2.resolvedOptions().ignorePunctuation).toBe(ignorePunctuation); + + const th2 = new Intl.Collator("th", { ignorePunctuation: ignorePunctuation }); + expect(th2.resolvedOptions().ignorePunctuation).toBe(ignorePunctuation); }); }); diff --git a/Userland/Libraries/LibUnicode/Collator.cpp b/Userland/Libraries/LibUnicode/Collator.cpp index 617eabc386d..a23d549e31c 100644 --- a/Userland/Libraries/LibUnicode/Collator.cpp +++ b/Userland/Libraries/LibUnicode/Collator.cpp @@ -129,6 +129,16 @@ static constexpr UColAttributeValue icu_case_first(CaseFirst case_first) VERIFY_NOT_REACHED(); } +static bool ignore_punctuation_for_collator(icu::Collator const& collator) +{ + UErrorCode status = U_ZERO_ERROR; + + auto attribute = collator.getAttribute(UCOL_ALTERNATE_HANDLING, status); + VERIFY(icu_success(status)); + + return attribute == UCOL_SHIFTED; +} + class CollatorImpl : public Collator { public: explicit CollatorImpl(NonnullOwnPtr collator) @@ -155,6 +165,11 @@ public: VERIFY_NOT_REACHED(); } + virtual bool ignore_punctuation() const override + { + return ignore_punctuation_for_collator(*m_collator); + } + private: NonnullOwnPtr m_collator; }; @@ -166,7 +181,7 @@ NonnullOwnPtr Collator::create( Sensitivity sensitivity, CaseFirst case_first, bool numeric, - bool ignore_punctuation) + Optional ignore_punctuation) { UErrorCode status = U_ZERO_ERROR; @@ -183,11 +198,14 @@ NonnullOwnPtr Collator::create( VERIFY(icu_success(status)); }; + if (!ignore_punctuation.has_value()) + ignore_punctuation = ignore_punctuation_for_collator(*collator); + set_attribute(UCOL_STRENGTH, icu_sensitivity(sensitivity)); set_attribute(UCOL_CASE_LEVEL, sensitivity == Sensitivity::Case ? UCOL_ON : UCOL_OFF); set_attribute(UCOL_CASE_FIRST, icu_case_first(case_first)); set_attribute(UCOL_NUMERIC_COLLATION, numeric ? UCOL_ON : UCOL_OFF); - set_attribute(UCOL_ALTERNATE_HANDLING, ignore_punctuation ? UCOL_SHIFTED : UCOL_NON_IGNORABLE); + set_attribute(UCOL_ALTERNATE_HANDLING, *ignore_punctuation ? UCOL_SHIFTED : UCOL_NON_IGNORABLE); set_attribute(UCOL_NORMALIZATION_MODE, UCOL_ON); return adopt_own(*new CollatorImpl(move(collator))); diff --git a/Userland/Libraries/LibUnicode/Collator.h b/Userland/Libraries/LibUnicode/Collator.h index 1949139eef5..7e37c7afaac 100644 --- a/Userland/Libraries/LibUnicode/Collator.h +++ b/Userland/Libraries/LibUnicode/Collator.h @@ -44,7 +44,7 @@ public: Sensitivity, CaseFirst, bool numeric, - bool ignore_punctuation); + Optional ignore_punctuation); virtual ~Collator() = default; @@ -55,6 +55,8 @@ public: }; virtual Order compare(StringView, StringView) const = 0; + virtual bool ignore_punctuation() const = 0; + protected: Collator() = default; };