Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/js/i18n.js

Issue 1812673005: Use ICU case conversion/transliterator for case conversion behind a flag (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Yang's comment addressed - return right away for no-change Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // ECMAScript 402 API implementation. 5 // ECMAScript 402 API implementation.
6 6
7 /** 7 /**
8 * Intl object is a single object that has some named properties, 8 * Intl object is a single object that has some named properties,
9 * all of which are constructors. 9 * all of which are constructors.
10 */ 10 */
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 'numberformat': UNDEFINED, 135 'numberformat': UNDEFINED,
136 'dateformat': UNDEFINED, 136 'dateformat': UNDEFINED,
137 'breakiterator': UNDEFINED 137 'breakiterator': UNDEFINED
138 }; 138 };
139 139
140 /** 140 /**
141 * Caches default ICU locale. 141 * Caches default ICU locale.
142 */ 142 */
143 var DEFAULT_ICU_LOCALE = UNDEFINED; 143 var DEFAULT_ICU_LOCALE = UNDEFINED;
144 144
145 function GetDefaultICULocaleJS() {
146 if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) {
147 DEFAULT_ICU_LOCALE = %GetDefaultICULocale();
148 }
149 return DEFAULT_ICU_LOCALE;
150 }
151
145 /** 152 /**
146 * Unicode extension regular expression. 153 * Unicode extension regular expression.
147 */ 154 */
148 var UNICODE_EXTENSION_RE = UNDEFINED; 155 var UNICODE_EXTENSION_RE = UNDEFINED;
149 156
150 function GetUnicodeExtensionRE() { 157 function GetUnicodeExtensionRE() {
151 if (IS_UNDEFINED(UNDEFINED)) { 158 if (IS_UNDEFINED(UNDEFINED)) {
152 UNICODE_EXTENSION_RE = new GlobalRegExp('-u(-[a-z0-9]{2,8})+', 'g'); 159 UNICODE_EXTENSION_RE = new GlobalRegExp('-u(-[a-z0-9]{2,8})+', 'g');
153 } 160 }
154 return UNICODE_EXTENSION_RE; 161 return UNICODE_EXTENSION_RE;
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 // Truncate locale if possible. 446 // Truncate locale if possible.
440 var pos = %_Call(StringLastIndexOf, locale, '-'); 447 var pos = %_Call(StringLastIndexOf, locale, '-');
441 if (pos === -1) { 448 if (pos === -1) {
442 break; 449 break;
443 } 450 }
444 locale = %_Call(StringSubstring, locale, 0, pos); 451 locale = %_Call(StringSubstring, locale, 0, pos);
445 } while (true); 452 } while (true);
446 } 453 }
447 454
448 // Didn't find a match, return default. 455 // Didn't find a match, return default.
449 if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) { 456 return {'locale': GetDefaultICULocaleJS(), 'extension': '', 'position': -1};
450 DEFAULT_ICU_LOCALE = %GetDefaultICULocale();
451 }
452
453 return {'locale': DEFAULT_ICU_LOCALE, 'extension': '', 'position': -1};
454 } 457 }
455 458
456 459
457 /** 460 /**
458 * Returns best matched supported locale and extension info using 461 * Returns best matched supported locale and extension info using
459 * implementation dependend algorithm. 462 * implementation dependend algorithm.
460 */ 463 */
461 function bestFitMatcher(service, requestedLocales) { 464 function bestFitMatcher(service, requestedLocales) {
462 // TODO(cira): implement better best fit algorithm. 465 // TODO(cira): implement better best fit algorithm.
463 return lookupMatcher(service, requestedLocales); 466 return lookupMatcher(service, requestedLocales);
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
715 } 718 }
716 } 719 }
717 return result; 720 return result;
718 } 721 }
719 722
720 /** 723 /**
721 * Canonicalizes the language tag, or throws in case the tag is invalid. 724 * Canonicalizes the language tag, or throws in case the tag is invalid.
722 */ 725 */
723 function canonicalizeLanguageTag(localeID) { 726 function canonicalizeLanguageTag(localeID) {
724 // null is typeof 'object' so we have to do extra check. 727 // null is typeof 'object' so we have to do extra check.
725 if (typeof localeID !== 'string' && typeof localeID !== 'object' || 728 if ((!IS_STRING(localeID) && !IS_RECEIVER(localeID)) ||
726 IS_NULL(localeID)) { 729 IS_NULL(localeID)) {
727 throw MakeTypeError(kLanguageID); 730 throw MakeTypeError(kLanguageID);
728 } 731 }
729 732
733 // Optimize for the most common case; a language code alone in
734 // the canonical form/lowercase (e.g. "en", "fil").
735 if (IS_STRING(localeID) &&
736 !IS_NULL(InternalRegExpMatch(/^[a-z]{2,3}$/, localeID))) {
737 return localeID;
738 }
739
730 var localeString = GlobalString(localeID); 740 var localeString = GlobalString(localeID);
731 741
732 if (isValidLanguageTag(localeString) === false) { 742 if (isValidLanguageTag(localeString) === false) {
733 throw MakeRangeError(kInvalidLanguageTag, localeString); 743 throw MakeRangeError(kInvalidLanguageTag, localeString);
734 } 744 }
735 745
736 // This call will strip -kn but not -kn-true extensions.
737 // ICU bug filled - http://bugs.icu-project.org/trac/ticket/9265.
738 // TODO(cira): check if -u-kn-true-kc-true-kh-true still throws after
739 // upgrade to ICU 4.9.
740 var tag = %CanonicalizeLanguageTag(localeString); 746 var tag = %CanonicalizeLanguageTag(localeString);
741 if (tag === 'invalid-tag') { 747 if (tag === 'invalid-tag') {
742 throw MakeRangeError(kInvalidLanguageTag, localeString); 748 throw MakeRangeError(kInvalidLanguageTag, localeString);
743 } 749 }
744 750
745 return tag; 751 return tag;
746 } 752 }
747 753
748 754
749 /** 755 /**
(...skipping 1232 matching lines...) Expand 10 before | Expand all | Expand 10 after
1982 var useOptions = (IS_UNDEFINED(defaults)) ? options : defaults; 1988 var useOptions = (IS_UNDEFINED(defaults)) ? options : defaults;
1983 if (IS_UNDEFINED(locales) && IS_UNDEFINED(options)) { 1989 if (IS_UNDEFINED(locales) && IS_UNDEFINED(options)) {
1984 if (IS_UNDEFINED(defaultObjects[service])) { 1990 if (IS_UNDEFINED(defaultObjects[service])) {
1985 defaultObjects[service] = new savedObjects[service](locales, useOptions); 1991 defaultObjects[service] = new savedObjects[service](locales, useOptions);
1986 } 1992 }
1987 return defaultObjects[service]; 1993 return defaultObjects[service];
1988 } 1994 }
1989 return new savedObjects[service](locales, useOptions); 1995 return new savedObjects[service](locales, useOptions);
1990 } 1996 }
1991 1997
1998 function LocaleConvertCase(s, locales, isToUpper) {
1999 // ECMA 402 section 13.1.2 steps 1 through 12.
2000 var language;
2001 // Optimize for the most common two cases. initializeLocaleList() can handle
2002 // them as well, but it's rather slow accounting for over 60% of
2003 // toLocale{U,L}Case() and about 40% of toLocale{U,L}Case("<locale>").
srl295 2016/07/27 18:53:39 if it's slow, please file a bug in ICU to address.
2004 if (IS_UNDEFINED(locales)) {
2005 language = GetDefaultICULocaleJS();
2006 } else if (IS_STRING(locales)) {
2007 language = canonicalizeLanguageTag(locales);
2008 } else {
2009 var locales = initializeLocaleList(locales);
2010 language = locales.length > 0 ? locales[0] : GetDefaultICULocaleJS();
2011 }
2012
2013 // StringSplit is slower than this.
2014 var pos = %_Call(StringIndexOf, language, '-');
2015 if (pos != -1) {
2016 language = %_Call(StringSubstring, language, 0, pos);
2017 }
2018
2019 var CUSTOM_CASE_LANGUAGES = ['az', 'el', 'lt', 'tr'];
srl295 2016/07/27 18:53:39 Filed : http://bugs.icu-project.org/trac/ticket/12
srl295 2016/07/27 18:53:39 Why are these hard coded? This decision should be
2020 var langIndex = %_Call(ArrayIndexOf, CUSTOM_CASE_LANGUAGES, language);
2021 if (langIndex == -1) {
2022 // language-independent case conversion.
2023 return isToUpper ? %StringToUpperCaseI18N(s) : %StringToLowerCaseI18N(s);
2024 }
2025 return %StringLocaleConvertCase(s, isToUpper,
2026 CUSTOM_CASE_LANGUAGES[langIndex]);
2027 }
2028
1992 /** 2029 /**
1993 * Compares this and that, and returns less than 0, 0 or greater than 0 value. 2030 * Compares this and that, and returns less than 0, 0 or greater than 0 value.
1994 * Overrides the built-in method. 2031 * Overrides the built-in method.
1995 */ 2032 */
1996 OverrideFunction(GlobalString.prototype, 'localeCompare', function(that) { 2033 OverrideFunction(GlobalString.prototype, 'localeCompare', function(that) {
1997 if (!IS_UNDEFINED(new.target)) { 2034 if (!IS_UNDEFINED(new.target)) {
1998 throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 2035 throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor);
1999 } 2036 }
2000 2037
2001 if (IS_NULL_OR_UNDEFINED(this)) { 2038 if (IS_NULL_OR_UNDEFINED(this)) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2034 var normalizationForm = %_Call(ArrayIndexOf, NORMALIZATION_FORMS, form); 2071 var normalizationForm = %_Call(ArrayIndexOf, NORMALIZATION_FORMS, form);
2035 if (normalizationForm === -1) { 2072 if (normalizationForm === -1) {
2036 throw MakeRangeError(kNormalizationForm, 2073 throw MakeRangeError(kNormalizationForm,
2037 %_Call(ArrayJoin, NORMALIZATION_FORMS, ', ')); 2074 %_Call(ArrayJoin, NORMALIZATION_FORMS, ', '));
2038 } 2075 }
2039 2076
2040 return %StringNormalize(s, normalizationForm); 2077 return %StringNormalize(s, normalizationForm);
2041 } 2078 }
2042 ); 2079 );
2043 2080
2081 function ToLowerCaseI18N() {
2082 if (!IS_UNDEFINED(new.target)) {
2083 throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor);
2084 }
2085 CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLowerCase");
2086 var s = TO_STRING(this);
2087 return %StringToLowerCaseI18N(s);
2088 }
2089
2090 function ToUpperCaseI18N() {
2091 if (!IS_UNDEFINED(new.target)) {
2092 throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor);
2093 }
2094 CHECK_OBJECT_COERCIBLE(this, "String.prototype.toUpperCase");
2095 var s = TO_STRING(this);
2096 return %StringToUpperCaseI18N(s);
2097 }
2098
2099 function ToLocaleLowerCaseI18N(locales) {
2100 if (!IS_UNDEFINED(new.target)) {
2101 throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor);
2102 }
2103 CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLocaleLowerCase");
2104 return LocaleConvertCase(TO_STRING(this), locales, false);
2105 }
2106
2107 %FunctionSetLength(ToLocaleLowerCaseI18N, 0);
2108
2109 function ToLocaleUpperCaseI18N(locales) {
2110 if (!IS_UNDEFINED(new.target)) {
2111 throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor);
2112 }
2113 CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLocaleUpperCase");
2114 return LocaleConvertCase(TO_STRING(this), locales, true);
2115 }
2116
2117 %FunctionSetLength(ToLocaleUpperCaseI18N, 0);
2118
2119 %FunctionRemovePrototype(ToLowerCaseI18N);
2120 %FunctionRemovePrototype(ToUpperCaseI18N);
2121 %FunctionRemovePrototype(ToLocaleLowerCaseI18N);
2122 %FunctionRemovePrototype(ToLocaleUpperCaseI18N);
2123
2124 utils.Export(function(to) {
2125 to.ToLowerCaseI18N = ToLowerCaseI18N;
2126 to.ToUpperCaseI18N = ToUpperCaseI18N;
2127 to.ToLocaleLowerCaseI18N = ToLocaleLowerCaseI18N;
2128 to.ToLocaleUpperCaseI18N = ToLocaleUpperCaseI18N;
2129 });
2130
2044 2131
2045 /** 2132 /**
2046 * Formats a Number object (this) using locale and options values. 2133 * Formats a Number object (this) using locale and options values.
2047 * If locale or options are omitted, defaults are used. 2134 * If locale or options are omitted, defaults are used.
2048 */ 2135 */
2049 OverrideFunction(GlobalNumber.prototype, 'toLocaleString', function() { 2136 OverrideFunction(GlobalNumber.prototype, 'toLocaleString', function() {
2050 if (!IS_UNDEFINED(new.target)) { 2137 if (!IS_UNDEFINED(new.target)) {
2051 throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 2138 throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor);
2052 } 2139 }
2053 2140
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
2129 } 2216 }
2130 2217
2131 var locales = arguments[0]; 2218 var locales = arguments[0];
2132 var options = arguments[1]; 2219 var options = arguments[1];
2133 return toLocaleDateTime( 2220 return toLocaleDateTime(
2134 this, locales, options, 'time', 'time', 'dateformattime'); 2221 this, locales, options, 'time', 'time', 'dateformattime');
2135 } 2222 }
2136 ); 2223 );
2137 2224
2138 }) 2225 })
OLDNEW
« no previous file with comments | « src/flag-definitions.h ('k') | src/js/icu-case-mapping.js » ('j') | src/runtime/runtime-i18n.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698