Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (264499 => 264500)
--- trunk/Source/_javascript_Core/ChangeLog 2020-07-17 05:18:58 UTC (rev 264499)
+++ trunk/Source/_javascript_Core/ChangeLog 2020-07-17 06:07:57 UTC (rev 264500)
@@ -1,3 +1,30 @@
+2020-07-16 Yusuke Suzuki <[email protected]>
+
+ [JSC] Clean up Intl option parsing code by introducing intlOption<>
+ https://bugs.webkit.org/show_bug.cgi?id=214437
+
+ Reviewed by Ross Kirsling.
+
+ This patch introduces intlOption<>(...) function and remove redundant string comparisons.
+ This makes option handling efficient, and it makes code clean.
+
+ * runtime/IntlCollator.cpp:
+ (JSC::IntlCollator::initializeCollator):
+ * runtime/IntlDateTimeFormat.cpp:
+ (JSC::IntlDateTimeFormat::initializeDateTimeFormat):
+ * runtime/IntlNumberFormat.cpp:
+ (JSC::IntlNumberFormat::initializeNumberFormat):
+ * runtime/IntlObject.cpp:
+ (JSC::resolveLocale):
+ (JSC::supportedLocales):
+ * runtime/IntlObject.h:
+ * runtime/IntlObjectInlines.h:
+ (JSC::intlOption):
+ * runtime/IntlPluralRules.cpp:
+ (JSC::IntlPluralRules::initializePluralRules):
+ * runtime/IntlRelativeTimeFormat.cpp:
+ (JSC::IntlRelativeTimeFormat::initializeRelativeTimeFormat):
+
2020-07-16 Fujii Hironori <[email protected]>
[WTF] Remove the unnecessary inner class DefaultHash<T>::Hash
Modified: trunk/Source/_javascript_Core/runtime/IntlCollator.cpp (264499 => 264500)
--- trunk/Source/_javascript_Core/runtime/IntlCollator.cpp 2020-07-17 05:18:58 UTC (rev 264499)
+++ trunk/Source/_javascript_Core/runtime/IntlCollator.cpp 2020-07-17 06:07:57 UTC (rev 264500)
@@ -28,7 +28,7 @@
#include "config.h"
#include "IntlCollator.h"
-#include "IntlObject.h"
+#include "IntlObjectInlines.h"
#include "JSBoundFunction.h"
#include "JSCInlines.h"
#include "ObjectConstructor.h"
@@ -178,22 +178,15 @@
RETURN_IF_EXCEPTION(scope, void());
}
- String usageString = intlStringOption(globalObject, options, vm.propertyNames->usage, { "sort", "search" }, "usage must be either \"sort\" or \"search\"", "sort");
+ m_usage = intlOption<Usage>(globalObject, options, vm.propertyNames->usage, { { "sort"_s, Usage::Sort }, { "search"_s, Usage::Search } }, "usage must be either \"sort\" or \"search\""_s, Usage::Sort);
RETURN_IF_EXCEPTION(scope, void());
- if (usageString == "sort")
- m_usage = Usage::Sort;
- else if (usageString == "search")
- m_usage = Usage::Search;
- else
- ASSERT_NOT_REACHED();
auto localeData = (m_usage == Usage::Sort) ? sortLocaleData : searchLocaleData;
HashMap<String, String> opt;
- String matcher = intlStringOption(globalObject, options, vm.propertyNames->localeMatcher, { "lookup", "best fit" }, "localeMatcher must be either \"lookup\" or \"best fit\"", "best fit");
+ LocaleMatcher localeMatcher = intlOption<LocaleMatcher>(globalObject, options, vm.propertyNames->localeMatcher, { { "lookup"_s, LocaleMatcher::Lookup }, { "best fit"_s, LocaleMatcher::BestFit } }, "localeMatcher must be either \"lookup\" or \"best fit\""_s, LocaleMatcher::BestFit);
RETURN_IF_EXCEPTION(scope, void());
- opt.add("localeMatcher"_s, matcher);
TriState numeric = intlBooleanOption(globalObject, options, vm.propertyNames->numeric);
RETURN_IF_EXCEPTION(scope, void());
@@ -206,7 +199,7 @@
opt.add("kf"_s, caseFirstOption);
auto& availableLocales = intlCollatorAvailableLocales();
- auto result = resolveLocale(globalObject, availableLocales, requestedLocales, opt, IntlCollatorInternal::relevantExtensionKeys, WTF_ARRAY_LENGTH(IntlCollatorInternal::relevantExtensionKeys), localeData);
+ auto result = resolveLocale(globalObject, availableLocales, requestedLocales, localeMatcher, opt, IntlCollatorInternal::relevantExtensionKeys, WTF_ARRAY_LENGTH(IntlCollatorInternal::relevantExtensionKeys), localeData);
m_locale = result.get("locale"_s);
if (m_locale.isEmpty()) {
@@ -226,16 +219,8 @@
else
m_caseFirst = CaseFirst::False;
- String sensitivityString = intlStringOption(globalObject, options, vm.propertyNames->sensitivity, { "base", "accent", "case", "variant" }, "sensitivity must be either \"base\", \"accent\", \"case\", or \"variant\"", nullptr);
+ m_sensitivity = intlOption<Sensitivity>(globalObject, options, vm.propertyNames->sensitivity, { { "base"_s, Sensitivity::Base }, { "accent"_s, Sensitivity::Accent }, { "case"_s, Sensitivity::Case }, { "variant"_s, Sensitivity::Variant } }, "sensitivity must be either \"base\", \"accent\", \"case\", or \"variant\""_s, Sensitivity::Variant);
RETURN_IF_EXCEPTION(scope, void());
- if (sensitivityString == "base")
- m_sensitivity = Sensitivity::Base;
- else if (sensitivityString == "accent")
- m_sensitivity = Sensitivity::Accent;
- else if (sensitivityString == "case")
- m_sensitivity = Sensitivity::Case;
- else
- m_sensitivity = Sensitivity::Variant;
TriState ignorePunctuation = intlBooleanOption(globalObject, options, vm.propertyNames->ignorePunctuation);
RETURN_IF_EXCEPTION(scope, void());
Modified: trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.cpp (264499 => 264500)
--- trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.cpp 2020-07-17 05:18:58 UTC (rev 264499)
+++ trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.cpp 2020-07-17 06:07:57 UTC (rev 264500)
@@ -421,9 +421,8 @@
HashMap<String, String> opt;
- String localeMatcher = intlStringOption(globalObject, options, vm.propertyNames->localeMatcher, { "lookup", "best fit" }, "localeMatcher must be either \"lookup\" or \"best fit\"", "best fit");
+ LocaleMatcher localeMatcher = intlOption<LocaleMatcher>(globalObject, options, vm.propertyNames->localeMatcher, { { "lookup"_s, LocaleMatcher::Lookup }, { "best fit"_s, LocaleMatcher::BestFit } }, "localeMatcher must be either \"lookup\" or \"best fit\""_s, LocaleMatcher::BestFit);
RETURN_IF_EXCEPTION(scope, void());
- opt.add(vm.propertyNames->localeMatcher.string(), localeMatcher);
String calendar = intlStringOption(globalObject, options, vm.propertyNames->calendar, { }, nullptr, nullptr);
RETURN_IF_EXCEPTION(scope, void());
@@ -460,7 +459,7 @@
opt.add("hc"_s, String());
const HashSet<String>& availableLocales = intlDateTimeFormatAvailableLocales();
- HashMap<String, String> resolved = resolveLocale(globalObject, availableLocales, requestedLocales, opt, IntlDateTimeFormatInternal::relevantExtensionKeys, WTF_ARRAY_LENGTH(IntlDateTimeFormatInternal::relevantExtensionKeys), localeData);
+ HashMap<String, String> resolved = resolveLocale(globalObject, availableLocales, requestedLocales, localeMatcher, opt, IntlDateTimeFormatInternal::relevantExtensionKeys, WTF_ARRAY_LENGTH(IntlDateTimeFormatInternal::relevantExtensionKeys), localeData);
m_locale = resolved.get(vm.propertyNames->locale.string());
if (m_locale.isEmpty()) {
@@ -496,69 +495,91 @@
m_timeZone = tz;
StringBuilder skeletonBuilder;
- auto narrowShortLong = { "narrow", "short", "long" };
- auto twoDigitNumeric = { "2-digit", "numeric" };
- auto twoDigitNumericNarrowShortLong = { "2-digit", "numeric", "narrow", "short", "long" };
- auto shortLong = { "short", "long" };
- String weekday = intlStringOption(globalObject, options, vm.propertyNames->weekday, narrowShortLong, "weekday must be \"narrow\", \"short\", or \"long\"", nullptr);
+ Weekday weekday = intlOption<Weekday>(globalObject, options, vm.propertyNames->weekday, { { "narrow"_s, Weekday::Narrow }, { "short"_s, Weekday::Short }, { "long"_s, Weekday::Long } }, "weekday must be \"narrow\", \"short\", or \"long\""_s, Weekday::None);
RETURN_IF_EXCEPTION(scope, void());
- if (!weekday.isNull()) {
- if (weekday == "narrow")
- skeletonBuilder.appendLiteral("EEEEE");
- else if (weekday == "short")
- skeletonBuilder.appendLiteral("EEE");
- else if (weekday == "long")
- skeletonBuilder.appendLiteral("EEEE");
+ switch (weekday) {
+ case Weekday::Narrow:
+ skeletonBuilder.appendLiteral("EEEEE");
+ break;
+ case Weekday::Short:
+ skeletonBuilder.appendLiteral("EEE");
+ break;
+ case Weekday::Long:
+ skeletonBuilder.appendLiteral("EEEE");
+ break;
+ case Weekday::None:
+ break;
}
- String era = intlStringOption(globalObject, options, vm.propertyNames->era, narrowShortLong, "era must be \"narrow\", \"short\", or \"long\"", nullptr);
+ Era era = intlOption<Era>(globalObject, options, vm.propertyNames->era, { { "narrow"_s, Era::Narrow }, { "short"_s, Era::Short }, { "long"_s, Era::Long } }, "era must be \"narrow\", \"short\", or \"long\""_s, Era::None);
RETURN_IF_EXCEPTION(scope, void());
- if (!era.isNull()) {
- if (era == "narrow")
- skeletonBuilder.appendLiteral("GGGGG");
- else if (era == "short")
- skeletonBuilder.appendLiteral("GGG");
- else if (era == "long")
- skeletonBuilder.appendLiteral("GGGG");
+ switch (era) {
+ case Era::Narrow:
+ skeletonBuilder.appendLiteral("GGGGG");
+ break;
+ case Era::Short:
+ skeletonBuilder.appendLiteral("GGG");
+ break;
+ case Era::Long:
+ skeletonBuilder.appendLiteral("GGGG");
+ break;
+ case Era::None:
+ break;
}
- String year = intlStringOption(globalObject, options, vm.propertyNames->year, twoDigitNumeric, "year must be \"2-digit\" or \"numeric\"", nullptr);
+ Year year = intlOption<Year>(globalObject, options, vm.propertyNames->year, { { "2-digit"_s, Year::TwoDigit }, { "numeric"_s, Year::Numeric } }, "year must be \"2-digit\" or \"numeric\""_s, Year::None);
RETURN_IF_EXCEPTION(scope, void());
- if (!year.isNull()) {
- if (year == "2-digit")
- skeletonBuilder.appendLiteral("yy");
- else if (year == "numeric")
- skeletonBuilder.append('y');
+ switch (year) {
+ case Year::TwoDigit:
+ skeletonBuilder.appendLiteral("yy");
+ break;
+ case Year::Numeric:
+ skeletonBuilder.append('y');
+ break;
+ case Year::None:
+ break;
}
- String month = intlStringOption(globalObject, options, vm.propertyNames->month, twoDigitNumericNarrowShortLong, "month must be \"2-digit\", \"numeric\", \"narrow\", \"short\", or \"long\"", nullptr);
+ Month month = intlOption<Month>(globalObject, options, vm.propertyNames->month, { { "2-digit"_s, Month::TwoDigit }, { "numeric"_s, Month::Numeric }, { "narrow"_s, Month::Narrow }, { "short"_s, Month::Short }, { "long"_s, Month::Long } }, "month must be \"2-digit\", \"numeric\", \"narrow\", \"short\", or \"long\""_s, Month::None);
RETURN_IF_EXCEPTION(scope, void());
- if (!month.isNull()) {
- if (month == "2-digit")
- skeletonBuilder.appendLiteral("MM");
- else if (month == "numeric")
- skeletonBuilder.append('M');
- else if (month == "narrow")
- skeletonBuilder.appendLiteral("MMMMM");
- else if (month == "short")
- skeletonBuilder.appendLiteral("MMM");
- else if (month == "long")
- skeletonBuilder.appendLiteral("MMMM");
+ switch (month) {
+ case Month::TwoDigit:
+ skeletonBuilder.appendLiteral("MM");
+ break;
+ case Month::Numeric:
+ skeletonBuilder.append('M');
+ break;
+ case Month::Narrow:
+ skeletonBuilder.appendLiteral("MMMMM");
+ break;
+ case Month::Short:
+ skeletonBuilder.appendLiteral("MMM");
+ break;
+ case Month::Long:
+ skeletonBuilder.appendLiteral("MMMM");
+ break;
+ case Month::None:
+ break;
}
- String day = intlStringOption(globalObject, options, vm.propertyNames->day, twoDigitNumeric, "day must be \"2-digit\" or \"numeric\"", nullptr);
+ Day day = intlOption<Day>(globalObject, options, vm.propertyNames->day, { { "2-digit"_s, Day::TwoDigit }, { "numeric"_s, Day::Numeric } }, "day must be \"2-digit\" or \"numeric\""_s, Day::None);
RETURN_IF_EXCEPTION(scope, void());
- if (!day.isNull()) {
- if (day == "2-digit")
- skeletonBuilder.appendLiteral("dd");
- else if (day == "numeric")
- skeletonBuilder.append('d');
+ switch (day) {
+ case Day::TwoDigit:
+ skeletonBuilder.appendLiteral("dd");
+ break;
+ case Day::Numeric:
+ skeletonBuilder.append('d');
+ break;
+ case Day::None:
+ break;
}
- String hour = intlStringOption(globalObject, options, vm.propertyNames->hour, twoDigitNumeric, "hour must be \"2-digit\" or \"numeric\"", nullptr);
+ Hour hour = intlOption<Hour>(globalObject, options, vm.propertyNames->hour, { { "2-digit"_s, Hour::TwoDigit }, { "numeric"_s, Hour::Numeric } }, "hour must be \"2-digit\" or \"numeric\""_s, Hour::None);
RETURN_IF_EXCEPTION(scope, void());
- if (hour == "2-digit") {
+ switch (hour) {
+ case Hour::TwoDigit:
if (isHour12Undefined && m_hourCycle.isNull())
skeletonBuilder.appendLiteral("jj");
else if (hour12 == TriState::True)
@@ -565,7 +586,8 @@
skeletonBuilder.appendLiteral("hh");
else
skeletonBuilder.appendLiteral("HH");
- } else if (hour == "numeric") {
+ break;
+ case Hour::Numeric:
if (isHour12Undefined && m_hourCycle.isNull())
skeletonBuilder.append('j');
else if (hour12 == TriState::True)
@@ -572,34 +594,49 @@
skeletonBuilder.append('h');
else
skeletonBuilder.append('H');
- } else
+ break;
+ case Hour::None:
m_hourCycle = String();
+ break;
+ }
- String minute = intlStringOption(globalObject, options, vm.propertyNames->minute, twoDigitNumeric, "minute must be \"2-digit\" or \"numeric\"", nullptr);
+ Minute minute = intlOption<Minute>(globalObject, options, vm.propertyNames->minute, { { "2-digit"_s, Minute::TwoDigit }, { "numeric"_s, Minute::Numeric } }, "minute must be \"2-digit\" or \"numeric\""_s, Minute::None);
RETURN_IF_EXCEPTION(scope, void());
- if (!minute.isNull()) {
- if (minute == "2-digit")
- skeletonBuilder.appendLiteral("mm");
- else if (minute == "numeric")
- skeletonBuilder.append('m');
+ switch (minute) {
+ case Minute::TwoDigit:
+ skeletonBuilder.appendLiteral("mm");
+ break;
+ case Minute::Numeric:
+ skeletonBuilder.append('m');
+ break;
+ case Minute::None:
+ break;
}
- String second = intlStringOption(globalObject, options, vm.propertyNames->second, twoDigitNumeric, "second must be \"2-digit\" or \"numeric\"", nullptr);
+ Second second = intlOption<Second>(globalObject, options, vm.propertyNames->second, { { "2-digit"_s, Second::TwoDigit }, { "numeric"_s, Second::Numeric } }, "second must be \"2-digit\" or \"numeric\""_s, Second::None);
RETURN_IF_EXCEPTION(scope, void());
- if (!second.isNull()) {
- if (second == "2-digit")
- skeletonBuilder.appendLiteral("ss");
- else if (second == "numeric")
- skeletonBuilder.append('s');
+ switch (second) {
+ case Second::TwoDigit:
+ skeletonBuilder.appendLiteral("ss");
+ break;
+ case Second::Numeric:
+ skeletonBuilder.append('s');
+ break;
+ case Second::None:
+ break;
}
- String timeZoneName = intlStringOption(globalObject, options, vm.propertyNames->timeZoneName, shortLong, "timeZoneName must be \"short\" or \"long\"", nullptr);
+ TimeZoneName timeZoneName = intlOption<TimeZoneName>(globalObject, options, vm.propertyNames->timeZoneName, { { "short"_s, TimeZoneName::Short }, { "long"_s, TimeZoneName::Long } }, "timeZoneName must be \"short\" or \"long\""_s, TimeZoneName::None);
RETURN_IF_EXCEPTION(scope, void());
- if (!timeZoneName.isNull()) {
- if (timeZoneName == "short")
- skeletonBuilder.append('z');
- else if (timeZoneName == "long")
- skeletonBuilder.appendLiteral("zzzz");
+ switch (timeZoneName) {
+ case TimeZoneName::Short:
+ skeletonBuilder.append('z');
+ break;
+ case TimeZoneName::Long:
+ skeletonBuilder.appendLiteral("zzzz");
+ break;
+ case TimeZoneName::None:
+ break;
}
intlStringOption(globalObject, options, vm.propertyNames->formatMatcher, { "basic", "best fit" }, "formatMatcher must be either \"basic\" or \"best fit\"", "best fit");
Modified: trunk/Source/_javascript_Core/runtime/IntlNumberFormat.cpp (264499 => 264500)
--- trunk/Source/_javascript_Core/runtime/IntlNumberFormat.cpp 2020-07-17 05:18:58 UTC (rev 264499)
+++ trunk/Source/_javascript_Core/runtime/IntlNumberFormat.cpp 2020-07-17 06:07:57 UTC (rev 264500)
@@ -30,7 +30,7 @@
#include "IntlNumberFormat.h"
#include "Error.h"
-#include "IntlObject.h"
+#include "IntlObjectInlines.h"
#include "JSBoundFunction.h"
#include "JSCInlines.h"
#include "ObjectConstructor.h"
@@ -173,9 +173,8 @@
HashMap<String, String> opt;
- String matcher = intlStringOption(globalObject, options, vm.propertyNames->localeMatcher, { "lookup", "best fit" }, "localeMatcher must be either \"lookup\" or \"best fit\"", "best fit");
+ LocaleMatcher localeMatcher = intlOption<LocaleMatcher>(globalObject, options, vm.propertyNames->localeMatcher, { { "lookup"_s, LocaleMatcher::Lookup }, { "best fit"_s, LocaleMatcher::BestFit } }, "localeMatcher must be either \"lookup\" or \"best fit\""_s, LocaleMatcher::BestFit);
RETURN_IF_EXCEPTION(scope, void());
- opt.add("localeMatcher"_s, matcher);
String numberingSystem = intlStringOption(globalObject, options, vm.propertyNames->numberingSystem, { }, nullptr, nullptr);
RETURN_IF_EXCEPTION(scope, void());
@@ -188,7 +187,7 @@
}
auto& availableLocales = intlNumberFormatAvailableLocales();
- auto result = resolveLocale(globalObject, availableLocales, requestedLocales, opt, IntlNumberFormatInternal::relevantExtensionKeys, WTF_ARRAY_LENGTH(IntlNumberFormatInternal::relevantExtensionKeys), localeData);
+ auto result = resolveLocale(globalObject, availableLocales, requestedLocales, localeMatcher, opt, IntlNumberFormatInternal::relevantExtensionKeys, WTF_ARRAY_LENGTH(IntlNumberFormatInternal::relevantExtensionKeys), localeData);
m_locale = result.get("locale"_s);
if (m_locale.isEmpty()) {
@@ -198,16 +197,8 @@
m_numberingSystem = result.get("nu"_s);
- String styleString = intlStringOption(globalObject, options, vm.propertyNames->style, { "decimal", "percent", "currency" }, "style must be either \"decimal\", \"percent\", or \"currency\"", "decimal");
+ m_style = intlOption<Style>(globalObject, options, vm.propertyNames->style, { { "decimal"_s, Style::Decimal }, { "percent"_s, Style::Percent }, { "currency"_s, Style::Currency } }, "style must be either \"decimal\", \"percent\", or \"currency\""_s, Style::Decimal);
RETURN_IF_EXCEPTION(scope, void());
- if (styleString == "decimal")
- m_style = Style::Decimal;
- else if (styleString == "percent")
- m_style = Style::Percent;
- else if (styleString == "currency")
- m_style = Style::Currency;
- else
- ASSERT_NOT_REACHED();
String currency = intlStringOption(globalObject, options, Identifier::fromString(vm, "currency"), { }, nullptr, nullptr);
RETURN_IF_EXCEPTION(scope, void());
@@ -230,18 +221,8 @@
currencyDigits = computeCurrencyDigits(currency);
}
- String currencyDisplayString = intlStringOption(globalObject, options, Identifier::fromString(vm, "currencyDisplay"), { "code", "symbol", "name" }, "currencyDisplay must be either \"code\", \"symbol\", or \"name\"", "symbol");
+ m_currencyDisplay = intlOption<CurrencyDisplay>(globalObject, options, Identifier::fromString(vm, "currencyDisplay"), { { "code"_s, CurrencyDisplay::Code }, { "symbol"_s, CurrencyDisplay::Symbol }, { "name"_s, CurrencyDisplay::Name } }, "currencyDisplay must be either \"code\", \"symbol\", or \"name\""_s, CurrencyDisplay::Symbol);
RETURN_IF_EXCEPTION(scope, void());
- if (m_style == Style::Currency) {
- if (currencyDisplayString == "code")
- m_currencyDisplay = CurrencyDisplay::Code;
- else if (currencyDisplayString == "symbol")
- m_currencyDisplay = CurrencyDisplay::Symbol;
- else if (currencyDisplayString == "name")
- m_currencyDisplay = CurrencyDisplay::Name;
- else
- ASSERT_NOT_REACHED();
- }
unsigned minimumIntegerDigits = intlNumberOption(globalObject, options, Identifier::fromString(vm, "minimumIntegerDigits"), 1, 21, 1);
RETURN_IF_EXCEPTION(scope, void());
Modified: trunk/Source/_javascript_Core/runtime/IntlObject.cpp (264499 => 264500)
--- trunk/Source/_javascript_Core/runtime/IntlObject.cpp 2020-07-17 05:18:58 UTC (rev 264499)
+++ trunk/Source/_javascript_Core/runtime/IntlObject.cpp 2020-07-17 06:07:57 UTC (rev 264500)
@@ -629,13 +629,12 @@
subtags.append(extension.substring(valueStart, extensionLength - valueStart));
}
-HashMap<String, String> resolveLocale(JSGlobalObject* globalObject, const HashSet<String>& availableLocales, const Vector<String>& requestedLocales, const HashMap<String, String>& options, const char* const relevantExtensionKeys[], size_t relevantExtensionKeyCount, Vector<String> (*localeData)(const String&, size_t))
+HashMap<String, String> resolveLocale(JSGlobalObject* globalObject, const HashSet<String>& availableLocales, const Vector<String>& requestedLocales, LocaleMatcher localeMatcher, const HashMap<String, String>& options, const char* const relevantExtensionKeys[], size_t relevantExtensionKeyCount, Vector<String> (*localeData)(const String&, size_t))
{
// ResolveLocale (availableLocales, requestedLocales, options, relevantExtensionKeys, localeData)
// https://tc39.github.io/ecma402/#sec-resolvelocale
- const String& matcher = options.get("localeMatcher"_s);
- MatcherResult matcherResult = (matcher == "lookup")
+ MatcherResult matcherResult = localeMatcher == LocaleMatcher::Lookup
? lookupMatcher(globalObject, availableLocales, requestedLocales)
: bestFitMatcher(globalObject, availableLocales, requestedLocales);
@@ -744,13 +743,10 @@
auto scope = DECLARE_THROW_SCOPE(vm);
String matcher;
- if (!options.isUndefined()) {
- matcher = intlStringOption(globalObject, options, vm.propertyNames->localeMatcher, { "lookup", "best fit" }, "localeMatcher must be either \"lookup\" or \"best fit\"", "best fit");
- RETURN_IF_EXCEPTION(scope, JSValue());
- } else
- matcher = "best fit"_s;
+ LocaleMatcher localeMatcher = intlOption<LocaleMatcher>(globalObject, options, vm.propertyNames->localeMatcher, { { "lookup"_s, LocaleMatcher::Lookup }, { "best fit"_s, LocaleMatcher::BestFit } }, "localeMatcher must be either \"lookup\" or \"best fit\""_s, LocaleMatcher::BestFit);
+ RETURN_IF_EXCEPTION(scope, JSValue());
- JSArray* supportedLocales = (matcher == "best fit")
+ JSArray* supportedLocales = localeMatcher == LocaleMatcher::BestFit
? bestFitSupportedLocales(globalObject, availableLocales, requestedLocales)
: lookupSupportedLocales(globalObject, availableLocales, requestedLocales);
RETURN_IF_EXCEPTION(scope, JSValue());
Modified: trunk/Source/_javascript_Core/runtime/IntlObject.h (264499 => 264500)
--- trunk/Source/_javascript_Core/runtime/IntlObject.h 2020-07-17 05:18:58 UTC (rev 264499)
+++ trunk/Source/_javascript_Core/runtime/IntlObject.h 2020-07-17 06:07:57 UTC (rev 264500)
@@ -34,6 +34,11 @@
namespace JSC {
+enum class LocaleMatcher : uint8_t {
+ Lookup,
+ BestFit,
+};
+
class IntlObject final : public JSNonFinalObject {
public:
using Base = JSNonFinalObject;
@@ -71,7 +76,7 @@
Vector<char, 32> localeIDBufferForLanguageTag(const CString&);
String languageTagForLocaleID(const char*, bool isImmortal = false);
Vector<String> canonicalizeLocaleList(JSGlobalObject*, JSValue locales);
-HashMap<String, String> resolveLocale(JSGlobalObject*, const HashSet<String>& availableLocales, const Vector<String>& requestedLocales, const HashMap<String, String>& options, const char* const relevantExtensionKeys[], size_t relevantExtensionKeyCount, Vector<String> (*localeData)(const String&, size_t));
+HashMap<String, String> resolveLocale(JSGlobalObject*, const HashSet<String>& availableLocales, const Vector<String>& requestedLocales, LocaleMatcher, const HashMap<String, String>& options, const char* const relevantExtensionKeys[], size_t relevantExtensionKeyCount, Vector<String> (*localeData)(const String&, size_t));
JSValue supportedLocales(JSGlobalObject*, const HashSet<String>& availableLocales, const Vector<String>& requestedLocales, JSValue options);
String removeUnicodeLocaleExtension(const String& locale);
String bestAvailableLocale(const HashSet<String>& availableLocales, const String& requestedLocale);
Modified: trunk/Source/_javascript_Core/runtime/IntlObjectInlines.h (264499 => 264500)
--- trunk/Source/_javascript_Core/runtime/IntlObjectInlines.h 2020-07-17 05:18:58 UTC (rev 264499)
+++ trunk/Source/_javascript_Core/runtime/IntlObjectInlines.h 2020-07-17 06:07:57 UTC (rev 264500)
@@ -81,4 +81,39 @@
RELEASE_AND_RETURN(scope, factory(vm));
}
+template<typename ResultType>
+ResultType intlOption(JSGlobalObject* globalObject, JSValue options, PropertyName property, std::initializer_list<std::pair<ASCIILiteral, ResultType>> values, ASCIILiteral notFoundMessage, ResultType fallback)
+{
+ // GetOption (options, property, type="string", values, fallback)
+ // https://tc39.github.io/ecma402/#sec-getoption
+
+ ASSERT(values.size() > 0);
+
+ VM& vm = globalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (options.isUndefined())
+ return fallback;
+
+ JSObject* opts = options.toObject(globalObject);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ JSValue value = opts->get(globalObject, property);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ if (!value.isUndefined()) {
+ String stringValue = value.toWTFString(globalObject);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ for (const auto& entry : values) {
+ if (entry.first == stringValue)
+ return entry.second;
+ }
+ throwException(globalObject, scope, createRangeError(globalObject, notFoundMessage));
+ return { };
+ }
+
+ return fallback;
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/IntlPluralRules.cpp (264499 => 264500)
--- trunk/Source/_javascript_Core/runtime/IntlPluralRules.cpp 2020-07-17 05:18:58 UTC (rev 264499)
+++ trunk/Source/_javascript_Core/runtime/IntlPluralRules.cpp 2020-07-17 06:07:57 UTC (rev 264500)
@@ -27,7 +27,7 @@
#include "config.h"
#include "IntlPluralRules.h"
-#include "IntlObject.h"
+#include "IntlObjectInlines.h"
#include "JSCInlines.h"
#include "ObjectConstructor.h"
@@ -109,12 +109,11 @@
}
HashMap<String, String> localeOpt;
- String localeMatcher = intlStringOption(globalObject, options, vm.propertyNames->localeMatcher, { "lookup", "best fit" }, "localeMatcher must be either \"lookup\" or \"best fit\"", "best fit");
+ LocaleMatcher localeMatcher = intlOption<LocaleMatcher>(globalObject, options, vm.propertyNames->localeMatcher, { { "lookup"_s, LocaleMatcher::Lookup }, { "best fit"_s, LocaleMatcher::BestFit } }, "localeMatcher must be either \"lookup\" or \"best fit\""_s, LocaleMatcher::BestFit);
RETURN_IF_EXCEPTION(scope, void());
- localeOpt.add(vm.propertyNames->localeMatcher.string(), localeMatcher);
const HashSet<String>& availableLocales = intlPluralRulesAvailableLocales();
- HashMap<String, String> resolved = resolveLocale(globalObject, availableLocales, requestedLocales, localeOpt, nullptr, 0, localeData);
+ HashMap<String, String> resolved = resolveLocale(globalObject, availableLocales, requestedLocales, localeMatcher, localeOpt, nullptr, 0, localeData);
m_locale = resolved.get(vm.propertyNames->locale.string());
if (m_locale.isEmpty()) {
throwTypeError(globalObject, scope, "failed to initialize PluralRules due to invalid locale"_s);
@@ -121,9 +120,8 @@
return;
}
- String typeString = intlStringOption(globalObject, options, vm.propertyNames->type, { "cardinal", "ordinal" }, "type must be \"cardinal\" or \"ordinal\"", "cardinal");
+ m_type = intlOption<Type>(globalObject, options, vm.propertyNames->type, { { "cardinal"_s, Type::Cardinal }, { "ordinal"_s, Type::Ordinal } }, "type must be \"cardinal\" or \"ordinal\""_s, Type::Cardinal);
RETURN_IF_EXCEPTION(scope, void());
- m_type = typeString == "ordinal" ? Type::Ordinal : Type::Cardinal;
unsigned minimumIntegerDigits = intlNumberOption(globalObject, options, Identifier::fromString(vm, "minimumIntegerDigits"), 1, 21, 1);
RETURN_IF_EXCEPTION(scope, void());
Modified: trunk/Source/_javascript_Core/runtime/IntlRelativeTimeFormat.cpp (264499 => 264500)
--- trunk/Source/_javascript_Core/runtime/IntlRelativeTimeFormat.cpp 2020-07-17 05:18:58 UTC (rev 264499)
+++ trunk/Source/_javascript_Core/runtime/IntlRelativeTimeFormat.cpp 2020-07-17 06:07:57 UTC (rev 264500)
@@ -27,7 +27,7 @@
#include "IntlRelativeTimeFormat.h"
#include "IntlNumberFormat.h"
-#include "IntlObject.h"
+#include "IntlObjectInlines.h"
#include "JSCInlines.h"
#include "ObjectConstructor.h"
#include <wtf/unicode/icu/ICUHelpers.h>
@@ -108,9 +108,8 @@
}
HashMap<String, String> opt;
- String localeMatcher = intlStringOption(globalObject, options, vm.propertyNames->localeMatcher, { "lookup", "best fit" }, "localeMatcher must be either \"lookup\" or \"best fit\"", "best fit");
+ LocaleMatcher localeMatcher = intlOption<LocaleMatcher>(globalObject, options, vm.propertyNames->localeMatcher, { { "lookup"_s, LocaleMatcher::Lookup }, { "best fit"_s, LocaleMatcher::BestFit } }, "localeMatcher must be either \"lookup\" or \"best fit\""_s, LocaleMatcher::BestFit);
RETURN_IF_EXCEPTION(scope, void());
- opt.add(vm.propertyNames->localeMatcher.string(), localeMatcher);
String numberingSystem = intlStringOption(globalObject, options, vm.propertyNames->numberingSystem, { }, nullptr, nullptr);
RETURN_IF_EXCEPTION(scope, void());
@@ -123,7 +122,7 @@
}
const HashSet<String>& availableLocales = intlRelativeTimeFormatAvailableLocales();
- HashMap<String, String> resolved = resolveLocale(globalObject, availableLocales, requestedLocales, opt, IntlRelativeTimeFormatInternal::relevantExtensionKeys, WTF_ARRAY_LENGTH(IntlRelativeTimeFormatInternal::relevantExtensionKeys), localeData);
+ HashMap<String, String> resolved = resolveLocale(globalObject, availableLocales, requestedLocales, localeMatcher, opt, IntlRelativeTimeFormatInternal::relevantExtensionKeys, WTF_ARRAY_LENGTH(IntlRelativeTimeFormatInternal::relevantExtensionKeys), localeData);
m_locale = resolved.get(vm.propertyNames->locale.string());
if (m_locale.isEmpty()) {
throwTypeError(globalObject, scope, "failed to initialize RelativeTimeFormat due to invalid locale"_s);
@@ -133,24 +132,23 @@
m_numberingSystem = resolved.get("nu"_s);
CString dataLocaleWithExtensions = makeString(resolved.get("dataLocale"_s), "-u-nu-", m_numberingSystem).utf8();
- String style = intlStringOption(globalObject, options, vm.propertyNames->style, { "long", "short", "narrow" }, "style must be either \"long\", \"short\", or \"narrow\"", "long");
+ m_style = intlOption<Style>(globalObject, options, vm.propertyNames->style, { { "long"_s, Style::Long }, { "short"_s, Style::Short }, { "narrow"_s, Style::Narrow } }, "style must be either \"long\", \"short\", or \"narrow\""_s, Style::Long);
RETURN_IF_EXCEPTION(scope, void());
- UDateRelativeDateTimeFormatterStyle icuStyle;
- if (style == "long") {
+ UDateRelativeDateTimeFormatterStyle icuStyle = UDAT_STYLE_LONG;
+ switch (m_style) {
+ case Style::Long:
icuStyle = UDAT_STYLE_LONG;
- m_style = Style::Long;
- } else if (style == "short") {
+ break;
+ case Style::Short:
icuStyle = UDAT_STYLE_SHORT;
- m_style = Style::Short;
- } else {
- ASSERT(style == "narrow");
+ break;
+ case Style::Narrow:
icuStyle = UDAT_STYLE_NARROW;
- m_style = Style::Narrow;
+ break;
}
- String numeric = intlStringOption(globalObject, options, vm.propertyNames->numeric, { "always", "auto" }, "numeric must be either \"always\" or \"auto\"", "always");
+ m_numeric = intlOption<bool>(globalObject, options, vm.propertyNames->numeric, { { "always"_s, true }, { "auto"_s, false } }, "numeric must be either \"always\" or \"auto\""_s, true);
RETURN_IF_EXCEPTION(scope, void());
- m_numeric = (numeric == "always");
UErrorCode status = U_ZERO_ERROR;
m_numberFormat = std::unique_ptr<UNumberFormat, UNumberFormatDeleter>(unum_open(UNUM_DECIMAL, nullptr, 0, dataLocaleWithExtensions.data(), nullptr, &status));