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 */ |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 configurable: true | 242 configurable: true |
243 }); | 243 }); |
244 } | 244 } |
245 | 245 |
246 | 246 |
247 /** | 247 /** |
248 * Returns an intersection of locales and service supported locales. | 248 * Returns an intersection of locales and service supported locales. |
249 * Parameter locales is treated as a priority list. | 249 * Parameter locales is treated as a priority list. |
250 */ | 250 */ |
251 function supportedLocalesOf(service, locales, options) { | 251 function supportedLocalesOf(service, locales, options) { |
252 if (IS_NULL(%_CallFunction(service, GetServiceRE(), StringMatch))) { | 252 if (IS_NULL(%_Call(StringMatch, service, GetServiceRE()))) { |
253 throw MakeError(kWrongServiceType, service); | 253 throw MakeError(kWrongServiceType, service); |
254 } | 254 } |
255 | 255 |
256 // Provide defaults if matcher was not specified. | 256 // Provide defaults if matcher was not specified. |
257 if (IS_UNDEFINED(options)) { | 257 if (IS_UNDEFINED(options)) { |
258 options = {}; | 258 options = {}; |
259 } else { | 259 } else { |
260 options = TO_OBJECT(options); | 260 options = TO_OBJECT(options); |
261 } | 261 } |
262 | 262 |
(...skipping 27 matching lines...) Expand all Loading... |
290 | 290 |
291 /** | 291 /** |
292 * Returns the subset of the provided BCP 47 language priority list for which | 292 * Returns the subset of the provided BCP 47 language priority list for which |
293 * this service has a matching locale when using the BCP 47 Lookup algorithm. | 293 * this service has a matching locale when using the BCP 47 Lookup algorithm. |
294 * Locales appear in the same order in the returned list as in the input list. | 294 * Locales appear in the same order in the returned list as in the input list. |
295 */ | 295 */ |
296 function lookupSupportedLocalesOf(requestedLocales, availableLocales) { | 296 function lookupSupportedLocalesOf(requestedLocales, availableLocales) { |
297 var matchedLocales = []; | 297 var matchedLocales = []; |
298 for (var i = 0; i < requestedLocales.length; ++i) { | 298 for (var i = 0; i < requestedLocales.length; ++i) { |
299 // Remove -u- extension. | 299 // Remove -u- extension. |
300 var locale = %_CallFunction(requestedLocales[i], GetUnicodeExtensionRE(), | 300 var locale = %_Call(StringReplace, |
301 '', StringReplace); | 301 requestedLocales[i], |
| 302 GetUnicodeExtensionRE(), |
| 303 ''); |
302 do { | 304 do { |
303 if (!IS_UNDEFINED(availableLocales[locale])) { | 305 if (!IS_UNDEFINED(availableLocales[locale])) { |
304 // Push requested locale not the resolved one. | 306 // Push requested locale not the resolved one. |
305 %_CallFunction(matchedLocales, requestedLocales[i], ArrayPush); | 307 %_Call(ArrayPush, matchedLocales, requestedLocales[i]); |
306 break; | 308 break; |
307 } | 309 } |
308 // Truncate locale if possible, if not break. | 310 // Truncate locale if possible, if not break. |
309 var pos = %_CallFunction(locale, '-', StringLastIndexOf); | 311 var pos = %_Call(StringLastIndexOf, locale, '-'); |
310 if (pos === -1) { | 312 if (pos === -1) { |
311 break; | 313 break; |
312 } | 314 } |
313 locale = %_CallFunction(locale, 0, pos, StringSubstring); | 315 locale = %_Call(StringSubstring, locale, 0, pos); |
314 } while (true); | 316 } while (true); |
315 } | 317 } |
316 | 318 |
317 return matchedLocales; | 319 return matchedLocales; |
318 } | 320 } |
319 | 321 |
320 | 322 |
321 /** | 323 /** |
322 * Returns the subset of the provided BCP 47 language priority list for which | 324 * Returns the subset of the provided BCP 47 language priority list for which |
323 * this service has a matching locale when using the implementation | 325 * this service has a matching locale when using the implementation |
(...skipping 24 matching lines...) Expand all Loading... |
348 case 'string': | 350 case 'string': |
349 value = GlobalString(value); | 351 value = GlobalString(value); |
350 break; | 352 break; |
351 case 'number': | 353 case 'number': |
352 value = GlobalNumber(value); | 354 value = GlobalNumber(value); |
353 break; | 355 break; |
354 default: | 356 default: |
355 throw MakeError(kWrongValueType); | 357 throw MakeError(kWrongValueType); |
356 } | 358 } |
357 | 359 |
358 if (!IS_UNDEFINED(values) && | 360 if (!IS_UNDEFINED(values) && %_Call(ArrayIndexOf, values, value) === -1) { |
359 %_CallFunction(values, value, ArrayIndexOf) === -1) { | |
360 throw MakeRangeError(kValueOutOfRange, value, caller, property); | 361 throw MakeRangeError(kValueOutOfRange, value, caller, property); |
361 } | 362 } |
362 | 363 |
363 return value; | 364 return value; |
364 } | 365 } |
365 | 366 |
366 return defaultValue; | 367 return defaultValue; |
367 } | 368 } |
368 | 369 |
369 return getOption; | 370 return getOption; |
(...skipping 28 matching lines...) Expand all Loading... |
398 | 399 |
399 return resolved; | 400 return resolved; |
400 } | 401 } |
401 | 402 |
402 | 403 |
403 /** | 404 /** |
404 * Returns best matched supported locale and extension info using basic | 405 * Returns best matched supported locale and extension info using basic |
405 * lookup algorithm. | 406 * lookup algorithm. |
406 */ | 407 */ |
407 function lookupMatcher(service, requestedLocales) { | 408 function lookupMatcher(service, requestedLocales) { |
408 if (IS_NULL(%_CallFunction(service, GetServiceRE(), StringMatch))) { | 409 if (IS_NULL(%_Call(StringMatch, service, GetServiceRE()))) { |
409 throw MakeError(kWrongServiceType, service); | 410 throw MakeError(kWrongServiceType, service); |
410 } | 411 } |
411 | 412 |
412 // Cache these, they don't ever change per service. | 413 // Cache these, they don't ever change per service. |
413 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { | 414 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { |
414 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); | 415 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); |
415 } | 416 } |
416 | 417 |
417 for (var i = 0; i < requestedLocales.length; ++i) { | 418 for (var i = 0; i < requestedLocales.length; ++i) { |
418 // Remove all extensions. | 419 // Remove all extensions. |
419 var locale = %_CallFunction(requestedLocales[i], GetAnyExtensionRE(), '', | 420 var locale = %_Call(StringReplace, requestedLocales[i], |
420 StringReplace); | 421 GetAnyExtensionRE(), ''); |
421 do { | 422 do { |
422 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { | 423 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { |
423 // Return the resolved locale and extension. | 424 // Return the resolved locale and extension. |
424 var extensionMatch = | 425 var extensionMatch = |
425 %_CallFunction(requestedLocales[i], GetUnicodeExtensionRE(), | 426 %_Call(StringMatch, requestedLocales[i], GetUnicodeExtensionRE()); |
426 StringMatch); | |
427 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; | 427 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; |
428 return {'locale': locale, 'extension': extension, 'position': i}; | 428 return {'locale': locale, 'extension': extension, 'position': i}; |
429 } | 429 } |
430 // Truncate locale if possible. | 430 // Truncate locale if possible. |
431 var pos = %_CallFunction(locale, '-', StringLastIndexOf); | 431 var pos = %_Call(StringLastIndexOf, locale, '-'); |
432 if (pos === -1) { | 432 if (pos === -1) { |
433 break; | 433 break; |
434 } | 434 } |
435 locale = %_CallFunction(locale, 0, pos, StringSubstring); | 435 locale = %_Call(StringSubstring, locale, 0, pos); |
436 } while (true); | 436 } while (true); |
437 } | 437 } |
438 | 438 |
439 // Didn't find a match, return default. | 439 // Didn't find a match, return default. |
440 if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) { | 440 if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) { |
441 DEFAULT_ICU_LOCALE = %GetDefaultICULocale(); | 441 DEFAULT_ICU_LOCALE = %GetDefaultICULocale(); |
442 } | 442 } |
443 | 443 |
444 return {'locale': DEFAULT_ICU_LOCALE, 'extension': '', 'position': -1}; | 444 return {'locale': DEFAULT_ICU_LOCALE, 'extension': '', 'position': -1}; |
445 } | 445 } |
446 | 446 |
447 | 447 |
448 /** | 448 /** |
449 * Returns best matched supported locale and extension info using | 449 * Returns best matched supported locale and extension info using |
450 * implementation dependend algorithm. | 450 * implementation dependend algorithm. |
451 */ | 451 */ |
452 function bestFitMatcher(service, requestedLocales) { | 452 function bestFitMatcher(service, requestedLocales) { |
453 // TODO(cira): implement better best fit algorithm. | 453 // TODO(cira): implement better best fit algorithm. |
454 return lookupMatcher(service, requestedLocales); | 454 return lookupMatcher(service, requestedLocales); |
455 } | 455 } |
456 | 456 |
457 | 457 |
458 /** | 458 /** |
459 * Parses Unicode extension into key - value map. | 459 * Parses Unicode extension into key - value map. |
460 * Returns empty object if the extension string is invalid. | 460 * Returns empty object if the extension string is invalid. |
461 * We are not concerned with the validity of the values at this point. | 461 * We are not concerned with the validity of the values at this point. |
462 */ | 462 */ |
463 function parseExtension(extension) { | 463 function parseExtension(extension) { |
464 var extensionSplit = %_CallFunction(extension, '-', StringSplit); | 464 var extensionSplit = %_Call(StringSplit, extension, '-'); |
465 | 465 |
466 // Assume ['', 'u', ...] input, but don't throw. | 466 // Assume ['', 'u', ...] input, but don't throw. |
467 if (extensionSplit.length <= 2 || | 467 if (extensionSplit.length <= 2 || |
468 (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) { | 468 (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) { |
469 return {}; | 469 return {}; |
470 } | 470 } |
471 | 471 |
472 // Key is {2}alphanum, value is {3,8}alphanum. | 472 // Key is {2}alphanum, value is {3,8}alphanum. |
473 // Some keys may not have explicit values (booleans). | 473 // Some keys may not have explicit values (booleans). |
474 var extensionMap = {}; | 474 var extensionMap = {}; |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
591 return original; | 591 return original; |
592 } | 592 } |
593 | 593 |
594 var locales = %GetLanguageTagVariants([original, resolved]); | 594 var locales = %GetLanguageTagVariants([original, resolved]); |
595 if (locales[0].maximized !== locales[1].maximized) { | 595 if (locales[0].maximized !== locales[1].maximized) { |
596 return resolved; | 596 return resolved; |
597 } | 597 } |
598 | 598 |
599 // Preserve extensions of resolved locale, but swap base tags with original. | 599 // Preserve extensions of resolved locale, but swap base tags with original. |
600 var resolvedBase = new GlobalRegExp('^' + locales[1].base); | 600 var resolvedBase = new GlobalRegExp('^' + locales[1].base); |
601 return %_CallFunction(resolved, resolvedBase, locales[0].base, StringReplace); | 601 return %_Call(StringReplace, resolved, resolvedBase, locales[0].base); |
602 } | 602 } |
603 | 603 |
604 | 604 |
605 /** | 605 /** |
606 * Returns an Object that contains all of supported locales for a given | 606 * Returns an Object that contains all of supported locales for a given |
607 * service. | 607 * service. |
608 * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ | 608 * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ |
609 * that is supported. This is required by the spec. | 609 * that is supported. This is required by the spec. |
610 */ | 610 */ |
611 function getAvailableLocalesOf(service) { | 611 function getAvailableLocalesOf(service) { |
612 var available = %AvailableLocalesOf(service); | 612 var available = %AvailableLocalesOf(service); |
613 | 613 |
614 for (var i in available) { | 614 for (var i in available) { |
615 if (%HasOwnProperty(available, i)) { | 615 if (%HasOwnProperty(available, i)) { |
616 var parts = %_CallFunction(i, /^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/, | 616 var parts = |
617 StringMatch); | 617 %_Call(StringMatch, i, /^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/); |
618 if (parts !== null) { | 618 if (parts !== null) { |
619 // Build xx-ZZ. We don't care about the actual value, | 619 // Build xx-ZZ. We don't care about the actual value, |
620 // as long it's not undefined. | 620 // as long it's not undefined. |
621 available[parts[1] + '-' + parts[3]] = null; | 621 available[parts[1] + '-' + parts[3]] = null; |
622 } | 622 } |
623 } | 623 } |
624 } | 624 } |
625 | 625 |
626 return available; | 626 return available; |
627 } | 627 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 if (!IS_UNDEFINED(value)) { | 667 if (!IS_UNDEFINED(value)) { |
668 defineWECProperty(object, property, value); | 668 defineWECProperty(object, property, value); |
669 } | 669 } |
670 } | 670 } |
671 | 671 |
672 | 672 |
673 /** | 673 /** |
674 * Returns titlecased word, aMeRricA -> America. | 674 * Returns titlecased word, aMeRricA -> America. |
675 */ | 675 */ |
676 function toTitleCaseWord(word) { | 676 function toTitleCaseWord(word) { |
677 return %StringToUpperCase(%_CallFunction(word, 0, 1, StringSubstr)) + | 677 return %StringToUpperCase(%_Call(StringSubstr, word, 0, 1)) + |
678 %StringToLowerCase(%_CallFunction(word, 1, StringSubstr)); | 678 %StringToLowerCase(%_Call(StringSubstr, word, 1)); |
679 } | 679 } |
680 | 680 |
681 /** | 681 /** |
682 * Canonicalizes the language tag, or throws in case the tag is invalid. | 682 * Canonicalizes the language tag, or throws in case the tag is invalid. |
683 */ | 683 */ |
684 function canonicalizeLanguageTag(localeID) { | 684 function canonicalizeLanguageTag(localeID) { |
685 // null is typeof 'object' so we have to do extra check. | 685 // null is typeof 'object' so we have to do extra check. |
686 if (typeof localeID !== 'string' && typeof localeID !== 'object' || | 686 if (typeof localeID !== 'string' && typeof localeID !== 'object' || |
687 IS_NULL(localeID)) { | 687 IS_NULL(localeID)) { |
688 throw MakeTypeError(kLanguageID); | 688 throw MakeTypeError(kLanguageID); |
(...skipping 23 matching lines...) Expand all Loading... |
712 * Throws on locales that are not well formed BCP47 tags. | 712 * Throws on locales that are not well formed BCP47 tags. |
713 */ | 713 */ |
714 function initializeLocaleList(locales) { | 714 function initializeLocaleList(locales) { |
715 var seen = []; | 715 var seen = []; |
716 if (IS_UNDEFINED(locales)) { | 716 if (IS_UNDEFINED(locales)) { |
717 // Constructor is called without arguments. | 717 // Constructor is called without arguments. |
718 seen = []; | 718 seen = []; |
719 } else { | 719 } else { |
720 // We allow single string localeID. | 720 // We allow single string localeID. |
721 if (typeof locales === 'string') { | 721 if (typeof locales === 'string') { |
722 %_CallFunction(seen, canonicalizeLanguageTag(locales), ArrayPush); | 722 %_Call(ArrayPush, seen, canonicalizeLanguageTag(locales)); |
723 return freezeArray(seen); | 723 return freezeArray(seen); |
724 } | 724 } |
725 | 725 |
726 var o = TO_OBJECT(locales); | 726 var o = TO_OBJECT(locales); |
727 var len = TO_UINT32(o.length); | 727 var len = TO_UINT32(o.length); |
728 | 728 |
729 for (var k = 0; k < len; k++) { | 729 for (var k = 0; k < len; k++) { |
730 if (k in o) { | 730 if (k in o) { |
731 var value = o[k]; | 731 var value = o[k]; |
732 | 732 |
733 var tag = canonicalizeLanguageTag(value); | 733 var tag = canonicalizeLanguageTag(value); |
734 | 734 |
735 if (%_CallFunction(seen, tag, ArrayIndexOf) === -1) { | 735 if (%_Call(ArrayIndexOf, seen, tag) === -1) { |
736 %_CallFunction(seen, tag, ArrayPush); | 736 %_Call(ArrayPush, seen, tag); |
737 } | 737 } |
738 } | 738 } |
739 } | 739 } |
740 } | 740 } |
741 | 741 |
742 return freezeArray(seen); | 742 return freezeArray(seen); |
743 } | 743 } |
744 | 744 |
745 | 745 |
746 /** | 746 /** |
747 * Validates the language tag. Section 2.2.9 of the bcp47 spec | 747 * Validates the language tag. Section 2.2.9 of the bcp47 spec |
748 * defines a valid tag. | 748 * defines a valid tag. |
749 * | 749 * |
750 * ICU is too permissible and lets invalid tags, like | 750 * ICU is too permissible and lets invalid tags, like |
751 * hant-cmn-cn, through. | 751 * hant-cmn-cn, through. |
752 * | 752 * |
753 * Returns false if the language tag is invalid. | 753 * Returns false if the language tag is invalid. |
754 */ | 754 */ |
755 function isValidLanguageTag(locale) { | 755 function isValidLanguageTag(locale) { |
756 // Check if it's well-formed, including grandfadered tags. | 756 // Check if it's well-formed, including grandfadered tags. |
757 if (!%_CallFunction(GetLanguageTagRE(), locale, RegExpTest)) { | 757 if (!%_Call(RegExpTest, GetLanguageTagRE(), locale)) { |
758 return false; | 758 return false; |
759 } | 759 } |
760 | 760 |
761 // Just return if it's a x- form. It's all private. | 761 // Just return if it's a x- form. It's all private. |
762 if (%_CallFunction(locale, 'x-', StringIndexOf) === 0) { | 762 if (%_Call(StringIndexOf, locale, 'x-') === 0) { |
763 return true; | 763 return true; |
764 } | 764 } |
765 | 765 |
766 // Check if there are any duplicate variants or singletons (extensions). | 766 // Check if there are any duplicate variants or singletons (extensions). |
767 | 767 |
768 // Remove private use section. | 768 // Remove private use section. |
769 locale = %_CallFunction(locale, /-x-/, StringSplit)[0]; | 769 locale = %_Call(StringSplit, locale, /-x-/)[0]; |
770 | 770 |
771 // Skip language since it can match variant regex, so we start from 1. | 771 // Skip language since it can match variant regex, so we start from 1. |
772 // We are matching i-klingon here, but that's ok, since i-klingon-klingon | 772 // We are matching i-klingon here, but that's ok, since i-klingon-klingon |
773 // is not valid and would fail LANGUAGE_TAG_RE test. | 773 // is not valid and would fail LANGUAGE_TAG_RE test. |
774 var variants = []; | 774 var variants = []; |
775 var extensions = []; | 775 var extensions = []; |
776 var parts = %_CallFunction(locale, /-/, StringSplit); | 776 var parts = %_Call(StringSplit, locale, /-/); |
777 for (var i = 1; i < parts.length; i++) { | 777 for (var i = 1; i < parts.length; i++) { |
778 var value = parts[i]; | 778 var value = parts[i]; |
779 if (%_CallFunction(GetLanguageVariantRE(), value, RegExpTest) && | 779 if (%_Call(RegExpTest, GetLanguageVariantRE(), value) && |
780 extensions.length === 0) { | 780 extensions.length === 0) { |
781 if (%_CallFunction(variants, value, ArrayIndexOf) === -1) { | 781 if (%_Call(ArrayIndexOf, variants, value) === -1) { |
782 %_CallFunction(variants, value, ArrayPush); | 782 %_Call(ArrayPush, variants, value); |
783 } else { | 783 } else { |
784 return false; | 784 return false; |
785 } | 785 } |
786 } | 786 } |
787 | 787 |
788 if (%_CallFunction(GetLanguageSingletonRE(), value, RegExpTest)) { | 788 if (%_Call(RegExpTest, GetLanguageSingletonRE(), value)) { |
789 if (%_CallFunction(extensions, value, ArrayIndexOf) === -1) { | 789 if (%_Call(ArrayIndexOf, extensions, value) === -1) { |
790 %_CallFunction(extensions, value, ArrayPush); | 790 %_Call(ArrayPush, extensions, value); |
791 } else { | 791 } else { |
792 return false; | 792 return false; |
793 } | 793 } |
794 } | 794 } |
795 } | 795 } |
796 | 796 |
797 return true; | 797 return true; |
798 } | 798 } |
799 | 799 |
800 | 800 |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 | 894 |
895 /** | 895 /** |
896 * Allowed -u-co- values. List taken from: | 896 * Allowed -u-co- values. List taken from: |
897 * http://unicode.org/repos/cldr/trunk/common/bcp47/collation.xml | 897 * http://unicode.org/repos/cldr/trunk/common/bcp47/collation.xml |
898 */ | 898 */ |
899 var ALLOWED_CO_VALUES = [ | 899 var ALLOWED_CO_VALUES = [ |
900 'big5han', 'dict', 'direct', 'ducet', 'gb2312', 'phonebk', 'phonetic', | 900 'big5han', 'dict', 'direct', 'ducet', 'gb2312', 'phonebk', 'phonetic', |
901 'pinyin', 'reformed', 'searchjl', 'stroke', 'trad', 'unihan', 'zhuyin' | 901 'pinyin', 'reformed', 'searchjl', 'stroke', 'trad', 'unihan', 'zhuyin' |
902 ]; | 902 ]; |
903 | 903 |
904 if (%_CallFunction(ALLOWED_CO_VALUES, extensionMap.co, ArrayIndexOf) !== | 904 if (%_Call(ArrayIndexOf, ALLOWED_CO_VALUES, extensionMap.co) !== -1) { |
905 -1) { | |
906 extension = '-u-co-' + extensionMap.co; | 905 extension = '-u-co-' + extensionMap.co; |
907 // ICU can't tell us what the collation is, so save user's input. | 906 // ICU can't tell us what the collation is, so save user's input. |
908 collation = extensionMap.co; | 907 collation = extensionMap.co; |
909 } | 908 } |
910 } else if (internalOptions.usage === 'search') { | 909 } else if (internalOptions.usage === 'search') { |
911 extension = '-u-co-search'; | 910 extension = '-u-co-search'; |
912 } | 911 } |
913 defineWEProperty(internalOptions, 'collation', collation); | 912 defineWEProperty(internalOptions, 'collation', collation); |
914 | 913 |
915 var requestedLocale = locale.locale + extension; | 914 var requestedLocale = locale.locale + extension; |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1035 addBoundMethod(Intl.Collator, 'compare', compare, 2); | 1034 addBoundMethod(Intl.Collator, 'compare', compare, 2); |
1036 | 1035 |
1037 /** | 1036 /** |
1038 * Verifies that the input is a well-formed ISO 4217 currency code. | 1037 * Verifies that the input is a well-formed ISO 4217 currency code. |
1039 * Don't uppercase to test. It could convert invalid code into a valid one. | 1038 * Don't uppercase to test. It could convert invalid code into a valid one. |
1040 * For example \u00DFP (Eszett+P) becomes SSP. | 1039 * For example \u00DFP (Eszett+P) becomes SSP. |
1041 */ | 1040 */ |
1042 function isWellFormedCurrencyCode(currency) { | 1041 function isWellFormedCurrencyCode(currency) { |
1043 return typeof currency == "string" && | 1042 return typeof currency == "string" && |
1044 currency.length == 3 && | 1043 currency.length == 3 && |
1045 %_CallFunction(currency, /[^A-Za-z]/, StringMatch) == null; | 1044 %_Call(StringMatch, currency, /[^A-Za-z]/) == null; |
1046 } | 1045 } |
1047 | 1046 |
1048 | 1047 |
1049 /** | 1048 /** |
1050 * Returns the valid digit count for a property, or throws RangeError on | 1049 * Returns the valid digit count for a property, or throws RangeError on |
1051 * a value out of the range. | 1050 * a value out of the range. |
1052 */ | 1051 */ |
1053 function getNumberOption(options, property, min, max, fallback) { | 1052 function getNumberOption(options, property, min, max, fallback) { |
1054 var value = options[property]; | 1053 var value = options[property]; |
1055 if (!IS_UNDEFINED(value)) { | 1054 if (!IS_UNDEFINED(value)) { |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1364 return ''; | 1363 return ''; |
1365 } | 1364 } |
1366 } | 1365 } |
1367 | 1366 |
1368 | 1367 |
1369 /** | 1368 /** |
1370 * Returns object that matches LDML representation of the date. | 1369 * Returns object that matches LDML representation of the date. |
1371 */ | 1370 */ |
1372 function fromLDMLString(ldmlString) { | 1371 function fromLDMLString(ldmlString) { |
1373 // First remove '' quoted text, so we lose 'Uhr' strings. | 1372 // First remove '' quoted text, so we lose 'Uhr' strings. |
1374 ldmlString = %_CallFunction(ldmlString, GetQuotedStringRE(), '', | 1373 ldmlString = %_Call(StringReplace, ldmlString, GetQuotedStringRE(), ''); |
1375 StringReplace); | |
1376 | 1374 |
1377 var options = {}; | 1375 var options = {}; |
1378 var match = %_CallFunction(ldmlString, /E{3,5}/g, StringMatch); | 1376 var match = %_Call(StringMatch, ldmlString, /E{3,5}/g); |
1379 options = appendToDateTimeObject( | 1377 options = appendToDateTimeObject( |
1380 options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'}); | 1378 options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'}); |
1381 | 1379 |
1382 match = %_CallFunction(ldmlString, /G{3,5}/g, StringMatch); | 1380 match = %_Call(StringMatch, ldmlString, /G{3,5}/g); |
1383 options = appendToDateTimeObject( | 1381 options = appendToDateTimeObject( |
1384 options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'}); | 1382 options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'}); |
1385 | 1383 |
1386 match = %_CallFunction(ldmlString, /y{1,2}/g, StringMatch); | 1384 match = %_Call(StringMatch, ldmlString, /y{1,2}/g); |
1387 options = appendToDateTimeObject( | 1385 options = appendToDateTimeObject( |
1388 options, 'year', match, {y: 'numeric', yy: '2-digit'}); | 1386 options, 'year', match, {y: 'numeric', yy: '2-digit'}); |
1389 | 1387 |
1390 match = %_CallFunction(ldmlString, /M{1,5}/g, StringMatch); | 1388 match = %_Call(StringMatch, ldmlString, /M{1,5}/g); |
1391 options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit', | 1389 options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit', |
1392 M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'}); | 1390 M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'}); |
1393 | 1391 |
1394 // Sometimes we get L instead of M for month - standalone name. | 1392 // Sometimes we get L instead of M for month - standalone name. |
1395 match = %_CallFunction(ldmlString, /L{1,5}/g, StringMatch); | 1393 match = %_Call(StringMatch, ldmlString, /L{1,5}/g); |
1396 options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit', | 1394 options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit', |
1397 L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'}); | 1395 L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'}); |
1398 | 1396 |
1399 match = %_CallFunction(ldmlString, /d{1,2}/g, StringMatch); | 1397 match = %_Call(StringMatch, ldmlString, /d{1,2}/g); |
1400 options = appendToDateTimeObject( | 1398 options = appendToDateTimeObject( |
1401 options, 'day', match, {d: 'numeric', dd: '2-digit'}); | 1399 options, 'day', match, {d: 'numeric', dd: '2-digit'}); |
1402 | 1400 |
1403 match = %_CallFunction(ldmlString, /h{1,2}/g, StringMatch); | 1401 match = %_Call(StringMatch, ldmlString, /h{1,2}/g); |
1404 if (match !== null) { | 1402 if (match !== null) { |
1405 options['hour12'] = true; | 1403 options['hour12'] = true; |
1406 } | 1404 } |
1407 options = appendToDateTimeObject( | 1405 options = appendToDateTimeObject( |
1408 options, 'hour', match, {h: 'numeric', hh: '2-digit'}); | 1406 options, 'hour', match, {h: 'numeric', hh: '2-digit'}); |
1409 | 1407 |
1410 match = %_CallFunction(ldmlString, /H{1,2}/g, StringMatch); | 1408 match = %_Call(StringMatch, ldmlString, /H{1,2}/g); |
1411 if (match !== null) { | 1409 if (match !== null) { |
1412 options['hour12'] = false; | 1410 options['hour12'] = false; |
1413 } | 1411 } |
1414 options = appendToDateTimeObject( | 1412 options = appendToDateTimeObject( |
1415 options, 'hour', match, {H: 'numeric', HH: '2-digit'}); | 1413 options, 'hour', match, {H: 'numeric', HH: '2-digit'}); |
1416 | 1414 |
1417 match = %_CallFunction(ldmlString, /m{1,2}/g, StringMatch); | 1415 match = %_Call(StringMatch, ldmlString, /m{1,2}/g); |
1418 options = appendToDateTimeObject( | 1416 options = appendToDateTimeObject( |
1419 options, 'minute', match, {m: 'numeric', mm: '2-digit'}); | 1417 options, 'minute', match, {m: 'numeric', mm: '2-digit'}); |
1420 | 1418 |
1421 match = %_CallFunction(ldmlString, /s{1,2}/g, StringMatch); | 1419 match = %_Call(StringMatch, ldmlString, /s{1,2}/g); |
1422 options = appendToDateTimeObject( | 1420 options = appendToDateTimeObject( |
1423 options, 'second', match, {s: 'numeric', ss: '2-digit'}); | 1421 options, 'second', match, {s: 'numeric', ss: '2-digit'}); |
1424 | 1422 |
1425 match = %_CallFunction(ldmlString, /z|zzzz/g, StringMatch); | 1423 match = %_Call(StringMatch, ldmlString, /z|zzzz/g); |
1426 options = appendToDateTimeObject( | 1424 options = appendToDateTimeObject( |
1427 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); | 1425 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); |
1428 | 1426 |
1429 return options; | 1427 return options; |
1430 } | 1428 } |
1431 | 1429 |
1432 | 1430 |
1433 function appendToDateTimeObject(options, option, match, pairs) { | 1431 function appendToDateTimeObject(options, option, match, pairs) { |
1434 if (IS_NULL(match)) { | 1432 if (IS_NULL(match)) { |
1435 if (!%HasOwnProperty(options, option)) { | 1433 if (!%HasOwnProperty(options, option)) { |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1748 | 1746 |
1749 // Special case handling (UTC, GMT). | 1747 // Special case handling (UTC, GMT). |
1750 var upperID = %StringToUpperCase(tzID); | 1748 var upperID = %StringToUpperCase(tzID); |
1751 if (upperID === 'UTC' || upperID === 'GMT' || | 1749 if (upperID === 'UTC' || upperID === 'GMT' || |
1752 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { | 1750 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { |
1753 return 'UTC'; | 1751 return 'UTC'; |
1754 } | 1752 } |
1755 | 1753 |
1756 // We expect only _ and / beside ASCII letters. | 1754 // We expect only _ and / beside ASCII letters. |
1757 // All inputs should conform to Area/Location from now on. | 1755 // All inputs should conform to Area/Location from now on. |
1758 var match = %_CallFunction(tzID, GetTimezoneNameCheckRE(), StringMatch); | 1756 var match = %_Call(StringMatch, tzID, GetTimezoneNameCheckRE()); |
1759 if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, tzID); | 1757 if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, tzID); |
1760 | 1758 |
1761 var result = toTitleCaseWord(match[1]) + '/' + toTitleCaseWord(match[2]); | 1759 var result = toTitleCaseWord(match[1]) + '/' + toTitleCaseWord(match[2]); |
1762 var i = 3; | 1760 var i = 3; |
1763 while (!IS_UNDEFINED(match[i]) && i < match.length) { | 1761 while (!IS_UNDEFINED(match[i]) && i < match.length) { |
1764 result = result + '_' + toTitleCaseWord(match[i]); | 1762 result = result + '_' + toTitleCaseWord(match[i]); |
1765 i++; | 1763 i++; |
1766 } | 1764 } |
1767 | 1765 |
1768 return result; | 1766 return result; |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2010 } | 2008 } |
2011 | 2009 |
2012 CHECK_OBJECT_COERCIBLE(this, "String.prototype.normalize"); | 2010 CHECK_OBJECT_COERCIBLE(this, "String.prototype.normalize"); |
2013 var s = TO_STRING(this); | 2011 var s = TO_STRING(this); |
2014 | 2012 |
2015 var formArg = %_Arguments(0); | 2013 var formArg = %_Arguments(0); |
2016 var form = IS_UNDEFINED(formArg) ? 'NFC' : TO_STRING(formArg); | 2014 var form = IS_UNDEFINED(formArg) ? 'NFC' : TO_STRING(formArg); |
2017 | 2015 |
2018 var NORMALIZATION_FORMS = ['NFC', 'NFD', 'NFKC', 'NFKD']; | 2016 var NORMALIZATION_FORMS = ['NFC', 'NFD', 'NFKC', 'NFKD']; |
2019 | 2017 |
2020 var normalizationForm = | 2018 var normalizationForm = %_Call(ArrayIndexOf, NORMALIZATION_FORMS, form); |
2021 %_CallFunction(NORMALIZATION_FORMS, form, ArrayIndexOf); | |
2022 if (normalizationForm === -1) { | 2019 if (normalizationForm === -1) { |
2023 throw MakeRangeError(kNormalizationForm, | 2020 throw MakeRangeError(kNormalizationForm, |
2024 %_CallFunction(NORMALIZATION_FORMS, ', ', ArrayJoin)); | 2021 %_Call(ArrayJoin, NORMALIZATION_FORMS, ', ')); |
2025 } | 2022 } |
2026 | 2023 |
2027 return %StringNormalize(s, normalizationForm); | 2024 return %StringNormalize(s, normalizationForm); |
2028 } | 2025 } |
2029 ); | 2026 ); |
2030 | 2027 |
2031 | 2028 |
2032 /** | 2029 /** |
2033 * Formats a Number object (this) using locale and options values. | 2030 * Formats a Number object (this) using locale and options values. |
2034 * If locale or options are omitted, defaults are used. | 2031 * If locale or options are omitted, defaults are used. |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2116 } | 2113 } |
2117 | 2114 |
2118 var locales = %_Arguments(0); | 2115 var locales = %_Arguments(0); |
2119 var options = %_Arguments(1); | 2116 var options = %_Arguments(1); |
2120 return toLocaleDateTime( | 2117 return toLocaleDateTime( |
2121 this, locales, options, 'time', 'time', 'dateformattime'); | 2118 this, locales, options, 'time', 'time', 'dateformattime'); |
2122 } | 2119 } |
2123 ); | 2120 ); |
2124 | 2121 |
2125 }) | 2122 }) |
OLD | NEW |