diff --git a/ecmascript/date_parse.cpp b/ecmascript/date_parse.cpp index eea8fc5809..2bd7c516b7 100644 --- a/ecmascript/date_parse.cpp +++ b/ecmascript/date_parse.cpp @@ -16,6 +16,10 @@ #include "ecmascript/date_parse.h" namespace panda::ecmascript { + const std::array DateParse::MONTH_NAME = { + "jan", "feb", "mar", "apr", "may", "jun", + "jul", "aug", "sep", "oct", "nov", "dec" +}; bool DateParse::ParseDateString(const char *str, int length, int *time) { StringReader reader(str, length); @@ -327,12 +331,8 @@ DateParse::DateValueType DateParse::DateProxy::MatchKeyWord(const CString &str, *value = 1; return DATE_TIME_ZONE; } - std::array monthName = { - "jan", "feb", "mar", "apr", "may", "jun", - "jul", "aug", "sep", "oct", "nov", "dec" - }; for (int i = 0; i < MOUTH_PER_YEAR; i++) { - if (str == monthName[i]) { + if (str == DateParse::MONTH_NAME[i]) { *value = i + 1; return DATE_MONTH; } diff --git a/ecmascript/date_parse.h b/ecmascript/date_parse.h index 855d71c94b..87797084e2 100644 --- a/ecmascript/date_parse.h +++ b/ecmascript/date_parse.h @@ -21,6 +21,7 @@ namespace panda::ecmascript { class DateParse { public: + static const std::array MONTH_NAME; static bool ParseDateString(const char *str, int length, int *time); private: diff --git a/ecmascript/js_collator.cpp b/ecmascript/js_collator.cpp index 609581f7a8..0046adf589 100644 --- a/ecmascript/js_collator.cpp +++ b/ecmascript/js_collator.cpp @@ -33,6 +33,34 @@ const std::map JSCollator::uColAttributeVal {CaseFirstOption::FALSE_OPTION, UCOL_OFF}, {CaseFirstOption::UNDEFINED, UCOL_OFF} }; +const std::vector JSCollator::LOCALE_MATCHER_OPTION = { + LocaleMatcherOption::LOOKUP, LocaleMatcherOption::BEST_FIT +}; +const std::vector JSCollator::LOCALE_MATCHER_OPTION_NAME = {"lookup", "best fit"}; + +const std::vector JSCollator::CASE_FIRST_OPTION = { + CaseFirstOption::UPPER, CaseFirstOption::LOWER, CaseFirstOption::FALSE_OPTION +}; +const std::vector JSCollator::CASE_FIRST_OPTION_NAME = {"upper", "lower", "false"}; + +const std::set JSCollator::RELEVANT_EXTENSION_KEYS = {"co", "kn", "kf"}; + +const std::vector JSCollator::SENSITIVITY_OPTION = { + SensitivityOption::BASE, SensitivityOption::ACCENT, + SensitivityOption::CASE, SensitivityOption::VARIANT +}; +const std::vector JSCollator::SENSITIVITY_OPTION_NAME = {"base", "accent", "case", "variant"}; + +const std::vector JSCollator::USAGE_OPTION = {UsageOption::SORT, UsageOption::SEARCH}; +const std::vector JSCollator::USAGE_OPTION_NAME = {"sort", "search"}; + +// All the available locales that are statically known to fulfill fast path conditions. +const char* const JSCollator::FAST_LOCALE[] = { + "en-US", "en", "fr", "es", "de", "pt", "it", "ca", + "de-AT", "fi", "id", "id-ID", "ms", "nl", "pl", "ro", + "sl", "sv", "sw", "vi", "en-DE", "en-GB", +}; + JSHandle JSCollator::GetAvailableLocales(JSThread *thread, bool enableLocaleCache) { @@ -99,7 +127,7 @@ JSHandle JSCollator::InitializeCollator(JSThread *thread, } // 4. Let usage be ? GetOption(options, "usage", "string", « "sort", "search" », "sort"). auto usage = JSLocale::GetOptionOfString(thread, optionsObject, globalConst->GetHandledUsageString(), - {UsageOption::SORT, UsageOption::SEARCH}, {"sort", "search"}, + JSCollator::USAGE_OPTION, JSCollator::USAGE_OPTION_NAME, UsageOption::SORT); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSCollator, thread); collator->SetUsage(usage); @@ -107,7 +135,7 @@ JSHandle JSCollator::InitializeCollator(JSThread *thread, // 5. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). auto matcher = JSLocale::GetOptionOfString( thread, optionsObject, globalConst->GetHandledLocaleMatcherString(), - {LocaleMatcherOption::LOOKUP, LocaleMatcherOption::BEST_FIT}, {"lookup", "best fit"}, + JSCollator::LOCALE_MATCHER_OPTION, JSCollator::LOCALE_MATCHER_OPTION_NAME, LocaleMatcherOption::BEST_FIT); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSCollator, thread); @@ -138,13 +166,12 @@ JSHandle JSCollator::InitializeCollator(JSThread *thread, // 14. Let caseFirst be ? GetOption(options, "caseFirst", "string", « "upper", "lower", "false" », undefined). CaseFirstOption caseFirst = JSLocale::GetOptionOfString( thread, optionsObject, globalConst->GetHandledCaseFirstString(), - {CaseFirstOption::UPPER, CaseFirstOption::LOWER, CaseFirstOption::FALSE_OPTION}, {"upper", "lower", "false"}, + JSCollator::CASE_FIRST_OPTION, JSCollator::CASE_FIRST_OPTION_NAME, CaseFirstOption::UNDEFINED); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSCollator, thread); collator->SetCaseFirst(caseFirst); // 16. Let relevantExtensionKeys be %Collator%.[[RelevantExtensionKeys]]. - std::set relevantExtensionKeys = {"co", "kn", "kf"}; // 17. Let r be ResolveLocale(%Collator%.[[AvailableLocales]], requestedLocales, opt, // %Collator%.[[RelevantExtensionKeys]], localeData). @@ -155,7 +182,7 @@ JSHandle JSCollator::InitializeCollator(JSThread *thread, availableLocales = GetAvailableLocales(thread, enableLocaleCache); } ResolvedLocale r = - JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, matcher, relevantExtensionKeys); + JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, matcher, RELEVANT_EXTENSION_KEYS); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSCollator, thread); icu::Locale icuLocale = r.localeData; JSHandle localeStr = intl::LocaleHelper::ToLanguageTag(thread, icuLocale); @@ -251,8 +278,8 @@ JSHandle JSCollator::InitializeCollator(JSThread *thread, // undefined). SensitivityOption sensitivity = JSLocale::GetOptionOfString( thread, optionsObject, globalConst->GetHandledSensitivityString(), - {SensitivityOption::BASE, SensitivityOption::ACCENT, SensitivityOption::CASE, SensitivityOption::VARIANT}, - {"base", "accent", "case", "variant"}, SensitivityOption::UNDEFINED); + JSCollator::SENSITIVITY_OPTION, JSCollator::SENSITIVITY_OPTION_NAME, + SensitivityOption::UNDEFINED); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSCollator, thread); // 25. If sensitivity is undefined, then // a. If usage is "sort", then @@ -474,12 +501,6 @@ JSHandle JSCollator::ResolvedOptions(JSThread *thread, const JSHandle< CompareStringsOption JSCollator::CompareStringsOptionFor(JSThread* thread, JSHandle locales) { - // All the available locales that are statically known to fulfill fast path conditions. - static const char* const FAST_LOCALE[] = { - "en-US", "en", "fr", "es", "de", "pt", "it", "ca", - "de-AT", "fi", "id", "id-ID", "ms", "nl", "pl", "ro", - "sl", "sv", "sw", "vi", "en-DE", "en-GB", - }; if (locales->IsUndefined()) { auto context = thread->GetCurrentEcmaContext(); auto defaultCompareOption = context->GetDefaultCompareStringsOption(); diff --git a/ecmascript/js_collator.h b/ecmascript/js_collator.h index 244a4f513f..a6b7c7f9a1 100644 --- a/ecmascript/js_collator.h +++ b/ecmascript/js_collator.h @@ -35,6 +35,23 @@ public: static const std::map uColAttributeValueMap; + static const std::vector LOCALE_MATCHER_OPTION; + static const std::vector LOCALE_MATCHER_OPTION_NAME; + + static const std::vector CASE_FIRST_OPTION; + static const std::vector CASE_FIRST_OPTION_NAME; + + static const std::set RELEVANT_EXTENSION_KEYS; + + static const std::vector SENSITIVITY_OPTION; + static const std::vector SENSITIVITY_OPTION_NAME; + + static const std::vector USAGE_OPTION; + static const std::vector USAGE_OPTION_NAME; + + // All the available locales that are statically known to fulfill fast path conditions. + static const char *const FAST_LOCALE[]; + CAST_CHECK(JSCollator, IsJSCollator); static constexpr size_t ICU_FIELD_OFFSET = JSObject::SIZE; diff --git a/ecmascript/js_displaynames.cpp b/ecmascript/js_displaynames.cpp index 0850f3f774..3e298ce416 100644 --- a/ecmascript/js_displaynames.cpp +++ b/ecmascript/js_displaynames.cpp @@ -35,6 +35,41 @@ #endif namespace panda::ecmascript { + +const std::vector JSDisplayNames::LOCALE_MATCHER_OPTION = { + LocaleMatcherOption::LOOKUP, LocaleMatcherOption::BEST_FIT +}; +const std::vector JSDisplayNames::LOCALE_MATCHER_OPTION_NAME = {"lookup", "best fit"}; + +const std::vector JSDisplayNames::STY_OPTION = { + StyOption::NARROW, StyOption::SHORT, StyOption::LONG +}; +const std::vector JSDisplayNames::STY_OPTION_NAME = {"narrow", "short", "long"}; + +const std::vector JSDisplayNames::TYPED_NS_OPTION = { + TypednsOption::LANGUAGE, TypednsOption::REGION, + TypednsOption::SCRIPT, TypednsOption::CURRENCY, + TypednsOption::CALENDAR, TypednsOption::DATETIMEFIELD +}; +const std::vector JSDisplayNames::TYPED_NS_OPTION_NAME = { + "language", "region", "script", "currency", + "calendar", "dateTimeField" +}; + +const std::vector JSDisplayNames::FALLBACK_OPTION = { + FallbackOption::CODE, FallbackOption::NONE +}; +const std::vector JSDisplayNames::FALLBACK_OPTION_OPTION_NAME = { + "code", "none" +}; + +const std::vector JSDisplayNames::LANGUAGE_DISPLAY_OPTION = { + LanguageDisplayOption::DIALECT, LanguageDisplayOption::STANDARD +}; +const std::vector JSDisplayNames::LANGUAGE_DISPLAY_OPTION_NAME = { + "dialect", "standard" +}; + icu::LocaleDisplayNames *JSDisplayNames::GetIcuLocaleDisplayNames() const { ASSERT(GetIcuLDN().IsJSNativePointer()); @@ -125,8 +160,9 @@ JSHandle JSDisplayNames::InitializeDisplayNames(JSThread *thread // 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). JSHandle property = globalConst->GetHandledLocaleMatcherString(); auto matcher = JSLocale::GetOptionOfString( - thread, optionsObject, property, {LocaleMatcherOption::LOOKUP, LocaleMatcherOption::BEST_FIT}, - {"lookup", "best fit"}, LocaleMatcherOption::BEST_FIT); + thread, optionsObject, property, + JSDisplayNames::LOCALE_MATCHER_OPTION, JSDisplayNames::LOCALE_MATCHER_OPTION_NAME, + LocaleMatcherOption::BEST_FIT); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSDisplayNames, thread); // 10. Let r be ResolveLocale(%DisplayNames%.[[AvailableLocales]], requestedLocales, opt, @@ -146,8 +182,8 @@ JSHandle JSDisplayNames::InitializeDisplayNames(JSThread *thread // 11. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). property = globalConst->GetHandledStyleString(); auto StyOpt = JSLocale::GetOptionOfString(thread, optionsObject, property, - {StyOption::NARROW, StyOption::SHORT, StyOption::LONG}, - {"narrow", "short", "long"}, StyOption::LONG); + JSDisplayNames::STY_OPTION, JSDisplayNames::STY_OPTION_NAME, + StyOption::LONG); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSDisplayNames, thread); // 12. Set DisplayNames.[[Style]] to style. @@ -157,12 +193,8 @@ JSHandle JSDisplayNames::InitializeDisplayNames(JSThread *thread // "undefined"). property = globalConst->GetHandledTypeString(); auto type = JSLocale::GetOptionOfString(thread, optionsObject, property, - {TypednsOption::LANGUAGE, TypednsOption::REGION, - TypednsOption::SCRIPT, TypednsOption::CURRENCY, - TypednsOption::CALENDAR, TypednsOption::DATETIMEFIELD}, - {"language", "region", "script", "currency", - "calendar", "dateTimeField"}, - TypednsOption::UNDEFINED); + JSDisplayNames::TYPED_NS_OPTION, JSDisplayNames::TYPED_NS_OPTION_NAME, + TypednsOption::UNDEFINED); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSDisplayNames, thread); // 14. If type is undefined, throw a TypeError exception. @@ -176,8 +208,8 @@ JSHandle JSDisplayNames::InitializeDisplayNames(JSThread *thread // 16. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). property = globalConst->GetHandledFallbackString(); auto fallback = JSLocale::GetOptionOfString(thread, optionsObject, property, - {FallbackOption::CODE, FallbackOption::NONE}, - {"code", "none"}, FallbackOption::CODE); + JSDisplayNames::FALLBACK_OPTION, JSDisplayNames::FALLBACK_OPTION_OPTION_NAME, + FallbackOption::CODE); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSDisplayNames, thread); // 17. Set displayNames.[[Fallback]] to fallback. @@ -186,8 +218,9 @@ JSHandle JSDisplayNames::InitializeDisplayNames(JSThread *thread // Let languageDisplay be ? GetOption(options, "languageDisplay", string, « "dialect", "standard" », "dialect"). property = globalConst->GetHandledLanguageDisplayString(); auto langDisplay = JSLocale::GetOptionOfString( - thread, optionsObject, property, {LanguageDisplayOption::DIALECT, LanguageDisplayOption::STANDARD}, - {"dialect", "standard"}, LanguageDisplayOption::DIALECT); + thread, optionsObject, property, + JSDisplayNames::LANGUAGE_DISPLAY_OPTION, + JSDisplayNames::LANGUAGE_DISPLAY_OPTION_NAME, LanguageDisplayOption::DIALECT); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSDisplayNames, thread); displayNames->SetLanguageDisplay(langDisplay); diff --git a/ecmascript/js_displaynames.h b/ecmascript/js_displaynames.h index 9d2419490e..196c6bc6c6 100644 --- a/ecmascript/js_displaynames.h +++ b/ecmascript/js_displaynames.h @@ -63,6 +63,20 @@ enum class LanguageDisplayOption : uint8_t { class JSDisplayNames : public JSObject { public: + static const std::vector LOCALE_MATCHER_OPTION; + static const std::vector LOCALE_MATCHER_OPTION_NAME; + + static const std::vector STY_OPTION; + static const std::vector STY_OPTION_NAME; + + static const std::vector TYPED_NS_OPTION; + static const std::vector TYPED_NS_OPTION_NAME; + + static const std::vector FALLBACK_OPTION; + static const std::vector FALLBACK_OPTION_OPTION_NAME; + + static const std::vector LANGUAGE_DISPLAY_OPTION; + static const std::vector LANGUAGE_DISPLAY_OPTION_NAME; CAST_CHECK(JSDisplayNames, IsJSDisplayNames); static constexpr size_t LOCALE_OFFSET = JSObject::SIZE; diff --git a/ecmascript/js_locale.cpp b/ecmascript/js_locale.cpp index 5931436a6f..b395f00339 100644 --- a/ecmascript/js_locale.cpp +++ b/ecmascript/js_locale.cpp @@ -34,7 +34,27 @@ #endif namespace panda::ecmascript { -const std::string LATN_STRING = "latn"; +const std::string JSLocale::LATN_STRING = "latn"; + +const std::vector JSLocale::LOCALE_MATCHER_OPTION = { + LocaleMatcherOption::LOOKUP, LocaleMatcherOption::BEST_FIT +}; +const std::vector JSLocale::LOCALE_MATCHER_OPTION_NAME = { + "lookup", "best fit" +}; + +const std::map> JSLocale::LOCALE_MAP = { + {"hc", {"h11", "h12", "h23", "h24"}}, + {"lb", {"strict", "normal", "loose"}}, + {"kn", {"true", "false"}}, + {"kf", {"upper", "lower", "false"}} +}; + +const std::vector JSLocale::HOUR_CYCLE = {"h11", "h12", "h23", "h24"}; +const std::vector JSLocale::CASE_FIRST = {"upper", "lower", "false"}; + +const std::set JSLocale::WELL_NUMBER_SYSTEM = {"native", "traditio", "finance"}; +const std::set JSLocale::WELL_COLLATION = {"standard", "search"}; // 6.4.1 IsValidTimeZoneName ( timeZone ) bool JSLocale::IsValidTimeZoneName(const icu::TimeZone &tz) { @@ -236,7 +256,7 @@ JSHandle JSLocale::SupportedLocales(JSThread *thread, const JSHandle(thread, obj, globalConst->GetHandledLocaleMatcherString(), - {LocaleMatcherOption::LOOKUP, LocaleMatcherOption::BEST_FIT}, {"lookup", "best fit"}, + JSLocale::LOCALE_MATCHER_OPTION, JSLocale::LOCALE_MATCHER_OPTION_NAME, LocaleMatcherOption::BEST_FIT); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSArray, thread); } @@ -445,13 +465,6 @@ ResolvedLocale JSLocale::ResolveLocale(JSThread *thread, const JSHandle &relevantExtensionKeys) { - std::map> localeMap = { - {"hc", {"h11", "h12", "h23", "h24"}}, - {"lb", {"strict", "normal", "loose"}}, - {"kn", {"true", "false"}}, - {"kf", {"upper", "lower", "false"}} - }; - // 1. Let matcher be options.[[localeMatcher]]. // 2. If matcher is "lookup" "lookup", then // a. Let r be LookupMatcher(availableLocales, requestedLocales). @@ -497,9 +510,12 @@ ResolvedLocale JSLocale::ResolveLocale(JSThread *thread, const JSHandle]]. // e. Let value be keyLocaleData[0]. if ((key != "ca") && (key != "co") && (key != "nu")) { - keyLocaleData = localeMap[key]; + auto find = JSLocale::LOCALE_MAP.find(key); + if (find != JSLocale::LOCALE_MAP.end()) { + keyLocaleData = find->second; + } if (key == "") { - keyLocaleData = localeMap["lb"]; + keyLocaleData = JSLocale::LOCALE_MAP.at("lb"); } value = *keyLocaleData.begin(); } @@ -627,7 +643,7 @@ std::string JSLocale::GetNumberingSystem(const icu::Locale &icuLocale) if (U_SUCCESS(status) != 0) { return numberingSystem->getName(); } - return LATN_STRING; + return JSLocale::LATN_STRING; } bool JSLocale::IsWellFormedCurrencyCode(const std::string ¤cy) @@ -857,8 +873,6 @@ bool BuildOptionsTags(const JSHandle &tag, icu::LocaleBuilder *build bool InsertOptions(JSThread *thread, const JSHandle &options, icu::LocaleBuilder *builder) { - const std::vector hourCycleValues = {"h11", "h12", "h23", "h24"}; - const std::vector caseFirstValues = {"upper", "lower", "false"}; const std::vector emptyValues = {}; const GlobalEnvConstants *globalConst = thread->GlobalConstants(); std::string strResult; @@ -885,7 +899,7 @@ bool InsertOptions(JSThread *thread, const JSHandle &options, icu::Loc } bool findhc = JSLocale::GetOptionOfString(thread, options, globalConst->GetHandledHourCycleString(), - hourCycleValues, &strResult); + JSLocale::HOUR_CYCLE, &strResult); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false); if (findhc) { if (!uloc_toLegacyType(uloc_toLegacyKey("hc"), strResult.c_str())) { @@ -896,7 +910,7 @@ bool InsertOptions(JSThread *thread, const JSHandle &options, icu::Loc } bool findkf = JSLocale::GetOptionOfString(thread, options, globalConst->GetHandledCaseFirstString(), - caseFirstValues, &strResult); + JSLocale::CASE_FIRST, &strResult); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false); if (findkf) { if (!uloc_toLegacyType(uloc_toLegacyKey("kf"), strResult.c_str())) { diff --git a/ecmascript/js_locale.h b/ecmascript/js_locale.h index dba53a293e..6f7f2e8ea9 100644 --- a/ecmascript/js_locale.h +++ b/ecmascript/js_locale.h @@ -49,6 +49,7 @@ #include "unicode/uversion.h" namespace panda::ecmascript { + enum class OptionType : uint8_t { STRING = 0x01, BOOLEAN }; enum class LocaleMatcherOption : uint8_t { LOOKUP = 0x01, BEST_FIT, EXCEPTION }; enum class FormatMatcherOption : uint8_t { BASIC = 0x01, BEST_FIT, EXCEPTION }; @@ -148,6 +149,18 @@ struct TagElements { class JSLocale : public JSObject { public: + static const std::set WELL_NUMBER_SYSTEM; + static const std::set WELL_COLLATION; + + static const std::string LATN_STRING; + + static const std::vector LOCALE_MATCHER_OPTION; + static const std::vector LOCALE_MATCHER_OPTION_NAME; + + static const std::map> LOCALE_MAP; + + static const std::vector HOUR_CYCLE; + static const std::vector CASE_FIRST; static JSLocale *Cast(TaggedObject *object) { ASSERT(JSTaggedValue(object).IsJSLocale()); @@ -321,8 +334,7 @@ public: static bool IsWellNumberingSystem(const std::string &value) { - std::set irregularList = {"native", "traditio", "finance"}; - if (irregularList.find(value) != irregularList.end()) { + if (JSLocale::WELL_NUMBER_SYSTEM.find(value) != JSLocale::WELL_NUMBER_SYSTEM.end()) { return false; } UErrorCode status = U_ZERO_ERROR; @@ -335,8 +347,7 @@ public: static bool IsWellCollation(const icu::Locale &locale, const std::string &value) { - std::set irregularList = {"standard", "search"}; - if (irregularList.find(value) != irregularList.end()) { + if (JSLocale::WELL_COLLATION.find(value) != JSLocale::WELL_COLLATION.end()) { return false; } return IsWellExtension(locale, "collation", value); diff --git a/ecmascript/js_number_format.cpp b/ecmascript/js_number_format.cpp index 55b0ef54ec..9a41b2c721 100644 --- a/ecmascript/js_number_format.cpp +++ b/ecmascript/js_number_format.cpp @@ -19,8 +19,57 @@ #include "ecmascript/object_factory-inl.h" namespace panda::ecmascript { -constexpr uint32_t DEFAULT_FRACTION_DIGITS = 2; -constexpr uint32_t PERUNIT_STRING = 5; + +const std::vector JSNumberFormat::STYLE_OPTION = { + StyleOption::DECIMAL, StyleOption::PERCENT, StyleOption::CURRENCY, StyleOption::UNIT +}; +const std::vector JSNumberFormat::STYLE_OPTION_NAME = { + "decimal", "percent", "currency", "unit" +}; + +const std::vector JSNumberFormat::CURRENCY_DISPLAY_OPTION = { + CurrencyDisplayOption::CODE, CurrencyDisplayOption::SYMBOL, + CurrencyDisplayOption::NARROWSYMBOL, CurrencyDisplayOption::NAME +}; +const std::vector JSNumberFormat::CURRENCY_DISPLAY_OPTION_NAME = { + "code", "symbol", "narrowSymbol", "name" +}; + +const std::vector JSNumberFormat::CURRENCY_SIGN_OPTION = { + CurrencySignOption::STANDARD, CurrencySignOption::ACCOUNTING +}; +const std::vector JSNumberFormat::CURRENCY_SIGN_OPTION_NAME = {"standard", "accounting"}; + +const std::vector JSNumberFormat::UNIT_DISPLAY_OPTION = { + UnitDisplayOption::SHORT, UnitDisplayOption::NARROW, UnitDisplayOption::LONG +}; +const std::vector JSNumberFormat::UNIT_DISPLAY_OPTION_NAME = {"short", "narrow", "long"}; + +const std::vector JSNumberFormat::LOCALE_MATCHER_OPTION = { + LocaleMatcherOption::LOOKUP, LocaleMatcherOption::BEST_FIT +}; +const std::vector JSNumberFormat::LOCALE_MATCHER_OPTION_NAME = {"lookup", "best fit"}; + +const std::vector JSNumberFormat::NOTATION_OPTION = { + NotationOption::STANDARD, NotationOption::SCIENTIFIC, + NotationOption::ENGINEERING, NotationOption::COMPACT +}; +const std::vector JSNumberFormat::NOTATION_OPTION_NAME = { + "standard", "scientific", "engineering", "compact" +}; + +const std::vector JSNumberFormat::SIGN_DISPLAY_OPTION = { + SignDisplayOption::AUTO, SignDisplayOption::NEVER, + SignDisplayOption::ALWAYS, SignDisplayOption::EXCEPTZERO +}; +const std::vector JSNumberFormat::SIGN_DISPLAY_OPTION_NAME = { + "auto", "never", "always", "exceptZero" +}; + +const std::vector JSNumberFormat::COMPACT_DISPLAY_OPTION = { + CompactDisplayOption::SHORT, CompactDisplayOption::LONG +}; +const std::vector JSNumberFormat::COMPACT_DISPLAY_OPTION_NAME = {"short", "long"}; JSHandle OptionToEcmaString(JSThread *thread, StyleOption style) { @@ -225,7 +274,7 @@ bool IsWellFormedUnitIdentifier(const std::string &unit, icu::MeasureUnit &icuUn // 2. If the substring "-per-" does not occur exactly once in unitIdentifier, // a. then false - size_t afterPos = pos + PERUNIT_STRING; + size_t afterPos = pos + JSNumberFormat::PERUNIT_STRING; if (pos == std::string::npos || unit.find("-per-", afterPos) != std::string::npos) { return false; } @@ -241,7 +290,7 @@ bool IsWellFormedUnitIdentifier(const std::string &unit, icu::MeasureUnit &icuUn } // 5. Let denominator be the substring of unitIdentifier from just after "-per-" to the end. - std::string denominator = unit.substr(pos + PERUNIT_STRING); + std::string denominator = unit.substr(pos + JSNumberFormat::PERUNIT_STRING); // 6. If the result of IsSanctionedUnitIdentifier(denominator) is false, then // a. Return false @@ -270,8 +319,8 @@ FractionDigitsOption SetNumberFormatUnitOptions(JSThread *thread, JSHandle property = globalConst->GetHandledStyleString(); auto style = JSLocale::GetOptionOfString( thread, optionsObject, property, - {StyleOption::DECIMAL, StyleOption::PERCENT, StyleOption::CURRENCY, StyleOption::UNIT}, - {"decimal", "percent", "currency", "unit"}, StyleOption::DECIMAL); + JSNumberFormat::STYLE_OPTION, JSNumberFormat::STYLE_OPTION_NAME, + StyleOption::DECIMAL); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, fractionDigitsOption); // 4. Set intlObj.[[Style]] to style. @@ -307,17 +356,17 @@ FractionDigitsOption SetNumberFormatUnitOptions(JSThread *thread, property = globalConst->GetHandledCurrencyDisplayString(); auto currencyDisplay = JSLocale::GetOptionOfString( thread, optionsObject, property, - {CurrencyDisplayOption::CODE, CurrencyDisplayOption::SYMBOL, CurrencyDisplayOption::NARROWSYMBOL, - CurrencyDisplayOption::NAME}, - {"code", "symbol", "narrowSymbol", "name"}, CurrencyDisplayOption::SYMBOL); + JSNumberFormat::CURRENCY_DISPLAY_OPTION, JSNumberFormat::CURRENCY_DISPLAY_OPTION_NAME, + CurrencyDisplayOption::SYMBOL); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, fractionDigitsOption); numberFormat->SetCurrencyDisplay(currencyDisplay); // 9. Let currencySign be ? GetOption(options, "currencySign", "string", « "standard", "accounting" », "standard"). property = globalConst->GetHandledCurrencySignString(); auto currencySign = JSLocale::GetOptionOfString( - thread, optionsObject, property, {CurrencySignOption::STANDARD, CurrencySignOption::ACCOUNTING}, - {"standard", "accounting"}, CurrencySignOption::STANDARD); + thread, optionsObject, property, + JSNumberFormat::CURRENCY_SIGN_OPTION, JSNumberFormat::CURRENCY_SIGN_OPTION_NAME, + CurrencySignOption::STANDARD); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, fractionDigitsOption); numberFormat->SetCurrencySign(currencySign); @@ -351,8 +400,9 @@ FractionDigitsOption SetNumberFormatUnitOptions(JSThread *thread, // 13. Let unitDisplay be ? GetOption(options, "unitDisplay", "string", « "short", "narrow", "long" », "short"). property = globalConst->GetHandledUnitDisplayString(); auto unitDisplay = JSLocale::GetOptionOfString( - thread, optionsObject, property, {UnitDisplayOption::SHORT, UnitDisplayOption::NARROW, UnitDisplayOption::LONG}, - {"short", "narrow", "long"}, UnitDisplayOption::SHORT); + thread, optionsObject, property, + JSNumberFormat::UNIT_DISPLAY_OPTION, JSNumberFormat::UNIT_DISPLAY_OPTION_NAME, + UnitDisplayOption::SHORT); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, fractionDigitsOption); numberFormat->SetUnitDisplay(unitDisplay); @@ -463,8 +513,9 @@ void JSNumberFormat::InitializeNumberFormat(JSThread *thread, const JSHandle property = globalConst->GetHandledLocaleMatcherString(); auto matcher = JSLocale::GetOptionOfString( - thread, optionsObject, property, {LocaleMatcherOption::LOOKUP, LocaleMatcherOption::BEST_FIT}, - {"lookup", "best fit"}, LocaleMatcherOption::BEST_FIT); + thread, optionsObject, property, + JSNumberFormat::LOCALE_MATCHER_OPTION, JSNumberFormat::LOCALE_MATCHER_OPTION_NAME, + LocaleMatcherOption::BEST_FIT); RETURN_IF_ABRUPT_COMPLETION(thread); // 7. Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined). @@ -569,8 +620,8 @@ void JSNumberFormat::InitializeNumberFormat(JSThread *thread, const JSHandleGetHandledNotationString(); auto notation = JSLocale::GetOptionOfString( thread, optionsObject, property, - {NotationOption::STANDARD, NotationOption::SCIENTIFIC, NotationOption::ENGINEERING, NotationOption::COMPACT}, - {"standard", "scientific", "engineering", "compact"}, NotationOption::STANDARD); + JSNumberFormat::NOTATION_OPTION, JSNumberFormat::NOTATION_OPTION_NAME, + NotationOption::STANDARD); RETURN_IF_ABRUPT_COMPLETION(thread); numberFormat->SetNotation(notation); @@ -583,7 +634,8 @@ void JSNumberFormat::InitializeNumberFormat(JSThread *thread, const JSHandleGetHandledCompactDisplayString(); auto compactDisplay = JSLocale::GetOptionOfString( - thread, optionsObject, property, {CompactDisplayOption::SHORT, CompactDisplayOption::LONG}, {"short", "long"}, + thread, optionsObject, property, + JSNumberFormat::COMPACT_DISPLAY_OPTION, JSNumberFormat::COMPACT_DISPLAY_OPTION_NAME, CompactDisplayOption::SHORT); numberFormat->SetCompactDisplay(compactDisplay); @@ -632,8 +684,8 @@ void JSNumberFormat::InitializeNumberFormat(JSThread *thread, const JSHandleGetHandledSignDisplayString(); auto signDisplay = JSLocale::GetOptionOfString( thread, optionsObject, property, - {SignDisplayOption::AUTO, SignDisplayOption::NEVER, SignDisplayOption::ALWAYS, SignDisplayOption::EXCEPTZERO}, - {"auto", "never", "always", "exceptZero"}, SignDisplayOption::AUTO); + JSNumberFormat::SIGN_DISPLAY_OPTION, JSNumberFormat::SIGN_DISPLAY_OPTION_NAME, + SignDisplayOption::AUTO); RETURN_IF_ABRUPT_COMPLETION(thread); numberFormat->SetSignDisplay(signDisplay); @@ -701,7 +753,7 @@ int32_t JSNumberFormat::CurrencyDigits(const icu::UnicodeString ¤cy) if (U_SUCCESS(status)) { return fractionDigits; } - return DEFAULT_FRACTION_DIGITS; + return JSNumberFormat::DEFAULT_FRACTION_DIGITS; } icu::number::LocalizedNumberFormatter *JSNumberFormat::GetCachedIcuNumberFormatter(JSThread *thread, diff --git a/ecmascript/js_number_format.h b/ecmascript/js_number_format.h index 97efa1bcf3..02e5763efb 100644 --- a/ecmascript/js_number_format.h +++ b/ecmascript/js_number_format.h @@ -52,6 +52,31 @@ static const std::set SANCTIONED_UNIT({ "acre", "bit", "byte", "cel class JSNumberFormat : public JSObject { public: + static constexpr uint32_t DEFAULT_FRACTION_DIGITS = 2; + static constexpr uint32_t PERUNIT_STRING = 5; + static const std::vector STYLE_OPTION; + static const std::vector STYLE_OPTION_NAME; + + static const std::vector CURRENCY_DISPLAY_OPTION; + static const std::vector CURRENCY_DISPLAY_OPTION_NAME; + + static const std::vector CURRENCY_SIGN_OPTION; + static const std::vector CURRENCY_SIGN_OPTION_NAME; + + static const std::vector UNIT_DISPLAY_OPTION; + static const std::vector UNIT_DISPLAY_OPTION_NAME; + + static const std::vector LOCALE_MATCHER_OPTION; + static const std::vector LOCALE_MATCHER_OPTION_NAME; + + static const std::vector NOTATION_OPTION; + static const std::vector NOTATION_OPTION_NAME; + + static const std::vector SIGN_DISPLAY_OPTION; + static const std::vector SIGN_DISPLAY_OPTION_NAME; + + static const std::vector COMPACT_DISPLAY_OPTION; + static const std::vector COMPACT_DISPLAY_OPTION_NAME; CAST_CHECK(JSNumberFormat, IsJSNumberFormat); static constexpr size_t LOCALE_OFFSET = JSObject::SIZE;