[intl] NumberFormat v3 Part 4 SelectRange
Implement the Intl.PluralRules.prototype.selectRange (start, end) of the spec See https://tc39.es/proposal-intl-numberformat-v3/out/pluralrules/diff.html https://chromestatus.com/guide/edit/5707621009981440 Design Doc: https://docs.google.com/document/d/19jAogPBb6W4Samt8NWGZKu47iv0_KoQhBvLgQH3xvr8/edit Bug: v8:10776 Change-Id: Ie9c56df7ce68199492281fdf2483c3d6f822cc9e Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3504421 Reviewed-by: Shu-yu Guo <syg@chromium.org> Commit-Queue: Frank Tang <ftang@chromium.org> Cr-Commit-Position: refs/heads/main@{#79495}
This commit is contained in:
parent
d782fd1da9
commit
09de56b06e
@ -1789,6 +1789,8 @@ namespace internal {
|
||||
CPP(PluralRulesPrototypeResolvedOptions) \
|
||||
/* ecma402 #sec-intl.pluralrules.prototype.select */ \
|
||||
CPP(PluralRulesPrototypeSelect) \
|
||||
/* ecma402 #sec-intl.pluralrules.prototype.selectrange */ \
|
||||
CPP(PluralRulesPrototypeSelectRange) \
|
||||
/* ecma402 #sec-intl.pluralrules.supportedlocalesof */ \
|
||||
CPP(PluralRulesSupportedLocalesOf) \
|
||||
/* ecma402 #sec-intl.RelativeTimeFormat.constructor */ \
|
||||
|
@ -987,6 +987,64 @@ BUILTIN(PluralRulesPrototypeSelect) {
|
||||
isolate, plural_rules, number_double));
|
||||
}
|
||||
|
||||
BUILTIN(PluralRulesPrototypeSelectRange) {
|
||||
HandleScope scope(isolate);
|
||||
|
||||
// 1. Let pr be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(pr, [[InitializedPluralRules]]).
|
||||
CHECK_RECEIVER(JSPluralRules, plural_rules,
|
||||
"Intl.PluralRules.prototype.selectRange");
|
||||
|
||||
// 3. If start is undefined or end is undefined, throw a TypeError exception.
|
||||
Handle<Object> start = args.atOrUndefined(isolate, 1);
|
||||
Handle<Object> end = args.atOrUndefined(isolate, 2);
|
||||
if (start->IsUndefined()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewTypeError(MessageTemplate::kInvalid,
|
||||
isolate->factory()->startRange_string(), start));
|
||||
}
|
||||
if (end->IsUndefined()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewTypeError(MessageTemplate::kInvalid,
|
||||
isolate->factory()->endRange_string(), end));
|
||||
}
|
||||
|
||||
// 4. Let x be ? ToNumber(start).
|
||||
Handle<Object> x;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x,
|
||||
Object::ToNumber(isolate, start));
|
||||
|
||||
// 5. Let y be ? ToNumber(end).
|
||||
Handle<Object> y;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, y,
|
||||
Object::ToNumber(isolate, end));
|
||||
|
||||
// 6. Return ! ResolvePluralRange(pr, x, y).
|
||||
// Inside ResolvePluralRange
|
||||
// 5. If x is NaN or y is NaN, throw a RangeError exception.
|
||||
if (x->IsNaN()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewRangeError(MessageTemplate::kInvalid,
|
||||
isolate->factory()->startRange_string(), x));
|
||||
}
|
||||
if (y->IsNaN()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewRangeError(MessageTemplate::kInvalid,
|
||||
isolate->factory()->endRange_string(), y));
|
||||
}
|
||||
|
||||
// 6. If x > y, throw a RangeError exception.
|
||||
double x_double = x->Number();
|
||||
double y_double = y->Number();
|
||||
if (x_double > y_double) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewRangeError(MessageTemplate::kInvalid, x, y));
|
||||
}
|
||||
RETURN_RESULT_OR_FAILURE(
|
||||
isolate, JSPluralRules::ResolvePluralRange(isolate, plural_rules,
|
||||
x_double, y_double));
|
||||
}
|
||||
|
||||
BUILTIN(PluralRulesSupportedLocalesOf) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> locales = args.atOrUndefined(isolate, 1);
|
||||
|
@ -5351,6 +5351,7 @@ void Genesis::InitializeGlobal_harmony_intl_number_format_v3() {
|
||||
factory()->InternalizeUtf8String("Intl"))
|
||||
.ToHandleChecked());
|
||||
|
||||
{
|
||||
Handle<JSFunction> number_format_constructor = Handle<JSFunction>::cast(
|
||||
JSReceiver::GetProperty(
|
||||
isolate(), Handle<JSReceiver>(JSReceiver::cast(*intl), isolate()),
|
||||
@ -5366,6 +5367,20 @@ void Genesis::InitializeGlobal_harmony_intl_number_format_v3() {
|
||||
Builtin::kNumberFormatPrototypeFormatRangeToParts, 2,
|
||||
false);
|
||||
}
|
||||
{
|
||||
Handle<JSFunction> plural_rules_constructor = Handle<JSFunction>::cast(
|
||||
JSReceiver::GetProperty(
|
||||
isolate(), Handle<JSReceiver>(JSReceiver::cast(*intl), isolate()),
|
||||
factory()->InternalizeUtf8String("PluralRules"))
|
||||
.ToHandleChecked());
|
||||
|
||||
Handle<JSObject> prototype(
|
||||
JSObject::cast(plural_rules_constructor->prototype()), isolate());
|
||||
|
||||
SimpleInstallFunction(isolate(), prototype, "selectRange",
|
||||
Builtin::kPluralRulesPrototypeSelectRange, 2, false);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // V8_INTL_SUPPORT
|
||||
|
||||
|
@ -28,6 +28,9 @@ ACCESSORS(JSPluralRules, icu_plural_rules, Managed<icu::PluralRules>,
|
||||
ACCESSORS(JSPluralRules, icu_number_formatter,
|
||||
Managed<icu::number::LocalizedNumberFormatter>,
|
||||
kIcuNumberFormatterOffset)
|
||||
ACCESSORS(JSPluralRules, icu_number_range_formatter,
|
||||
Managed<icu::number::LocalizedNumberRangeFormatter>,
|
||||
kIcuNumberRangeFormatterOffset)
|
||||
|
||||
inline void JSPluralRules::set_type(Type type) {
|
||||
DCHECK_LE(type, TypeBit::kMax);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "src/objects/option-utils.h"
|
||||
#include "unicode/locid.h"
|
||||
#include "unicode/numberformatter.h"
|
||||
#include "unicode/numberrangeformatter.h"
|
||||
#include "unicode/plurrule.h"
|
||||
#include "unicode/unumberformatter.h"
|
||||
|
||||
@ -145,6 +146,10 @@ MaybeHandle<JSPluralRules> JSPluralRules::New(Isolate* isolate, Handle<Map> map,
|
||||
|
||||
icu::number::LocalizedNumberFormatter icu_number_formatter =
|
||||
settings.locale(icu_locale);
|
||||
icu::number::LocalizedNumberRangeFormatter icu_number_range_formatter =
|
||||
icu::number::UnlocalizedNumberRangeFormatter()
|
||||
.numberFormatterBoth(settings)
|
||||
.locale(icu_locale);
|
||||
|
||||
Handle<Managed<icu::PluralRules>> managed_plural_rules =
|
||||
Managed<icu::PluralRules>::FromUniquePtr(isolate, 0,
|
||||
@ -155,6 +160,12 @@ MaybeHandle<JSPluralRules> JSPluralRules::New(Isolate* isolate, Handle<Map> map,
|
||||
Managed<icu::number::LocalizedNumberFormatter>::FromRawPtr(
|
||||
isolate, 0,
|
||||
new icu::number::LocalizedNumberFormatter(icu_number_formatter));
|
||||
Handle<Managed<icu::number::LocalizedNumberRangeFormatter>>
|
||||
managed_number_range_formatter =
|
||||
Managed<icu::number::LocalizedNumberRangeFormatter>::FromRawPtr(
|
||||
isolate, 0,
|
||||
new icu::number::LocalizedNumberRangeFormatter(
|
||||
icu_number_range_formatter));
|
||||
|
||||
// Now all properties are ready, so we can allocate the result object.
|
||||
Handle<JSPluralRules> plural_rules = Handle<JSPluralRules>::cast(
|
||||
@ -170,6 +181,7 @@ MaybeHandle<JSPluralRules> JSPluralRules::New(Isolate* isolate, Handle<Map> map,
|
||||
|
||||
plural_rules->set_icu_plural_rules(*managed_plural_rules);
|
||||
plural_rules->set_icu_number_formatter(*managed_number_formatter);
|
||||
plural_rules->set_icu_number_range_formatter(*managed_number_range_formatter);
|
||||
|
||||
// 13. Return pluralRules.
|
||||
return plural_rules;
|
||||
@ -196,6 +208,26 @@ MaybeHandle<String> JSPluralRules::ResolvePlural(
|
||||
return Intl::ToString(isolate, result);
|
||||
}
|
||||
|
||||
MaybeHandle<String> JSPluralRules::ResolvePluralRange(
|
||||
Isolate* isolate, Handle<JSPluralRules> plural_rules, double x, double y) {
|
||||
icu::PluralRules* icu_plural_rules = plural_rules->icu_plural_rules().raw();
|
||||
DCHECK_NOT_NULL(icu_plural_rules);
|
||||
|
||||
icu::number::LocalizedNumberRangeFormatter* fmt =
|
||||
plural_rules->icu_number_range_formatter().raw();
|
||||
DCHECK_NOT_NULL(fmt);
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
icu::number::FormattedNumberRange formatted = fmt->formatFormattableRange(
|
||||
icu::Formattable(x), icu::Formattable(y), status);
|
||||
|
||||
DCHECK(U_SUCCESS(status));
|
||||
icu::UnicodeString result = icu_plural_rules->select(formatted, status);
|
||||
DCHECK(U_SUCCESS(status));
|
||||
|
||||
return Intl::ToString(isolate, result);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void CreateDataPropertyForOptions(Isolate* isolate, Handle<JSObject> options,
|
||||
|
@ -26,6 +26,7 @@ namespace U_ICU_NAMESPACE {
|
||||
class PluralRules;
|
||||
namespace number {
|
||||
class LocalizedNumberFormatter;
|
||||
class LocalizedNumberRangeFormatter;
|
||||
} // namespace number
|
||||
} // namespace U_ICU_NAMESPACE
|
||||
|
||||
@ -47,6 +48,9 @@ class JSPluralRules
|
||||
V8_WARN_UNUSED_RESULT static MaybeHandle<String> ResolvePlural(
|
||||
Isolate* isolate, Handle<JSPluralRules> plural_rules, double number);
|
||||
|
||||
V8_WARN_UNUSED_RESULT static MaybeHandle<String> ResolvePluralRange(
|
||||
Isolate* isolate, Handle<JSPluralRules> plural_rules, double x, double y);
|
||||
|
||||
V8_EXPORT_PRIVATE static const std::set<std::string>& GetAvailableLocales();
|
||||
|
||||
// [[Type]] is one of the values "cardinal" or "ordinal",
|
||||
@ -68,6 +72,8 @@ class JSPluralRules
|
||||
DECL_ACCESSORS(icu_plural_rules, Managed<icu::PluralRules>)
|
||||
DECL_ACCESSORS(icu_number_formatter,
|
||||
Managed<icu::number::LocalizedNumberFormatter>)
|
||||
DECL_ACCESSORS(icu_number_range_formatter,
|
||||
Managed<icu::number::LocalizedNumberRangeFormatter>)
|
||||
|
||||
TQ_OBJECT_CONSTRUCTORS(JSPluralRules)
|
||||
};
|
||||
|
@ -15,4 +15,6 @@ extern class JSPluralRules extends JSObject {
|
||||
icu_plural_rules: Foreign; // Managed<icu::PluralRules>
|
||||
icu_number_formatter:
|
||||
Foreign; // Managed<icu::number::LocalizedNumberFormatter>
|
||||
icu_number_range_formatter:
|
||||
Foreign; // Managed<icu::number::LocalizedNumberRangeFormatter>
|
||||
}
|
||||
|
7
test/intl/plural-rules/select-range.js
Normal file
7
test/intl/plural-rules/select-range.js
Normal file
@ -0,0 +1,7 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --harmony-intl-number-format-v3
|
||||
const pl = new Intl.PluralRules("sl");
|
||||
assertEquals("few", pl.selectRange(102, 201));
|
@ -2776,15 +2776,6 @@
|
||||
'intl402/NumberFormat/prototype/formatRange/x-greater-than-y-throws': [FAIL],
|
||||
'intl402/NumberFormat/prototype/formatRangeToParts/x-greater-than-y-throws': [FAIL],
|
||||
|
||||
# PluralRules.prototype.selectRange
|
||||
'intl402/PluralRules/prototype/selectRange/default-en-us': [FAIL],
|
||||
'intl402/PluralRules/prototype/selectRange/invoked-as-func': [FAIL],
|
||||
'intl402/PluralRules/prototype/selectRange/length': [FAIL],
|
||||
'intl402/PluralRules/prototype/selectRange/name': [FAIL],
|
||||
'intl402/PluralRules/prototype/selectRange/prop-desc': [FAIL],
|
||||
'intl402/PluralRules/prototype/selectRange/nan-arguments-throws': [FAIL],
|
||||
'intl402/PluralRules/prototype/selectRange/x-greater-than-y-throws': [FAIL],
|
||||
|
||||
# String handling
|
||||
'intl402/NumberFormat/prototype/format/format-rounding-increment-1000': [FAIL],
|
||||
'intl402/NumberFormat/prototype/format/format-rounding-increment-100': [FAIL],
|
||||
|
Loading…
Reference in New Issue
Block a user