| 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 |