WebKit Bugzilla
Attachment 340884 Details for
Bug 185836
: [INTL] Language tags are not canonicalized
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Naive
bug-185836-20180521150127.patch (text/plain), 52.02 KB, created by
Andy VanWagoner
on 2018-05-21 14:01:29 PDT
(
hide
)
Description:
Naive
Filename:
MIME Type:
Creator:
Andy VanWagoner
Created:
2018-05-21 14:01:29 PDT
Size:
52.02 KB
patch
obsolete
>Subversion Revision: 231993 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 88cdd95b5162a2c12027f68bfed82e5557792be1..7480f8a0af69fd965efc5dba60fa2d89201e526f 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,47 @@ >+2018-05-21 Andy VanWagoner <andy@vanwagoner.family> >+ >+ [INTL] Language tags are not canonicalized >+ https://bugs.webkit.org/show_bug.cgi?id=185836 >+ >+ Canonicalize language tags, replacing deprecated tag parts with the >+ preferred values. Remove broken support for algorithmic numbering systems, >+ that would cause an error in icu, or cause odd extra characters in final >+ string. >+ >+ Also initialize the UNumberFormat in initializeNumberFormat so any >+ failures are thrown immediately instead of failing to format later. >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * runtime/IntlDateTimeFormat.cpp: >+ (JSC::IntlDateTimeFormat::initializeDateTimeFormat): >+ * runtime/IntlNumberFormat.cpp: >+ (JSC::IntlNumberFormat::initializeNumberFormat): Open UNumberFormat. >+ (JSC::IntlNumberFormat::formatNumber): >+ (JSC::IntlNumberFormat::formatToParts): >+ (JSC::IntlNumberFormat::createNumberFormat): Deleted. >+ * runtime/IntlNumberFormat.h: >+ * runtime/IntlObject.cpp: >+ (JSC::intlNumberOption): >+ (JSC::intlDefaultNumberOption): >+ (JSC::preferredLanguageFor): >+ (JSC::shouldExtLangReplaceLanguage): >+ (JSC::preferredRegionFor): >+ (JSC::preferredLanguageTagFor): >+ (JSC::canonicalLangTag): >+ (JSC::grandfatheredLangTag): >+ (JSC::removeUnicodeLocaleExtension): >+ (JSC::numberingSystemsForLocale): >+ * runtime/IntlObject.h: >+ * runtime/IntlPluralRules.cpp: >+ (JSC::IntlPluralRules::initializePluralRules): >+ * runtime/JSGlobalObject.cpp: >+ (JSC::addMissingScriptLocales): >+ (JSC::JSGlobalObject::intlCollatorAvailableLocales): >+ (JSC::JSGlobalObject::intlDateTimeFormatAvailableLocales): >+ (JSC::JSGlobalObject::intlNumberFormatAvailableLocales): >+ (JSC::JSGlobalObject::intlPluralRulesAvailableLocales): >+ > 2018-05-18 Commit Queue <commit-queue@webkit.org> > > Unreviewed, rolling out r231982. >diff --git a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp >index 1573c7295f149796a05ad79782d07263347233e4..91193866d7270ac9ab4bb9c3cdc1e1c6f401bf7b 100644 >--- a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp >+++ b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp >@@ -466,8 +466,8 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local > // 14. Set dateTimeFormat.[[calendar]] to the value of r.[[ca]]. > m_calendar = resolved.get(ASCIILiteral("ca")); > // Switch to preferred aliases. >- if (m_calendar == "gregory") >- m_calendar = ASCIILiteral("gregorian"); >+ if (m_calendar == "gregorian") >+ m_calendar = ASCIILiteral("gregory"); > else if (m_calendar == "islamicc") > m_calendar = ASCIILiteral("islamic-civil"); > else if (m_calendar == "ethioaa") >@@ -673,6 +673,11 @@ void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue local > return; > } > >+ // Gregorian calendar should be used from the beginning of ECMAScript time. >+ // Failure here means unsupported calendar, and can safely be ignored. >+ UCalendar* cal = const_cast<UCalendar*>(udat_getCalendar(m_dateFormat.get())); >+ ucal_setGregorianChange(cal, -8.64E15, &status); >+ > // 37. Set dateTimeFormat.[[boundFormat]] to undefined. > // Already undefined. > >diff --git a/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp b/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp >index a1466346b29aa163de95dc589b146d4c0479fbdd..2a07acdc3e64238b7b8ce088da31fc79a4e4dbb8 100644 >--- a/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp >+++ b/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp >@@ -269,9 +269,9 @@ void IntlNumberFormat::initializeNumberFormat(ExecState& state, JSValue locales, > RETURN_IF_EXCEPTION(scope, void()); > > if (!minimumSignificantDigitsValue.isUndefined() || !maximumSignificantDigitsValue.isUndefined()) { >- unsigned minimumSignificantDigits = intlNumberOption(state, options, Identifier::fromString(&vm, "minimumSignificantDigits"), 1, 21, 1); >+ unsigned minimumSignificantDigits = intlDefaultNumberOption(state, minimumSignificantDigitsValue, Identifier::fromString(&vm, "minimumSignificantDigits"), 1, 21, 1); > RETURN_IF_EXCEPTION(scope, void()); >- unsigned maximumSignificantDigits = intlNumberOption(state, options, Identifier::fromString(&vm, "maximumSignificantDigits"), minimumSignificantDigits, 21, 21); >+ unsigned maximumSignificantDigits = intlDefaultNumberOption(state, maximumSignificantDigitsValue, Identifier::fromString(&vm, "maximumSignificantDigits"), minimumSignificantDigits, 21, 21); > RETURN_IF_EXCEPTION(scope, void()); > m_minimumSignificantDigits = minimumSignificantDigits; > m_maximumSignificantDigits = maximumSignificantDigits; >@@ -284,21 +284,6 @@ void IntlNumberFormat::initializeNumberFormat(ExecState& state, JSValue locales, > RETURN_IF_EXCEPTION(scope, void()); > m_useGrouping = useGrouping; > >- m_initializedNumberFormat = true; >-} >- >-void IntlNumberFormat::createNumberFormat(ExecState& state) >-{ >- VM& vm = state.vm(); >- auto scope = DECLARE_CATCH_SCOPE(vm); >- >- ASSERT(!m_numberFormat); >- >- if (!m_initializedNumberFormat) { >- initializeNumberFormat(state, jsUndefined(), jsUndefined()); >- scope.assertNoException(); >- } >- > UNumberFormatStyle style = UNUM_DEFAULT; > switch (m_style) { > case Style::Decimal: >@@ -327,27 +312,32 @@ void IntlNumberFormat::createNumberFormat(ExecState& state) > } > > UErrorCode status = U_ZERO_ERROR; >- auto numberFormat = std::unique_ptr<UNumberFormat, UNumberFormatDeleter>(unum_open(style, nullptr, 0, m_locale.utf8().data(), nullptr, &status)); >- if (U_FAILURE(status)) >+ m_numberFormat = std::unique_ptr<UNumberFormat, UNumberFormatDeleter>(unum_open(style, nullptr, 0, m_locale.utf8().data(), nullptr, &status)); >+ if (U_FAILURE(status)) { >+ throwTypeError(&state, scope, ASCIILiteral("failed to initialize NumberFormat")); > return; >+ } > >- if (m_style == Style::Currency) >- unum_setTextAttribute(numberFormat.get(), UNUM_CURRENCY_CODE, StringView(m_currency).upconvertedCharacters(), 3, &status); >+ if (m_style == Style::Currency) { >+ unum_setTextAttribute(m_numberFormat.get(), UNUM_CURRENCY_CODE, StringView(m_currency).upconvertedCharacters(), m_currency.length(), &status); >+ if (U_FAILURE(status)) { >+ throwTypeError(&state, scope, ASCIILiteral("failed to initialize NumberFormat")); >+ return; >+ } >+ } > if (!m_minimumSignificantDigits) { >- unum_setAttribute(numberFormat.get(), UNUM_MIN_INTEGER_DIGITS, m_minimumIntegerDigits); >- unum_setAttribute(numberFormat.get(), UNUM_MIN_FRACTION_DIGITS, m_minimumFractionDigits); >- unum_setAttribute(numberFormat.get(), UNUM_MAX_FRACTION_DIGITS, m_maximumFractionDigits); >+ unum_setAttribute(m_numberFormat.get(), UNUM_MIN_INTEGER_DIGITS, m_minimumIntegerDigits); >+ unum_setAttribute(m_numberFormat.get(), UNUM_MIN_FRACTION_DIGITS, m_minimumFractionDigits); >+ unum_setAttribute(m_numberFormat.get(), UNUM_MAX_FRACTION_DIGITS, m_maximumFractionDigits); > } else { >- unum_setAttribute(numberFormat.get(), UNUM_SIGNIFICANT_DIGITS_USED, true); >- unum_setAttribute(numberFormat.get(), UNUM_MIN_SIGNIFICANT_DIGITS, m_minimumSignificantDigits); >- unum_setAttribute(numberFormat.get(), UNUM_MAX_SIGNIFICANT_DIGITS, m_maximumSignificantDigits); >+ unum_setAttribute(m_numberFormat.get(), UNUM_SIGNIFICANT_DIGITS_USED, true); >+ unum_setAttribute(m_numberFormat.get(), UNUM_MIN_SIGNIFICANT_DIGITS, m_minimumSignificantDigits); >+ unum_setAttribute(m_numberFormat.get(), UNUM_MAX_SIGNIFICANT_DIGITS, m_maximumSignificantDigits); > } >- unum_setAttribute(numberFormat.get(), UNUM_GROUPING_USED, m_useGrouping); >- unum_setAttribute(numberFormat.get(), UNUM_ROUNDING_MODE, UNUM_ROUND_HALFUP); >- if (U_FAILURE(status)) >- return; >+ unum_setAttribute(m_numberFormat.get(), UNUM_GROUPING_USED, m_useGrouping); >+ unum_setAttribute(m_numberFormat.get(), UNUM_ROUNDING_MODE, UNUM_ROUND_HALFUP); > >- m_numberFormat = WTFMove(numberFormat); >+ m_initializedNumberFormat = true; > } > > JSValue IntlNumberFormat::formatNumber(ExecState& state, double number) >@@ -355,12 +345,10 @@ JSValue IntlNumberFormat::formatNumber(ExecState& state, double number) > VM& vm = state.vm(); > auto scope = DECLARE_THROW_SCOPE(vm); > >- // 11.3.4 FormatNumber abstract operation (ECMA-402 2.0) >- if (!m_numberFormat) { >- createNumberFormat(state); >- if (!m_numberFormat) >- return throwException(&state, scope, createError(&state, ASCIILiteral("Failed to format a number."))); >- } >+ // FormatNumber (numberFormat, x) (ECMA-402) >+ // https://tc39.github.io/ecma402/#sec-formatnumber >+ if (!m_initializedNumberFormat) >+ return throwTypeError(&state, scope, ASCIILiteral("Intl.NumberFormat.prototype.format called on value that's not an object initialized as a NumberFormat")); > > // Map negative zero to positive zero. > if (!number) >@@ -504,9 +492,7 @@ JSValue IntlNumberFormat::formatToParts(ExecState& exec, double value) > // https://tc39.github.io/ecma402/#sec-formatnumbertoparts > // https://tc39.github.io/ecma402/#sec-partitionnumberpattern > >- if (!m_numberFormat) >- createNumberFormat(exec); >- if (!m_initializedNumberFormat || !m_numberFormat) >+ if (!m_initializedNumberFormat) > return throwTypeError(&exec, scope, ASCIILiteral("Intl.NumberFormat.prototype.formatToParts called on value that's not an object initialized as a NumberFormat")); > > UErrorCode status = U_ZERO_ERROR; >diff --git a/Source/JavaScriptCore/runtime/IntlNumberFormat.h b/Source/JavaScriptCore/runtime/IntlNumberFormat.h >index c36bd727433b2067111698f619cc47297ede8e82..443343c50a5cf1d53a3a8dfeee5aee42312bf5a9 100644 >--- a/Source/JavaScriptCore/runtime/IntlNumberFormat.h >+++ b/Source/JavaScriptCore/runtime/IntlNumberFormat.h >@@ -71,7 +71,6 @@ private: > void operator()(UNumberFormat*) const; > }; > >- void createNumberFormat(ExecState&); > static const char* styleString(Style); > static const char* currencyDisplayString(CurrencyDisplay); > >diff --git a/Source/JavaScriptCore/runtime/IntlObject.cpp b/Source/JavaScriptCore/runtime/IntlObject.cpp >index 68e0ca8ae1759e6c13024f70f872bbd8208b68ae..0684feb3958dce45b000b0c88ec1f019e3d20215 100644 >--- a/Source/JavaScriptCore/runtime/IntlObject.cpp >+++ b/Source/JavaScriptCore/runtime/IntlObject.cpp >@@ -201,6 +201,17 @@ unsigned intlNumberOption(ExecState& state, JSValue options, PropertyName proper > JSValue value = opts->get(&state, property); > RETURN_IF_EXCEPTION(scope, 0); > >+ return intlDefaultNumberOption(state, value, property, minimum, maximum, fallback); >+} >+ >+unsigned intlDefaultNumberOption(ExecState& state, JSValue value, PropertyName property, unsigned minimum, unsigned maximum, unsigned fallback) >+{ >+ // DefaultNumberOption (value, minimum, maximum, fallback) >+ // https://tc39.github.io/ecma402/#sec-defaultnumberoption >+ >+ VM& vm = state.vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ > if (!value.isUndefined()) { > double doubleValue = value.toNumber(&state); > RETURN_IF_EXCEPTION(scope, 0); >@@ -261,6 +272,397 @@ static String privateUseLangTag(const Vector<String>& parts, size_t startIndex) > return privateuse.toString(); > } > >+static String preferredLanguageFor(const String& language) >+{ >+ // Mappings from language tags to preferred values. >+ // https://www.iana.org/assignments/language-subtag-registry >+ // FIXME: convert to a compile time hash table if this is causing performance issues. >+ HashMap<String, String> map = { >+ { ASCIILiteral("aam"), ASCIILiteral("aas") }, >+ { ASCIILiteral("adp"), ASCIILiteral("dz") }, >+ { ASCIILiteral("aue"), ASCIILiteral("ktz") }, >+ { ASCIILiteral("ayx"), ASCIILiteral("nun") }, >+ { ASCIILiteral("bgm"), ASCIILiteral("bcg") }, >+ { ASCIILiteral("bjd"), ASCIILiteral("drl") }, >+ { ASCIILiteral("ccq"), ASCIILiteral("rki") }, >+ { ASCIILiteral("cjr"), ASCIILiteral("mom") }, >+ { ASCIILiteral("cka"), ASCIILiteral("cmr") }, >+ { ASCIILiteral("cmk"), ASCIILiteral("xch") }, >+ { ASCIILiteral("coy"), ASCIILiteral("pij") }, >+ { ASCIILiteral("cqu"), ASCIILiteral("quh") }, >+ { ASCIILiteral("drh"), ASCIILiteral("khk") }, >+ { ASCIILiteral("drw"), ASCIILiteral("prs") }, >+ { ASCIILiteral("gav"), ASCIILiteral("dev") }, >+ { ASCIILiteral("gfx"), ASCIILiteral("vaj") }, >+ { ASCIILiteral("ggn"), ASCIILiteral("gvr") }, >+ { ASCIILiteral("gti"), ASCIILiteral("nyc") }, >+ { ASCIILiteral("guv"), ASCIILiteral("duz") }, >+ { ASCIILiteral("hrr"), ASCIILiteral("jal") }, >+ { ASCIILiteral("ibi"), ASCIILiteral("opa") }, >+ { ASCIILiteral("ilw"), ASCIILiteral("gal") }, >+ { ASCIILiteral("in"), ASCIILiteral("id") }, >+ { ASCIILiteral("iw"), ASCIILiteral("he") }, >+ { ASCIILiteral("jeg"), ASCIILiteral("oyb") }, >+ { ASCIILiteral("ji"), ASCIILiteral("yi") }, >+ { ASCIILiteral("jw"), ASCIILiteral("jv") }, >+ { ASCIILiteral("kgc"), ASCIILiteral("tdf") }, >+ { ASCIILiteral("kgh"), ASCIILiteral("kml") }, >+ { ASCIILiteral("koj"), ASCIILiteral("kwv") }, >+ { ASCIILiteral("krm"), ASCIILiteral("bmf") }, >+ { ASCIILiteral("ktr"), ASCIILiteral("dtp") }, >+ { ASCIILiteral("kvs"), ASCIILiteral("gdj") }, >+ { ASCIILiteral("kwq"), ASCIILiteral("yam") }, >+ { ASCIILiteral("kxe"), ASCIILiteral("tvd") }, >+ { ASCIILiteral("kzj"), ASCIILiteral("dtp") }, >+ { ASCIILiteral("kzt"), ASCIILiteral("dtp") }, >+ { ASCIILiteral("lii"), ASCIILiteral("raq") }, >+ { ASCIILiteral("lmm"), ASCIILiteral("rmx") }, >+ { ASCIILiteral("meg"), ASCIILiteral("cir") }, >+ { ASCIILiteral("mo"), ASCIILiteral("ro") }, >+ { ASCIILiteral("mst"), ASCIILiteral("mry") }, >+ { ASCIILiteral("mwj"), ASCIILiteral("vaj") }, >+ { ASCIILiteral("myt"), ASCIILiteral("mry") }, >+ { ASCIILiteral("nad"), ASCIILiteral("xny") }, >+ { ASCIILiteral("ncp"), ASCIILiteral("kdz") }, >+ { ASCIILiteral("nnx"), ASCIILiteral("ngv") }, >+ { ASCIILiteral("nts"), ASCIILiteral("pij") }, >+ { ASCIILiteral("oun"), ASCIILiteral("vaj") }, >+ { ASCIILiteral("pcr"), ASCIILiteral("adx") }, >+ { ASCIILiteral("pmc"), ASCIILiteral("huw") }, >+ { ASCIILiteral("pmu"), ASCIILiteral("phr") }, >+ { ASCIILiteral("ppa"), ASCIILiteral("bfy") }, >+ { ASCIILiteral("ppr"), ASCIILiteral("lcq") }, >+ { ASCIILiteral("pry"), ASCIILiteral("prt") }, >+ { ASCIILiteral("puz"), ASCIILiteral("pub") }, >+ { ASCIILiteral("sca"), ASCIILiteral("hle") }, >+ { ASCIILiteral("skk"), ASCIILiteral("oyb") }, >+ { ASCIILiteral("tdu"), ASCIILiteral("dtp") }, >+ { ASCIILiteral("thc"), ASCIILiteral("tpo") }, >+ { ASCIILiteral("thx"), ASCIILiteral("oyb") }, >+ { ASCIILiteral("tie"), ASCIILiteral("ras") }, >+ { ASCIILiteral("tkk"), ASCIILiteral("twm") }, >+ { ASCIILiteral("tlw"), ASCIILiteral("weo") }, >+ { ASCIILiteral("tmp"), ASCIILiteral("tyj") }, >+ { ASCIILiteral("tne"), ASCIILiteral("kak") }, >+ { ASCIILiteral("tnf"), ASCIILiteral("prs") }, >+ { ASCIILiteral("tsf"), ASCIILiteral("taj") }, >+ { ASCIILiteral("uok"), ASCIILiteral("ema") }, >+ { ASCIILiteral("xba"), ASCIILiteral("cax") }, >+ { ASCIILiteral("xia"), ASCIILiteral("acn") }, >+ { ASCIILiteral("xkh"), ASCIILiteral("waw") }, >+ { ASCIILiteral("xsj"), ASCIILiteral("suj") }, >+ { ASCIILiteral("ybd"), ASCIILiteral("rki") }, >+ { ASCIILiteral("yma"), ASCIILiteral("lrr") }, >+ { ASCIILiteral("ymt"), ASCIILiteral("mtm") }, >+ { ASCIILiteral("yos"), ASCIILiteral("zom") }, >+ { ASCIILiteral("yuu"), ASCIILiteral("yug") } >+ }; >+ auto preferred = map.get(language); >+ if (!preferred.isNull()) >+ return preferred; >+ return language; >+} >+ >+static bool shouldExtLangReplaceLanguage(const String& extlang, const String& language) >+{ >+ // Deprecated extlang are of form {lang}-{extlang}, and should be just {extlang}. >+ // https://www.iana.org/assignments/language-subtag-registry >+ // FIXME: convert to a compile time hash table if this is causing performance issues. >+ HashMap<String, String> map = { >+ { ASCIILiteral("aao"), ASCIILiteral("ar") }, >+ { ASCIILiteral("abh"), ASCIILiteral("ar") }, >+ { ASCIILiteral("abv"), ASCIILiteral("ar") }, >+ { ASCIILiteral("acm"), ASCIILiteral("ar") }, >+ { ASCIILiteral("acq"), ASCIILiteral("ar") }, >+ { ASCIILiteral("acw"), ASCIILiteral("ar") }, >+ { ASCIILiteral("acx"), ASCIILiteral("ar") }, >+ { ASCIILiteral("acy"), ASCIILiteral("ar") }, >+ { ASCIILiteral("adf"), ASCIILiteral("ar") }, >+ { ASCIILiteral("ads"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("aeb"), ASCIILiteral("ar") }, >+ { ASCIILiteral("aec"), ASCIILiteral("ar") }, >+ { ASCIILiteral("aed"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("aen"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("afb"), ASCIILiteral("ar") }, >+ { ASCIILiteral("afg"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("ajp"), ASCIILiteral("ar") }, >+ { ASCIILiteral("apc"), ASCIILiteral("ar") }, >+ { ASCIILiteral("apd"), ASCIILiteral("ar") }, >+ { ASCIILiteral("arb"), ASCIILiteral("ar") }, >+ { ASCIILiteral("arq"), ASCIILiteral("ar") }, >+ { ASCIILiteral("ars"), ASCIILiteral("ar") }, >+ { ASCIILiteral("ary"), ASCIILiteral("ar") }, >+ { ASCIILiteral("arz"), ASCIILiteral("ar") }, >+ { ASCIILiteral("ase"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("asf"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("asp"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("asq"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("asw"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("auz"), ASCIILiteral("ar") }, >+ { ASCIILiteral("avl"), ASCIILiteral("ar") }, >+ { ASCIILiteral("ayh"), ASCIILiteral("ar") }, >+ { ASCIILiteral("ayl"), ASCIILiteral("ar") }, >+ { ASCIILiteral("ayn"), ASCIILiteral("ar") }, >+ { ASCIILiteral("ayp"), ASCIILiteral("ar") }, >+ { ASCIILiteral("bbz"), ASCIILiteral("ar") }, >+ { ASCIILiteral("bfi"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("bfk"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("bjn"), ASCIILiteral("ms") }, >+ { ASCIILiteral("bog"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("bqn"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("bqy"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("btj"), ASCIILiteral("ms") }, >+ { ASCIILiteral("bve"), ASCIILiteral("ms") }, >+ { ASCIILiteral("bvl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("bvu"), ASCIILiteral("ms") }, >+ { ASCIILiteral("bzs"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("cdo"), ASCIILiteral("zh") }, >+ { ASCIILiteral("cds"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("cjy"), ASCIILiteral("zh") }, >+ { ASCIILiteral("cmn"), ASCIILiteral("zh") }, >+ { ASCIILiteral("coa"), ASCIILiteral("ms") }, >+ { ASCIILiteral("cpx"), ASCIILiteral("zh") }, >+ { ASCIILiteral("csc"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("csd"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("cse"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("csf"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("csg"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("csl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("csn"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("csq"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("csr"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("czh"), ASCIILiteral("zh") }, >+ { ASCIILiteral("czo"), ASCIILiteral("zh") }, >+ { ASCIILiteral("doq"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("dse"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("dsl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("dup"), ASCIILiteral("ms") }, >+ { ASCIILiteral("ecs"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("esl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("esn"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("eso"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("eth"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("fcs"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("fse"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("fsl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("fss"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("gan"), ASCIILiteral("zh") }, >+ { ASCIILiteral("gds"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("gom"), ASCIILiteral("kok") }, >+ { ASCIILiteral("gse"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("gsg"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("gsm"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("gss"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("gus"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("hab"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("haf"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("hak"), ASCIILiteral("zh") }, >+ { ASCIILiteral("hds"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("hji"), ASCIILiteral("ms") }, >+ { ASCIILiteral("hks"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("hos"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("hps"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("hsh"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("hsl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("hsn"), ASCIILiteral("zh") }, >+ { ASCIILiteral("icl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("iks"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("ils"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("inl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("ins"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("ise"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("isg"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("isr"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("jak"), ASCIILiteral("ms") }, >+ { ASCIILiteral("jax"), ASCIILiteral("ms") }, >+ { ASCIILiteral("jcs"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("jhs"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("jls"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("jos"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("jsl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("jus"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("kgi"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("knn"), ASCIILiteral("kok") }, >+ { ASCIILiteral("kvb"), ASCIILiteral("ms") }, >+ { ASCIILiteral("kvk"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("kvr"), ASCIILiteral("ms") }, >+ { ASCIILiteral("kxd"), ASCIILiteral("ms") }, >+ { ASCIILiteral("lbs"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("lce"), ASCIILiteral("ms") }, >+ { ASCIILiteral("lcf"), ASCIILiteral("ms") }, >+ { ASCIILiteral("liw"), ASCIILiteral("ms") }, >+ { ASCIILiteral("lls"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("lsl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("lso"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("lsp"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("lst"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("lsy"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("ltg"), ASCIILiteral("lv") }, >+ { ASCIILiteral("lvs"), ASCIILiteral("lv") }, >+ { ASCIILiteral("lws"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("lzh"), ASCIILiteral("zh") }, >+ { ASCIILiteral("max"), ASCIILiteral("ms") }, >+ { ASCIILiteral("mdl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("meo"), ASCIILiteral("ms") }, >+ { ASCIILiteral("mfa"), ASCIILiteral("ms") }, >+ { ASCIILiteral("mfb"), ASCIILiteral("ms") }, >+ { ASCIILiteral("mfs"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("min"), ASCIILiteral("ms") }, >+ { ASCIILiteral("mnp"), ASCIILiteral("zh") }, >+ { ASCIILiteral("mqg"), ASCIILiteral("ms") }, >+ { ASCIILiteral("mre"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("msd"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("msi"), ASCIILiteral("ms") }, >+ { ASCIILiteral("msr"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("mui"), ASCIILiteral("ms") }, >+ { ASCIILiteral("mzc"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("mzg"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("mzy"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("nan"), ASCIILiteral("zh") }, >+ { ASCIILiteral("nbs"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("ncs"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("nsi"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("nsl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("nsp"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("nsr"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("nzs"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("okl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("orn"), ASCIILiteral("ms") }, >+ { ASCIILiteral("ors"), ASCIILiteral("ms") }, >+ { ASCIILiteral("pel"), ASCIILiteral("ms") }, >+ { ASCIILiteral("pga"), ASCIILiteral("ar") }, >+ { ASCIILiteral("pgz"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("pks"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("prl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("prz"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("psc"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("psd"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("pse"), ASCIILiteral("ms") }, >+ { ASCIILiteral("psg"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("psl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("pso"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("psp"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("psr"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("pys"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("rms"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("rsl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("rsm"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("sdl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("sfb"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("sfs"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("sgg"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("sgx"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("shu"), ASCIILiteral("ar") }, >+ { ASCIILiteral("slf"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("sls"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("sqk"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("sqs"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("ssh"), ASCIILiteral("ar") }, >+ { ASCIILiteral("ssp"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("ssr"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("svk"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("swc"), ASCIILiteral("sw") }, >+ { ASCIILiteral("swh"), ASCIILiteral("sw") }, >+ { ASCIILiteral("swl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("syy"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("szs"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("tmw"), ASCIILiteral("ms") }, >+ { ASCIILiteral("tse"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("tsm"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("tsq"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("tss"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("tsy"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("tza"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("ugn"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("ugy"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("ukl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("uks"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("urk"), ASCIILiteral("ms") }, >+ { ASCIILiteral("uzn"), ASCIILiteral("uz") }, >+ { ASCIILiteral("uzs"), ASCIILiteral("uz") }, >+ { ASCIILiteral("vgt"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("vkk"), ASCIILiteral("ms") }, >+ { ASCIILiteral("vkt"), ASCIILiteral("ms") }, >+ { ASCIILiteral("vsi"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("vsl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("vsv"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("wbs"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("wuu"), ASCIILiteral("zh") }, >+ { ASCIILiteral("xki"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("xml"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("xmm"), ASCIILiteral("ms") }, >+ { ASCIILiteral("xms"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("ygs"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("yhs"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("ysl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("yue"), ASCIILiteral("zh") }, >+ { ASCIILiteral("zib"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("zlm"), ASCIILiteral("ms") }, >+ { ASCIILiteral("zmi"), ASCIILiteral("ms") }, >+ { ASCIILiteral("zsl"), ASCIILiteral("sgn") }, >+ { ASCIILiteral("zsm"), ASCIILiteral("ms") } >+ }; >+ return map.get(extlang) == language; >+} >+ >+static String preferredRegionFor(const String& region) >+{ >+ // Map to preferred region subtag. >+ // https://www.iana.org/assignments/language-subtag-registry >+ // FIXME: convert to a compile time hash table if this is causing performance issues. >+ HashMap<String, String> map = { >+ { ASCIILiteral("BU"), ASCIILiteral("MM") }, >+ { ASCIILiteral("DD"), ASCIILiteral("DE") }, >+ { ASCIILiteral("FX"), ASCIILiteral("TL") }, >+ { ASCIILiteral("TP"), ASCIILiteral("YE") }, >+ { ASCIILiteral("YD"), ASCIILiteral("DE") }, >+ { ASCIILiteral("ZR"), ASCIILiteral("CD") } >+ }; >+ auto preferred = map.get(region); >+ if (!preferred.isNull()) >+ return preferred; >+ return region; >+ >+} >+ >+static String preferredLanguageTagFor(const String& tag) >+{ >+ // Map full language tags to preferred tags. >+ // https://www.iana.org/assignments/language-subtag-registry >+ // FIXME: convert to a compile time hash table if this is causing performance issues. >+ HashMap<String, String> map = { >+ // FIXME: These replacements should happen even when there are extra parts present, >+ // but this map only replaces if the whole tag matches. >+ { ASCIILiteral("hy-arevela"), ASCIILiteral("hy") }, >+ { ASCIILiteral("hy-arevmda"), ASCIILiteral("hyw") }, >+ { ASCIILiteral("ja-Latn-hepburn-heploc"), ASCIILiteral("ja-Latn-alalc97") }, >+ >+ { ASCIILiteral("sgn-BR"), ASCIILiteral("bzs") }, >+ { ASCIILiteral("sgn-CO"), ASCIILiteral("csn") }, >+ { ASCIILiteral("sgn-DE"), ASCIILiteral("gsg") }, >+ { ASCIILiteral("sgn-DK"), ASCIILiteral("dsl") }, >+ { ASCIILiteral("sgn-ES"), ASCIILiteral("ssp") }, >+ { ASCIILiteral("sgn-FR"), ASCIILiteral("fsl") }, >+ { ASCIILiteral("sgn-GB"), ASCIILiteral("bfi") }, >+ { ASCIILiteral("sgn-GR"), ASCIILiteral("gss") }, >+ { ASCIILiteral("sgn-IE"), ASCIILiteral("isg") }, >+ { ASCIILiteral("sgn-IT"), ASCIILiteral("ise") }, >+ { ASCIILiteral("sgn-JP"), ASCIILiteral("jsl") }, >+ { ASCIILiteral("sgn-MX"), ASCIILiteral("mfs") }, >+ { ASCIILiteral("sgn-NI"), ASCIILiteral("ncs") }, >+ { ASCIILiteral("sgn-NL"), ASCIILiteral("dse") }, >+ { ASCIILiteral("sgn-NO"), ASCIILiteral("nsl") }, >+ { ASCIILiteral("sgn-PT"), ASCIILiteral("psr") }, >+ { ASCIILiteral("sgn-SE"), ASCIILiteral("swl") }, >+ { ASCIILiteral("sgn-US"), ASCIILiteral("ase") }, >+ { ASCIILiteral("sgn-ZA"), ASCIILiteral("sfs") } >+ }; >+ const String preferred = map.get(tag); >+ if (!preferred.isNull()) >+ return preferred; >+ return tag; >+} >+ > static String canonicalLangTag(const Vector<String>& parts) > { > ASSERT(!parts.isEmpty()); >@@ -281,7 +683,8 @@ static String canonicalLangTag(const Vector<String>& parts) > > ++currentIndex; > StringBuilder canonical; >- canonical.append(language.convertToASCIILowercase()); >+ >+ canonical.append(preferredLanguageFor(language.convertToASCIILowercase())); > > // Check for extlang. > // extlang = 3ALPHA *2("-" 3ALPHA) >@@ -291,8 +694,16 @@ static String canonicalLangTag(const Vector<String>& parts) > unsigned extlangLength = extlang.length(); > if (extlangLength == 3 && extlang.isAllSpecialCharacters<isASCIIAlpha>()) { > ++currentIndex; >+ auto extlangLower = extlang.convertToASCIILowercase(); >+ if (!times) { >+ if (shouldExtLangReplaceLanguage(extlangLower, language)) { >+ canonical.clear(); >+ canonical.append(extlangLower); >+ continue; >+ } >+ } > canonical.append('-'); >- canonical.append(extlang.convertToASCIILowercase()); >+ canonical.append(extlangLower); > } else > break; > } >@@ -323,7 +734,7 @@ static String canonicalLangTag(const Vector<String>& parts) > if (isValidRegion) { > ++currentIndex; > canonical.append('-'); >- canonical.append(region.convertToASCIIUppercase()); >+ canonical.append(preferredRegionFor(region.convertToASCIIUppercase())); > } > } > >@@ -417,9 +828,7 @@ static String canonicalLangTag(const Vector<String>& parts) > canonical.append(privateuse); > } > >- // FIXME: Replace subtags with their preferred values. >- >- return canonical.toString(); >+ return preferredLanguageTagFor(canonical.toString()); > } > > static String grandfatheredLangTag(const String& locale) >@@ -428,7 +837,7 @@ static String grandfatheredLangTag(const String& locale) > // FIXME: convert to a compile time hash table if this is causing performance issues. > HashMap<String, String> tagMap = { > // Irregular. >- { ASCIILiteral("en-gb-oed"), ASCIILiteral("en-GB-oed") }, >+ { ASCIILiteral("en-gb-oed"), ASCIILiteral("en-GB-oxendict") }, > { ASCIILiteral("i-ami"), ASCIILiteral("ami") }, > { ASCIILiteral("i-bnn"), ASCIILiteral("bnn") }, > { ASCIILiteral("i-default"), ASCIILiteral("i-default") }, >@@ -611,10 +1020,13 @@ String removeUnicodeLocaleExtension(const String& locale) > locale.split('-', parts); > StringBuilder builder; > size_t partsSize = parts.size(); >+ bool atPrivate = false; > if (partsSize > 0) > builder.append(parts[0]); > for (size_t p = 1; p < partsSize; ++p) { >- if (parts[p] == "u" && p + 1 < partsSize) { >+ if (parts[p] == "x") >+ atPrivate = true; >+ if (!atPrivate && parts[p] == "u" && p + 1 < partsSize) { > // Skip the u- and anything that follows until another singleton. > // While the next part is part of the unicode extension, skip it. > while (p + 1 < partsSize && parts[p + 1].length() > 1) >@@ -878,7 +1290,12 @@ Vector<String> numberingSystemsForLocale(const String& locale) > // Numbering system names are always ASCII, so use char[]. > while (const char* result = uenum_next(numberingSystemNames, &resultLength, &status)) { > ASSERT(U_SUCCESS(status)); >- availableNumberingSystems.append(String(result, resultLength)); >+ auto numsys = unumsys_openByName(result, &status); >+ ASSERT(U_SUCCESS(status)); >+ // Only support algorithmic if it is the default fot the locale, handled below. >+ if (!unumsys_isAlgorithmic(numsys)) >+ availableNumberingSystems.append(String(result, resultLength)); >+ unumsys_close(numsys); > } > uenum_close(numberingSystemNames); > } >diff --git a/Source/JavaScriptCore/runtime/IntlObject.h b/Source/JavaScriptCore/runtime/IntlObject.h >index f2445f676b526e518dfdefb874eb53c83febaaf8..7e5386465d61841cc2e8f8d2487614e55bc38f95 100644 >--- a/Source/JavaScriptCore/runtime/IntlObject.h >+++ b/Source/JavaScriptCore/runtime/IntlObject.h >@@ -63,6 +63,7 @@ void convertICULocaleToBCP47LanguageTag(String& locale); > bool intlBooleanOption(ExecState&, JSValue options, PropertyName, bool& usesFallback); > String intlStringOption(ExecState&, JSValue options, PropertyName, std::initializer_list<const char*> values, const char* notFound, const char* fallback); > unsigned intlNumberOption(ExecState&, JSValue options, PropertyName, unsigned minimum, unsigned maximum, unsigned fallback); >+unsigned intlDefaultNumberOption(ExecState&, JSValue, PropertyName, unsigned minimum, unsigned maximum, unsigned fallback); > Vector<String> canonicalizeLocaleList(ExecState&, JSValue locales); > HashMap<String, String> resolveLocale(ExecState&, 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)); > JSValue supportedLocales(ExecState&, const HashSet<String>& availableLocales, const Vector<String>& requestedLocales, JSValue options); >diff --git a/Source/JavaScriptCore/runtime/IntlPluralRules.cpp b/Source/JavaScriptCore/runtime/IntlPluralRules.cpp >index 4ded13b42f35e32cd896e6e8c13e1c1b1313ec3d..babf82b5f147abb3abf7174312befdb6aeba9e06 100644 >--- a/Source/JavaScriptCore/runtime/IntlPluralRules.cpp >+++ b/Source/JavaScriptCore/runtime/IntlPluralRules.cpp >@@ -114,7 +114,7 @@ void IntlPluralRules::initializePluralRules(ExecState& exec, JSValue locales, JS > > JSObject* options; > if (optionsValue.isUndefined()) >- options = constructEmptyObject(&exec); >+ options = constructEmptyObject(&exec, exec.lexicalGlobalObject()->nullPrototypeObjectStructure()); > else { > options = optionsValue.toObject(&exec); > RETURN_IF_EXCEPTION(scope, void()); >diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >index 69b537eb5d6e921e72d46850e196c0aa2df94632..cd892ed2a3aa2035ebed9af6ec4ce50b769862f8 100644 >--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >@@ -1549,6 +1549,20 @@ void JSGlobalObject::setName(const String& name) > } > > # if ENABLE(INTL) >+static void addMissingScriptLocales(HashSet<String>& availableLocales) >+{ >+ if (availableLocales.contains("pa-Arab-PK")) >+ availableLocales.add(ASCIILiteral("pa-PK")); >+ if (availableLocales.contains("zh-Hans-CN")) >+ availableLocales.add(ASCIILiteral("zh-CN")); >+ if (availableLocales.contains("zh-Hant-HK")) >+ availableLocales.add(ASCIILiteral("zh-HK")); >+ if (availableLocales.contains("zh-Hans-SG")) >+ availableLocales.add(ASCIILiteral("zh-SG")); >+ if (availableLocales.contains("zh-Hant-TW")) >+ availableLocales.add(ASCIILiteral("zh-TW")); >+} >+ > const HashSet<String>& JSGlobalObject::intlCollatorAvailableLocales() > { > if (m_intlCollatorAvailableLocales.isEmpty()) { >@@ -1558,6 +1572,7 @@ const HashSet<String>& JSGlobalObject::intlCollatorAvailableLocales() > convertICULocaleToBCP47LanguageTag(locale); > m_intlCollatorAvailableLocales.add(locale); > } >+ addMissingScriptLocales(m_intlCollatorAvailableLocales); > } > return m_intlCollatorAvailableLocales; > } >@@ -1571,6 +1586,7 @@ const HashSet<String>& JSGlobalObject::intlDateTimeFormatAvailableLocales() > convertICULocaleToBCP47LanguageTag(locale); > m_intlDateTimeFormatAvailableLocales.add(locale); > } >+ addMissingScriptLocales(m_intlDateTimeFormatAvailableLocales); > } > return m_intlDateTimeFormatAvailableLocales; > } >@@ -1584,6 +1600,7 @@ const HashSet<String>& JSGlobalObject::intlNumberFormatAvailableLocales() > convertICULocaleToBCP47LanguageTag(locale); > m_intlNumberFormatAvailableLocales.add(locale); > } >+ addMissingScriptLocales(m_intlNumberFormatAvailableLocales); > } > return m_intlNumberFormatAvailableLocales; > } >@@ -1597,6 +1614,7 @@ const HashSet<String>& JSGlobalObject::intlPluralRulesAvailableLocales() > convertICULocaleToBCP47LanguageTag(locale); > m_intlPluralRulesAvailableLocales.add(locale); > } >+ addMissingScriptLocales(m_intlPluralRulesAvailableLocales); > } > return m_intlPluralRulesAvailableLocales; > } >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index a261cb3715e8ef9e3ac9e7787282de6b1e04fba3..e8cc1f55ddbd9041c876b66adbe73f7b44b3bc7c 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,14 @@ >+2018-05-21 Andy VanWagoner <andy@vanwagoner.family> >+ >+ [INTL] Language tags are not canonicalized >+ https://bugs.webkit.org/show_bug.cgi?id=185836 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Use gregory instead of gregorian, matching test262/intl402 and other engines. >+ >+ * js/script-tests/intl-datetimeformat.js: >+ > 2018-05-18 Commit Queue <commit-queue@webkit.org> > > Unreviewed, rolling out r231982. >diff --git a/LayoutTests/js/script-tests/intl-datetimeformat.js b/LayoutTests/js/script-tests/intl-datetimeformat.js >index a006993ab71081ad413807a65b99cf53cbb2f141..6bd7ae9c95b42db49158fa4152de7fbcafda656a 100644 >--- a/LayoutTests/js/script-tests/intl-datetimeformat.js >+++ b/LayoutTests/js/script-tests/intl-datetimeformat.js >@@ -263,9 +263,9 @@ shouldBe("Intl.DateTimeFormat('ar-sa').resolvedOptions().locale", "'ar-SA'"); > shouldBe("Intl.DateTimeFormat('fa-IR').resolvedOptions().calendar", "'persian'"); > shouldBe("Intl.DateTimeFormat('ar').resolvedOptions().numberingSystem", "'arab'"); > >-shouldBe("Intl.DateTimeFormat('en', { calendar:'dangi' }).resolvedOptions().calendar", "'gregorian'"); >+shouldBe("Intl.DateTimeFormat('en', { calendar:'dangi' }).resolvedOptions().calendar", "'gregory'"); > shouldBe("Intl.DateTimeFormat('en-u-ca-bogus').resolvedOptions().locale", "'en'"); >-shouldBe("Intl.DateTimeFormat('en-u-ca-bogus').resolvedOptions().calendar", "'gregorian'"); >+shouldBe("Intl.DateTimeFormat('en-u-ca-bogus').resolvedOptions().calendar", "'gregory'"); > shouldBe("Intl.DateTimeFormat('en-u-ca-buddhist').resolvedOptions().locale", "'en-u-ca-buddhist'"); > shouldBe("Intl.DateTimeFormat('en-u-ca-buddhist').resolvedOptions().calendar", "'buddhist'"); > shouldBe("Intl.DateTimeFormat('en-u-ca-chinese').resolvedOptions().calendar", "'chinese'"); >@@ -273,7 +273,7 @@ shouldBe("Intl.DateTimeFormat('en-u-ca-coptic').resolvedOptions().calendar", "'c > shouldBe("Intl.DateTimeFormat('en-u-ca-dangi').resolvedOptions().calendar", "'dangi'"); > shouldBe("Intl.DateTimeFormat('en-u-ca-ethioaa').resolvedOptions().calendar", "'ethiopic-amete-alem'"); > shouldBe("Intl.DateTimeFormat('en-u-ca-ethiopic').resolvedOptions().calendar", "'ethiopic'"); >-shouldBe("Intl.DateTimeFormat('ar-SA-u-ca-gregory').resolvedOptions().calendar", "'gregorian'"); >+shouldBe("Intl.DateTimeFormat('ar-SA-u-ca-gregory').resolvedOptions().calendar", "'gregory'"); > shouldBe("Intl.DateTimeFormat('en-u-ca-hebrew').resolvedOptions().calendar", "'hebrew'"); > shouldBe("Intl.DateTimeFormat('en-u-ca-indian').resolvedOptions().calendar", "'indian'"); > shouldBe("Intl.DateTimeFormat('en-u-ca-islamic').resolvedOptions().calendar", "'islamic'"); >diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog >index b6ad0467d35298f789aae755fbad821b258773b6..1b78169fa1ae4705a6ef9e9b9edb3c99833a4d83 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,14 @@ >+2018-05-21 Andy VanWagoner <andy@vanwagoner.family> >+ >+ [INTL] Language tags are not canonicalized >+ https://bugs.webkit.org/show_bug.cgi?id=185836 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Remove expected failures that have been fixed. >+ >+ * test262/expectations.yaml: >+ > 2018-05-18 Keith Miller <keith_miller@apple.com> > > op_in should mark if it sees out of bounds accesses >diff --git a/JSTests/test262/expectations.yaml b/JSTests/test262/expectations.yaml >index ee0b3801600a254346402a1620e8878091611272..10af60c1112e3c37d55fd4004b1f90bef8734788 100644 >--- a/JSTests/test262/expectations.yaml >+++ b/JSTests/test262/expectations.yaml >@@ -1853,42 +1853,24 @@ test/intl402/Collator/length.js: > test/intl402/Collator/prototype/compare/compare-function-name.js: > default: 'Test262Error: Expected SameValue(ëtrueû, ëfalseû) to be true' > strict mode: 'Test262Error: Expected SameValue(ëtrueû, ëfalseû) to be true' >-test/intl402/Collator/unicode-ext-seq-in-private-tag.js: >- default: 'Test262Error: Expected SameValue(ëphonebkû, ëdefaultû) to be true' >- strict mode: 'Test262Error: Expected SameValue(ëphonebkû, ëdefaultû) to be true' > test/intl402/DateTimeFormat/length.js: > default: 'Test262Error: Expected obj[length] to have configurable:true.' > strict mode: 'Test262Error: Expected obj[length] to have configurable:true.' > test/intl402/DateTimeFormat/prototype/format/format-function-name.js: > default: 'Test262Error: Expected SameValue(ëtrueû, ëfalseû) to be true' > strict mode: 'Test262Error: Expected SameValue(ëtrueû, ëfalseû) to be true' >-test/intl402/DateTimeFormat/prototype/format/proleptic-gregorian-calendar.js: >- default: "Test262Error: Internal error: Didn't find Gregorian calendar Expected SameValue(ëgregorianû, ëgregoryû) to be true" >- strict mode: "Test262Error: Internal error: Didn't find Gregorian calendar Expected SameValue(ëgregorianû, ëgregoryû) to be true" > test/intl402/DateTimeFormat/prototype/formatToParts/length.js: > default: 'Test262Error: Expected SameValue(ë0û, ë1û) to be true' > strict mode: 'Test262Error: Expected SameValue(ë0û, ë1û) to be true' >-test/intl402/DateTimeFormat/prototype/resolvedOptions/basic.js: >- default: 'Test262Error: Invalid calendar: gregorian Expected SameValue(ë-1û, ë-1û) to be false' >- strict mode: 'Test262Error: Invalid calendar: gregorian Expected SameValue(ë-1û, ë-1û) to be false' > test/intl402/DateTimeFormat/prototype/resolvedOptions/hourCycle.js: > default: 'Test262Error: Expected SameValue(ëundefinedû, ëh11û) to be true' > strict mode: 'Test262Error: Expected SameValue(ëundefinedû, ëh11û) to be true' > test/intl402/DateTimeFormat/prototype/resolvedOptions/resolved-locale-with-hc-unicode.js: > default: 'Test262Error: Only hc Unicode extension value is present. (With hour option.) Expected SameValue(ëen-USû, ëen-US-u-hc-h11û) to be true' > strict mode: 'Test262Error: Only hc Unicode extension value is present. (With hour option.) Expected SameValue(ëen-USû, ëen-US-u-hc-h11û) to be true' >-test/intl402/Intl/getCanonicalLocales/canonicalized-tags.js: >- default: 'Test262Error: Expected SameValue(ësgn-GRû, ëgssû) to be true' >- strict mode: 'Test262Error: Expected SameValue(ësgn-GRû, ëgssû) to be true' > test/intl402/Intl/getCanonicalLocales/invalid-tags.js: > default: 'Test262Error: Test data "de-gregory-gregory" is a canonicalized and structurally valid language tag.' > strict mode: 'Test262Error: Test data "de-gregory-gregory" is a canonicalized and structurally valid language tag.' >-test/intl402/Intl/getCanonicalLocales/preferred-grandfathered.js: >- default: 'Test262Error: Expected SameValue(ëen-GB-oedû, ëen-GB-oxendictû) to be true' >- strict mode: 'Test262Error: Expected SameValue(ëen-GB-oedû, ëen-GB-oxendictû) to be true' >-test/intl402/Intl/getCanonicalLocales/preferred-variant.js: >- default: 'Test262Error: Expected SameValue(ëja-Latn-hepburn-heplocû, ëja-Latn-alalc97û) to be true' >- strict mode: 'Test262Error: Expected SameValue(ëja-Latn-hepburn-heplocû, ëja-Latn-alalc97û) to be true' > test/intl402/Locale/constructor-options-calendar-invalid.js: > default: 'Test262Error: is an invalid calendar option value Expected a RangeError but got a TypeError' > strict mode: 'Test262Error: is an invalid calendar option value Expected a RangeError but got a TypeError' >@@ -1952,15 +1934,9 @@ test/intl402/Locale/prototype/prop-desc.js: > test/intl402/Locale/prototype/toStringTag.js: > default: "TypeError: undefined is not an object (evaluating 'Intl.Locale.prototype')" > strict mode: "TypeError: undefined is not an object (evaluating 'Intl.Locale.prototype')" >-test/intl402/Number/prototype/toLocaleString/returns-same-results-as-NumberFormat.js: >- default: 'Error: Failed to format a number.' >- strict mode: 'Error: Failed to format a number.' > test/intl402/NumberFormat/length.js: > default: 'Test262Error: Expected obj[length] to have configurable:true.' > strict mode: 'Test262Error: Expected obj[length] to have configurable:true.' >-test/intl402/NumberFormat/prototype/format/bound-to-numberformat-instance.js: >- default: 'Error: Failed to format a number.' >- strict mode: 'Error: Failed to format a number.' > test/intl402/NumberFormat/prototype/format/format-fraction-digits.js: > default: 'Test262Error: Formatted value for 12344501000000000000000000000000000, en-US-u-nu-arab and options {"useGrouping":false,"minimumIntegerDigits":3,"minimumFractionDigits":1,"maximumFractionDigits":3} is áâãääÃ¥àáàààààààààààààààààààààààààààëà; expected áâãääÃ¥àáàààààààààäèçèáÃ¥äääæçèãááéãæëà.' > strict mode: 'Test262Error: Formatted value for 12344501000000000000000000000000000, en-US-u-nu-arab and options {"useGrouping":false,"minimumIntegerDigits":3,"minimumFractionDigits":1,"maximumFractionDigits":3} is áâãääÃ¥àáàààààààààààààààààààààààààààëà; expected áâãääÃ¥àáàààààààààäèçèáÃ¥äääæçèãááéãæëà.' >@@ -1988,24 +1964,12 @@ test/intl402/NumberFormat/prototype/formatToParts/name.js: > test/intl402/NumberFormat/prototype/formatToParts/return-abrupt-tonumber.js: > default: 'Test262Error: valueOf Expected a Test262Error but got a TypeError' > strict mode: 'Test262Error: valueOf Expected a Test262Error but got a TypeError' >-test/intl402/NumberFormat/significant-digits-options-get-sequence.js: >- default: 'Test262Error: minimumSignificantDigits getter already called Expected SameValue(ëtrueû, ëfalseû) to be true' >- strict mode: 'Test262Error: minimumSignificantDigits getter already called Expected SameValue(ëtrueû, ëfalseû) to be true' >-test/intl402/PluralRules/default-options-object-prototype.js: >- default: 'Test262Error: Expected SameValue(ëordinalû, ëcardinalû) to be true' >- strict mode: 'Test262Error: Expected SameValue(ëordinalû, ëcardinalû) to be true' > test/intl402/PluralRules/length.js: > default: 'Test262Error: Expected obj[length] to have configurable:true.' > strict mode: 'Test262Error: Expected obj[length] to have configurable:true.' > test/intl402/TypedArray/prototype/toLocaleString/calls-toLocaleString-number-elements.js: > default: 'Test262Error: Expected SameValue(ë0û, Ã«à ¹Â.à ¹Âà ¹Âà ¹Âû) to be true (Testing with Float64Array.)' > strict mode: 'Test262Error: Expected SameValue(ë0û, Ã«à ¹Â.à ¹Âà ¹Âà ¹Âû) to be true (Testing with Float64Array.)' >-test/intl402/fallback-locales-are-supported.js: >- default: "Test262Error: Locale zh-Hans-CN is supported, but fallback zh-CN isn't. Expected SameValue(ë-1û, ë-1û) to be false (Testing with NumberFormat.)" >- strict mode: "Test262Error: Locale zh-Hans-CN is supported, but fallback zh-CN isn't. Expected SameValue(ë-1û, ë-1û) to be false (Testing with NumberFormat.)" >-test/intl402/language-tags-canonicalized.js: >- default: 'Test262Error: For de-DD got de-DD; expected de-DE. (Testing with Collator.)' >- strict mode: 'Test262Error: For de-DD got de-DD; expected de-DE. (Testing with Collator.)' > test/language/arguments-object/mapped/nonconfigurable-nonenumerable-nonwritable-descriptors-set-by-arguments.js: > default: 'Test262Error: Expected obj[0] to have enumerable:false.' > test/language/arguments-object/mapped/nonconfigurable-nonenumerable-nonwritable-descriptors-set-by-param.js:
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 185836
:
340884
|
340902
|
340904
|
340911
|
340912
|
341106
|
341113
|
341131
|
343739
|
343802
|
344285
|
344292
|
345573
|
345599
|
345600