LibJS: Implement a nearly empty Intl.PluralRules object

This adds plumbing for the Intl.PluralRules object, constructor, and
prototype.
This commit is contained in:
Timothy Flynn 2022-01-28 12:56:04 -05:00 committed by Linus Groh
parent ac3e42a8de
commit 0087804d10
Notes: sideshowbarker 2024-07-17 20:05:36 +09:00
12 changed files with 229 additions and 0 deletions

View File

@ -106,6 +106,9 @@ set(SOURCES
Runtime/Intl/NumberFormatConstructor.cpp
Runtime/Intl/NumberFormatFunction.cpp
Runtime/Intl/NumberFormatPrototype.cpp
Runtime/Intl/PluralRules.cpp
Runtime/Intl/PluralRulesConstructor.cpp
Runtime/Intl/PluralRulesPrototype.cpp
Runtime/Intl/RelativeTimeFormat.cpp
Runtime/Intl/RelativeTimeFormatConstructor.cpp
Runtime/Intl/RelativeTimeFormatPrototype.cpp

View File

@ -73,6 +73,7 @@
__JS_ENUMERATE(ListFormat, list_format, ListFormatPrototype, ListFormatConstructor) \
__JS_ENUMERATE(Locale, locale, LocalePrototype, LocaleConstructor) \
__JS_ENUMERATE(NumberFormat, number_format, NumberFormatPrototype, NumberFormatConstructor) \
__JS_ENUMERATE(PluralRules, plural_rules, PluralRulesPrototype, PluralRulesConstructor) \
__JS_ENUMERATE(RelativeTimeFormat, relative_time_format, RelativeTimeFormatPrototype, RelativeTimeFormatConstructor)
#define JS_ENUMERATE_TEMPORAL_OBJECTS \

View File

@ -61,6 +61,8 @@
#include <LibJS/Runtime/Intl/LocalePrototype.h>
#include <LibJS/Runtime/Intl/NumberFormatConstructor.h>
#include <LibJS/Runtime/Intl/NumberFormatPrototype.h>
#include <LibJS/Runtime/Intl/PluralRulesConstructor.h>
#include <LibJS/Runtime/Intl/PluralRulesPrototype.h>
#include <LibJS/Runtime/Intl/RelativeTimeFormatConstructor.h>
#include <LibJS/Runtime/Intl/RelativeTimeFormatPrototype.h>
#include <LibJS/Runtime/IteratorPrototype.h>

View File

@ -13,6 +13,7 @@
#include <LibJS/Runtime/Intl/ListFormatConstructor.h>
#include <LibJS/Runtime/Intl/LocaleConstructor.h>
#include <LibJS/Runtime/Intl/NumberFormatConstructor.h>
#include <LibJS/Runtime/Intl/PluralRulesConstructor.h>
#include <LibJS/Runtime/Intl/RelativeTimeFormatConstructor.h>
namespace JS::Intl {
@ -38,6 +39,7 @@ void Intl::initialize(GlobalObject& global_object)
define_direct_property(vm.names.ListFormat, global_object.intl_list_format_constructor(), attr);
define_direct_property(vm.names.Locale, global_object.intl_locale_constructor(), attr);
define_direct_property(vm.names.NumberFormat, global_object.intl_number_format_constructor(), attr);
define_direct_property(vm.names.PluralRules, global_object.intl_plural_rules_constructor(), attr);
define_direct_property(vm.names.RelativeTimeFormat, global_object.intl_relative_time_format_constructor(), attr);
define_native_function(vm.names.getCanonicalLocales, get_canonical_locales, 1, attr);

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2022, Tim Flynn <trflynn89@pm.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/Intl/PluralRules.h>
namespace JS::Intl {
// 16 PluralRules Objects, https://tc39.es/ecma402/#pluralrules-objects
PluralRules::PluralRules(Object& prototype)
: NumberFormatBase(prototype)
{
}
void PluralRules::set_type(StringView type)
{
if (type == "cardinal"sv) {
m_type = Type::Cardinal;
} else if (type == "ordinal"sv) {
m_type = Type::Ordinal;
} else {
VERIFY_NOT_REACHED();
}
}
StringView PluralRules::type_string() const
{
switch (m_type) {
case Type::Cardinal:
return "cardinal"sv;
case Type::Ordinal:
return "ordinal"sv;
default:
VERIFY_NOT_REACHED();
}
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2022, Tim Flynn <trflynn89@pm.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/String.h>
#include <AK/StringView.h>
#include <LibJS/Runtime/Intl/NumberFormat.h>
#include <LibJS/Runtime/Object.h>
namespace JS::Intl {
class PluralRules final : public NumberFormatBase {
JS_OBJECT(PluralRules, NumberFormatBase);
public:
enum class Type {
Cardinal,
Ordinal,
};
PluralRules(Object& prototype);
virtual ~PluralRules() override = default;
Type type() const { return m_type; }
StringView type_string() const;
void set_type(StringView type);
private:
Type m_type { Type::Cardinal }; // [[Type]]
};
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2022, Tim Flynn <trflynn89@pm.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/AbstractOperations.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/Intl/PluralRules.h>
#include <LibJS/Runtime/Intl/PluralRulesConstructor.h>
namespace JS::Intl {
// 16.2 The Intl.PluralRules Constructor, https://tc39.es/ecma402/#sec-intl-pluralrules-constructor
PluralRulesConstructor::PluralRulesConstructor(GlobalObject& global_object)
: NativeFunction(vm().names.PluralRules.as_string(), *global_object.function_prototype())
{
}
void PluralRulesConstructor::initialize(GlobalObject& global_object)
{
NativeFunction::initialize(global_object);
auto& vm = this->vm();
// 16.3.1 Intl.PluralRules.prototype, https://tc39.es/ecma402/#sec-intl.pluralrules.prototype
define_direct_property(vm.names.prototype, global_object.intl_plural_rules_prototype(), 0);
define_direct_property(vm.names.length, Value(0), Attribute::Configurable);
}
// 16.2.1 Intl.PluralRules ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sec-intl.pluralrules
ThrowCompletionOr<Value> PluralRulesConstructor::call()
{
// 1. If NewTarget is undefined, throw a TypeError exception.
return vm().throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.PluralRules");
}
// 16.2.1 Intl.PluralRules ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sec-intl.pluralrules
ThrowCompletionOr<Object*> PluralRulesConstructor::construct(FunctionObject& new_target)
{
auto& global_object = this->global_object();
// 2. Let pluralRules be ? OrdinaryCreateFromConstructor(NewTarget, "%PluralRules.prototype%", « [[InitializedPluralRules]], [[Locale]], [[Type]], [[MinimumIntegerDigits]], [[MinimumFractionDigits]], [[MaximumFractionDigits]], [[MinimumSignificantDigits]], [[MaximumSignificantDigits]], [[RoundingType]] »).
auto* plural_rules = TRY(ordinary_create_from_constructor<PluralRules>(global_object, new_target, &GlobalObject::intl_plural_rules_prototype));
// 3. Return ? InitializePluralRules(pluralRules, locales, options).
return plural_rules;
}
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2022, Tim Flynn <trflynn89@pm.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/NativeFunction.h>
namespace JS::Intl {
class PluralRulesConstructor final : public NativeFunction {
JS_OBJECT(PluralRulesConstructor, NativeFunction);
public:
explicit PluralRulesConstructor(GlobalObject&);
virtual void initialize(GlobalObject&) override;
virtual ~PluralRulesConstructor() override = default;
virtual ThrowCompletionOr<Value> call() override;
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private:
virtual bool has_constructor() const override { return true; }
};
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2022, Tim Flynn <trflynn89@pm.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/Intl/PluralRulesPrototype.h>
namespace JS::Intl {
// 16.4 Properties of the Intl.PluralRules Prototype Object, https://tc39.es/ecma402/#sec-properties-of-intl-pluralrules-prototype-object
PluralRulesPrototype::PluralRulesPrototype(GlobalObject& global_object)
: PrototypeObject(*global_object.object_prototype())
{
}
void PluralRulesPrototype::initialize(GlobalObject& global_object)
{
Object::initialize(global_object);
auto& vm = this->vm();
// 16.4.2 Intl.PluralRules.prototype [ @@toStringTag ], https://tc39.es/ecma402/#sec-intl.pluralrules.prototype-tostringtag
define_direct_property(*vm.well_known_symbol_to_string_tag(), js_string(vm, "Intl.PluralRules"sv), Attribute::Configurable);
}
}

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2022, Tim Flynn <trflynn89@pm.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/Intl/PluralRules.h>
#include <LibJS/Runtime/PrototypeObject.h>
namespace JS::Intl {
class PluralRulesPrototype final : public PrototypeObject<PluralRulesPrototype, PluralRules> {
JS_PROTOTYPE_OBJECT(PluralRulesPrototype, PluralRules, Intl.PluralRules);
public:
explicit PluralRulesPrototype(GlobalObject&);
virtual void initialize(GlobalObject&) override;
virtual ~PluralRulesPrototype() override = default;
};
}

View File

@ -0,0 +1,3 @@
test("basic functionality", () => {
expect(Intl.PluralRules.prototype[Symbol.toStringTag]).toBe("Intl.PluralRules");
});

View File

@ -0,0 +1,13 @@
describe("errors", () => {
test("called without new", () => {
expect(() => {
Intl.PluralRules();
}).toThrowWithMessage(TypeError, "Intl.PluralRules constructor must be called with 'new'");
});
});
describe("normal behavior", () => {
test("length is 0", () => {
expect(Intl.PluralRules).toHaveLength(0);
});
});