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

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

Issue 2717613005: [intl] Fix NumberFormat options handling spec compliance issues (Closed)
Patch Set: Remove test262 failure expectation line Created 3 years, 8 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
« no previous file with comments | « src/i18n.cc ('k') | src/runtime/runtime.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 871 matching lines...) Expand 10 before | Expand all | Expand 10 after
927 var language = '(' + alpha + '{2,3}(-' + extLang + ')?|' + alpha + '{4}|' + 929 var language = '(' + alpha + '{2,3}(-' + extLang + ')?|' + alpha + '{4}|' +
928 alpha + '{5,8})'; 930 alpha + '{5,8})';
929 var langTag = language + '(-' + script + ')?(-' + region + ')?(-' + 931 var langTag = language + '(-' + script + ')?(-' + region + ')?(-' +
930 variant + ')*(-' + extension + ')*(-' + privateUse + ')?'; 932 variant + ')*(-' + extension + ')*(-' + privateUse + ')?';
931 933
932 var languageTag = 934 var languageTag =
933 '^(' + langTag + '|' + privateUse + '|' + grandfathered + ')$'; 935 '^(' + langTag + '|' + privateUse + '|' + grandfathered + ')$';
934 LANGUAGE_TAG_RE = new GlobalRegExp(languageTag, 'i'); 936 LANGUAGE_TAG_RE = new GlobalRegExp(languageTag, 'i');
935 } 937 }
936 938
937 var resolvedAccessor = {
938 get() {
939 %IncrementUseCounter(kIntlResolved);
940 return this[resolvedSymbol];
941 },
942 set(value) {
943 this[resolvedSymbol] = value;
944 }
945 };
946
947 // ECMA 402 section 8.2.1 939 // ECMA 402 section 8.2.1
948 InstallFunction(GlobalIntl, 'getCanonicalLocales', function(locales) { 940 InstallFunction(GlobalIntl, 'getCanonicalLocales', function(locales) {
949 return makeArray(canonicalizeLocaleList(locales)); 941 return makeArray(canonicalizeLocaleList(locales));
950 } 942 }
951 ); 943 );
952 944
953 /** 945 /**
954 * Initializes the given object so it's a valid Collator instance. 946 * Initializes the given object so it's a valid Collator instance.
955 * Useful for subclassing. 947 * Useful for subclassing.
956 */ 948 */
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
1130 value = TO_NUMBER(value); 1122 value = TO_NUMBER(value);
1131 if (NUMBER_IS_NAN(value) || value < min || value > max) { 1123 if (NUMBER_IS_NAN(value) || value < min || value > max) {
1132 throw %make_range_error(kPropertyValueOutOfRange, property); 1124 throw %make_range_error(kPropertyValueOutOfRange, property);
1133 } 1125 }
1134 return %math_floor(value); 1126 return %math_floor(value);
1135 } 1127 }
1136 1128
1137 return fallback; 1129 return fallback;
1138 } 1130 }
1139 1131
1140
1141 /** 1132 /**
1142 * Returns the valid digit count for a property, or throws RangeError on 1133 * Returns the valid digit count for a property, or throws RangeError on
1143 * a value out of the range. 1134 * a value out of the range.
1144 */ 1135 */
1145 function getNumberOption(options, property, min, max, fallback) { 1136 function getNumberOption(options, property, min, max, fallback) {
1146 var value = options[property]; 1137 var value = options[property];
1147 return defaultNumberOption(value, min, max, fallback, property); 1138 return defaultNumberOption(value, min, max, fallback, property);
1148 } 1139 }
1149 1140
1150 var patternAccessor = { 1141 // ECMA 402 #sec-setnfdigitoptions
1151 get() { 1142 // SetNumberFormatDigitOptions ( intlObj, options, mnfdDefault, mxfdDefault )
1152 %IncrementUseCounter(kIntlPattern); 1143 function SetNumberFormatDigitOptions(internalOptions, options,
1153 return this[patternSymbol]; 1144 mnfdDefault, mxfdDefault) {
1154 }, 1145 // Digit ranges.
1155 set(value) { 1146 var mnid = getNumberOption(options, 'minimumIntegerDigits', 1, 21, 1);
1156 this[patternSymbol] = value; 1147 defineWEProperty(internalOptions, 'minimumIntegerDigits', mnid);
1148
1149 var mnfd = getNumberOption(options, 'minimumFractionDigits', 0, 20,
1150 mnfdDefault);
1151 defineWEProperty(internalOptions, 'minimumFractionDigits', mnfd);
1152
1153 var mxfdActualDefault = MaxSimple(mnfd, mxfdDefault);
1154
1155 var mxfd = getNumberOption(options, 'maximumFractionDigits', mnfd, 20,
1156 mxfdActualDefault);
1157
1158 defineWEProperty(internalOptions, 'maximumFractionDigits', mxfd);
1159
1160 var mnsd = options['minimumSignificantDigits'];
1161 var mxsd = options['maximumSignificantDigits'];
1162 if (!IS_UNDEFINED(mnsd) || !IS_UNDEFINED(mxsd)) {
1163 mnsd = defaultNumberOption(mnsd, 1, 21, 1, 'minimumSignificantDigits');
1164 defineWEProperty(internalOptions, 'minimumSignificantDigits', mnsd);
1165
1166 mxsd = defaultNumberOption(mxsd, mnsd, 21, 21, 'maximumSignificantDigits');
1167 defineWEProperty(internalOptions, 'maximumSignificantDigits', mxsd);
1157 } 1168 }
1158 }; 1169 }
1159 1170
1160 /** 1171 /**
1161 * Initializes the given object so it's a valid NumberFormat instance. 1172 * Initializes the given object so it's a valid NumberFormat instance.
1162 * Useful for subclassing. 1173 * Useful for subclassing.
1163 */ 1174 */
1164 function CreateNumberFormat(locales, options) { 1175 function CreateNumberFormat(locales, options) {
1165 if (IS_UNDEFINED(options)) { 1176 if (IS_UNDEFINED(options)) {
1166 options = {}; 1177 options = {};
1167 } 1178 }
1168 1179
1169 var getOption = getGetOption(options, 'numberformat'); 1180 var getOption = getGetOption(options, 'numberformat');
1170 1181
1171 var locale = resolveLocale('numberformat', locales, options); 1182 var locale = resolveLocale('numberformat', locales, options);
1172 1183
1173 var internalOptions = {}; 1184 var internalOptions = {};
1174 defineWEProperty(internalOptions, 'style', getOption( 1185 defineWEProperty(internalOptions, 'style', getOption(
1175 'style', 'string', ['decimal', 'percent', 'currency'], 'decimal')); 1186 'style', 'string', ['decimal', 'percent', 'currency'], 'decimal'));
1176 1187
1177 var currency = getOption('currency', 'string'); 1188 var currency = getOption('currency', 'string');
1178 if (!IS_UNDEFINED(currency) && !isWellFormedCurrencyCode(currency)) { 1189 if (!IS_UNDEFINED(currency) && !isWellFormedCurrencyCode(currency)) {
1179 throw %make_range_error(kInvalidCurrencyCode, currency); 1190 throw %make_range_error(kInvalidCurrencyCode, currency);
1180 } 1191 }
1181 1192
1182 if (internalOptions.style === 'currency' && IS_UNDEFINED(currency)) { 1193 if (internalOptions.style === 'currency' && IS_UNDEFINED(currency)) {
1183 throw %make_type_error(kCurrencyCode); 1194 throw %make_type_error(kCurrencyCode);
1184 } 1195 }
1185 1196
1197 var mnfdDefault, mxfdDefault;
1198
1186 var currencyDisplay = getOption( 1199 var currencyDisplay = getOption(
1187 'currencyDisplay', 'string', ['code', 'symbol', 'name'], 'symbol'); 1200 'currencyDisplay', 'string', ['code', 'symbol', 'name'], 'symbol');
1188 if (internalOptions.style === 'currency') { 1201 if (internalOptions.style === 'currency') {
1189 defineWEProperty(internalOptions, 'currency', %StringToUpperCaseI18N(currenc y)); 1202 defineWEProperty(internalOptions, 'currency', %StringToUpperCaseI18N(currenc y));
1190 defineWEProperty(internalOptions, 'currencyDisplay', currencyDisplay); 1203 defineWEProperty(internalOptions, 'currencyDisplay', currencyDisplay);
1204
1205 mnfdDefault = mxfdDefault = %CurrencyDigits(internalOptions.currency);
1206 } else {
1207 mnfdDefault = 0;
1208 mxfdDefault = internalOptions.style === 'percent' ? 0 : 3;
1191 } 1209 }
1192 1210
1193 // Digit ranges. 1211 SetNumberFormatDigitOptions(internalOptions, options, mnfdDefault,
1194 var mnid = getNumberOption(options, 'minimumIntegerDigits', 1, 21, 1); 1212 mxfdDefault);
1195 defineWEProperty(internalOptions, 'minimumIntegerDigits', mnid);
1196
1197 var mnfd = options['minimumFractionDigits'];
1198 var mxfd = options['maximumFractionDigits'];
1199 if (!IS_UNDEFINED(mnfd) || internalOptions.style !== 'currency') {
1200 mnfd = getNumberOption(options, 'minimumFractionDigits', 0, 20, 0);
1201 defineWEProperty(internalOptions, 'minimumFractionDigits', mnfd);
1202 }
1203
1204 if (!IS_UNDEFINED(mxfd) || internalOptions.style !== 'currency') {
1205 var min_mxfd = internalOptions.style === 'percent' ? 0 : 3;
1206 mnfd = IS_UNDEFINED(mnfd) ? 0 : mnfd;
1207 var fallback_limit = (mnfd > min_mxfd) ? mnfd : min_mxfd;
1208 mxfd = getNumberOption(options, 'maximumFractionDigits', mnfd, 20, fallback_ limit);
1209 defineWEProperty(internalOptions, 'maximumFractionDigits', mxfd);
1210 }
1211
1212 var mnsd = options['minimumSignificantDigits'];
1213 var mxsd = options['maximumSignificantDigits'];
1214 if (!IS_UNDEFINED(mnsd) || !IS_UNDEFINED(mxsd)) {
1215 mnsd = defaultNumberOption(mnsd, 1, 21, 1, 'minimumSignificantDigits');
1216 defineWEProperty(internalOptions, 'minimumSignificantDigits', mnsd);
1217
1218 mxsd = defaultNumberOption(mxsd, mnsd, 21, 21, 'maximumSignificantDigits');
1219 defineWEProperty(internalOptions, 'maximumSignificantDigits', mxsd);
1220 }
1221 1213
1222 // Grouping. 1214 // Grouping.
1223 defineWEProperty(internalOptions, 'useGrouping', getOption( 1215 defineWEProperty(internalOptions, 'useGrouping', getOption(
1224 'useGrouping', 'boolean', UNDEFINED, true)); 1216 'useGrouping', 'boolean', UNDEFINED, true));
1225 1217
1226 // ICU prefers options to be passed using -u- extension key/values for 1218 // ICU prefers options to be passed using -u- extension key/values for
1227 // number format, so we need to build that. 1219 // number format, so we need to build that.
1228 var extensionMap = parseExtension(locale.extension); 1220 var extensionMap = parseExtension(locale.extension);
1229 1221
1230 /** 1222 /**
(...skipping 918 matching lines...) Expand 10 before | Expand all | Expand 10 after
2149 2141
2150 utils.Export(function(to) { 2142 utils.Export(function(to) {
2151 to.FormatDateToParts = FormatDateToParts; 2143 to.FormatDateToParts = FormatDateToParts;
2152 to.ToLowerCaseI18N = ToLowerCaseI18N; 2144 to.ToLowerCaseI18N = ToLowerCaseI18N;
2153 to.ToUpperCaseI18N = ToUpperCaseI18N; 2145 to.ToUpperCaseI18N = ToUpperCaseI18N;
2154 to.ToLocaleLowerCaseI18N = ToLocaleLowerCaseI18N; 2146 to.ToLocaleLowerCaseI18N = ToLocaleLowerCaseI18N;
2155 to.ToLocaleUpperCaseI18N = ToLocaleUpperCaseI18N; 2147 to.ToLocaleUpperCaseI18N = ToLocaleUpperCaseI18N;
2156 }); 2148 });
2157 2149
2158 }) 2150 })
OLDNEW
« no previous file with comments | « src/i18n.cc ('k') | src/runtime/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698