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

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

Issue 2717613005: [intl] Fix NumberFormat options handling spec compliance issues (Closed)
Patch Set: Slight cleanup Created 3 years, 9 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 14 matching lines...) Expand all
25 var GlobalIntlNumberFormat = GlobalIntl.NumberFormat; 25 var GlobalIntlNumberFormat = GlobalIntl.NumberFormat;
26 var GlobalIntlCollator = GlobalIntl.Collator; 26 var GlobalIntlCollator = GlobalIntl.Collator;
27 var GlobalIntlv8BreakIterator = GlobalIntl.v8BreakIterator; 27 var GlobalIntlv8BreakIterator = GlobalIntl.v8BreakIterator;
28 var GlobalNumber = global.Number; 28 var GlobalNumber = global.Number;
29 var GlobalRegExp = global.RegExp; 29 var GlobalRegExp = global.RegExp;
30 var GlobalString = global.String; 30 var GlobalString = global.String;
31 var IntlFallbackSymbol = utils.ImportNow("intl_fallback_symbol"); 31 var IntlFallbackSymbol = utils.ImportNow("intl_fallback_symbol");
32 var InstallFunctions = utils.InstallFunctions; 32 var InstallFunctions = utils.InstallFunctions;
33 var InstallGetter = utils.InstallGetter; 33 var InstallGetter = utils.InstallGetter;
34 var InternalArray = utils.InternalArray; 34 var InternalArray = utils.InternalArray;
35 var MaxSimple;
35 var ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty"); 36 var ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty");
36 var OverrideFunction = utils.OverrideFunction; 37 var OverrideFunction = utils.OverrideFunction;
37 var patternSymbol = utils.ImportNow("intl_pattern_symbol"); 38 var patternSymbol = utils.ImportNow("intl_pattern_symbol");
38 var resolvedSymbol = utils.ImportNow("intl_resolved_symbol"); 39 var resolvedSymbol = utils.ImportNow("intl_resolved_symbol");
39 var SetFunctionName = utils.SetFunctionName; 40 var SetFunctionName = utils.SetFunctionName;
40 var StringSubstr = GlobalString.prototype.substr; 41 var StringSubstr = GlobalString.prototype.substr;
41 var StringSubstring = GlobalString.prototype.substring; 42 var StringSubstring = GlobalString.prototype.substring;
42 43
43 utils.Import(function(from) { 44 utils.Import(function(from) {
44 ArrayJoin = from.ArrayJoin; 45 ArrayJoin = from.ArrayJoin;
45 ArrayPush = from.ArrayPush; 46 ArrayPush = from.ArrayPush;
47 MaxSimple = from.MaxSimple;
46 }); 48 });
47 49
48 // Utilities for definitions 50 // Utilities for definitions
49 51
50 function InstallFunction(object, name, func) { 52 function InstallFunction(object, name, func) {
51 InstallFunctions(object, DONT_ENUM, [name, func]); 53 InstallFunctions(object, DONT_ENUM, [name, func]);
52 } 54 }
53 55
54 56
55 /** 57 /**
(...skipping 877 matching lines...) Expand 10 before | Expand all | Expand 10 after
933 var language = '(' + alpha + '{2,3}(-' + extLang + ')?|' + alpha + '{4}|' + 935 var language = '(' + alpha + '{2,3}(-' + extLang + ')?|' + alpha + '{4}|' +
934 alpha + '{5,8})'; 936 alpha + '{5,8})';
935 var langTag = language + '(-' + script + ')?(-' + region + ')?(-' + 937 var langTag = language + '(-' + script + ')?(-' + region + ')?(-' +
936 variant + ')*(-' + extension + ')*(-' + privateUse + ')?'; 938 variant + ')*(-' + extension + ')*(-' + privateUse + ')?';
937 939
938 var languageTag = 940 var languageTag =
939 '^(' + langTag + '|' + privateUse + '|' + grandfathered + ')$'; 941 '^(' + langTag + '|' + privateUse + '|' + grandfathered + ')$';
940 LANGUAGE_TAG_RE = new GlobalRegExp(languageTag, 'i'); 942 LANGUAGE_TAG_RE = new GlobalRegExp(languageTag, 'i');
941 } 943 }
942 944
943 var resolvedAccessor = {
944 get() {
945 %IncrementUseCounter(kIntlResolved);
946 return this[resolvedSymbol];
947 },
948 set(value) {
949 this[resolvedSymbol] = value;
950 }
951 };
952
953 // ECMA 402 section 8.2.1 945 // ECMA 402 section 8.2.1
954 InstallFunction(GlobalIntl, 'getCanonicalLocales', function(locales) { 946 InstallFunction(GlobalIntl, 'getCanonicalLocales', function(locales) {
955 return makeArray(canonicalizeLocaleList(locales)); 947 return makeArray(canonicalizeLocaleList(locales));
956 } 948 }
957 ); 949 );
958 950
959 /** 951 /**
960 * Initializes the given object so it's a valid Collator instance. 952 * Initializes the given object so it's a valid Collator instance.
961 * Useful for subclassing. 953 * Useful for subclassing.
962 */ 954 */
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
1141 value = TO_NUMBER(value); 1133 value = TO_NUMBER(value);
1142 if (NUMBER_IS_NAN(value) || value < min || value > max) { 1134 if (NUMBER_IS_NAN(value) || value < min || value > max) {
1143 throw %make_range_error(kPropertyValueOutOfRange, property); 1135 throw %make_range_error(kPropertyValueOutOfRange, property);
1144 } 1136 }
1145 return %math_floor(value); 1137 return %math_floor(value);
1146 } 1138 }
1147 1139
1148 return fallback; 1140 return fallback;
1149 } 1141 }
1150 1142
1151 var patternAccessor = { 1143 // ECMA 402 #sec-setnfdigitoptions
1152 get() { 1144 // SetNumberFormatDigitOptions ( intlObj, options, mnfdDefault, mxfdDefault )
1153 %IncrementUseCounter(kIntlPattern); 1145 function SetNumberFormatDigitOptions(internalOptions, options,
1154 return this[patternSymbol]; 1146 mnfdDefault, mxfdDefault) {
1155 }, 1147 // Digit ranges.
1156 set(value) { 1148 var mnid = getNumberOption(options, 'minimumIntegerDigits', 1, 21, 1);
1157 this[patternSymbol] = value; 1149 defineWEProperty(internalOptions, 'minimumIntegerDigits', mnid);
1150
1151 var mnfd = getNumberOption(options, 'minimumFractionDigits', 0, 20,
1152 mnfdDefault);
1153 defineWEProperty(internalOptions, 'minimumFractionDigits', mnfd);
1154
1155 var mxfdActualDefault = MaxSimple(mnfd, mxfdDefault);
1156
1157 var mxfd = getNumberOption(options, 'maximumFractionDigits', mnfd, 20,
1158 mxfdActualDefault);
1159
1160 defineWEProperty(internalOptions, 'maximumFractionDigits', mxfd);
1161
1162 var mnsd = options['minimumSignificantDigits'];
1163 var mxsd = options['maximumSignificantDigits'];
1164 if (!IS_UNDEFINED(mnsd) || !IS_UNDEFINED(mxsd)) {
1165 mnsd = getNumberOption(options, 'minimumSignificantDigits', 1, 21, 1);
1166 defineWEProperty(internalOptions, 'minimumSignificantDigits', mnsd);
1167
1168 mxsd = getNumberOption(options, 'maximumSignificantDigits', mnsd, 21, 21);
1169 defineWEProperty(internalOptions, 'maximumSignificantDigits', mxsd);
1158 } 1170 }
1159 }; 1171 }
1160 1172
1161 /** 1173 /**
1162 * Initializes the given object so it's a valid NumberFormat instance. 1174 * Initializes the given object so it's a valid NumberFormat instance.
1163 * Useful for subclassing. 1175 * Useful for subclassing.
1164 */ 1176 */
1165 function CreateNumberFormat(locales, options) { 1177 function CreateNumberFormat(locales, options) {
1166 if (IS_UNDEFINED(options)) { 1178 if (IS_UNDEFINED(options)) {
1167 options = {}; 1179 options = {};
1168 } 1180 }
1169 1181
1170 var getOption = getGetOption(options, 'numberformat'); 1182 var getOption = getGetOption(options, 'numberformat');
1171 1183
1172 var locale = resolveLocale('numberformat', locales, options); 1184 var locale = resolveLocale('numberformat', locales, options);
1173 1185
1174 var internalOptions = {}; 1186 var internalOptions = {};
1175 defineWEProperty(internalOptions, 'style', getOption( 1187 defineWEProperty(internalOptions, 'style', getOption(
1176 'style', 'string', ['decimal', 'percent', 'currency'], 'decimal')); 1188 'style', 'string', ['decimal', 'percent', 'currency'], 'decimal'));
1177 1189
1178 var currency = getOption('currency', 'string'); 1190 var currency = getOption('currency', 'string');
1179 if (!IS_UNDEFINED(currency) && !isWellFormedCurrencyCode(currency)) { 1191 if (!IS_UNDEFINED(currency) && !isWellFormedCurrencyCode(currency)) {
1180 throw %make_range_error(kInvalidCurrencyCode, currency); 1192 throw %make_range_error(kInvalidCurrencyCode, currency);
1181 } 1193 }
1182 1194
1183 if (internalOptions.style === 'currency' && IS_UNDEFINED(currency)) { 1195 if (internalOptions.style === 'currency' && IS_UNDEFINED(currency)) {
1184 throw %make_type_error(kCurrencyCode); 1196 throw %make_type_error(kCurrencyCode);
1185 } 1197 }
1186 1198
1199 var mnfdDefault, mxfdDefault;
1200
1187 var currencyDisplay = getOption( 1201 var currencyDisplay = getOption(
1188 'currencyDisplay', 'string', ['code', 'symbol', 'name'], 'symbol'); 1202 'currencyDisplay', 'string', ['code', 'symbol', 'name'], 'symbol');
1189 if (internalOptions.style === 'currency') { 1203 if (internalOptions.style === 'currency') {
1190 defineWEProperty(internalOptions, 'currency', %StringToUpperCaseI18N(currenc y)); 1204 defineWEProperty(internalOptions, 'currency', %StringToUpperCaseI18N(currenc y));
1191 defineWEProperty(internalOptions, 'currencyDisplay', currencyDisplay); 1205 defineWEProperty(internalOptions, 'currencyDisplay', currencyDisplay);
1206
1207 mnfdDefault = mxfdDefault = %CurrencyDigits(internalOptions.currency);
1208 } else {
1209 mnfdDefault = 0;
1210 mxfdDefault = internalOptions.style === 'percent' ? 0 : 3;
1192 } 1211 }
1193 1212
1194 // Digit ranges. 1213 SetNumberFormatDigitOptions(internalOptions, options, mnfdDefault,
1195 var mnid = getNumberOption(options, 'minimumIntegerDigits', 1, 21, 1); 1214 mxfdDefault);
1196 defineWEProperty(internalOptions, 'minimumIntegerDigits', mnid);
1197
1198 var mnfd = options['minimumFractionDigits'];
1199 var mxfd = options['maximumFractionDigits'];
1200 if (!IS_UNDEFINED(mnfd) || internalOptions.style !== 'currency') {
1201 mnfd = getNumberOption(options, 'minimumFractionDigits', 0, 20, 0);
1202 defineWEProperty(internalOptions, 'minimumFractionDigits', mnfd);
1203 }
1204
1205 if (!IS_UNDEFINED(mxfd) || internalOptions.style !== 'currency') {
1206 var min_mxfd = internalOptions.style === 'percent' ? 0 : 3;
1207 mnfd = IS_UNDEFINED(mnfd) ? 0 : mnfd;
1208 var fallback_limit = (mnfd > min_mxfd) ? mnfd : min_mxfd;
1209 mxfd = getNumberOption(options, 'maximumFractionDigits', mnfd, 20, fallback_ limit);
1210 defineWEProperty(internalOptions, 'maximumFractionDigits', mxfd);
1211 }
1212
1213 var mnsd = options['minimumSignificantDigits'];
1214 var mxsd = options['maximumSignificantDigits'];
1215 if (!IS_UNDEFINED(mnsd) || !IS_UNDEFINED(mxsd)) {
1216 mnsd = getNumberOption(options, 'minimumSignificantDigits', 1, 21, 1);
1217 defineWEProperty(internalOptions, 'minimumSignificantDigits', mnsd);
1218
1219 mxsd = getNumberOption(options, 'maximumSignificantDigits', mnsd, 21, 21);
1220 defineWEProperty(internalOptions, 'maximumSignificantDigits', mxsd);
1221 }
1222 1215
1223 // Grouping. 1216 // Grouping.
1224 defineWEProperty(internalOptions, 'useGrouping', getOption( 1217 defineWEProperty(internalOptions, 'useGrouping', getOption(
1225 'useGrouping', 'boolean', UNDEFINED, true)); 1218 'useGrouping', 'boolean', UNDEFINED, true));
1226 1219
1227 // ICU prefers options to be passed using -u- extension key/values for 1220 // ICU prefers options to be passed using -u- extension key/values for
1228 // number format, so we need to build that. 1221 // number format, so we need to build that.
1229 var extensionMap = parseExtension(locale.extension); 1222 var extensionMap = parseExtension(locale.extension);
1230 1223
1231 /** 1224 /**
(...skipping 947 matching lines...) Expand 10 before | Expand all | Expand 10 after
2179 2172
2180 utils.Export(function(to) { 2173 utils.Export(function(to) {
2181 to.FormatDateToParts = FormatDateToParts; 2174 to.FormatDateToParts = FormatDateToParts;
2182 to.ToLowerCaseI18N = ToLowerCaseI18N; 2175 to.ToLowerCaseI18N = ToLowerCaseI18N;
2183 to.ToUpperCaseI18N = ToUpperCaseI18N; 2176 to.ToUpperCaseI18N = ToUpperCaseI18N;
2184 to.ToLocaleLowerCaseI18N = ToLocaleLowerCaseI18N; 2177 to.ToLocaleLowerCaseI18N = ToLocaleLowerCaseI18N;
2185 to.ToLocaleUpperCaseI18N = ToLocaleUpperCaseI18N; 2178 to.ToLocaleUpperCaseI18N = ToLocaleUpperCaseI18N;
2186 }); 2179 });
2187 2180
2188 }) 2181 })
OLDNEW
« no previous file with comments | « src/i18n.cc ('k') | src/runtime/runtime.h » ('j') | src/runtime/runtime-i18n.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698