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

Side by Side Diff: src/i18n.js

Issue 1144163002: Revert of Use shared container to manage imports/exports. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 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
« no previous file with comments | « src/harmony-typedarray.js ('k') | src/iterator-prototype.js » ('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 */
11 (function(global, utils) { 11 (function(global, shared, exports) {
12 12
13 "use strict"; 13 "use strict";
14 14
15 %CheckIsBootstrapping(); 15 %CheckIsBootstrapping();
16 16
17 // -------------------------------------------------------------------
18 // Imports
19
20 var GlobalBoolean = global.Boolean; 17 var GlobalBoolean = global.Boolean;
21 var GlobalDate = global.Date; 18 var GlobalDate = global.Date;
22 var GlobalNumber = global.Number; 19 var GlobalNumber = global.Number;
23 var GlobalRegExp = global.RegExp; 20 var GlobalRegExp = global.RegExp;
24 var GlobalString = global.String; 21 var GlobalString = global.String;
25 22
26 var MathFloor; 23 var undefined = global.undefined;
27
28 utils.Import(function(from) {
29 MathFloor = from.MathFloor;
30 });
31
32 // -------------------------------------------------------------------
33 24
34 var Intl = {}; 25 var Intl = {};
35 26
36 %AddNamedProperty(global, "Intl", Intl, DONT_ENUM); 27 %AddNamedProperty(global, "Intl", Intl, DONT_ENUM);
37 28
38 /** 29 /**
39 * Caches available locales for each service. 30 * Caches available locales for each service.
40 */ 31 */
41 var AVAILABLE_LOCALES = { 32 var AVAILABLE_LOCALES = {
42 'collator': UNDEFINED, 33 'collator': undefined,
43 'numberformat': UNDEFINED, 34 'numberformat': undefined,
44 'dateformat': UNDEFINED, 35 'dateformat': undefined,
45 'breakiterator': UNDEFINED 36 'breakiterator': undefined
46 }; 37 };
47 38
48 /** 39 /**
49 * Caches default ICU locale. 40 * Caches default ICU locale.
50 */ 41 */
51 var DEFAULT_ICU_LOCALE = UNDEFINED; 42 var DEFAULT_ICU_LOCALE = undefined;
52 43
53 /** 44 /**
54 * Unicode extension regular expression. 45 * Unicode extension regular expression.
55 */ 46 */
56 var UNICODE_EXTENSION_RE = UNDEFINED; 47 var UNICODE_EXTENSION_RE = undefined;
57 48
58 function GetUnicodeExtensionRE() { 49 function GetUnicodeExtensionRE() {
59 if (IS_UNDEFINED(UNDEFINED)) { 50 if (UNICODE_EXTENSION_RE === undefined) {
60 UNICODE_EXTENSION_RE = new GlobalRegExp('-u(-[a-z0-9]{2,8})+', 'g'); 51 UNICODE_EXTENSION_RE = new GlobalRegExp('-u(-[a-z0-9]{2,8})+', 'g');
61 } 52 }
62 return UNICODE_EXTENSION_RE; 53 return UNICODE_EXTENSION_RE;
63 } 54 }
64 55
65 /** 56 /**
66 * Matches any Unicode extension. 57 * Matches any Unicode extension.
67 */ 58 */
68 var ANY_EXTENSION_RE = UNDEFINED; 59 var ANY_EXTENSION_RE = undefined;
69 60
70 function GetAnyExtensionRE() { 61 function GetAnyExtensionRE() {
71 if (IS_UNDEFINED(ANY_EXTENSION_RE)) { 62 if (ANY_EXTENSION_RE === undefined) {
72 ANY_EXTENSION_RE = new GlobalRegExp('-[a-z0-9]{1}-.*', 'g'); 63 ANY_EXTENSION_RE = new GlobalRegExp('-[a-z0-9]{1}-.*', 'g');
73 } 64 }
74 return ANY_EXTENSION_RE; 65 return ANY_EXTENSION_RE;
75 } 66 }
76 67
77 /** 68 /**
78 * Replace quoted text (single quote, anything but the quote and quote again). 69 * Replace quoted text (single quote, anything but the quote and quote again).
79 */ 70 */
80 var QUOTED_STRING_RE = UNDEFINED; 71 var QUOTED_STRING_RE = undefined;
81 72
82 function GetQuotedStringRE() { 73 function GetQuotedStringRE() {
83 if (IS_UNDEFINED(QUOTED_STRING_RE)) { 74 if (QUOTED_STRING_RE === undefined) {
84 QUOTED_STRING_RE = new GlobalRegExp("'[^']+'", 'g'); 75 QUOTED_STRING_RE = new GlobalRegExp("'[^']+'", 'g');
85 } 76 }
86 return QUOTED_STRING_RE; 77 return QUOTED_STRING_RE;
87 } 78 }
88 79
89 /** 80 /**
90 * Matches valid service name. 81 * Matches valid service name.
91 */ 82 */
92 var SERVICE_RE = UNDEFINED; 83 var SERVICE_RE = undefined;
93 84
94 function GetServiceRE() { 85 function GetServiceRE() {
95 if (IS_UNDEFINED(SERVICE_RE)) { 86 if (SERVICE_RE === undefined) {
96 SERVICE_RE = 87 SERVICE_RE =
97 new GlobalRegExp('^(collator|numberformat|dateformat|breakiterator)$'); 88 new GlobalRegExp('^(collator|numberformat|dateformat|breakiterator)$');
98 } 89 }
99 return SERVICE_RE; 90 return SERVICE_RE;
100 } 91 }
101 92
102 /** 93 /**
103 * Validates a language tag against bcp47 spec. 94 * Validates a language tag against bcp47 spec.
104 * Actual value is assigned on first run. 95 * Actual value is assigned on first run.
105 */ 96 */
106 var LANGUAGE_TAG_RE = UNDEFINED; 97 var LANGUAGE_TAG_RE = undefined;
107 98
108 function GetLanguageTagRE() { 99 function GetLanguageTagRE() {
109 if (IS_UNDEFINED(LANGUAGE_TAG_RE)) { 100 if (LANGUAGE_TAG_RE === undefined) {
110 BuildLanguageTagREs(); 101 BuildLanguageTagREs();
111 } 102 }
112 return LANGUAGE_TAG_RE; 103 return LANGUAGE_TAG_RE;
113 } 104 }
114 105
115 /** 106 /**
116 * Helps find duplicate variants in the language tag. 107 * Helps find duplicate variants in the language tag.
117 */ 108 */
118 var LANGUAGE_VARIANT_RE = UNDEFINED; 109 var LANGUAGE_VARIANT_RE = undefined;
119 110
120 function GetLanguageVariantRE() { 111 function GetLanguageVariantRE() {
121 if (IS_UNDEFINED(LANGUAGE_VARIANT_RE)) { 112 if (LANGUAGE_VARIANT_RE === undefined) {
122 BuildLanguageTagREs(); 113 BuildLanguageTagREs();
123 } 114 }
124 return LANGUAGE_VARIANT_RE; 115 return LANGUAGE_VARIANT_RE;
125 } 116 }
126 117
127 /** 118 /**
128 * Helps find duplicate singletons in the language tag. 119 * Helps find duplicate singletons in the language tag.
129 */ 120 */
130 var LANGUAGE_SINGLETON_RE = UNDEFINED; 121 var LANGUAGE_SINGLETON_RE = undefined;
131 122
132 function GetLanguageSingletonRE() { 123 function GetLanguageSingletonRE() {
133 if (IS_UNDEFINED(LANGUAGE_SINGLETON_RE)) { 124 if (LANGUAGE_SINGLETON_RE === undefined) {
134 BuildLanguageTagREs(); 125 BuildLanguageTagREs();
135 } 126 }
136 return LANGUAGE_SINGLETON_RE; 127 return LANGUAGE_SINGLETON_RE;
137 } 128 }
138 129
139 /** 130 /**
140 * Matches valid IANA time zone names. 131 * Matches valid IANA time zone names.
141 */ 132 */
142 var TIMEZONE_NAME_CHECK_RE = UNDEFINED; 133 var TIMEZONE_NAME_CHECK_RE = undefined;
143 134
144 function GetTimezoneNameCheckRE() { 135 function GetTimezoneNameCheckRE() {
145 if (IS_UNDEFINED(TIMEZONE_NAME_CHECK_RE)) { 136 if (TIMEZONE_NAME_CHECK_RE === undefined) {
146 TIMEZONE_NAME_CHECK_RE = 137 TIMEZONE_NAME_CHECK_RE =
147 new GlobalRegExp('^([A-Za-z]+)/([A-Za-z]+)(?:_([A-Za-z]+))*$'); 138 new GlobalRegExp('^([A-Za-z]+)/([A-Za-z]+)(?:_([A-Za-z]+))*$');
148 } 139 }
149 return TIMEZONE_NAME_CHECK_RE; 140 return TIMEZONE_NAME_CHECK_RE;
150 } 141 }
151 142
152 /** 143 /**
153 * Adds bound method to the prototype of the given object. 144 * Adds bound method to the prototype of the given object.
154 */ 145 */
155 function addBoundMethod(obj, methodName, implementation, length) { 146 function addBoundMethod(obj, methodName, implementation, length) {
156 function getter() { 147 function getter() {
157 if (!%IsInitializedIntlObject(this)) { 148 if (!%IsInitializedIntlObject(this)) {
158 throw MakeTypeError(kMethodCalledOnWrongObject, methodName); 149 throw MakeTypeError(kMethodCalledOnWrongObject, methodName);
159 } 150 }
160 var internalName = '__bound' + methodName + '__'; 151 var internalName = '__bound' + methodName + '__';
161 if (IS_UNDEFINED(this[internalName])) { 152 if (this[internalName] === undefined) {
162 var that = this; 153 var that = this;
163 var boundMethod; 154 var boundMethod;
164 if (IS_UNDEFINED(length) || length === 2) { 155 if (length === undefined || length === 2) {
165 boundMethod = function(x, y) { 156 boundMethod = function(x, y) {
166 if (%_IsConstructCall()) { 157 if (%_IsConstructCall()) {
167 throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 158 throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor);
168 } 159 }
169 return implementation(that, x, y); 160 return implementation(that, x, y);
170 } 161 }
171 } else if (length === 1) { 162 } else if (length === 1) {
172 boundMethod = function(x) { 163 boundMethod = function(x) {
173 if (%_IsConstructCall()) { 164 if (%_IsConstructCall()) {
174 throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); 165 throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 /** 204 /**
214 * Returns an intersection of locales and service supported locales. 205 * Returns an intersection of locales and service supported locales.
215 * Parameter locales is treated as a priority list. 206 * Parameter locales is treated as a priority list.
216 */ 207 */
217 function supportedLocalesOf(service, locales, options) { 208 function supportedLocalesOf(service, locales, options) {
218 if (IS_NULL(service.match(GetServiceRE()))) { 209 if (IS_NULL(service.match(GetServiceRE()))) {
219 throw MakeError(kWrongServiceType, service); 210 throw MakeError(kWrongServiceType, service);
220 } 211 }
221 212
222 // Provide defaults if matcher was not specified. 213 // Provide defaults if matcher was not specified.
223 if (IS_UNDEFINED(options)) { 214 if (options === undefined) {
224 options = {}; 215 options = {};
225 } else { 216 } else {
226 options = $toObject(options); 217 options = $toObject(options);
227 } 218 }
228 219
229 var matcher = options.localeMatcher; 220 var matcher = options.localeMatcher;
230 if (!IS_UNDEFINED(matcher)) { 221 if (matcher !== undefined) {
231 matcher = GlobalString(matcher); 222 matcher = GlobalString(matcher);
232 if (matcher !== 'lookup' && matcher !== 'best fit') { 223 if (matcher !== 'lookup' && matcher !== 'best fit') {
233 throw MakeRangeError(kLocaleMatcher, matcher); 224 throw MakeRangeError(kLocaleMatcher, matcher);
234 } 225 }
235 } else { 226 } else {
236 matcher = 'best fit'; 227 matcher = 'best fit';
237 } 228 }
238 229
239 var requestedLocales = initializeLocaleList(locales); 230 var requestedLocales = initializeLocaleList(locales);
240 231
241 // Cache these, they don't ever change per service. 232 // Cache these, they don't ever change per service.
242 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { 233 if (AVAILABLE_LOCALES[service] === undefined) {
243 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); 234 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service);
244 } 235 }
245 236
246 // Use either best fit or lookup algorithm to match locales. 237 // Use either best fit or lookup algorithm to match locales.
247 if (matcher === 'best fit') { 238 if (matcher === 'best fit') {
248 return initializeLocaleList(bestFitSupportedLocalesOf( 239 return initializeLocaleList(bestFitSupportedLocalesOf(
249 requestedLocales, AVAILABLE_LOCALES[service])); 240 requestedLocales, AVAILABLE_LOCALES[service]));
250 } 241 }
251 242
252 return initializeLocaleList(lookupSupportedLocalesOf( 243 return initializeLocaleList(lookupSupportedLocalesOf(
253 requestedLocales, AVAILABLE_LOCALES[service])); 244 requestedLocales, AVAILABLE_LOCALES[service]));
254 } 245 }
255 246
256 247
257 /** 248 /**
258 * Returns the subset of the provided BCP 47 language priority list for which 249 * Returns the subset of the provided BCP 47 language priority list for which
259 * this service has a matching locale when using the BCP 47 Lookup algorithm. 250 * this service has a matching locale when using the BCP 47 Lookup algorithm.
260 * Locales appear in the same order in the returned list as in the input list. 251 * Locales appear in the same order in the returned list as in the input list.
261 */ 252 */
262 function lookupSupportedLocalesOf(requestedLocales, availableLocales) { 253 function lookupSupportedLocalesOf(requestedLocales, availableLocales) {
263 var matchedLocales = []; 254 var matchedLocales = [];
264 for (var i = 0; i < requestedLocales.length; ++i) { 255 for (var i = 0; i < requestedLocales.length; ++i) {
265 // Remove -u- extension. 256 // Remove -u- extension.
266 var locale = requestedLocales[i].replace(GetUnicodeExtensionRE(), ''); 257 var locale = requestedLocales[i].replace(GetUnicodeExtensionRE(), '');
267 do { 258 do {
268 if (!IS_UNDEFINED(availableLocales[locale])) { 259 if (availableLocales[locale] !== undefined) {
269 // Push requested locale not the resolved one. 260 // Push requested locale not the resolved one.
270 matchedLocales.push(requestedLocales[i]); 261 matchedLocales.push(requestedLocales[i]);
271 break; 262 break;
272 } 263 }
273 // Truncate locale if possible, if not break. 264 // Truncate locale if possible, if not break.
274 var pos = locale.lastIndexOf('-'); 265 var pos = locale.lastIndexOf('-');
275 if (pos === -1) { 266 if (pos === -1) {
276 break; 267 break;
277 } 268 }
278 locale = locale.substring(0, pos); 269 locale = locale.substring(0, pos);
(...skipping 15 matching lines...) Expand all
294 return lookupSupportedLocalesOf(requestedLocales, availableLocales); 285 return lookupSupportedLocalesOf(requestedLocales, availableLocales);
295 } 286 }
296 287
297 288
298 /** 289 /**
299 * Returns a getOption function that extracts property value for given 290 * Returns a getOption function that extracts property value for given
300 * options object. If property is missing it returns defaultValue. If value 291 * options object. If property is missing it returns defaultValue. If value
301 * is out of range for that property it throws RangeError. 292 * is out of range for that property it throws RangeError.
302 */ 293 */
303 function getGetOption(options, caller) { 294 function getGetOption(options, caller) {
304 if (IS_UNDEFINED(options)) throw MakeError(kDefaultOptionsMissing, caller); 295 if (options === undefined) throw MakeError(kDefaultOptionsMissing, caller);
305 296
306 var getOption = function getOption(property, type, values, defaultValue) { 297 var getOption = function getOption(property, type, values, defaultValue) {
307 if (!IS_UNDEFINED(options[property])) { 298 if (options[property] !== undefined) {
308 var value = options[property]; 299 var value = options[property];
309 switch (type) { 300 switch (type) {
310 case 'boolean': 301 case 'boolean':
311 value = GlobalBoolean(value); 302 value = GlobalBoolean(value);
312 break; 303 break;
313 case 'string': 304 case 'string':
314 value = GlobalString(value); 305 value = GlobalString(value);
315 break; 306 break;
316 case 'number': 307 case 'number':
317 value = GlobalNumber(value); 308 value = GlobalNumber(value);
318 break; 309 break;
319 default: 310 default:
320 throw MakeError(kWrongValueType); 311 throw MakeError(kWrongValueType);
321 } 312 }
322 if (!IS_UNDEFINED(values) && values.indexOf(value) === -1) { 313 if (values !== undefined && values.indexOf(value) === -1) {
323 throw MakeRangeError(kValueOutOfRange, value, caller, property); 314 throw MakeRangeError(kValueOutOfRange, value, caller, property);
324 } 315 }
325 316
326 return value; 317 return value;
327 } 318 }
328 319
329 return defaultValue; 320 return defaultValue;
330 } 321 }
331 322
332 return getOption; 323 return getOption;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 /** 357 /**
367 * Returns best matched supported locale and extension info using basic 358 * Returns best matched supported locale and extension info using basic
368 * lookup algorithm. 359 * lookup algorithm.
369 */ 360 */
370 function lookupMatcher(service, requestedLocales) { 361 function lookupMatcher(service, requestedLocales) {
371 if (IS_NULL(service.match(GetServiceRE()))) { 362 if (IS_NULL(service.match(GetServiceRE()))) {
372 throw MakeError(kWrongServiceType, service); 363 throw MakeError(kWrongServiceType, service);
373 } 364 }
374 365
375 // Cache these, they don't ever change per service. 366 // Cache these, they don't ever change per service.
376 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { 367 if (AVAILABLE_LOCALES[service] === undefined) {
377 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); 368 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service);
378 } 369 }
379 370
380 for (var i = 0; i < requestedLocales.length; ++i) { 371 for (var i = 0; i < requestedLocales.length; ++i) {
381 // Remove all extensions. 372 // Remove all extensions.
382 var locale = requestedLocales[i].replace(GetAnyExtensionRE(), ''); 373 var locale = requestedLocales[i].replace(GetAnyExtensionRE(), '');
383 do { 374 do {
384 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { 375 if (AVAILABLE_LOCALES[service][locale] !== undefined) {
385 // Return the resolved locale and extension. 376 // Return the resolved locale and extension.
386 var extensionMatch = requestedLocales[i].match(GetUnicodeExtensionRE()); 377 var extensionMatch = requestedLocales[i].match(GetUnicodeExtensionRE());
387 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; 378 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0];
388 return {'locale': locale, 'extension': extension, 'position': i}; 379 return {'locale': locale, 'extension': extension, 'position': i};
389 } 380 }
390 // Truncate locale if possible. 381 // Truncate locale if possible.
391 var pos = locale.lastIndexOf('-'); 382 var pos = locale.lastIndexOf('-');
392 if (pos === -1) { 383 if (pos === -1) {
393 break; 384 break;
394 } 385 }
395 locale = locale.substring(0, pos); 386 locale = locale.substring(0, pos);
396 } while (true); 387 } while (true);
397 } 388 }
398 389
399 // Didn't find a match, return default. 390 // Didn't find a match, return default.
400 if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) { 391 if (DEFAULT_ICU_LOCALE === undefined) {
401 DEFAULT_ICU_LOCALE = %GetDefaultICULocale(); 392 DEFAULT_ICU_LOCALE = %GetDefaultICULocale();
402 } 393 }
403 394
404 return {'locale': DEFAULT_ICU_LOCALE, 'extension': '', 'position': -1}; 395 return {'locale': DEFAULT_ICU_LOCALE, 'extension': '', 'position': -1};
405 } 396 }
406 397
407 398
408 /** 399 /**
409 * Returns best matched supported locale and extension info using 400 * Returns best matched supported locale and extension info using
410 * implementation dependend algorithm. 401 * implementation dependend algorithm.
(...skipping 14 matching lines...) Expand all
425 416
426 // Assume ['', 'u', ...] input, but don't throw. 417 // Assume ['', 'u', ...] input, but don't throw.
427 if (extensionSplit.length <= 2 || 418 if (extensionSplit.length <= 2 ||
428 (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) { 419 (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) {
429 return {}; 420 return {};
430 } 421 }
431 422
432 // Key is {2}alphanum, value is {3,8}alphanum. 423 // Key is {2}alphanum, value is {3,8}alphanum.
433 // Some keys may not have explicit values (booleans). 424 // Some keys may not have explicit values (booleans).
434 var extensionMap = {}; 425 var extensionMap = {};
435 var previousKey = UNDEFINED; 426 var previousKey = undefined;
436 for (var i = 2; i < extensionSplit.length; ++i) { 427 for (var i = 2; i < extensionSplit.length; ++i) {
437 var length = extensionSplit[i].length; 428 var length = extensionSplit[i].length;
438 var element = extensionSplit[i]; 429 var element = extensionSplit[i];
439 if (length === 2) { 430 if (length === 2) {
440 extensionMap[element] = UNDEFINED; 431 extensionMap[element] = undefined;
441 previousKey = element; 432 previousKey = element;
442 } else if (length >= 3 && length <=8 && !IS_UNDEFINED(previousKey)) { 433 } else if (length >= 3 && length <=8 && previousKey !== undefined) {
443 extensionMap[previousKey] = element; 434 extensionMap[previousKey] = element;
444 previousKey = UNDEFINED; 435 previousKey = undefined;
445 } else { 436 } else {
446 // There is a value that's too long, or that doesn't have a key. 437 // There is a value that's too long, or that doesn't have a key.
447 return {}; 438 return {};
448 } 439 }
449 } 440 }
450 441
451 return extensionMap; 442 return extensionMap;
452 } 443 }
453 444
454 445
(...skipping 12 matching lines...) Expand all
467 458
468 var updateExtension = function updateExtension(key, value) { 459 var updateExtension = function updateExtension(key, value) {
469 return '-' + key + '-' + GlobalString(value); 460 return '-' + key + '-' + GlobalString(value);
470 } 461 }
471 462
472 var updateProperty = function updateProperty(property, type, value) { 463 var updateProperty = function updateProperty(property, type, value) {
473 if (type === 'boolean' && (typeof value === 'string')) { 464 if (type === 'boolean' && (typeof value === 'string')) {
474 value = (value === 'true') ? true : false; 465 value = (value === 'true') ? true : false;
475 } 466 }
476 467
477 if (!IS_UNDEFINED(property)) { 468 if (property !== undefined) {
478 defineWEProperty(outOptions, property, value); 469 defineWEProperty(outOptions, property, value);
479 } 470 }
480 } 471 }
481 472
482 for (var key in keyValues) { 473 for (var key in keyValues) {
483 if (keyValues.hasOwnProperty(key)) { 474 if (keyValues.hasOwnProperty(key)) {
484 var value = UNDEFINED; 475 var value = undefined;
485 var map = keyValues[key]; 476 var map = keyValues[key];
486 if (!IS_UNDEFINED(map.property)) { 477 if (map.property !== undefined) {
487 // This may return true if user specifies numeric: 'false', since 478 // This may return true if user specifies numeric: 'false', since
488 // Boolean('nonempty') === true. 479 // Boolean('nonempty') === true.
489 value = getOption(map.property, map.type, map.values); 480 value = getOption(map.property, map.type, map.values);
490 } 481 }
491 if (!IS_UNDEFINED(value)) { 482 if (value !== undefined) {
492 updateProperty(map.property, map.type, value); 483 updateProperty(map.property, map.type, value);
493 extension += updateExtension(key, value); 484 extension += updateExtension(key, value);
494 continue; 485 continue;
495 } 486 }
496 // User options didn't have it, check Unicode extension. 487 // User options didn't have it, check Unicode extension.
497 // Here we want to convert strings 'true', 'false' into proper Boolean 488 // Here we want to convert strings 'true', 'false' into proper Boolean
498 // values (not a user error). 489 // values (not a user error).
499 if (extensionMap.hasOwnProperty(key)) { 490 if (extensionMap.hasOwnProperty(key)) {
500 value = extensionMap[key]; 491 value = extensionMap[key];
501 if (!IS_UNDEFINED(value)) { 492 if (value !== undefined) {
502 updateProperty(map.property, map.type, value); 493 updateProperty(map.property, map.type, value);
503 extension += updateExtension(key, value); 494 extension += updateExtension(key, value);
504 } else if (map.type === 'boolean') { 495 } else if (map.type === 'boolean') {
505 // Boolean keys are allowed not to have values in Unicode extension. 496 // Boolean keys are allowed not to have values in Unicode extension.
506 // Those default to true. 497 // Those default to true.
507 updateProperty(map.property, map.type, true); 498 updateProperty(map.property, map.type, true);
508 extension += updateExtension(key, true); 499 extension += updateExtension(key, true);
509 } 500 }
510 } 501 }
511 } 502 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 $objectDefineProperty(object, property, 583 $objectDefineProperty(object, property,
593 {value: value, writable: true, enumerable: true}); 584 {value: value, writable: true, enumerable: true});
594 } 585 }
595 586
596 587
597 /** 588 /**
598 * Adds property to an object if the value is not undefined. 589 * Adds property to an object if the value is not undefined.
599 * Sets configurable descriptor to false. 590 * Sets configurable descriptor to false.
600 */ 591 */
601 function addWEPropertyIfDefined(object, property, value) { 592 function addWEPropertyIfDefined(object, property, value) {
602 if (!IS_UNDEFINED(value)) { 593 if (value !== undefined) {
603 defineWEProperty(object, property, value); 594 defineWEProperty(object, property, value);
604 } 595 }
605 } 596 }
606 597
607 598
608 /** 599 /**
609 * Defines a property and sets writable, enumerable and configurable to true. 600 * Defines a property and sets writable, enumerable and configurable to true.
610 */ 601 */
611 function defineWECProperty(object, property, value) { 602 function defineWECProperty(object, property, value) {
612 $objectDefineProperty(object, property, {value: value, 603 $objectDefineProperty(object, property, {value: value,
613 writable: true, 604 writable: true,
614 enumerable: true, 605 enumerable: true,
615 configurable: true}); 606 configurable: true});
616 } 607 }
617 608
618 609
619 /** 610 /**
620 * Adds property to an object if the value is not undefined. 611 * Adds property to an object if the value is not undefined.
621 * Sets all descriptors to true. 612 * Sets all descriptors to true.
622 */ 613 */
623 function addWECPropertyIfDefined(object, property, value) { 614 function addWECPropertyIfDefined(object, property, value) {
624 if (!IS_UNDEFINED(value)) { 615 if (value !== undefined) {
625 defineWECProperty(object, property, value); 616 defineWECProperty(object, property, value);
626 } 617 }
627 } 618 }
628 619
629 620
630 /** 621 /**
631 * Returns titlecased word, aMeRricA -> America. 622 * Returns titlecased word, aMeRricA -> America.
632 */ 623 */
633 function toTitleCaseWord(word) { 624 function toTitleCaseWord(word) {
634 return word.substr(0, 1).toUpperCase() + word.substr(1).toLowerCase(); 625 return word.substr(0, 1).toUpperCase() + word.substr(1).toLowerCase();
(...skipping 27 matching lines...) Expand all
662 return tag; 653 return tag;
663 } 654 }
664 655
665 656
666 /** 657 /**
667 * Returns an array where all locales are canonicalized and duplicates removed. 658 * Returns an array where all locales are canonicalized and duplicates removed.
668 * Throws on locales that are not well formed BCP47 tags. 659 * Throws on locales that are not well formed BCP47 tags.
669 */ 660 */
670 function initializeLocaleList(locales) { 661 function initializeLocaleList(locales) {
671 var seen = []; 662 var seen = [];
672 if (IS_UNDEFINED(locales)) { 663 if (locales === undefined) {
673 // Constructor is called without arguments. 664 // Constructor is called without arguments.
674 seen = []; 665 seen = [];
675 } else { 666 } else {
676 // We allow single string localeID. 667 // We allow single string localeID.
677 if (typeof locales === 'string') { 668 if (typeof locales === 'string') {
678 seen.push(canonicalizeLanguageTag(locales)); 669 seen.push(canonicalizeLanguageTag(locales));
679 return freezeArray(seen); 670 return freezeArray(seen);
680 } 671 }
681 672
682 var o = $toObject(locales); 673 var o = $toObject(locales);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 786
796 /** 787 /**
797 * Initializes the given object so it's a valid Collator instance. 788 * Initializes the given object so it's a valid Collator instance.
798 * Useful for subclassing. 789 * Useful for subclassing.
799 */ 790 */
800 function initializeCollator(collator, locales, options) { 791 function initializeCollator(collator, locales, options) {
801 if (%IsInitializedIntlObject(collator)) { 792 if (%IsInitializedIntlObject(collator)) {
802 throw MakeTypeError(kReinitializeIntl, "Collator"); 793 throw MakeTypeError(kReinitializeIntl, "Collator");
803 } 794 }
804 795
805 if (IS_UNDEFINED(options)) { 796 if (options === undefined) {
806 options = {}; 797 options = {};
807 } 798 }
808 799
809 var getOption = getGetOption(options, 'collator'); 800 var getOption = getGetOption(options, 'collator');
810 801
811 var internalOptions = {}; 802 var internalOptions = {};
812 803
813 defineWEProperty(internalOptions, 'usage', getOption( 804 defineWEProperty(internalOptions, 'usage', getOption(
814 'usage', 'string', ['sort', 'search'], 'sort')); 805 'usage', 'string', ['sort', 'search'], 'sort'));
815 806
816 var sensitivity = getOption('sensitivity', 'string', 807 var sensitivity = getOption('sensitivity', 'string',
817 ['base', 'accent', 'case', 'variant']); 808 ['base', 'accent', 'case', 'variant']);
818 if (IS_UNDEFINED(sensitivity) && internalOptions.usage === 'sort') { 809 if (sensitivity === undefined && internalOptions.usage === 'sort') {
819 sensitivity = 'variant'; 810 sensitivity = 'variant';
820 } 811 }
821 defineWEProperty(internalOptions, 'sensitivity', sensitivity); 812 defineWEProperty(internalOptions, 'sensitivity', sensitivity);
822 813
823 defineWEProperty(internalOptions, 'ignorePunctuation', getOption( 814 defineWEProperty(internalOptions, 'ignorePunctuation', getOption(
824 'ignorePunctuation', 'boolean', UNDEFINED, false)); 815 'ignorePunctuation', 'boolean', undefined, false));
825 816
826 var locale = resolveLocale('collator', locales, options); 817 var locale = resolveLocale('collator', locales, options);
827 818
828 // ICU can't take kb, kc... parameters through localeID, so we need to pass 819 // ICU can't take kb, kc... parameters through localeID, so we need to pass
829 // them as options. 820 // them as options.
830 // One exception is -co- which has to be part of the extension, but only for 821 // One exception is -co- which has to be part of the extension, but only for
831 // usage: sort, and its value can't be 'standard' or 'search'. 822 // usage: sort, and its value can't be 'standard' or 'search'.
832 var extensionMap = parseExtension(locale.extension); 823 var extensionMap = parseExtension(locale.extension);
833 824
834 /** 825 /**
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 currency.match(/[^A-Za-z]/) == null; 991 currency.match(/[^A-Za-z]/) == null;
1001 } 992 }
1002 993
1003 994
1004 /** 995 /**
1005 * Returns the valid digit count for a property, or throws RangeError on 996 * Returns the valid digit count for a property, or throws RangeError on
1006 * a value out of the range. 997 * a value out of the range.
1007 */ 998 */
1008 function getNumberOption(options, property, min, max, fallback) { 999 function getNumberOption(options, property, min, max, fallback) {
1009 var value = options[property]; 1000 var value = options[property];
1010 if (!IS_UNDEFINED(value)) { 1001 if (value !== undefined) {
1011 value = GlobalNumber(value); 1002 value = GlobalNumber(value);
1012 if ($isNaN(value) || value < min || value > max) { 1003 if ($isNaN(value) || value < min || value > max) {
1013 throw MakeRangeError(kPropertyValueOutOfRange, property); 1004 throw MakeRangeError(kPropertyValueOutOfRange, property);
1014 } 1005 }
1015 return MathFloor(value); 1006 return $floor(value);
1016 } 1007 }
1017 1008
1018 return fallback; 1009 return fallback;
1019 } 1010 }
1020 1011
1021 1012
1022 /** 1013 /**
1023 * Initializes the given object so it's a valid NumberFormat instance. 1014 * Initializes the given object so it's a valid NumberFormat instance.
1024 * Useful for subclassing. 1015 * Useful for subclassing.
1025 */ 1016 */
1026 function initializeNumberFormat(numberFormat, locales, options) { 1017 function initializeNumberFormat(numberFormat, locales, options) {
1027 if (%IsInitializedIntlObject(numberFormat)) { 1018 if (%IsInitializedIntlObject(numberFormat)) {
1028 throw MakeTypeError(kReinitializeIntl, "NumberFormat"); 1019 throw MakeTypeError(kReinitializeIntl, "NumberFormat");
1029 } 1020 }
1030 1021
1031 if (IS_UNDEFINED(options)) { 1022 if (options === undefined) {
1032 options = {}; 1023 options = {};
1033 } 1024 }
1034 1025
1035 var getOption = getGetOption(options, 'numberformat'); 1026 var getOption = getGetOption(options, 'numberformat');
1036 1027
1037 var locale = resolveLocale('numberformat', locales, options); 1028 var locale = resolveLocale('numberformat', locales, options);
1038 1029
1039 var internalOptions = {}; 1030 var internalOptions = {};
1040 defineWEProperty(internalOptions, 'style', getOption( 1031 defineWEProperty(internalOptions, 'style', getOption(
1041 'style', 'string', ['decimal', 'percent', 'currency'], 'decimal')); 1032 'style', 'string', ['decimal', 'percent', 'currency'], 'decimal'));
1042 1033
1043 var currency = getOption('currency', 'string'); 1034 var currency = getOption('currency', 'string');
1044 if (!IS_UNDEFINED(currency) && !isWellFormedCurrencyCode(currency)) { 1035 if (currency !== undefined && !isWellFormedCurrencyCode(currency)) {
1045 throw MakeRangeError(kInvalidCurrencyCode, currency); 1036 throw MakeRangeError(kInvalidCurrencyCode, currency);
1046 } 1037 }
1047 1038
1048 if (internalOptions.style === 'currency' && IS_UNDEFINED(currency)) { 1039 if (internalOptions.style === 'currency' && currency === undefined) {
1049 throw MakeTypeError(kCurrencyCode); 1040 throw MakeTypeError(kCurrencyCode);
1050 } 1041 }
1051 1042
1052 var currencyDisplay = getOption( 1043 var currencyDisplay = getOption(
1053 'currencyDisplay', 'string', ['code', 'symbol', 'name'], 'symbol'); 1044 'currencyDisplay', 'string', ['code', 'symbol', 'name'], 'symbol');
1054 if (internalOptions.style === 'currency') { 1045 if (internalOptions.style === 'currency') {
1055 defineWEProperty(internalOptions, 'currency', currency.toUpperCase()); 1046 defineWEProperty(internalOptions, 'currency', currency.toUpperCase());
1056 defineWEProperty(internalOptions, 'currencyDisplay', currencyDisplay); 1047 defineWEProperty(internalOptions, 'currencyDisplay', currencyDisplay);
1057 } 1048 }
1058 1049
1059 // Digit ranges. 1050 // Digit ranges.
1060 var mnid = getNumberOption(options, 'minimumIntegerDigits', 1, 21, 1); 1051 var mnid = getNumberOption(options, 'minimumIntegerDigits', 1, 21, 1);
1061 defineWEProperty(internalOptions, 'minimumIntegerDigits', mnid); 1052 defineWEProperty(internalOptions, 'minimumIntegerDigits', mnid);
1062 1053
1063 var mnfd = getNumberOption(options, 'minimumFractionDigits', 0, 20, 0); 1054 var mnfd = getNumberOption(options, 'minimumFractionDigits', 0, 20, 0);
1064 defineWEProperty(internalOptions, 'minimumFractionDigits', mnfd); 1055 defineWEProperty(internalOptions, 'minimumFractionDigits', mnfd);
1065 1056
1066 var mxfd = getNumberOption(options, 'maximumFractionDigits', mnfd, 20, 3); 1057 var mxfd = getNumberOption(options, 'maximumFractionDigits', mnfd, 20, 3);
1067 defineWEProperty(internalOptions, 'maximumFractionDigits', mxfd); 1058 defineWEProperty(internalOptions, 'maximumFractionDigits', mxfd);
1068 1059
1069 var mnsd = options['minimumSignificantDigits']; 1060 var mnsd = options['minimumSignificantDigits'];
1070 var mxsd = options['maximumSignificantDigits']; 1061 var mxsd = options['maximumSignificantDigits'];
1071 if (!IS_UNDEFINED(mnsd) || !IS_UNDEFINED(mxsd)) { 1062 if (mnsd !== undefined || mxsd !== undefined) {
1072 mnsd = getNumberOption(options, 'minimumSignificantDigits', 1, 21, 0); 1063 mnsd = getNumberOption(options, 'minimumSignificantDigits', 1, 21, 0);
1073 defineWEProperty(internalOptions, 'minimumSignificantDigits', mnsd); 1064 defineWEProperty(internalOptions, 'minimumSignificantDigits', mnsd);
1074 1065
1075 mxsd = getNumberOption(options, 'maximumSignificantDigits', mnsd, 21, 21); 1066 mxsd = getNumberOption(options, 'maximumSignificantDigits', mnsd, 21, 21);
1076 defineWEProperty(internalOptions, 'maximumSignificantDigits', mxsd); 1067 defineWEProperty(internalOptions, 'maximumSignificantDigits', mxsd);
1077 } 1068 }
1078 1069
1079 // Grouping. 1070 // Grouping.
1080 defineWEProperty(internalOptions, 'useGrouping', getOption( 1071 defineWEProperty(internalOptions, 'useGrouping', getOption(
1081 'useGrouping', 'boolean', UNDEFINED, true)); 1072 'useGrouping', 'boolean', undefined, true));
1082 1073
1083 // ICU prefers options to be passed using -u- extension key/values for 1074 // ICU prefers options to be passed using -u- extension key/values for
1084 // number format, so we need to build that. 1075 // number format, so we need to build that.
1085 var extensionMap = parseExtension(locale.extension); 1076 var extensionMap = parseExtension(locale.extension);
1086 1077
1087 /** 1078 /**
1088 * Map of Unicode extensions to option properties, and their values and types, 1079 * Map of Unicode extensions to option properties, and their values and types,
1089 * for a number format. 1080 * for a number format.
1090 */ 1081 */
1091 var NUMBER_FORMAT_KEY_MAP = { 1082 var NUMBER_FORMAT_KEY_MAP = {
1092 'nu': {'property': UNDEFINED, 'type': 'string'} 1083 'nu': {'property': undefined, 'type': 'string'}
1093 }; 1084 };
1094 1085
1095 var extension = setOptions(options, extensionMap, NUMBER_FORMAT_KEY_MAP, 1086 var extension = setOptions(options, extensionMap, NUMBER_FORMAT_KEY_MAP,
1096 getOption, internalOptions); 1087 getOption, internalOptions);
1097 1088
1098 var requestedLocale = locale.locale + extension; 1089 var requestedLocale = locale.locale + extension;
1099 var resolved = $objectDefineProperties({}, { 1090 var resolved = $objectDefineProperties({}, {
1100 currency: {writable: true}, 1091 currency: {writable: true},
1101 currencyDisplay: {writable: true}, 1092 currencyDisplay: {writable: true},
1102 locale: {writable: true}, 1093 locale: {writable: true},
1103 maximumFractionDigits: {writable: true}, 1094 maximumFractionDigits: {writable: true},
1104 minimumFractionDigits: {writable: true}, 1095 minimumFractionDigits: {writable: true},
1105 minimumIntegerDigits: {writable: true}, 1096 minimumIntegerDigits: {writable: true},
1106 numberingSystem: {writable: true}, 1097 numberingSystem: {writable: true},
1107 requestedLocale: {value: requestedLocale, writable: true}, 1098 requestedLocale: {value: requestedLocale, writable: true},
1108 style: {value: internalOptions.style, writable: true}, 1099 style: {value: internalOptions.style, writable: true},
1109 useGrouping: {writable: true} 1100 useGrouping: {writable: true}
1110 }); 1101 });
1111 if (internalOptions.hasOwnProperty('minimumSignificantDigits')) { 1102 if (internalOptions.hasOwnProperty('minimumSignificantDigits')) {
1112 defineWEProperty(resolved, 'minimumSignificantDigits', UNDEFINED); 1103 defineWEProperty(resolved, 'minimumSignificantDigits', undefined);
1113 } 1104 }
1114 if (internalOptions.hasOwnProperty('maximumSignificantDigits')) { 1105 if (internalOptions.hasOwnProperty('maximumSignificantDigits')) {
1115 defineWEProperty(resolved, 'maximumSignificantDigits', UNDEFINED); 1106 defineWEProperty(resolved, 'maximumSignificantDigits', undefined);
1116 } 1107 }
1117 var formatter = %CreateNumberFormat(requestedLocale, 1108 var formatter = %CreateNumberFormat(requestedLocale,
1118 internalOptions, 1109 internalOptions,
1119 resolved); 1110 resolved);
1120 1111
1121 // We can't get information about number or currency style from ICU, so we 1112 // We can't get information about number or currency style from ICU, so we
1122 // assume user request was fulfilled. 1113 // assume user request was fulfilled.
1123 if (internalOptions.style === 'currency') { 1114 if (internalOptions.style === 'currency') {
1124 $objectDefineProperty(resolved, 'currencyDisplay', {value: currencyDisplay, 1115 $objectDefineProperty(resolved, 'currencyDisplay', {value: currencyDisplay,
1125 writable: true}); 1116 writable: true});
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 ['2-digit', 'numeric', 'narrow', 'short', 'long']); 1265 ['2-digit', 'numeric', 'narrow', 'short', 'long']);
1275 ldmlString += appendToLDMLString(option, {'2-digit': 'MM', 'numeric': 'M', 1266 ldmlString += appendToLDMLString(option, {'2-digit': 'MM', 'numeric': 'M',
1276 'narrow': 'MMMMM', 'short': 'MMM', 'long': 'MMMM'}); 1267 'narrow': 'MMMMM', 'short': 'MMM', 'long': 'MMMM'});
1277 1268
1278 option = getOption('day', 'string', ['2-digit', 'numeric']); 1269 option = getOption('day', 'string', ['2-digit', 'numeric']);
1279 ldmlString += appendToLDMLString( 1270 ldmlString += appendToLDMLString(
1280 option, {'2-digit': 'dd', 'numeric': 'd'}); 1271 option, {'2-digit': 'dd', 'numeric': 'd'});
1281 1272
1282 var hr12 = getOption('hour12', 'boolean'); 1273 var hr12 = getOption('hour12', 'boolean');
1283 option = getOption('hour', 'string', ['2-digit', 'numeric']); 1274 option = getOption('hour', 'string', ['2-digit', 'numeric']);
1284 if (IS_UNDEFINED(hr12)) { 1275 if (hr12 === undefined) {
1285 ldmlString += appendToLDMLString(option, {'2-digit': 'jj', 'numeric': 'j'}); 1276 ldmlString += appendToLDMLString(option, {'2-digit': 'jj', 'numeric': 'j'});
1286 } else if (hr12 === true) { 1277 } else if (hr12 === true) {
1287 ldmlString += appendToLDMLString(option, {'2-digit': 'hh', 'numeric': 'h'}); 1278 ldmlString += appendToLDMLString(option, {'2-digit': 'hh', 'numeric': 'h'});
1288 } else { 1279 } else {
1289 ldmlString += appendToLDMLString(option, {'2-digit': 'HH', 'numeric': 'H'}); 1280 ldmlString += appendToLDMLString(option, {'2-digit': 'HH', 'numeric': 'H'});
1290 } 1281 }
1291 1282
1292 option = getOption('minute', 'string', ['2-digit', 'numeric']); 1283 option = getOption('minute', 'string', ['2-digit', 'numeric']);
1293 ldmlString += appendToLDMLString(option, {'2-digit': 'mm', 'numeric': 'm'}); 1284 ldmlString += appendToLDMLString(option, {'2-digit': 'mm', 'numeric': 'm'});
1294 1285
1295 option = getOption('second', 'string', ['2-digit', 'numeric']); 1286 option = getOption('second', 'string', ['2-digit', 'numeric']);
1296 ldmlString += appendToLDMLString(option, {'2-digit': 'ss', 'numeric': 's'}); 1287 ldmlString += appendToLDMLString(option, {'2-digit': 'ss', 'numeric': 's'});
1297 1288
1298 option = getOption('timeZoneName', 'string', ['short', 'long']); 1289 option = getOption('timeZoneName', 'string', ['short', 'long']);
1299 ldmlString += appendToLDMLString(option, {short: 'z', long: 'zzzz'}); 1290 ldmlString += appendToLDMLString(option, {short: 'z', long: 'zzzz'});
1300 1291
1301 return ldmlString; 1292 return ldmlString;
1302 } 1293 }
1303 1294
1304 1295
1305 /** 1296 /**
1306 * Returns either LDML equivalent of the current option or empty string. 1297 * Returns either LDML equivalent of the current option or empty string.
1307 */ 1298 */
1308 function appendToLDMLString(option, pairs) { 1299 function appendToLDMLString(option, pairs) {
1309 if (!IS_UNDEFINED(option)) { 1300 if (option !== undefined) {
1310 return pairs[option]; 1301 return pairs[option];
1311 } else { 1302 } else {
1312 return ''; 1303 return '';
1313 } 1304 }
1314 } 1305 }
1315 1306
1316 1307
1317 /** 1308 /**
1318 * Returns object that matches LDML representation of the date. 1309 * Returns object that matches LDML representation of the date.
1319 */ 1310 */
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1373 options = appendToDateTimeObject( 1364 options = appendToDateTimeObject(
1374 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); 1365 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'});
1375 1366
1376 return options; 1367 return options;
1377 } 1368 }
1378 1369
1379 1370
1380 function appendToDateTimeObject(options, option, match, pairs) { 1371 function appendToDateTimeObject(options, option, match, pairs) {
1381 if (IS_NULL(match)) { 1372 if (IS_NULL(match)) {
1382 if (!options.hasOwnProperty(option)) { 1373 if (!options.hasOwnProperty(option)) {
1383 defineWEProperty(options, option, UNDEFINED); 1374 defineWEProperty(options, option, undefined);
1384 } 1375 }
1385 return options; 1376 return options;
1386 } 1377 }
1387 1378
1388 var property = match[0]; 1379 var property = match[0];
1389 defineWEProperty(options, option, pairs[property]); 1380 defineWEProperty(options, option, pairs[property]);
1390 1381
1391 return options; 1382 return options;
1392 } 1383 }
1393 1384
1394 1385
1395 /** 1386 /**
1396 * Returns options with at least default values in it. 1387 * Returns options with at least default values in it.
1397 */ 1388 */
1398 function toDateTimeOptions(options, required, defaults) { 1389 function toDateTimeOptions(options, required, defaults) {
1399 if (IS_UNDEFINED(options)) { 1390 if (options === undefined) {
1400 options = {}; 1391 options = {};
1401 } else { 1392 } else {
1402 options = TO_OBJECT_INLINE(options); 1393 options = TO_OBJECT_INLINE(options);
1403 } 1394 }
1404 1395
1405 var needsDefault = true; 1396 var needsDefault = true;
1406 if ((required === 'date' || required === 'any') && 1397 if ((required === 'date' || required === 'any') &&
1407 (!IS_UNDEFINED(options.weekday) || !IS_UNDEFINED(options.year) || 1398 (options.weekday !== undefined || options.year !== undefined ||
1408 !IS_UNDEFINED(options.month) || !IS_UNDEFINED(options.day))) { 1399 options.month !== undefined || options.day !== undefined)) {
1409 needsDefault = false; 1400 needsDefault = false;
1410 } 1401 }
1411 1402
1412 if ((required === 'time' || required === 'any') && 1403 if ((required === 'time' || required === 'any') &&
1413 (!IS_UNDEFINED(options.hour) || !IS_UNDEFINED(options.minute) || 1404 (options.hour !== undefined || options.minute !== undefined ||
1414 !IS_UNDEFINED(options.second))) { 1405 options.second !== undefined)) {
1415 needsDefault = false; 1406 needsDefault = false;
1416 } 1407 }
1417 1408
1418 if (needsDefault && (defaults === 'date' || defaults === 'all')) { 1409 if (needsDefault && (defaults === 'date' || defaults === 'all')) {
1419 $objectDefineProperty(options, 'year', {value: 'numeric', 1410 $objectDefineProperty(options, 'year', {value: 'numeric',
1420 writable: true, 1411 writable: true,
1421 enumerable: true, 1412 enumerable: true,
1422 configurable: true}); 1413 configurable: true});
1423 $objectDefineProperty(options, 'month', {value: 'numeric', 1414 $objectDefineProperty(options, 'month', {value: 'numeric',
1424 writable: true, 1415 writable: true,
(...skipping 27 matching lines...) Expand all
1452 /** 1443 /**
1453 * Initializes the given object so it's a valid DateTimeFormat instance. 1444 * Initializes the given object so it's a valid DateTimeFormat instance.
1454 * Useful for subclassing. 1445 * Useful for subclassing.
1455 */ 1446 */
1456 function initializeDateTimeFormat(dateFormat, locales, options) { 1447 function initializeDateTimeFormat(dateFormat, locales, options) {
1457 1448
1458 if (%IsInitializedIntlObject(dateFormat)) { 1449 if (%IsInitializedIntlObject(dateFormat)) {
1459 throw MakeTypeError(kReinitializeIntl, "DateTimeFormat"); 1450 throw MakeTypeError(kReinitializeIntl, "DateTimeFormat");
1460 } 1451 }
1461 1452
1462 if (IS_UNDEFINED(options)) { 1453 if (options === undefined) {
1463 options = {}; 1454 options = {};
1464 } 1455 }
1465 1456
1466 var locale = resolveLocale('dateformat', locales, options); 1457 var locale = resolveLocale('dateformat', locales, options);
1467 1458
1468 options = toDateTimeOptions(options, 'any', 'date'); 1459 options = toDateTimeOptions(options, 'any', 'date');
1469 1460
1470 var getOption = getGetOption(options, 'dateformat'); 1461 var getOption = getGetOption(options, 'dateformat');
1471 1462
1472 // We implement only best fit algorithm, but still need to check 1463 // We implement only best fit algorithm, but still need to check
(...skipping 12 matching lines...) Expand all
1485 // ICU prefers options to be passed using -u- extension key/values, so 1476 // ICU prefers options to be passed using -u- extension key/values, so
1486 // we need to build that. 1477 // we need to build that.
1487 var internalOptions = {}; 1478 var internalOptions = {};
1488 var extensionMap = parseExtension(locale.extension); 1479 var extensionMap = parseExtension(locale.extension);
1489 1480
1490 /** 1481 /**
1491 * Map of Unicode extensions to option properties, and their values and types, 1482 * Map of Unicode extensions to option properties, and their values and types,
1492 * for a date/time format. 1483 * for a date/time format.
1493 */ 1484 */
1494 var DATETIME_FORMAT_KEY_MAP = { 1485 var DATETIME_FORMAT_KEY_MAP = {
1495 'ca': {'property': UNDEFINED, 'type': 'string'}, 1486 'ca': {'property': undefined, 'type': 'string'},
1496 'nu': {'property': UNDEFINED, 'type': 'string'} 1487 'nu': {'property': undefined, 'type': 'string'}
1497 }; 1488 };
1498 1489
1499 var extension = setOptions(options, extensionMap, DATETIME_FORMAT_KEY_MAP, 1490 var extension = setOptions(options, extensionMap, DATETIME_FORMAT_KEY_MAP,
1500 getOption, internalOptions); 1491 getOption, internalOptions);
1501 1492
1502 var requestedLocale = locale.locale + extension; 1493 var requestedLocale = locale.locale + extension;
1503 var resolved = $objectDefineProperties({}, { 1494 var resolved = $objectDefineProperties({}, {
1504 calendar: {writable: true}, 1495 calendar: {writable: true},
1505 day: {writable: true}, 1496 day: {writable: true},
1506 era: {writable: true}, 1497 era: {writable: true},
1507 hour12: {writable: true}, 1498 hour12: {writable: true},
1508 hour: {writable: true}, 1499 hour: {writable: true},
1509 locale: {writable: true}, 1500 locale: {writable: true},
1510 minute: {writable: true}, 1501 minute: {writable: true},
1511 month: {writable: true}, 1502 month: {writable: true},
1512 numberingSystem: {writable: true}, 1503 numberingSystem: {writable: true},
1513 pattern: {writable: true}, 1504 pattern: {writable: true},
1514 requestedLocale: {value: requestedLocale, writable: true}, 1505 requestedLocale: {value: requestedLocale, writable: true},
1515 second: {writable: true}, 1506 second: {writable: true},
1516 timeZone: {writable: true}, 1507 timeZone: {writable: true},
1517 timeZoneName: {writable: true}, 1508 timeZoneName: {writable: true},
1518 tz: {value: tz, writable: true}, 1509 tz: {value: tz, writable: true},
1519 weekday: {writable: true}, 1510 weekday: {writable: true},
1520 year: {writable: true} 1511 year: {writable: true}
1521 }); 1512 });
1522 1513
1523 var formatter = %CreateDateTimeFormat( 1514 var formatter = %CreateDateTimeFormat(
1524 requestedLocale, {skeleton: ldmlString, timeZone: tz}, resolved); 1515 requestedLocale, {skeleton: ldmlString, timeZone: tz}, resolved);
1525 1516
1526 if (!IS_UNDEFINED(tz) && tz !== resolved.timeZone) { 1517 if (tz !== undefined && tz !== resolved.timeZone) {
1527 throw MakeRangeError(kUnsupportedTimeZone, tz); 1518 throw MakeRangeError(kUnsupportedTimeZone, tz);
1528 } 1519 }
1529 1520
1530 %MarkAsInitializedIntlObjectOfType(dateFormat, 'dateformat', formatter); 1521 %MarkAsInitializedIntlObjectOfType(dateFormat, 'dateformat', formatter);
1531 $objectDefineProperty(dateFormat, 'resolved', {value: resolved}); 1522 $objectDefineProperty(dateFormat, 'resolved', {value: resolved});
1532 1523
1533 return dateFormat; 1524 return dateFormat;
1534 } 1525 }
1535 1526
1536 1527
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1582 'chinese': 'chinese', 1573 'chinese': 'chinese',
1583 'indian': 'indian', 1574 'indian': 'indian',
1584 'coptic': 'coptic', 1575 'coptic': 'coptic',
1585 'ethiopic': 'ethiopic', 1576 'ethiopic': 'ethiopic',
1586 'ethiopic-amete-alem': 'ethioaa' 1577 'ethiopic-amete-alem': 'ethioaa'
1587 }; 1578 };
1588 1579
1589 var format = this; 1580 var format = this;
1590 var fromPattern = fromLDMLString(format.resolved.pattern); 1581 var fromPattern = fromLDMLString(format.resolved.pattern);
1591 var userCalendar = ICU_CALENDAR_MAP[format.resolved.calendar]; 1582 var userCalendar = ICU_CALENDAR_MAP[format.resolved.calendar];
1592 if (IS_UNDEFINED(userCalendar)) { 1583 if (userCalendar === undefined) {
1593 // Use ICU name if we don't have a match. It shouldn't happen, but 1584 // Use ICU name if we don't have a match. It shouldn't happen, but
1594 // it would be too strict to throw for this. 1585 // it would be too strict to throw for this.
1595 userCalendar = format.resolved.calendar; 1586 userCalendar = format.resolved.calendar;
1596 } 1587 }
1597 1588
1598 var locale = getOptimalLanguageTag(format.resolved.requestedLocale, 1589 var locale = getOptimalLanguageTag(format.resolved.requestedLocale,
1599 format.resolved.locale); 1590 format.resolved.locale);
1600 1591
1601 var result = { 1592 var result = {
1602 locale: locale, 1593 locale: locale,
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1646 %SetNativeFlag(Intl.DateTimeFormat.supportedLocalesOf); 1637 %SetNativeFlag(Intl.DateTimeFormat.supportedLocalesOf);
1647 1638
1648 1639
1649 /** 1640 /**
1650 * Returns a String value representing the result of calling ToNumber(date) 1641 * Returns a String value representing the result of calling ToNumber(date)
1651 * according to the effective locale and the formatting options of this 1642 * according to the effective locale and the formatting options of this
1652 * DateTimeFormat. 1643 * DateTimeFormat.
1653 */ 1644 */
1654 function formatDate(formatter, dateValue) { 1645 function formatDate(formatter, dateValue) {
1655 var dateMs; 1646 var dateMs;
1656 if (IS_UNDEFINED(dateValue)) { 1647 if (dateValue === undefined) {
1657 dateMs = GlobalDate.now(); 1648 dateMs = GlobalDate.now();
1658 } else { 1649 } else {
1659 dateMs = $toNumber(dateValue); 1650 dateMs = $toNumber(dateValue);
1660 } 1651 }
1661 1652
1662 if (!$isFinite(dateMs)) throw MakeRangeError(kDateRange); 1653 if (!$isFinite(dateMs)) throw MakeRangeError(kDateRange);
1663 1654
1664 return %InternalDateFormat(%GetImplFromInitializedIntlObject(formatter), 1655 return %InternalDateFormat(%GetImplFromInitializedIntlObject(formatter),
1665 new GlobalDate(dateMs)); 1656 new GlobalDate(dateMs));
1666 } 1657 }
(...skipping 15 matching lines...) Expand all
1682 addBoundMethod(Intl.DateTimeFormat, 'format', formatDate, 0); 1673 addBoundMethod(Intl.DateTimeFormat, 'format', formatDate, 0);
1683 addBoundMethod(Intl.DateTimeFormat, 'v8Parse', parseDate, 1); 1674 addBoundMethod(Intl.DateTimeFormat, 'v8Parse', parseDate, 1);
1684 1675
1685 1676
1686 /** 1677 /**
1687 * Returns canonical Area/Location name, or throws an exception if the zone 1678 * Returns canonical Area/Location name, or throws an exception if the zone
1688 * name is invalid IANA name. 1679 * name is invalid IANA name.
1689 */ 1680 */
1690 function canonicalizeTimeZoneID(tzID) { 1681 function canonicalizeTimeZoneID(tzID) {
1691 // Skip undefined zones. 1682 // Skip undefined zones.
1692 if (IS_UNDEFINED(tzID)) { 1683 if (tzID === undefined) {
1693 return tzID; 1684 return tzID;
1694 } 1685 }
1695 1686
1696 // Special case handling (UTC, GMT). 1687 // Special case handling (UTC, GMT).
1697 var upperID = tzID.toUpperCase(); 1688 var upperID = tzID.toUpperCase();
1698 if (upperID === 'UTC' || upperID === 'GMT' || 1689 if (upperID === 'UTC' || upperID === 'GMT' ||
1699 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { 1690 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') {
1700 return 'UTC'; 1691 return 'UTC';
1701 } 1692 }
1702 1693
1703 // We expect only _ and / beside ASCII letters. 1694 // We expect only _ and / beside ASCII letters.
1704 // All inputs should conform to Area/Location from now on. 1695 // All inputs should conform to Area/Location from now on.
1705 var match = GetTimezoneNameCheckRE().exec(tzID); 1696 var match = GetTimezoneNameCheckRE().exec(tzID);
1706 if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, tzID); 1697 if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, tzID);
1707 1698
1708 var result = toTitleCaseWord(match[1]) + '/' + toTitleCaseWord(match[2]); 1699 var result = toTitleCaseWord(match[1]) + '/' + toTitleCaseWord(match[2]);
1709 var i = 3; 1700 var i = 3;
1710 while (!IS_UNDEFINED(match[i]) && i < match.length) { 1701 while (match[i] !== undefined && i < match.length) {
1711 result = result + '_' + toTitleCaseWord(match[i]); 1702 result = result + '_' + toTitleCaseWord(match[i]);
1712 i++; 1703 i++;
1713 } 1704 }
1714 1705
1715 return result; 1706 return result;
1716 } 1707 }
1717 1708
1718 /** 1709 /**
1719 * Initializes the given object so it's a valid BreakIterator instance. 1710 * Initializes the given object so it's a valid BreakIterator instance.
1720 * Useful for subclassing. 1711 * Useful for subclassing.
1721 */ 1712 */
1722 function initializeBreakIterator(iterator, locales, options) { 1713 function initializeBreakIterator(iterator, locales, options) {
1723 if (%IsInitializedIntlObject(iterator)) { 1714 if (%IsInitializedIntlObject(iterator)) {
1724 throw MakeTypeError(kReinitializeIntl, "v8BreakIterator"); 1715 throw MakeTypeError(kReinitializeIntl, "v8BreakIterator");
1725 } 1716 }
1726 1717
1727 if (IS_UNDEFINED(options)) { 1718 if (options === undefined) {
1728 options = {}; 1719 options = {};
1729 } 1720 }
1730 1721
1731 var getOption = getGetOption(options, 'breakiterator'); 1722 var getOption = getGetOption(options, 'breakiterator');
1732 1723
1733 var internalOptions = {}; 1724 var internalOptions = {};
1734 1725
1735 defineWEProperty(internalOptions, 'type', getOption( 1726 defineWEProperty(internalOptions, 'type', getOption(
1736 'type', 'string', ['character', 'word', 'sentence', 'line'], 'word')); 1727 'type', 'string', ['character', 'word', 'sentence', 'line'], 'word'));
1737 1728
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1880 'numberformat': Intl.NumberFormat, 1871 'numberformat': Intl.NumberFormat,
1881 'dateformatall': Intl.DateTimeFormat, 1872 'dateformatall': Intl.DateTimeFormat,
1882 'dateformatdate': Intl.DateTimeFormat, 1873 'dateformatdate': Intl.DateTimeFormat,
1883 'dateformattime': Intl.DateTimeFormat 1874 'dateformattime': Intl.DateTimeFormat
1884 }; 1875 };
1885 1876
1886 1877
1887 // Default (created with undefined locales and options parameters) collator, 1878 // Default (created with undefined locales and options parameters) collator,
1888 // number and date format instances. They'll be created as needed. 1879 // number and date format instances. They'll be created as needed.
1889 var defaultObjects = { 1880 var defaultObjects = {
1890 'collator': UNDEFINED, 1881 'collator': undefined,
1891 'numberformat': UNDEFINED, 1882 'numberformat': undefined,
1892 'dateformatall': UNDEFINED, 1883 'dateformatall': undefined,
1893 'dateformatdate': UNDEFINED, 1884 'dateformatdate': undefined,
1894 'dateformattime': UNDEFINED, 1885 'dateformattime': undefined,
1895 }; 1886 };
1896 1887
1897 1888
1898 /** 1889 /**
1899 * Returns cached or newly created instance of a given service. 1890 * Returns cached or newly created instance of a given service.
1900 * We cache only default instances (where no locales or options are provided). 1891 * We cache only default instances (where no locales or options are provided).
1901 */ 1892 */
1902 function cachedOrNewService(service, locales, options, defaults) { 1893 function cachedOrNewService(service, locales, options, defaults) {
1903 var useOptions = (IS_UNDEFINED(defaults)) ? options : defaults; 1894 var useOptions = (defaults === undefined) ? options : defaults;
1904 if (IS_UNDEFINED(locales) && IS_UNDEFINED(options)) { 1895 if (locales === undefined && options === undefined) {
1905 if (IS_UNDEFINED(defaultObjects[service])) { 1896 if (defaultObjects[service] === undefined) {
1906 defaultObjects[service] = new savedObjects[service](locales, useOptions); 1897 defaultObjects[service] = new savedObjects[service](locales, useOptions);
1907 } 1898 }
1908 return defaultObjects[service]; 1899 return defaultObjects[service];
1909 } 1900 }
1910 return new savedObjects[service](locales, useOptions); 1901 return new savedObjects[service](locales, useOptions);
1911 } 1902 }
1912 1903
1913 1904
1914 /** 1905 /**
1915 * Compares this and that, and returns less than 0, 0 or greater than 0 value. 1906 * Compares this and that, and returns less than 0, 0 or greater than 0 value.
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
2049 } 2040 }
2050 2041
2051 var locales = %_Arguments(0); 2042 var locales = %_Arguments(0);
2052 var options = %_Arguments(1); 2043 var options = %_Arguments(1);
2053 return toLocaleDateTime( 2044 return toLocaleDateTime(
2054 this, locales, options, 'time', 'time', 'dateformattime'); 2045 this, locales, options, 'time', 'time', 'dateformattime');
2055 } 2046 }
2056 ); 2047 );
2057 2048
2058 }) 2049 })
OLDNEW
« no previous file with comments | « src/harmony-typedarray.js ('k') | src/iterator-prototype.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698