OLD | NEW |
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, utils) { |
12 | 12 |
13 "use strict"; | 13 "use strict"; |
14 | 14 |
15 %CheckIsBootstrapping(); | 15 %CheckIsBootstrapping(); |
16 | 16 |
17 // ------------------------------------------------------------------- | 17 // ------------------------------------------------------------------- |
18 // Imports | 18 // Imports |
19 | 19 |
20 var GlobalBoolean = global.Boolean; | 20 var GlobalBoolean = global.Boolean; |
21 var GlobalDate = global.Date; | 21 var GlobalDate = global.Date; |
22 var GlobalNumber = global.Number; | 22 var GlobalNumber = global.Number; |
23 var GlobalRegExp = global.RegExp; | 23 var GlobalRegExp = global.RegExp; |
24 var GlobalString = global.String; | 24 var GlobalString = global.String; |
25 var ObjectDefineProperties = utils.ObjectDefineProperties; | 25 var ObjectDefineProperties = utils.ObjectDefineProperties; |
26 var ObjectDefineProperty = utils.ObjectDefineProperty; | 26 var ObjectDefineProperty = utils.ObjectDefineProperty; |
27 var SetFunctionName = utils.SetFunctionName; | 27 var SetFunctionName = utils.SetFunctionName; |
28 | 28 |
| 29 var ArrayIndexOf; |
| 30 var ArrayJoin; |
29 var IsFinite; | 31 var IsFinite; |
30 var IsNaN; | 32 var IsNaN; |
31 var MathFloor; | 33 var MathFloor; |
| 34 var RegExpTest; |
| 35 var StringIndexOf; |
| 36 var StringLastIndexOf; |
| 37 var StringMatch; |
| 38 var StringReplace; |
| 39 var StringSplit; |
| 40 var StringSubstr; |
| 41 var StringSubstring; |
32 | 42 |
33 utils.Import(function(from) { | 43 utils.Import(function(from) { |
| 44 ArrayIndexOf = from.ArrayIndexOf; |
| 45 ArrayJoin = from.ArrayJoin; |
34 IsFinite = from.IsFinite; | 46 IsFinite = from.IsFinite; |
35 IsNaN = from.IsNaN; | 47 IsNaN = from.IsNaN; |
36 MathFloor = from.MathFloor; | 48 MathFloor = from.MathFloor; |
| 49 RegExpTest = from.RegExpTest; |
| 50 StringIndexOf = from.StringIndexOf; |
| 51 StringLastIndexOf = from.StringLastIndexOf; |
| 52 StringMatch = from.StringMatch; |
| 53 StringReplace = from.StringReplace; |
| 54 StringSplit = from.StringSplit; |
| 55 StringSubstr = from.StringSubstr; |
| 56 StringSubstring = from.StringSubstring; |
37 }); | 57 }); |
38 | 58 |
39 // ------------------------------------------------------------------- | 59 // ------------------------------------------------------------------- |
40 | 60 |
41 var Intl = {}; | 61 var Intl = {}; |
42 | 62 |
43 %AddNamedProperty(global, "Intl", Intl, DONT_ENUM); | 63 %AddNamedProperty(global, "Intl", Intl, DONT_ENUM); |
44 | 64 |
45 /** | 65 /** |
46 * Caches available locales for each service. | 66 * Caches available locales for each service. |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 configurable: true | 236 configurable: true |
217 }); | 237 }); |
218 } | 238 } |
219 | 239 |
220 | 240 |
221 /** | 241 /** |
222 * Returns an intersection of locales and service supported locales. | 242 * Returns an intersection of locales and service supported locales. |
223 * Parameter locales is treated as a priority list. | 243 * Parameter locales is treated as a priority list. |
224 */ | 244 */ |
225 function supportedLocalesOf(service, locales, options) { | 245 function supportedLocalesOf(service, locales, options) { |
226 if (IS_NULL(service.match(GetServiceRE()))) { | 246 if (IS_NULL(%_CallFunction(service, GetServiceRE(), StringMatch))) { |
227 throw MakeError(kWrongServiceType, service); | 247 throw MakeError(kWrongServiceType, service); |
228 } | 248 } |
229 | 249 |
230 // Provide defaults if matcher was not specified. | 250 // Provide defaults if matcher was not specified. |
231 if (IS_UNDEFINED(options)) { | 251 if (IS_UNDEFINED(options)) { |
232 options = {}; | 252 options = {}; |
233 } else { | 253 } else { |
234 options = $toObject(options); | 254 options = $toObject(options); |
235 } | 255 } |
236 | 256 |
(...skipping 27 matching lines...) Expand all Loading... |
264 | 284 |
265 /** | 285 /** |
266 * Returns the subset of the provided BCP 47 language priority list for which | 286 * Returns the subset of the provided BCP 47 language priority list for which |
267 * this service has a matching locale when using the BCP 47 Lookup algorithm. | 287 * this service has a matching locale when using the BCP 47 Lookup algorithm. |
268 * Locales appear in the same order in the returned list as in the input list. | 288 * Locales appear in the same order in the returned list as in the input list. |
269 */ | 289 */ |
270 function lookupSupportedLocalesOf(requestedLocales, availableLocales) { | 290 function lookupSupportedLocalesOf(requestedLocales, availableLocales) { |
271 var matchedLocales = []; | 291 var matchedLocales = []; |
272 for (var i = 0; i < requestedLocales.length; ++i) { | 292 for (var i = 0; i < requestedLocales.length; ++i) { |
273 // Remove -u- extension. | 293 // Remove -u- extension. |
274 var locale = requestedLocales[i].replace(GetUnicodeExtensionRE(), ''); | 294 var locale = %_CallFunction(requestedLocales[i], GetUnicodeExtensionRE(), |
| 295 '', StringReplace); |
275 do { | 296 do { |
276 if (!IS_UNDEFINED(availableLocales[locale])) { | 297 if (!IS_UNDEFINED(availableLocales[locale])) { |
277 // Push requested locale not the resolved one. | 298 // Push requested locale not the resolved one. |
278 matchedLocales.push(requestedLocales[i]); | 299 %_CallFunction(matchedLocales, requestedLocales[i], $arrayPush); |
279 break; | 300 break; |
280 } | 301 } |
281 // Truncate locale if possible, if not break. | 302 // Truncate locale if possible, if not break. |
282 var pos = locale.lastIndexOf('-'); | 303 var pos = %_CallFunction(locale, '-', StringLastIndexOf); |
283 if (pos === -1) { | 304 if (pos === -1) { |
284 break; | 305 break; |
285 } | 306 } |
286 locale = locale.substring(0, pos); | 307 locale = %_CallFunction(locale, 0, pos, StringSubstring); |
287 } while (true); | 308 } while (true); |
288 } | 309 } |
289 | 310 |
290 return matchedLocales; | 311 return matchedLocales; |
291 } | 312 } |
292 | 313 |
293 | 314 |
294 /** | 315 /** |
295 * Returns the subset of the provided BCP 47 language priority list for which | 316 * Returns the subset of the provided BCP 47 language priority list for which |
296 * this service has a matching locale when using the implementation | 317 * this service has a matching locale when using the implementation |
(...skipping 23 matching lines...) Expand all Loading... |
320 break; | 341 break; |
321 case 'string': | 342 case 'string': |
322 value = GlobalString(value); | 343 value = GlobalString(value); |
323 break; | 344 break; |
324 case 'number': | 345 case 'number': |
325 value = GlobalNumber(value); | 346 value = GlobalNumber(value); |
326 break; | 347 break; |
327 default: | 348 default: |
328 throw MakeError(kWrongValueType); | 349 throw MakeError(kWrongValueType); |
329 } | 350 } |
330 if (!IS_UNDEFINED(values) && values.indexOf(value) === -1) { | 351 |
| 352 if (!IS_UNDEFINED(values) && |
| 353 %_CallFunction(values, value, ArrayIndexOf) === -1) { |
331 throw MakeRangeError(kValueOutOfRange, value, caller, property); | 354 throw MakeRangeError(kValueOutOfRange, value, caller, property); |
332 } | 355 } |
333 | 356 |
334 return value; | 357 return value; |
335 } | 358 } |
336 | 359 |
337 return defaultValue; | 360 return defaultValue; |
338 } | 361 } |
339 | 362 |
340 return getOption; | 363 return getOption; |
(...skipping 28 matching lines...) Expand all Loading... |
369 | 392 |
370 return resolved; | 393 return resolved; |
371 } | 394 } |
372 | 395 |
373 | 396 |
374 /** | 397 /** |
375 * Returns best matched supported locale and extension info using basic | 398 * Returns best matched supported locale and extension info using basic |
376 * lookup algorithm. | 399 * lookup algorithm. |
377 */ | 400 */ |
378 function lookupMatcher(service, requestedLocales) { | 401 function lookupMatcher(service, requestedLocales) { |
379 if (IS_NULL(service.match(GetServiceRE()))) { | 402 if (IS_NULL(%_CallFunction(service, GetServiceRE(), StringMatch))) { |
380 throw MakeError(kWrongServiceType, service); | 403 throw MakeError(kWrongServiceType, service); |
381 } | 404 } |
382 | 405 |
383 // Cache these, they don't ever change per service. | 406 // Cache these, they don't ever change per service. |
384 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { | 407 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { |
385 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); | 408 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); |
386 } | 409 } |
387 | 410 |
388 for (var i = 0; i < requestedLocales.length; ++i) { | 411 for (var i = 0; i < requestedLocales.length; ++i) { |
389 // Remove all extensions. | 412 // Remove all extensions. |
390 var locale = requestedLocales[i].replace(GetAnyExtensionRE(), ''); | 413 var locale = %_CallFunction(requestedLocales[i], GetAnyExtensionRE(), '', |
| 414 StringReplace); |
391 do { | 415 do { |
392 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { | 416 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { |
393 // Return the resolved locale and extension. | 417 // Return the resolved locale and extension. |
394 var extensionMatch = requestedLocales[i].match(GetUnicodeExtensionRE()); | 418 var extensionMatch = |
| 419 %_CallFunction(requestedLocales[i], GetUnicodeExtensionRE(), |
| 420 StringMatch); |
395 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; | 421 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; |
396 return {'locale': locale, 'extension': extension, 'position': i}; | 422 return {'locale': locale, 'extension': extension, 'position': i}; |
397 } | 423 } |
398 // Truncate locale if possible. | 424 // Truncate locale if possible. |
399 var pos = locale.lastIndexOf('-'); | 425 var pos = %_CallFunction(locale, '-', StringLastIndexOf); |
400 if (pos === -1) { | 426 if (pos === -1) { |
401 break; | 427 break; |
402 } | 428 } |
403 locale = locale.substring(0, pos); | 429 locale = %_CallFunction(locale, 0, pos, StringSubstring); |
404 } while (true); | 430 } while (true); |
405 } | 431 } |
406 | 432 |
407 // Didn't find a match, return default. | 433 // Didn't find a match, return default. |
408 if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) { | 434 if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) { |
409 DEFAULT_ICU_LOCALE = %GetDefaultICULocale(); | 435 DEFAULT_ICU_LOCALE = %GetDefaultICULocale(); |
410 } | 436 } |
411 | 437 |
412 return {'locale': DEFAULT_ICU_LOCALE, 'extension': '', 'position': -1}; | 438 return {'locale': DEFAULT_ICU_LOCALE, 'extension': '', 'position': -1}; |
413 } | 439 } |
414 | 440 |
415 | 441 |
416 /** | 442 /** |
417 * Returns best matched supported locale and extension info using | 443 * Returns best matched supported locale and extension info using |
418 * implementation dependend algorithm. | 444 * implementation dependend algorithm. |
419 */ | 445 */ |
420 function bestFitMatcher(service, requestedLocales) { | 446 function bestFitMatcher(service, requestedLocales) { |
421 // TODO(cira): implement better best fit algorithm. | 447 // TODO(cira): implement better best fit algorithm. |
422 return lookupMatcher(service, requestedLocales); | 448 return lookupMatcher(service, requestedLocales); |
423 } | 449 } |
424 | 450 |
425 | 451 |
426 /** | 452 /** |
427 * Parses Unicode extension into key - value map. | 453 * Parses Unicode extension into key - value map. |
428 * Returns empty object if the extension string is invalid. | 454 * Returns empty object if the extension string is invalid. |
429 * We are not concerned with the validity of the values at this point. | 455 * We are not concerned with the validity of the values at this point. |
430 */ | 456 */ |
431 function parseExtension(extension) { | 457 function parseExtension(extension) { |
432 var extensionSplit = extension.split('-'); | 458 var extensionSplit = %_CallFunction(extension, '-', StringSplit); |
433 | 459 |
434 // Assume ['', 'u', ...] input, but don't throw. | 460 // Assume ['', 'u', ...] input, but don't throw. |
435 if (extensionSplit.length <= 2 || | 461 if (extensionSplit.length <= 2 || |
436 (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) { | 462 (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) { |
437 return {}; | 463 return {}; |
438 } | 464 } |
439 | 465 |
440 // Key is {2}alphanum, value is {3,8}alphanum. | 466 // Key is {2}alphanum, value is {3,8}alphanum. |
441 // Some keys may not have explicit values (booleans). | 467 // Some keys may not have explicit values (booleans). |
442 var extensionMap = {}; | 468 var extensionMap = {}; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
481 if (type === 'boolean' && (typeof value === 'string')) { | 507 if (type === 'boolean' && (typeof value === 'string')) { |
482 value = (value === 'true') ? true : false; | 508 value = (value === 'true') ? true : false; |
483 } | 509 } |
484 | 510 |
485 if (!IS_UNDEFINED(property)) { | 511 if (!IS_UNDEFINED(property)) { |
486 defineWEProperty(outOptions, property, value); | 512 defineWEProperty(outOptions, property, value); |
487 } | 513 } |
488 } | 514 } |
489 | 515 |
490 for (var key in keyValues) { | 516 for (var key in keyValues) { |
491 if (keyValues.hasOwnProperty(key)) { | 517 if (%HasOwnProperty(keyValues, key)) { |
492 var value = UNDEFINED; | 518 var value = UNDEFINED; |
493 var map = keyValues[key]; | 519 var map = keyValues[key]; |
494 if (!IS_UNDEFINED(map.property)) { | 520 if (!IS_UNDEFINED(map.property)) { |
495 // This may return true if user specifies numeric: 'false', since | 521 // This may return true if user specifies numeric: 'false', since |
496 // Boolean('nonempty') === true. | 522 // Boolean('nonempty') === true. |
497 value = getOption(map.property, map.type, map.values); | 523 value = getOption(map.property, map.type, map.values); |
498 } | 524 } |
499 if (!IS_UNDEFINED(value)) { | 525 if (!IS_UNDEFINED(value)) { |
500 updateProperty(map.property, map.type, value); | 526 updateProperty(map.property, map.type, value); |
501 extension += updateExtension(key, value); | 527 extension += updateExtension(key, value); |
502 continue; | 528 continue; |
503 } | 529 } |
504 // User options didn't have it, check Unicode extension. | 530 // User options didn't have it, check Unicode extension. |
505 // Here we want to convert strings 'true', 'false' into proper Boolean | 531 // Here we want to convert strings 'true', 'false' into proper Boolean |
506 // values (not a user error). | 532 // values (not a user error). |
507 if (extensionMap.hasOwnProperty(key)) { | 533 if (%HasOwnProperty(extensionMap, key)) { |
508 value = extensionMap[key]; | 534 value = extensionMap[key]; |
509 if (!IS_UNDEFINED(value)) { | 535 if (!IS_UNDEFINED(value)) { |
510 updateProperty(map.property, map.type, value); | 536 updateProperty(map.property, map.type, value); |
511 extension += updateExtension(key, value); | 537 extension += updateExtension(key, value); |
512 } else if (map.type === 'boolean') { | 538 } else if (map.type === 'boolean') { |
513 // Boolean keys are allowed not to have values in Unicode extension. | 539 // Boolean keys are allowed not to have values in Unicode extension. |
514 // Those default to true. | 540 // Those default to true. |
515 updateProperty(map.property, map.type, true); | 541 updateProperty(map.property, map.type, true); |
516 extension += updateExtension(key, true); | 542 extension += updateExtension(key, true); |
517 } | 543 } |
518 } | 544 } |
519 } | 545 } |
520 } | 546 } |
521 | 547 |
522 return extension === ''? '' : '-u' + extension; | 548 return extension === ''? '' : '-u' + extension; |
523 } | 549 } |
524 | 550 |
525 | 551 |
526 /** | 552 /** |
527 * Converts all OwnProperties into | 553 * Converts all OwnProperties into |
528 * configurable: false, writable: false, enumerable: true. | 554 * configurable: false, writable: false, enumerable: true. |
529 */ | 555 */ |
530 function freezeArray(array) { | 556 function freezeArray(array) { |
531 array.forEach(function(element, index) { | 557 var l = array.length; |
532 ObjectDefineProperty(array, index, {value: element, | 558 for (var i = 0; i < l; i++) { |
533 configurable: false, | 559 if (i in array) { |
534 writable: false, | 560 ObjectDefineProperty(array, i, {value: array[i], |
535 enumerable: true}); | 561 configurable: false, |
536 }); | 562 writable: false, |
| 563 enumerable: true}); |
| 564 } |
| 565 } |
537 | 566 |
538 ObjectDefineProperty(array, 'length', {value: array.length, | 567 ObjectDefineProperty(array, 'length', {value: l, writable: false}); |
539 writable: false}); | |
540 return array; | 568 return array; |
541 } | 569 } |
542 | 570 |
543 | 571 |
544 /** | 572 /** |
545 * It's sometimes desireable to leave user requested locale instead of ICU | 573 * It's sometimes desireable to leave user requested locale instead of ICU |
546 * supported one (zh-TW is equivalent to zh-Hant-TW, so we should keep shorter | 574 * supported one (zh-TW is equivalent to zh-Hant-TW, so we should keep shorter |
547 * one, if that was what user requested). | 575 * one, if that was what user requested). |
548 * This function returns user specified tag if its maximized form matches ICU | 576 * This function returns user specified tag if its maximized form matches ICU |
549 * resolved locale. If not we return ICU result. | 577 * resolved locale. If not we return ICU result. |
550 */ | 578 */ |
551 function getOptimalLanguageTag(original, resolved) { | 579 function getOptimalLanguageTag(original, resolved) { |
552 // Returns Array<Object>, where each object has maximized and base properties. | 580 // Returns Array<Object>, where each object has maximized and base properties. |
553 // Maximized: zh -> zh-Hans-CN | 581 // Maximized: zh -> zh-Hans-CN |
554 // Base: zh-CN-u-ca-gregory -> zh-CN | 582 // Base: zh-CN-u-ca-gregory -> zh-CN |
555 // Take care of grandfathered or simple cases. | 583 // Take care of grandfathered or simple cases. |
556 if (original === resolved) { | 584 if (original === resolved) { |
557 return original; | 585 return original; |
558 } | 586 } |
559 | 587 |
560 var locales = %GetLanguageTagVariants([original, resolved]); | 588 var locales = %GetLanguageTagVariants([original, resolved]); |
561 if (locales[0].maximized !== locales[1].maximized) { | 589 if (locales[0].maximized !== locales[1].maximized) { |
562 return resolved; | 590 return resolved; |
563 } | 591 } |
564 | 592 |
565 // Preserve extensions of resolved locale, but swap base tags with original. | 593 // Preserve extensions of resolved locale, but swap base tags with original. |
566 var resolvedBase = new GlobalRegExp('^' + locales[1].base); | 594 var resolvedBase = new GlobalRegExp('^' + locales[1].base); |
567 return resolved.replace(resolvedBase, locales[0].base); | 595 return %_CallFunction(resolved, resolvedBase, locales[0].base, StringReplace); |
568 } | 596 } |
569 | 597 |
570 | 598 |
571 /** | 599 /** |
572 * Returns an Object that contains all of supported locales for a given | 600 * Returns an Object that contains all of supported locales for a given |
573 * service. | 601 * service. |
574 * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ | 602 * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ |
575 * that is supported. This is required by the spec. | 603 * that is supported. This is required by the spec. |
576 */ | 604 */ |
577 function getAvailableLocalesOf(service) { | 605 function getAvailableLocalesOf(service) { |
578 var available = %AvailableLocalesOf(service); | 606 var available = %AvailableLocalesOf(service); |
579 | 607 |
580 for (var i in available) { | 608 for (var i in available) { |
581 if (available.hasOwnProperty(i)) { | 609 if (%HasOwnProperty(available, i)) { |
582 var parts = i.match(/^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/); | 610 var parts = %_CallFunction(i, /^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/, |
| 611 StringMatch); |
583 if (parts !== null) { | 612 if (parts !== null) { |
584 // Build xx-ZZ. We don't care about the actual value, | 613 // Build xx-ZZ. We don't care about the actual value, |
585 // as long it's not undefined. | 614 // as long it's not undefined. |
586 available[parts[1] + '-' + parts[3]] = null; | 615 available[parts[1] + '-' + parts[3]] = null; |
587 } | 616 } |
588 } | 617 } |
589 } | 618 } |
590 | 619 |
591 return available; | 620 return available; |
592 } | 621 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
632 if (!IS_UNDEFINED(value)) { | 661 if (!IS_UNDEFINED(value)) { |
633 defineWECProperty(object, property, value); | 662 defineWECProperty(object, property, value); |
634 } | 663 } |
635 } | 664 } |
636 | 665 |
637 | 666 |
638 /** | 667 /** |
639 * Returns titlecased word, aMeRricA -> America. | 668 * Returns titlecased word, aMeRricA -> America. |
640 */ | 669 */ |
641 function toTitleCaseWord(word) { | 670 function toTitleCaseWord(word) { |
642 return word.substr(0, 1).toUpperCase() + word.substr(1).toLowerCase(); | 671 return %StringToUpperCase(%_CallFunction(word, 0, 1, StringSubstr)) + |
| 672 %StringToLowerCase(%_CallFunction(word, 1, StringSubstr)); |
643 } | 673 } |
644 | 674 |
645 /** | 675 /** |
646 * Canonicalizes the language tag, or throws in case the tag is invalid. | 676 * Canonicalizes the language tag, or throws in case the tag is invalid. |
647 */ | 677 */ |
648 function canonicalizeLanguageTag(localeID) { | 678 function canonicalizeLanguageTag(localeID) { |
649 // null is typeof 'object' so we have to do extra check. | 679 // null is typeof 'object' so we have to do extra check. |
650 if (typeof localeID !== 'string' && typeof localeID !== 'object' || | 680 if (typeof localeID !== 'string' && typeof localeID !== 'object' || |
651 IS_NULL(localeID)) { | 681 IS_NULL(localeID)) { |
652 throw MakeTypeError(kLanguageID); | 682 throw MakeTypeError(kLanguageID); |
(...skipping 23 matching lines...) Expand all Loading... |
676 * Throws on locales that are not well formed BCP47 tags. | 706 * Throws on locales that are not well formed BCP47 tags. |
677 */ | 707 */ |
678 function initializeLocaleList(locales) { | 708 function initializeLocaleList(locales) { |
679 var seen = []; | 709 var seen = []; |
680 if (IS_UNDEFINED(locales)) { | 710 if (IS_UNDEFINED(locales)) { |
681 // Constructor is called without arguments. | 711 // Constructor is called without arguments. |
682 seen = []; | 712 seen = []; |
683 } else { | 713 } else { |
684 // We allow single string localeID. | 714 // We allow single string localeID. |
685 if (typeof locales === 'string') { | 715 if (typeof locales === 'string') { |
686 seen.push(canonicalizeLanguageTag(locales)); | 716 %_CallFunction(seen, canonicalizeLanguageTag(locales), $arrayPush); |
687 return freezeArray(seen); | 717 return freezeArray(seen); |
688 } | 718 } |
689 | 719 |
690 var o = $toObject(locales); | 720 var o = $toObject(locales); |
691 // Converts it to UInt32 (>>> is shr on 32bit integers). | 721 var len = TO_UINT32(o.length); |
692 var len = o.length >>> 0; | |
693 | 722 |
694 for (var k = 0; k < len; k++) { | 723 for (var k = 0; k < len; k++) { |
695 if (k in o) { | 724 if (k in o) { |
696 var value = o[k]; | 725 var value = o[k]; |
697 | 726 |
698 var tag = canonicalizeLanguageTag(value); | 727 var tag = canonicalizeLanguageTag(value); |
699 | 728 |
700 if (seen.indexOf(tag) === -1) { | 729 if (%_CallFunction(seen, tag, ArrayIndexOf) === -1) { |
701 seen.push(tag); | 730 %_CallFunction(seen, tag, $arrayPush); |
702 } | 731 } |
703 } | 732 } |
704 } | 733 } |
705 } | 734 } |
706 | 735 |
707 return freezeArray(seen); | 736 return freezeArray(seen); |
708 } | 737 } |
709 | 738 |
710 | 739 |
711 /** | 740 /** |
712 * Validates the language tag. Section 2.2.9 of the bcp47 spec | 741 * Validates the language tag. Section 2.2.9 of the bcp47 spec |
713 * defines a valid tag. | 742 * defines a valid tag. |
714 * | 743 * |
715 * ICU is too permissible and lets invalid tags, like | 744 * ICU is too permissible and lets invalid tags, like |
716 * hant-cmn-cn, through. | 745 * hant-cmn-cn, through. |
717 * | 746 * |
718 * Returns false if the language tag is invalid. | 747 * Returns false if the language tag is invalid. |
719 */ | 748 */ |
720 function isValidLanguageTag(locale) { | 749 function isValidLanguageTag(locale) { |
721 // Check if it's well-formed, including grandfadered tags. | 750 // Check if it's well-formed, including grandfadered tags. |
722 if (GetLanguageTagRE().test(locale) === false) { | 751 if (!%_CallFunction(GetLanguageTagRE(), locale, RegExpTest)) { |
723 return false; | 752 return false; |
724 } | 753 } |
725 | 754 |
726 // Just return if it's a x- form. It's all private. | 755 // Just return if it's a x- form. It's all private. |
727 if (locale.indexOf('x-') === 0) { | 756 if (%_CallFunction(locale, 'x-', StringIndexOf) === 0) { |
728 return true; | 757 return true; |
729 } | 758 } |
730 | 759 |
731 // Check if there are any duplicate variants or singletons (extensions). | 760 // Check if there are any duplicate variants or singletons (extensions). |
732 | 761 |
733 // Remove private use section. | 762 // Remove private use section. |
734 locale = locale.split(/-x-/)[0]; | 763 locale = %_CallFunction(locale, /-x-/, StringSplit)[0]; |
735 | 764 |
736 // Skip language since it can match variant regex, so we start from 1. | 765 // Skip language since it can match variant regex, so we start from 1. |
737 // We are matching i-klingon here, but that's ok, since i-klingon-klingon | 766 // We are matching i-klingon here, but that's ok, since i-klingon-klingon |
738 // is not valid and would fail LANGUAGE_TAG_RE test. | 767 // is not valid and would fail LANGUAGE_TAG_RE test. |
739 var variants = []; | 768 var variants = []; |
740 var extensions = []; | 769 var extensions = []; |
741 var parts = locale.split(/-/); | 770 var parts = %_CallFunction(locale, /-/, StringSplit); |
742 for (var i = 1; i < parts.length; i++) { | 771 for (var i = 1; i < parts.length; i++) { |
743 var value = parts[i]; | 772 var value = parts[i]; |
744 if (GetLanguageVariantRE().test(value) === true && extensions.length === 0)
{ | 773 if (%_CallFunction(GetLanguageVariantRE(), value, RegExpTest) && |
745 if (variants.indexOf(value) === -1) { | 774 extensions.length === 0) { |
746 variants.push(value); | 775 if (%_CallFunction(variants, value, ArrayIndexOf) === -1) { |
| 776 %_CallFunction(variants, value, $arrayPush); |
747 } else { | 777 } else { |
748 return false; | 778 return false; |
749 } | 779 } |
750 } | 780 } |
751 | 781 |
752 if (GetLanguageSingletonRE().test(value) === true) { | 782 if (%_CallFunction(GetLanguageSingletonRE(), value, RegExpTest)) { |
753 if (extensions.indexOf(value) === -1) { | 783 if (%_CallFunction(extensions, value, ArrayIndexOf) === -1) { |
754 extensions.push(value); | 784 %_CallFunction(extensions, value, $arrayPush); |
755 } else { | 785 } else { |
756 return false; | 786 return false; |
757 } | 787 } |
758 } | 788 } |
759 } | 789 } |
760 | 790 |
761 return true; | 791 return true; |
762 } | 792 } |
763 | 793 |
764 | 794 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
847 'kn': {'property': 'numeric', 'type': 'boolean'}, | 877 'kn': {'property': 'numeric', 'type': 'boolean'}, |
848 'kf': {'property': 'caseFirst', 'type': 'string', | 878 'kf': {'property': 'caseFirst', 'type': 'string', |
849 'values': ['false', 'lower', 'upper']} | 879 'values': ['false', 'lower', 'upper']} |
850 }; | 880 }; |
851 | 881 |
852 setOptions( | 882 setOptions( |
853 options, extensionMap, COLLATOR_KEY_MAP, getOption, internalOptions); | 883 options, extensionMap, COLLATOR_KEY_MAP, getOption, internalOptions); |
854 | 884 |
855 var collation = 'default'; | 885 var collation = 'default'; |
856 var extension = ''; | 886 var extension = ''; |
857 if (extensionMap.hasOwnProperty('co') && internalOptions.usage === 'sort') { | 887 if (%HasOwnProperty(extensionMap, 'co') && internalOptions.usage === 'sort') { |
858 | 888 |
859 /** | 889 /** |
860 * Allowed -u-co- values. List taken from: | 890 * Allowed -u-co- values. List taken from: |
861 * http://unicode.org/repos/cldr/trunk/common/bcp47/collation.xml | 891 * http://unicode.org/repos/cldr/trunk/common/bcp47/collation.xml |
862 */ | 892 */ |
863 var ALLOWED_CO_VALUES = [ | 893 var ALLOWED_CO_VALUES = [ |
864 'big5han', 'dict', 'direct', 'ducet', 'gb2312', 'phonebk', 'phonetic', | 894 'big5han', 'dict', 'direct', 'ducet', 'gb2312', 'phonebk', 'phonetic', |
865 'pinyin', 'reformed', 'searchjl', 'stroke', 'trad', 'unihan', 'zhuyin' | 895 'pinyin', 'reformed', 'searchjl', 'stroke', 'trad', 'unihan', 'zhuyin' |
866 ]; | 896 ]; |
867 | 897 |
868 if (ALLOWED_CO_VALUES.indexOf(extensionMap.co) !== -1) { | 898 if (%_CallFunction(ALLOWED_CO_VALUES, extensionMap.co, ArrayIndexOf) !== |
| 899 -1) { |
869 extension = '-u-co-' + extensionMap.co; | 900 extension = '-u-co-' + extensionMap.co; |
870 // ICU can't tell us what the collation is, so save user's input. | 901 // ICU can't tell us what the collation is, so save user's input. |
871 collation = extensionMap.co; | 902 collation = extensionMap.co; |
872 } | 903 } |
873 } else if (internalOptions.usage === 'search') { | 904 } else if (internalOptions.usage === 'search') { |
874 extension = '-u-co-search'; | 905 extension = '-u-co-search'; |
875 } | 906 } |
876 defineWEProperty(internalOptions, 'collation', collation); | 907 defineWEProperty(internalOptions, 'collation', collation); |
877 | 908 |
878 var requestedLocale = locale.locale + extension; | 909 var requestedLocale = locale.locale + extension; |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
998 addBoundMethod(Intl.Collator, 'compare', compare, 2); | 1029 addBoundMethod(Intl.Collator, 'compare', compare, 2); |
999 | 1030 |
1000 /** | 1031 /** |
1001 * Verifies that the input is a well-formed ISO 4217 currency code. | 1032 * Verifies that the input is a well-formed ISO 4217 currency code. |
1002 * Don't uppercase to test. It could convert invalid code into a valid one. | 1033 * Don't uppercase to test. It could convert invalid code into a valid one. |
1003 * For example \u00DFP (Eszett+P) becomes SSP. | 1034 * For example \u00DFP (Eszett+P) becomes SSP. |
1004 */ | 1035 */ |
1005 function isWellFormedCurrencyCode(currency) { | 1036 function isWellFormedCurrencyCode(currency) { |
1006 return typeof currency == "string" && | 1037 return typeof currency == "string" && |
1007 currency.length == 3 && | 1038 currency.length == 3 && |
1008 currency.match(/[^A-Za-z]/) == null; | 1039 %_CallFunction(currency, /[^A-Za-z]/, StringMatch) == null; |
1009 } | 1040 } |
1010 | 1041 |
1011 | 1042 |
1012 /** | 1043 /** |
1013 * Returns the valid digit count for a property, or throws RangeError on | 1044 * Returns the valid digit count for a property, or throws RangeError on |
1014 * a value out of the range. | 1045 * a value out of the range. |
1015 */ | 1046 */ |
1016 function getNumberOption(options, property, min, max, fallback) { | 1047 function getNumberOption(options, property, min, max, fallback) { |
1017 var value = options[property]; | 1048 var value = options[property]; |
1018 if (!IS_UNDEFINED(value)) { | 1049 if (!IS_UNDEFINED(value)) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1053 throw MakeRangeError(kInvalidCurrencyCode, currency); | 1084 throw MakeRangeError(kInvalidCurrencyCode, currency); |
1054 } | 1085 } |
1055 | 1086 |
1056 if (internalOptions.style === 'currency' && IS_UNDEFINED(currency)) { | 1087 if (internalOptions.style === 'currency' && IS_UNDEFINED(currency)) { |
1057 throw MakeTypeError(kCurrencyCode); | 1088 throw MakeTypeError(kCurrencyCode); |
1058 } | 1089 } |
1059 | 1090 |
1060 var currencyDisplay = getOption( | 1091 var currencyDisplay = getOption( |
1061 'currencyDisplay', 'string', ['code', 'symbol', 'name'], 'symbol'); | 1092 'currencyDisplay', 'string', ['code', 'symbol', 'name'], 'symbol'); |
1062 if (internalOptions.style === 'currency') { | 1093 if (internalOptions.style === 'currency') { |
1063 defineWEProperty(internalOptions, 'currency', currency.toUpperCase()); | 1094 defineWEProperty(internalOptions, 'currency', %StringToUpperCase(currency)); |
1064 defineWEProperty(internalOptions, 'currencyDisplay', currencyDisplay); | 1095 defineWEProperty(internalOptions, 'currencyDisplay', currencyDisplay); |
1065 } | 1096 } |
1066 | 1097 |
1067 // Digit ranges. | 1098 // Digit ranges. |
1068 var mnid = getNumberOption(options, 'minimumIntegerDigits', 1, 21, 1); | 1099 var mnid = getNumberOption(options, 'minimumIntegerDigits', 1, 21, 1); |
1069 defineWEProperty(internalOptions, 'minimumIntegerDigits', mnid); | 1100 defineWEProperty(internalOptions, 'minimumIntegerDigits', mnid); |
1070 | 1101 |
1071 var mnfd = getNumberOption(options, 'minimumFractionDigits', 0, 20, 0); | 1102 var mnfd = getNumberOption(options, 'minimumFractionDigits', 0, 20, 0); |
1072 defineWEProperty(internalOptions, 'minimumFractionDigits', mnfd); | 1103 defineWEProperty(internalOptions, 'minimumFractionDigits', mnfd); |
1073 | 1104 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1109 currencyDisplay: {writable: true}, | 1140 currencyDisplay: {writable: true}, |
1110 locale: {writable: true}, | 1141 locale: {writable: true}, |
1111 maximumFractionDigits: {writable: true}, | 1142 maximumFractionDigits: {writable: true}, |
1112 minimumFractionDigits: {writable: true}, | 1143 minimumFractionDigits: {writable: true}, |
1113 minimumIntegerDigits: {writable: true}, | 1144 minimumIntegerDigits: {writable: true}, |
1114 numberingSystem: {writable: true}, | 1145 numberingSystem: {writable: true}, |
1115 requestedLocale: {value: requestedLocale, writable: true}, | 1146 requestedLocale: {value: requestedLocale, writable: true}, |
1116 style: {value: internalOptions.style, writable: true}, | 1147 style: {value: internalOptions.style, writable: true}, |
1117 useGrouping: {writable: true} | 1148 useGrouping: {writable: true} |
1118 }); | 1149 }); |
1119 if (internalOptions.hasOwnProperty('minimumSignificantDigits')) { | 1150 if (%HasOwnProperty(internalOptions, 'minimumSignificantDigits')) { |
1120 defineWEProperty(resolved, 'minimumSignificantDigits', UNDEFINED); | 1151 defineWEProperty(resolved, 'minimumSignificantDigits', UNDEFINED); |
1121 } | 1152 } |
1122 if (internalOptions.hasOwnProperty('maximumSignificantDigits')) { | 1153 if (%HasOwnProperty(internalOptions, 'maximumSignificantDigits')) { |
1123 defineWEProperty(resolved, 'maximumSignificantDigits', UNDEFINED); | 1154 defineWEProperty(resolved, 'maximumSignificantDigits', UNDEFINED); |
1124 } | 1155 } |
1125 var formatter = %CreateNumberFormat(requestedLocale, | 1156 var formatter = %CreateNumberFormat(requestedLocale, |
1126 internalOptions, | 1157 internalOptions, |
1127 resolved); | 1158 resolved); |
1128 | 1159 |
1129 // We can't get information about number or currency style from ICU, so we | 1160 // We can't get information about number or currency style from ICU, so we |
1130 // assume user request was fulfilled. | 1161 // assume user request was fulfilled. |
1131 if (internalOptions.style === 'currency') { | 1162 if (internalOptions.style === 'currency') { |
1132 ObjectDefineProperty(resolved, 'currencyDisplay', {value: currencyDisplay, | 1163 ObjectDefineProperty(resolved, 'currencyDisplay', {value: currencyDisplay, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1186 minimumFractionDigits: format.resolved.minimumFractionDigits, | 1217 minimumFractionDigits: format.resolved.minimumFractionDigits, |
1187 maximumFractionDigits: format.resolved.maximumFractionDigits, | 1218 maximumFractionDigits: format.resolved.maximumFractionDigits, |
1188 }; | 1219 }; |
1189 | 1220 |
1190 if (result.style === 'currency') { | 1221 if (result.style === 'currency') { |
1191 defineWECProperty(result, 'currency', format.resolved.currency); | 1222 defineWECProperty(result, 'currency', format.resolved.currency); |
1192 defineWECProperty(result, 'currencyDisplay', | 1223 defineWECProperty(result, 'currencyDisplay', |
1193 format.resolved.currencyDisplay); | 1224 format.resolved.currencyDisplay); |
1194 } | 1225 } |
1195 | 1226 |
1196 if (format.resolved.hasOwnProperty('minimumSignificantDigits')) { | 1227 if (%HasOwnProperty(format.resolved, 'minimumSignificantDigits')) { |
1197 defineWECProperty(result, 'minimumSignificantDigits', | 1228 defineWECProperty(result, 'minimumSignificantDigits', |
1198 format.resolved.minimumSignificantDigits); | 1229 format.resolved.minimumSignificantDigits); |
1199 } | 1230 } |
1200 | 1231 |
1201 if (format.resolved.hasOwnProperty('maximumSignificantDigits')) { | 1232 if (%HasOwnProperty(format.resolved, 'maximumSignificantDigits')) { |
1202 defineWECProperty(result, 'maximumSignificantDigits', | 1233 defineWECProperty(result, 'maximumSignificantDigits', |
1203 format.resolved.maximumSignificantDigits); | 1234 format.resolved.maximumSignificantDigits); |
1204 } | 1235 } |
1205 | 1236 |
1206 return result; | 1237 return result; |
1207 }, | 1238 }, |
1208 DONT_ENUM | 1239 DONT_ENUM |
1209 ); | 1240 ); |
1210 SetFunctionName(Intl.NumberFormat.prototype.resolvedOptions, 'resolvedOptions'); | 1241 SetFunctionName(Intl.NumberFormat.prototype.resolvedOptions, 'resolvedOptions'); |
1211 %FunctionRemovePrototype(Intl.NumberFormat.prototype.resolvedOptions); | 1242 %FunctionRemovePrototype(Intl.NumberFormat.prototype.resolvedOptions); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1319 return ''; | 1350 return ''; |
1320 } | 1351 } |
1321 } | 1352 } |
1322 | 1353 |
1323 | 1354 |
1324 /** | 1355 /** |
1325 * Returns object that matches LDML representation of the date. | 1356 * Returns object that matches LDML representation of the date. |
1326 */ | 1357 */ |
1327 function fromLDMLString(ldmlString) { | 1358 function fromLDMLString(ldmlString) { |
1328 // First remove '' quoted text, so we lose 'Uhr' strings. | 1359 // First remove '' quoted text, so we lose 'Uhr' strings. |
1329 ldmlString = ldmlString.replace(GetQuotedStringRE(), ''); | 1360 ldmlString = %_CallFunction(ldmlString, GetQuotedStringRE(), '', |
| 1361 StringReplace); |
1330 | 1362 |
1331 var options = {}; | 1363 var options = {}; |
1332 var match = ldmlString.match(/E{3,5}/g); | 1364 var match = %_CallFunction(ldmlString, /E{3,5}/g, StringMatch); |
1333 options = appendToDateTimeObject( | 1365 options = appendToDateTimeObject( |
1334 options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'}); | 1366 options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'}); |
1335 | 1367 |
1336 match = ldmlString.match(/G{3,5}/g); | 1368 match = %_CallFunction(ldmlString, /G{3,5}/g, StringMatch); |
1337 options = appendToDateTimeObject( | 1369 options = appendToDateTimeObject( |
1338 options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'}); | 1370 options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'}); |
1339 | 1371 |
1340 match = ldmlString.match(/y{1,2}/g); | 1372 match = %_CallFunction(ldmlString, /y{1,2}/g, StringMatch); |
1341 options = appendToDateTimeObject( | 1373 options = appendToDateTimeObject( |
1342 options, 'year', match, {y: 'numeric', yy: '2-digit'}); | 1374 options, 'year', match, {y: 'numeric', yy: '2-digit'}); |
1343 | 1375 |
1344 match = ldmlString.match(/M{1,5}/g); | 1376 match = %_CallFunction(ldmlString, /M{1,5}/g, StringMatch); |
1345 options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit', | 1377 options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit', |
1346 M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'}); | 1378 M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'}); |
1347 | 1379 |
1348 // Sometimes we get L instead of M for month - standalone name. | 1380 // Sometimes we get L instead of M for month - standalone name. |
1349 match = ldmlString.match(/L{1,5}/g); | 1381 match = %_CallFunction(ldmlString, /L{1,5}/g, StringMatch); |
1350 options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit', | 1382 options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit', |
1351 L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'}); | 1383 L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'}); |
1352 | 1384 |
1353 match = ldmlString.match(/d{1,2}/g); | 1385 match = %_CallFunction(ldmlString, /d{1,2}/g, StringMatch); |
1354 options = appendToDateTimeObject( | 1386 options = appendToDateTimeObject( |
1355 options, 'day', match, {d: 'numeric', dd: '2-digit'}); | 1387 options, 'day', match, {d: 'numeric', dd: '2-digit'}); |
1356 | 1388 |
1357 match = ldmlString.match(/h{1,2}/g); | 1389 match = %_CallFunction(ldmlString, /h{1,2}/g, StringMatch); |
1358 if (match !== null) { | 1390 if (match !== null) { |
1359 options['hour12'] = true; | 1391 options['hour12'] = true; |
1360 } | 1392 } |
1361 options = appendToDateTimeObject( | 1393 options = appendToDateTimeObject( |
1362 options, 'hour', match, {h: 'numeric', hh: '2-digit'}); | 1394 options, 'hour', match, {h: 'numeric', hh: '2-digit'}); |
1363 | 1395 |
1364 match = ldmlString.match(/H{1,2}/g); | 1396 match = %_CallFunction(ldmlString, /H{1,2}/g, StringMatch); |
1365 if (match !== null) { | 1397 if (match !== null) { |
1366 options['hour12'] = false; | 1398 options['hour12'] = false; |
1367 } | 1399 } |
1368 options = appendToDateTimeObject( | 1400 options = appendToDateTimeObject( |
1369 options, 'hour', match, {H: 'numeric', HH: '2-digit'}); | 1401 options, 'hour', match, {H: 'numeric', HH: '2-digit'}); |
1370 | 1402 |
1371 match = ldmlString.match(/m{1,2}/g); | 1403 match = %_CallFunction(ldmlString, /m{1,2}/g, StringMatch); |
1372 options = appendToDateTimeObject( | 1404 options = appendToDateTimeObject( |
1373 options, 'minute', match, {m: 'numeric', mm: '2-digit'}); | 1405 options, 'minute', match, {m: 'numeric', mm: '2-digit'}); |
1374 | 1406 |
1375 match = ldmlString.match(/s{1,2}/g); | 1407 match = %_CallFunction(ldmlString, /s{1,2}/g, StringMatch); |
1376 options = appendToDateTimeObject( | 1408 options = appendToDateTimeObject( |
1377 options, 'second', match, {s: 'numeric', ss: '2-digit'}); | 1409 options, 'second', match, {s: 'numeric', ss: '2-digit'}); |
1378 | 1410 |
1379 match = ldmlString.match(/z|zzzz/g); | 1411 match = %_CallFunction(ldmlString, /z|zzzz/g, StringMatch); |
1380 options = appendToDateTimeObject( | 1412 options = appendToDateTimeObject( |
1381 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); | 1413 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); |
1382 | 1414 |
1383 return options; | 1415 return options; |
1384 } | 1416 } |
1385 | 1417 |
1386 | 1418 |
1387 function appendToDateTimeObject(options, option, match, pairs) { | 1419 function appendToDateTimeObject(options, option, match, pairs) { |
1388 if (IS_NULL(match)) { | 1420 if (IS_NULL(match)) { |
1389 if (!options.hasOwnProperty(option)) { | 1421 if (!%HasOwnProperty(options, option)) { |
1390 defineWEProperty(options, option, UNDEFINED); | 1422 defineWEProperty(options, option, UNDEFINED); |
1391 } | 1423 } |
1392 return options; | 1424 return options; |
1393 } | 1425 } |
1394 | 1426 |
1395 var property = match[0]; | 1427 var property = match[0]; |
1396 defineWEProperty(options, option, pairs[property]); | 1428 defineWEProperty(options, option, pairs[property]); |
1397 | 1429 |
1398 return options; | 1430 return options; |
1399 } | 1431 } |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1654 | 1686 |
1655 | 1687 |
1656 /** | 1688 /** |
1657 * Returns a String value representing the result of calling ToNumber(date) | 1689 * Returns a String value representing the result of calling ToNumber(date) |
1658 * according to the effective locale and the formatting options of this | 1690 * according to the effective locale and the formatting options of this |
1659 * DateTimeFormat. | 1691 * DateTimeFormat. |
1660 */ | 1692 */ |
1661 function formatDate(formatter, dateValue) { | 1693 function formatDate(formatter, dateValue) { |
1662 var dateMs; | 1694 var dateMs; |
1663 if (IS_UNDEFINED(dateValue)) { | 1695 if (IS_UNDEFINED(dateValue)) { |
1664 dateMs = GlobalDate.now(); | 1696 dateMs = %DateCurrentTime(); |
1665 } else { | 1697 } else { |
1666 dateMs = $toNumber(dateValue); | 1698 dateMs = $toNumber(dateValue); |
1667 } | 1699 } |
1668 | 1700 |
1669 if (!IsFinite(dateMs)) throw MakeRangeError(kDateRange); | 1701 if (!IsFinite(dateMs)) throw MakeRangeError(kDateRange); |
1670 | 1702 |
1671 return %InternalDateFormat(%GetImplFromInitializedIntlObject(formatter), | 1703 return %InternalDateFormat(%GetImplFromInitializedIntlObject(formatter), |
1672 new GlobalDate(dateMs)); | 1704 new GlobalDate(dateMs)); |
1673 } | 1705 } |
1674 | 1706 |
(...skipping 19 matching lines...) Expand all Loading... |
1694 * Returns canonical Area/Location name, or throws an exception if the zone | 1726 * Returns canonical Area/Location name, or throws an exception if the zone |
1695 * name is invalid IANA name. | 1727 * name is invalid IANA name. |
1696 */ | 1728 */ |
1697 function canonicalizeTimeZoneID(tzID) { | 1729 function canonicalizeTimeZoneID(tzID) { |
1698 // Skip undefined zones. | 1730 // Skip undefined zones. |
1699 if (IS_UNDEFINED(tzID)) { | 1731 if (IS_UNDEFINED(tzID)) { |
1700 return tzID; | 1732 return tzID; |
1701 } | 1733 } |
1702 | 1734 |
1703 // Special case handling (UTC, GMT). | 1735 // Special case handling (UTC, GMT). |
1704 var upperID = tzID.toUpperCase(); | 1736 var upperID = %StringToUpperCase(tzID); |
1705 if (upperID === 'UTC' || upperID === 'GMT' || | 1737 if (upperID === 'UTC' || upperID === 'GMT' || |
1706 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { | 1738 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { |
1707 return 'UTC'; | 1739 return 'UTC'; |
1708 } | 1740 } |
1709 | 1741 |
1710 // We expect only _ and / beside ASCII letters. | 1742 // We expect only _ and / beside ASCII letters. |
1711 // All inputs should conform to Area/Location from now on. | 1743 // All inputs should conform to Area/Location from now on. |
1712 var match = GetTimezoneNameCheckRE().exec(tzID); | 1744 var match = %_CallFunction(tzID, GetTimezoneNameCheckRE(), StringMatch); |
1713 if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, tzID); | 1745 if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, tzID); |
1714 | 1746 |
1715 var result = toTitleCaseWord(match[1]) + '/' + toTitleCaseWord(match[2]); | 1747 var result = toTitleCaseWord(match[1]) + '/' + toTitleCaseWord(match[2]); |
1716 var i = 3; | 1748 var i = 3; |
1717 while (!IS_UNDEFINED(match[i]) && i < match.length) { | 1749 while (!IS_UNDEFINED(match[i]) && i < match.length) { |
1718 result = result + '_' + toTitleCaseWord(match[i]); | 1750 result = result + '_' + toTitleCaseWord(match[i]); |
1719 i++; | 1751 i++; |
1720 } | 1752 } |
1721 | 1753 |
1722 return result; | 1754 return result; |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1961 if (%_IsConstructCall()) { | 1993 if (%_IsConstructCall()) { |
1962 throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); | 1994 throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor); |
1963 } | 1995 } |
1964 | 1996 |
1965 CHECK_OBJECT_COERCIBLE(this, "String.prototype.normalize"); | 1997 CHECK_OBJECT_COERCIBLE(this, "String.prototype.normalize"); |
1966 | 1998 |
1967 var form = GlobalString(%_Arguments(0) || 'NFC'); | 1999 var form = GlobalString(%_Arguments(0) || 'NFC'); |
1968 | 2000 |
1969 var NORMALIZATION_FORMS = ['NFC', 'NFD', 'NFKC', 'NFKD']; | 2001 var NORMALIZATION_FORMS = ['NFC', 'NFD', 'NFKC', 'NFKD']; |
1970 | 2002 |
1971 var normalizationForm = NORMALIZATION_FORMS.indexOf(form); | 2003 var normalizationForm = |
| 2004 %_CallFunction(NORMALIZATION_FORMS, form, ArrayIndexOf); |
1972 if (normalizationForm === -1) { | 2005 if (normalizationForm === -1) { |
1973 throw MakeRangeError(kNormalizationForm, NORMALIZATION_FORMS.join(', ')); | 2006 throw MakeRangeError(kNormalizationForm, |
| 2007 %_CallFunction(NORMALIZATION_FORMS, ', ', ArrayJoin)); |
1974 } | 2008 } |
1975 | 2009 |
1976 return %StringNormalize(this, normalizationForm); | 2010 return %StringNormalize(this, normalizationForm); |
1977 } | 2011 } |
1978 ); | 2012 ); |
1979 | 2013 |
1980 | 2014 |
1981 /** | 2015 /** |
1982 * Formats a Number object (this) using locale and options values. | 2016 * Formats a Number object (this) using locale and options values. |
1983 * If locale or options are omitted, defaults are used. | 2017 * If locale or options are omitted, defaults are used. |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2065 } | 2099 } |
2066 | 2100 |
2067 var locales = %_Arguments(0); | 2101 var locales = %_Arguments(0); |
2068 var options = %_Arguments(1); | 2102 var options = %_Arguments(1); |
2069 return toLocaleDateTime( | 2103 return toLocaleDateTime( |
2070 this, locales, options, 'time', 'time', 'dateformattime'); | 2104 this, locales, options, 'time', 'time', 'dateformattime'); |
2071 } | 2105 } |
2072 ); | 2106 ); |
2073 | 2107 |
2074 }) | 2108 }) |
OLD | NEW |