Chromium Code Reviews| 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 ArrayIndexOf; | 20 var ArrayIndexOf; |
| 21 var ArrayJoin; | 21 var ArrayJoin; |
| 22 var ArrayPush; | 22 var ArrayPush; |
| 23 var InstallFunctions = utils.InstallFunctions; | |
| 24 var InstallGetter = utils.InstallGetter; | |
| 25 var IsFinite; | |
| 26 var IsNaN; | |
| 27 var GlobalBoolean = global.Boolean; | 23 var GlobalBoolean = global.Boolean; |
| 28 var GlobalDate = global.Date; | 24 var GlobalDate = global.Date; |
| 29 var GlobalNumber = global.Number; | 25 var GlobalNumber = global.Number; |
| 30 var GlobalRegExp = global.RegExp; | 26 var GlobalRegExp = global.RegExp; |
| 31 var GlobalString = global.String; | 27 var GlobalString = global.String; |
| 28 var InstallFunctions = utils.InstallFunctions; | |
| 29 var InstallGetter = utils.InstallGetter; | |
| 30 var InternalPackedArray = utils.InternalPackedArray; | |
| 31 var IsFinite; | |
| 32 var IsNaN; | |
| 32 var MakeError; | 33 var MakeError; |
| 33 var MakeRangeError; | 34 var MakeRangeError; |
| 34 var MakeTypeError; | 35 var MakeTypeError; |
| 35 var MathFloor; | 36 var MathFloor; |
| 36 var ObjectDefineProperties = utils.ImportNow("ObjectDefineProperties"); | 37 var ObjectDefineProperties = utils.ImportNow("ObjectDefineProperties"); |
| 37 var ObjectDefineProperty = utils.ImportNow("ObjectDefineProperty"); | 38 var ObjectDefineProperty = utils.ImportNow("ObjectDefineProperty"); |
| 38 var ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty"); | 39 var ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty"); |
| 39 var patternSymbol = utils.ImportNow("intl_pattern_symbol"); | 40 var patternSymbol = utils.ImportNow("intl_pattern_symbol"); |
| 40 var RegExpTest; | |
| 41 var resolvedSymbol = utils.ImportNow("intl_resolved_symbol"); | 41 var resolvedSymbol = utils.ImportNow("intl_resolved_symbol"); |
| 42 var SetFunctionName = utils.SetFunctionName; | 42 var SetFunctionName = utils.SetFunctionName; |
| 43 var RegExpMatch; | |
| 44 var RegExpReplace | |
| 43 var StringIndexOf; | 45 var StringIndexOf; |
| 44 var StringLastIndexOf; | 46 var StringLastIndexOf; |
| 45 var StringMatch; | |
| 46 var StringReplace; | |
| 47 var StringSplit; | 47 var StringSplit; |
| 48 var StringSubstr; | 48 var StringSubstr; |
| 49 var StringSubstring; | 49 var StringSubstring; |
| 50 | 50 |
| 51 utils.Import(function(from) { | 51 utils.Import(function(from) { |
| 52 ArrayIndexOf = from.ArrayIndexOf; | 52 ArrayIndexOf = from.ArrayIndexOf; |
| 53 ArrayJoin = from.ArrayJoin; | 53 ArrayJoin = from.ArrayJoin; |
| 54 ArrayPush = from.ArrayPush; | 54 ArrayPush = from.ArrayPush; |
| 55 IsFinite = from.IsFinite; | 55 IsFinite = from.IsFinite; |
| 56 IsNaN = from.IsNaN; | 56 IsNaN = from.IsNaN; |
| 57 MakeError = from.MakeError; | 57 MakeError = from.MakeError; |
| 58 MakeRangeError = from.MakeRangeError; | 58 MakeRangeError = from.MakeRangeError; |
| 59 MakeTypeError = from.MakeTypeError; | 59 MakeTypeError = from.MakeTypeError; |
| 60 MathFloor = from.MathFloor; | 60 MathFloor = from.MathFloor; |
| 61 RegExpTest = from.RegExpTest; | 61 RegExpMatch = from.InternalRegExpMatch; |
| 62 RegExpReplace = from.InternalRegExpReplace; | |
|
Dan Ehrenberg
2016/03/23 15:55:41
Could you use the original names, so it's clearer
Yang
2016/03/24 06:14:13
Done.
| |
| 62 StringIndexOf = from.StringIndexOf; | 63 StringIndexOf = from.StringIndexOf; |
| 63 StringLastIndexOf = from.StringLastIndexOf; | 64 StringLastIndexOf = from.StringLastIndexOf; |
| 64 StringMatch = from.StringMatch; | |
| 65 StringReplace = from.StringReplace; | |
| 66 StringSplit = from.StringSplit; | 65 StringSplit = from.StringSplit; |
| 67 StringSubstr = from.StringSubstr; | 66 StringSubstr = from.StringSubstr; |
| 68 StringSubstring = from.StringSubstring; | 67 StringSubstring = from.StringSubstring; |
| 69 }); | 68 }); |
| 70 | 69 |
| 71 // Utilities for definitions | 70 // Utilities for definitions |
| 72 | 71 |
| 73 function OverrideFunction(object, name, f) { | 72 function OverrideFunction(object, name, f) { |
| 74 %CheckIsBootstrapping(); | 73 %CheckIsBootstrapping(); |
| 75 ObjectDefineProperty(object, name, { value: f, | 74 ObjectDefineProperty(object, name, { value: f, |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 } | 267 } |
| 269 return TIMEZONE_NAME_LOCATION_PART_RE; | 268 return TIMEZONE_NAME_LOCATION_PART_RE; |
| 270 } | 269 } |
| 271 | 270 |
| 272 | 271 |
| 273 /** | 272 /** |
| 274 * Returns an intersection of locales and service supported locales. | 273 * Returns an intersection of locales and service supported locales. |
| 275 * Parameter locales is treated as a priority list. | 274 * Parameter locales is treated as a priority list. |
| 276 */ | 275 */ |
| 277 function supportedLocalesOf(service, locales, options) { | 276 function supportedLocalesOf(service, locales, options) { |
| 278 if (IS_NULL(%_Call(StringMatch, service, GetServiceRE()))) { | 277 if (IS_NULL(RegExpMatch(GetServiceRE(), service))) { |
| 279 throw MakeError(kWrongServiceType, service); | 278 throw MakeError(kWrongServiceType, service); |
| 280 } | 279 } |
| 281 | 280 |
| 282 // Provide defaults if matcher was not specified. | 281 // Provide defaults if matcher was not specified. |
| 283 if (IS_UNDEFINED(options)) { | 282 if (IS_UNDEFINED(options)) { |
| 284 options = {}; | 283 options = {}; |
| 285 } else { | 284 } else { |
| 286 options = TO_OBJECT(options); | 285 options = TO_OBJECT(options); |
| 287 } | 286 } |
| 288 | 287 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 316 | 315 |
| 317 /** | 316 /** |
| 318 * Returns the subset of the provided BCP 47 language priority list for which | 317 * Returns the subset of the provided BCP 47 language priority list for which |
| 319 * this service has a matching locale when using the BCP 47 Lookup algorithm. | 318 * this service has a matching locale when using the BCP 47 Lookup algorithm. |
| 320 * Locales appear in the same order in the returned list as in the input list. | 319 * Locales appear in the same order in the returned list as in the input list. |
| 321 */ | 320 */ |
| 322 function lookupSupportedLocalesOf(requestedLocales, availableLocales) { | 321 function lookupSupportedLocalesOf(requestedLocales, availableLocales) { |
| 323 var matchedLocales = []; | 322 var matchedLocales = []; |
| 324 for (var i = 0; i < requestedLocales.length; ++i) { | 323 for (var i = 0; i < requestedLocales.length; ++i) { |
| 325 // Remove -u- extension. | 324 // Remove -u- extension. |
| 326 var locale = %_Call(StringReplace, | 325 var locale = RegExpReplace( |
| 327 requestedLocales[i], | 326 GetUnicodeExtensionRE(), requestedLocales[i], ''); |
| 328 GetUnicodeExtensionRE(), | |
| 329 ''); | |
| 330 do { | 327 do { |
| 331 if (!IS_UNDEFINED(availableLocales[locale])) { | 328 if (!IS_UNDEFINED(availableLocales[locale])) { |
| 332 // Push requested locale not the resolved one. | 329 // Push requested locale not the resolved one. |
| 333 %_Call(ArrayPush, matchedLocales, requestedLocales[i]); | 330 %_Call(ArrayPush, matchedLocales, requestedLocales[i]); |
| 334 break; | 331 break; |
| 335 } | 332 } |
| 336 // Truncate locale if possible, if not break. | 333 // Truncate locale if possible, if not break. |
| 337 var pos = %_Call(StringLastIndexOf, locale, '-'); | 334 var pos = %_Call(StringLastIndexOf, locale, '-'); |
| 338 if (pos === -1) { | 335 if (pos === -1) { |
| 339 break; | 336 break; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 425 | 422 |
| 426 return resolved; | 423 return resolved; |
| 427 } | 424 } |
| 428 | 425 |
| 429 | 426 |
| 430 /** | 427 /** |
| 431 * Returns best matched supported locale and extension info using basic | 428 * Returns best matched supported locale and extension info using basic |
| 432 * lookup algorithm. | 429 * lookup algorithm. |
| 433 */ | 430 */ |
| 434 function lookupMatcher(service, requestedLocales) { | 431 function lookupMatcher(service, requestedLocales) { |
| 435 if (IS_NULL(%_Call(StringMatch, service, GetServiceRE()))) { | 432 if (IS_NULL(RegExpMatch(GetServiceRE(), service))) { |
| 436 throw MakeError(kWrongServiceType, service); | 433 throw MakeError(kWrongServiceType, service); |
| 437 } | 434 } |
| 438 | 435 |
| 439 // Cache these, they don't ever change per service. | 436 // Cache these, they don't ever change per service. |
| 440 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { | 437 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { |
| 441 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); | 438 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); |
| 442 } | 439 } |
| 443 | 440 |
| 444 for (var i = 0; i < requestedLocales.length; ++i) { | 441 for (var i = 0; i < requestedLocales.length; ++i) { |
| 445 // Remove all extensions. | 442 // Remove all extensions. |
| 446 var locale = %_Call(StringReplace, requestedLocales[i], | 443 var locale = RegExpReplace(GetAnyExtensionRE(), requestedLocales[i], ''); |
| 447 GetAnyExtensionRE(), ''); | |
| 448 do { | 444 do { |
| 449 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { | 445 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { |
| 450 // Return the resolved locale and extension. | 446 // Return the resolved locale and extension. |
| 451 var extensionMatch = | 447 var extensionMatch = RegExpMatch( |
| 452 %_Call(StringMatch, requestedLocales[i], GetUnicodeExtensionRE()); | 448 GetUnicodeExtensionRE(), requestedLocales[i]); |
| 453 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; | 449 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; |
| 454 return {'locale': locale, 'extension': extension, 'position': i}; | 450 return {'locale': locale, 'extension': extension, 'position': i}; |
| 455 } | 451 } |
| 456 // Truncate locale if possible. | 452 // Truncate locale if possible. |
| 457 var pos = %_Call(StringLastIndexOf, locale, '-'); | 453 var pos = %_Call(StringLastIndexOf, locale, '-'); |
| 458 if (pos === -1) { | 454 if (pos === -1) { |
| 459 break; | 455 break; |
| 460 } | 456 } |
| 461 locale = %_Call(StringSubstring, locale, 0, pos); | 457 locale = %_Call(StringSubstring, locale, 0, pos); |
| 462 } while (true); | 458 } while (true); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 616 if (original === resolved) { | 612 if (original === resolved) { |
| 617 return original; | 613 return original; |
| 618 } | 614 } |
| 619 | 615 |
| 620 var locales = %GetLanguageTagVariants([original, resolved]); | 616 var locales = %GetLanguageTagVariants([original, resolved]); |
| 621 if (locales[0].maximized !== locales[1].maximized) { | 617 if (locales[0].maximized !== locales[1].maximized) { |
| 622 return resolved; | 618 return resolved; |
| 623 } | 619 } |
| 624 | 620 |
| 625 // Preserve extensions of resolved locale, but swap base tags with original. | 621 // Preserve extensions of resolved locale, but swap base tags with original. |
| 626 var resolvedBase = new GlobalRegExp('^' + locales[1].base); | 622 var resolvedBase = new GlobalRegExp('^' + locales[1].base, 'g'); |
| 627 return %_Call(StringReplace, resolved, resolvedBase, locales[0].base); | 623 return RegExpReplace(resolvedBase, resolved, locales[0].base); |
| 628 } | 624 } |
| 629 | 625 |
| 630 | 626 |
| 631 /** | 627 /** |
| 632 * Returns an Object that contains all of supported locales for a given | 628 * Returns an Object that contains all of supported locales for a given |
| 633 * service. | 629 * service. |
| 634 * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ | 630 * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ |
| 635 * that is supported. This is required by the spec. | 631 * that is supported. This is required by the spec. |
| 636 */ | 632 */ |
| 637 function getAvailableLocalesOf(service) { | 633 function getAvailableLocalesOf(service) { |
| 638 var available = %AvailableLocalesOf(service); | 634 var available = %AvailableLocalesOf(service); |
| 639 | 635 |
| 640 for (var i in available) { | 636 for (var i in available) { |
| 641 if (HAS_OWN_PROPERTY(available, i)) { | 637 if (HAS_OWN_PROPERTY(available, i)) { |
| 642 var parts = | 638 var parts = RegExpMatch(/^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/, i); |
| 643 %_Call(StringMatch, i, /^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/); | 639 if (!IS_NULL(parts)) { |
| 644 if (parts !== null) { | |
| 645 // Build xx-ZZ. We don't care about the actual value, | 640 // Build xx-ZZ. We don't care about the actual value, |
| 646 // as long it's not undefined. | 641 // as long it's not undefined. |
| 647 available[parts[1] + '-' + parts[3]] = null; | 642 available[parts[1] + '-' + parts[3]] = null; |
| 648 } | 643 } |
| 649 } | 644 } |
| 650 } | 645 } |
| 651 | 646 |
| 652 return available; | 647 return available; |
| 653 } | 648 } |
| 654 | 649 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 704 %StringToLowerCase(%_Call(StringSubstr, word, 1)); | 699 %StringToLowerCase(%_Call(StringSubstr, word, 1)); |
| 705 } | 700 } |
| 706 | 701 |
| 707 /** | 702 /** |
| 708 * Returns titlecased location, bueNos_airES -> Buenos_Aires | 703 * Returns titlecased location, bueNos_airES -> Buenos_Aires |
| 709 * or ho_cHi_minH -> Ho_Chi_Minh. It is locale-agnostic and only | 704 * or ho_cHi_minH -> Ho_Chi_Minh. It is locale-agnostic and only |
| 710 * deals with ASCII only characters. | 705 * deals with ASCII only characters. |
| 711 * 'of', 'au' and 'es' are special-cased and lowercased. | 706 * 'of', 'au' and 'es' are special-cased and lowercased. |
| 712 */ | 707 */ |
| 713 function toTitleCaseTimezoneLocation(location) { | 708 function toTitleCaseTimezoneLocation(location) { |
| 714 var match = %_Call(StringMatch, location, GetTimezoneNameLocationPartRE()); | 709 var match = RegExpMatch(GetTimezoneNameLocationPartRE(), location) |
| 715 if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, location); | 710 if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, location); |
| 716 | 711 |
| 717 var result = toTitleCaseWord(match[1]); | 712 var result = toTitleCaseWord(match[1]); |
| 718 if (!IS_UNDEFINED(match[2]) && 2 < match.length) { | 713 if (!IS_UNDEFINED(match[2]) && 2 < match.length) { |
| 719 // The first character is a separator, '_' or '-'. | 714 // The first character is a separator, '_' or '-'. |
| 720 // None of IANA zone names has both '_' and '-'. | 715 // None of IANA zone names has both '_' and '-'. |
| 721 var separator = %_Call(StringSubstring, match[2], 0, 1); | 716 var separator = %_Call(StringSubstring, match[2], 0, 1); |
| 722 var parts = %_Call(StringSplit, match[2], separator); | 717 var parts = %_Call(StringSplit, match[2], separator); |
| 723 for (var i = 1; i < parts.length; i++) { | 718 for (var i = 1; i < parts.length; i++) { |
| 724 var part = parts[i] | 719 var part = parts[i] |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 801 * Validates the language tag. Section 2.2.9 of the bcp47 spec | 796 * Validates the language tag. Section 2.2.9 of the bcp47 spec |
| 802 * defines a valid tag. | 797 * defines a valid tag. |
| 803 * | 798 * |
| 804 * ICU is too permissible and lets invalid tags, like | 799 * ICU is too permissible and lets invalid tags, like |
| 805 * hant-cmn-cn, through. | 800 * hant-cmn-cn, through. |
| 806 * | 801 * |
| 807 * Returns false if the language tag is invalid. | 802 * Returns false if the language tag is invalid. |
| 808 */ | 803 */ |
| 809 function isValidLanguageTag(locale) { | 804 function isValidLanguageTag(locale) { |
| 810 // Check if it's well-formed, including grandfadered tags. | 805 // Check if it's well-formed, including grandfadered tags. |
| 811 if (!%_Call(RegExpTest, GetLanguageTagRE(), locale)) { | 806 if (IS_NULL(RegExpMatch(GetLanguageTagRE(), locale))) { |
| 812 return false; | 807 return false; |
| 813 } | 808 } |
| 814 | 809 |
| 815 // Just return if it's a x- form. It's all private. | 810 // Just return if it's a x- form. It's all private. |
| 816 if (%_Call(StringIndexOf, locale, 'x-') === 0) { | 811 if (%_Call(StringIndexOf, locale, 'x-') === 0) { |
| 817 return true; | 812 return true; |
| 818 } | 813 } |
| 819 | 814 |
| 820 // Check if there are any duplicate variants or singletons (extensions). | 815 // Check if there are any duplicate variants or singletons (extensions). |
| 821 | 816 |
| 822 // Remove private use section. | 817 // Remove private use section. |
| 823 locale = %_Call(StringSplit, locale, /-x-/)[0]; | 818 locale = %_Call(StringSplit, locale, '-x-')[0]; |
| 824 | 819 |
| 825 // Skip language since it can match variant regex, so we start from 1. | 820 // Skip language since it can match variant regex, so we start from 1. |
| 826 // We are matching i-klingon here, but that's ok, since i-klingon-klingon | 821 // We are matching i-klingon here, but that's ok, since i-klingon-klingon |
| 827 // is not valid and would fail LANGUAGE_TAG_RE test. | 822 // is not valid and would fail LANGUAGE_TAG_RE test. |
| 828 var variants = []; | 823 var variants = []; |
| 829 var extensions = []; | 824 var extensions = []; |
| 830 var parts = %_Call(StringSplit, locale, /-/); | 825 var parts = %_Call(StringSplit, locale, '-'); |
| 831 for (var i = 1; i < parts.length; i++) { | 826 for (var i = 1; i < parts.length; i++) { |
| 832 var value = parts[i]; | 827 var value = parts[i]; |
| 833 if (%_Call(RegExpTest, GetLanguageVariantRE(), value) && | 828 if (!IS_NULL(RegExpMatch(GetLanguageVariantRE(), value)) && |
| 834 extensions.length === 0) { | 829 extensions.length === 0) { |
| 835 if (%_Call(ArrayIndexOf, variants, value) === -1) { | 830 if (%_Call(ArrayIndexOf, variants, value) === -1) { |
| 836 %_Call(ArrayPush, variants, value); | 831 %_Call(ArrayPush, variants, value); |
| 837 } else { | 832 } else { |
| 838 return false; | 833 return false; |
| 839 } | 834 } |
| 840 } | 835 } |
| 841 | 836 |
| 842 if (%_Call(RegExpTest, GetLanguageSingletonRE(), value)) { | 837 if (!IS_NULL(RegExpMatch(GetLanguageSingletonRE(), value))) { |
| 843 if (%_Call(ArrayIndexOf, extensions, value) === -1) { | 838 if (%_Call(ArrayIndexOf, extensions, value) === -1) { |
| 844 %_Call(ArrayPush, extensions, value); | 839 %_Call(ArrayPush, extensions, value); |
| 845 } else { | 840 } else { |
| 846 return false; | 841 return false; |
| 847 } | 842 } |
| 848 } | 843 } |
| 849 } | 844 } |
| 850 | 845 |
| 851 return true; | 846 return true; |
| 852 } | 847 } |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1088 | 1083 |
| 1089 | 1084 |
| 1090 AddBoundMethod(Intl.Collator, 'compare', compare, 2); | 1085 AddBoundMethod(Intl.Collator, 'compare', compare, 2); |
| 1091 | 1086 |
| 1092 /** | 1087 /** |
| 1093 * Verifies that the input is a well-formed ISO 4217 currency code. | 1088 * Verifies that the input is a well-formed ISO 4217 currency code. |
| 1094 * Don't uppercase to test. It could convert invalid code into a valid one. | 1089 * Don't uppercase to test. It could convert invalid code into a valid one. |
| 1095 * For example \u00DFP (Eszett+P) becomes SSP. | 1090 * For example \u00DFP (Eszett+P) becomes SSP. |
| 1096 */ | 1091 */ |
| 1097 function isWellFormedCurrencyCode(currency) { | 1092 function isWellFormedCurrencyCode(currency) { |
| 1098 return typeof currency == "string" && | 1093 return typeof currency == "string" && currency.length == 3 && |
| 1099 currency.length == 3 && | 1094 IS_NULL(RegExpMatch(/[^A-Za-z]/, currency)); |
| 1100 %_Call(StringMatch, currency, /[^A-Za-z]/) == null; | |
| 1101 } | 1095 } |
| 1102 | 1096 |
| 1103 | 1097 |
| 1104 /** | 1098 /** |
| 1105 * Returns the valid digit count for a property, or throws RangeError on | 1099 * Returns the valid digit count for a property, or throws RangeError on |
| 1106 * a value out of the range. | 1100 * a value out of the range. |
| 1107 */ | 1101 */ |
| 1108 function getNumberOption(options, property, min, max, fallback) { | 1102 function getNumberOption(options, property, min, max, fallback) { |
| 1109 var value = options[property]; | 1103 var value = options[property]; |
| 1110 if (!IS_UNDEFINED(value)) { | 1104 if (!IS_UNDEFINED(value)) { |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1420 return ''; | 1414 return ''; |
| 1421 } | 1415 } |
| 1422 } | 1416 } |
| 1423 | 1417 |
| 1424 | 1418 |
| 1425 /** | 1419 /** |
| 1426 * Returns object that matches LDML representation of the date. | 1420 * Returns object that matches LDML representation of the date. |
| 1427 */ | 1421 */ |
| 1428 function fromLDMLString(ldmlString) { | 1422 function fromLDMLString(ldmlString) { |
| 1429 // First remove '' quoted text, so we lose 'Uhr' strings. | 1423 // First remove '' quoted text, so we lose 'Uhr' strings. |
| 1430 ldmlString = %_Call(StringReplace, ldmlString, GetQuotedStringRE(), ''); | 1424 ldmlString = RegExpReplace(GetQuotedStringRE(), ldmlString, ''); |
| 1431 | 1425 |
| 1432 var options = {}; | 1426 var options = {}; |
| 1433 var match = %_Call(StringMatch, ldmlString, /E{3,5}/g); | 1427 var match = RegExpMatch(/E{3,5}/, ldmlString); |
| 1434 options = appendToDateTimeObject( | 1428 options = appendToDateTimeObject( |
| 1435 options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'}); | 1429 options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'}); |
| 1436 | 1430 |
| 1437 match = %_Call(StringMatch, ldmlString, /G{3,5}/g); | 1431 match = RegExpMatch(/G{3,5}/, ldmlString); |
| 1438 options = appendToDateTimeObject( | 1432 options = appendToDateTimeObject( |
| 1439 options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'}); | 1433 options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'}); |
| 1440 | 1434 |
| 1441 match = %_Call(StringMatch, ldmlString, /y{1,2}/g); | 1435 match = RegExpMatch(/y{1,2}/, ldmlString); |
| 1442 options = appendToDateTimeObject( | 1436 options = appendToDateTimeObject( |
| 1443 options, 'year', match, {y: 'numeric', yy: '2-digit'}); | 1437 options, 'year', match, {y: 'numeric', yy: '2-digit'}); |
| 1444 | 1438 |
| 1445 match = %_Call(StringMatch, ldmlString, /M{1,5}/g); | 1439 match = RegExpMatch(/M{1,5}/, ldmlString); |
| 1446 options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit', | 1440 options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit', |
| 1447 M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'}); | 1441 M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'}); |
| 1448 | 1442 |
| 1449 // Sometimes we get L instead of M for month - standalone name. | 1443 // Sometimes we get L instead of M for month - standalone name. |
| 1450 match = %_Call(StringMatch, ldmlString, /L{1,5}/g); | 1444 match = RegExpMatch(/L{1,5}/, ldmlString); |
| 1451 options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit', | 1445 options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit', |
| 1452 L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'}); | 1446 L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'}); |
| 1453 | 1447 |
| 1454 match = %_Call(StringMatch, ldmlString, /d{1,2}/g); | 1448 match = RegExpMatch(/d{1,2}/, ldmlString); |
| 1455 options = appendToDateTimeObject( | 1449 options = appendToDateTimeObject( |
| 1456 options, 'day', match, {d: 'numeric', dd: '2-digit'}); | 1450 options, 'day', match, {d: 'numeric', dd: '2-digit'}); |
| 1457 | 1451 |
| 1458 match = %_Call(StringMatch, ldmlString, /h{1,2}/g); | 1452 match = RegExpMatch(/h{1,2}/, ldmlString); |
| 1459 if (match !== null) { | 1453 if (match !== null) { |
| 1460 options['hour12'] = true; | 1454 options['hour12'] = true; |
| 1461 } | 1455 } |
| 1462 options = appendToDateTimeObject( | 1456 options = appendToDateTimeObject( |
| 1463 options, 'hour', match, {h: 'numeric', hh: '2-digit'}); | 1457 options, 'hour', match, {h: 'numeric', hh: '2-digit'}); |
| 1464 | 1458 |
| 1465 match = %_Call(StringMatch, ldmlString, /H{1,2}/g); | 1459 match = RegExpMatch(/H{1,2}/, ldmlString); |
| 1466 if (match !== null) { | 1460 if (match !== null) { |
| 1467 options['hour12'] = false; | 1461 options['hour12'] = false; |
| 1468 } | 1462 } |
| 1469 options = appendToDateTimeObject( | 1463 options = appendToDateTimeObject( |
| 1470 options, 'hour', match, {H: 'numeric', HH: '2-digit'}); | 1464 options, 'hour', match, {H: 'numeric', HH: '2-digit'}); |
| 1471 | 1465 |
| 1472 match = %_Call(StringMatch, ldmlString, /m{1,2}/g); | 1466 match = RegExpMatch(/m{1,2}/, ldmlString); |
| 1473 options = appendToDateTimeObject( | 1467 options = appendToDateTimeObject( |
| 1474 options, 'minute', match, {m: 'numeric', mm: '2-digit'}); | 1468 options, 'minute', match, {m: 'numeric', mm: '2-digit'}); |
| 1475 | 1469 |
| 1476 match = %_Call(StringMatch, ldmlString, /s{1,2}/g); | 1470 match = RegExpMatch(/s{1,2}/, ldmlString); |
| 1477 options = appendToDateTimeObject( | 1471 options = appendToDateTimeObject( |
| 1478 options, 'second', match, {s: 'numeric', ss: '2-digit'}); | 1472 options, 'second', match, {s: 'numeric', ss: '2-digit'}); |
| 1479 | 1473 |
| 1480 match = %_Call(StringMatch, ldmlString, /z|zzzz/g); | 1474 match = RegExpMatch(/z|zzzz/, ldmlString); |
| 1481 options = appendToDateTimeObject( | 1475 options = appendToDateTimeObject( |
| 1482 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); | 1476 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); |
| 1483 | 1477 |
| 1484 return options; | 1478 return options; |
| 1485 } | 1479 } |
| 1486 | 1480 |
| 1487 | 1481 |
| 1488 function appendToDateTimeObject(options, option, match, pairs) { | 1482 function appendToDateTimeObject(options, option, match, pairs) { |
| 1489 if (IS_NULL(match)) { | 1483 if (IS_NULL(match)) { |
| 1490 if (!HAS_OWN_PROPERTY(options, option)) { | 1484 if (!HAS_OWN_PROPERTY(options, option)) { |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1797 var upperID = %StringToUpperCase(tzID); | 1791 var upperID = %StringToUpperCase(tzID); |
| 1798 if (upperID === 'UTC' || upperID === 'GMT' || | 1792 if (upperID === 'UTC' || upperID === 'GMT' || |
| 1799 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { | 1793 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { |
| 1800 return 'UTC'; | 1794 return 'UTC'; |
| 1801 } | 1795 } |
| 1802 | 1796 |
| 1803 // TODO(jshin): Add support for Etc/GMT[+-]([1-9]|1[0-2]) | 1797 // TODO(jshin): Add support for Etc/GMT[+-]([1-9]|1[0-2]) |
| 1804 | 1798 |
| 1805 // We expect only _, '-' and / beside ASCII letters. | 1799 // We expect only _, '-' and / beside ASCII letters. |
| 1806 // All inputs should conform to Area/Location(/Location)* from now on. | 1800 // All inputs should conform to Area/Location(/Location)* from now on. |
| 1807 var match = %_Call(StringMatch, tzID, GetTimezoneNameCheckRE()); | 1801 var match = RegExpMatch(GetTimezoneNameCheckRE(), tzID); |
| 1808 if (IS_NULL(match)) throw MakeRangeError(kExpectedTimezoneID, tzID); | 1802 if (IS_NULL(match)) throw MakeRangeError(kExpectedTimezoneID, tzID); |
| 1809 | 1803 |
| 1810 var result = toTitleCaseTimezoneLocation(match[1]) + '/' + | 1804 var result = toTitleCaseTimezoneLocation(match[1]) + '/' + |
| 1811 toTitleCaseTimezoneLocation(match[2]); | 1805 toTitleCaseTimezoneLocation(match[2]); |
| 1812 | 1806 |
| 1813 if (!IS_UNDEFINED(match[3]) && 3 < match.length) { | 1807 if (!IS_UNDEFINED(match[3]) && 3 < match.length) { |
| 1814 var locations = %_Call(StringSplit, match[3], '/'); | 1808 var locations = %_Call(StringSplit, match[3], '/'); |
| 1815 // The 1st element is empty. Starts with i=1. | 1809 // The 1st element is empty. Starts with i=1. |
| 1816 for (var i = 1; i < locations.length; i++) { | 1810 for (var i = 1; i < locations.length; i++) { |
| 1817 result = result + '/' + toTitleCaseTimezoneLocation(locations[i]); | 1811 result = result + '/' + toTitleCaseTimezoneLocation(locations[i]); |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2148 } | 2142 } |
| 2149 | 2143 |
| 2150 var locales = arguments[0]; | 2144 var locales = arguments[0]; |
| 2151 var options = arguments[1]; | 2145 var options = arguments[1]; |
| 2152 return toLocaleDateTime( | 2146 return toLocaleDateTime( |
| 2153 this, locales, options, 'time', 'time', 'dateformattime'); | 2147 this, locales, options, 'time', 'time', 'dateformattime'); |
| 2154 } | 2148 } |
| 2155 ); | 2149 ); |
| 2156 | 2150 |
| 2157 }) | 2151 }) |
| OLD | NEW |