From f11cb7c075d9c5a78d6e341b839638f31dda8e21 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Thu, 7 Jul 2022 12:21:27 -0400 Subject: [PATCH] LibJS: Populate pluralCategories in Intl.PluralRules.resolvedOptions --- .../Runtime/Intl/PluralRulesPrototype.cpp | 10 +++++-- .../PluralRules.prototype.resolvedOptions.js | 28 ++++++++++++++++--- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/Intl/PluralRulesPrototype.cpp b/Userland/Libraries/LibJS/Runtime/Intl/PluralRulesPrototype.cpp index 40a7de57e4..8793c10db0 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/PluralRulesPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/PluralRulesPrototype.cpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace JS::Intl { @@ -58,11 +59,14 @@ JS_DEFINE_NATIVE_FUNCTION(PluralRulesPrototype::resolved_options) MUST(options->create_data_property_or_throw(vm.names.maximumSignificantDigits, Value(plural_rules->max_significant_digits()))); // 5. Let pluralCategories be a List of Strings containing all possible results of PluralRuleSelect for the selected locale pr.[[Locale]]. - // FIXME: Implement this when the data is available in LibUnicode. - MarkedVector plural_categories { vm.heap() }; + auto available_categories = Unicode::available_plural_categories(plural_rules->locale(), plural_rules->type()); + + auto* plural_categories = Array::create_from(global_object, available_categories, [&](auto category) { + return js_string(vm, Unicode::plural_category_to_string(category)); + }); // 6. Perform ! CreateDataProperty(options, "pluralCategories", CreateArrayFromList(pluralCategories)). - MUST(options->create_data_property_or_throw(vm.names.pluralCategories, Array::create_from(global_object, plural_categories))); + MUST(options->create_data_property_or_throw(vm.names.pluralCategories, plural_categories)); // 7. Return options. return options; diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/PluralRules/PluralRules.prototype.resolvedOptions.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/PluralRules/PluralRules.prototype.resolvedOptions.js index 29e7cd88ba..693bc248b4 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Intl/PluralRules/PluralRules.prototype.resolvedOptions.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/PluralRules/PluralRules.prototype.resolvedOptions.js @@ -79,9 +79,29 @@ describe("correct behavior", () => { }); test("plural categories", () => { - // FIXME: Write better tests when this is implemented. - const en = new Intl.PluralRules("en"); - expect(en.resolvedOptions().pluralCategories).toBeDefined(); - expect(en.resolvedOptions().pluralCategories).toEqual([]); + // The spec doesn't dictate an order of elements, and the generated CLDR data is ordered by + // hash map iteration. Instead of using toEqual(), just make sure all elements are the same. + const contains = (actual, expected) => { + if (actual.length !== expected.length) return false; + return expected.every(e => actual.includes(e)); + }; + + const enCardinal = new Intl.PluralRules("en", { type: "cardinal" }).resolvedOptions(); + expect(enCardinal.pluralCategories).toBeDefined(); + expect(contains(enCardinal.pluralCategories, ["other", "one"])).toBeTrue(); + + const enOrdinal = new Intl.PluralRules("en", { type: "ordinal" }).resolvedOptions(); + expect(enOrdinal.pluralCategories).toBeDefined(); + expect(contains(enOrdinal.pluralCategories, ["other", "one", "two", "few"])).toBeTrue(); + + const gaCardinal = new Intl.PluralRules("ga", { type: "cardinal" }).resolvedOptions(); + expect(gaCardinal.pluralCategories).toBeDefined(); + expect( + contains(gaCardinal.pluralCategories, ["other", "one", "two", "few", "many"]) + ).toBeTrue(); + + const gaOrdinal = new Intl.PluralRules("ga", { type: "ordinal" }).resolvedOptions(); + expect(gaOrdinal.pluralCategories).toBeDefined(); + expect(contains(gaOrdinal.pluralCategories, ["other", "one"])).toBeTrue(); }); });