| 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 ArrayJoin; | 20 var ArrayJoin; |
| 21 var ArrayPush; | 21 var ArrayPush; |
| 22 var GlobalDate = global.Date; | 22 var GlobalDate = global.Date; |
| 23 var GlobalNumber = global.Number; | 23 var GlobalNumber = global.Number; |
| 24 var GlobalRegExp = global.RegExp; | 24 var GlobalRegExp = global.RegExp; |
| 25 var GlobalString = global.String; | 25 var GlobalString = global.String; |
| 26 var InstallFunctions = utils.InstallFunctions; | 26 var InstallFunctions = utils.InstallFunctions; |
| 27 var InstallGetter = utils.InstallGetter; | 27 var InstallGetter = utils.InstallGetter; |
| 28 var InternalArray = utils.InternalArray; | 28 var InternalArray = utils.InternalArray; |
| 29 var InternalRegExpMatch; | |
| 30 var InternalRegExpReplace | |
| 31 var ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty"); | 29 var ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty"); |
| 32 var OverrideFunction = utils.OverrideFunction; | 30 var OverrideFunction = utils.OverrideFunction; |
| 33 var patternSymbol = utils.ImportNow("intl_pattern_symbol"); | 31 var patternSymbol = utils.ImportNow("intl_pattern_symbol"); |
| 34 var resolvedSymbol = utils.ImportNow("intl_resolved_symbol"); | 32 var resolvedSymbol = utils.ImportNow("intl_resolved_symbol"); |
| 35 var SetFunctionName = utils.SetFunctionName; | 33 var SetFunctionName = utils.SetFunctionName; |
| 36 var StringSubstr = GlobalString.prototype.substr; | 34 var StringSubstr = GlobalString.prototype.substr; |
| 37 var StringSubstring = GlobalString.prototype.substring; | 35 var StringSubstring = GlobalString.prototype.substring; |
| 38 | 36 |
| 39 utils.Import(function(from) { | 37 utils.Import(function(from) { |
| 40 ArrayJoin = from.ArrayJoin; | 38 ArrayJoin = from.ArrayJoin; |
| 41 ArrayPush = from.ArrayPush; | 39 ArrayPush = from.ArrayPush; |
| 42 InternalRegExpMatch = from.InternalRegExpMatch; | |
| 43 InternalRegExpReplace = from.InternalRegExpReplace; | |
| 44 }); | 40 }); |
| 45 | 41 |
| 46 // Utilities for definitions | 42 // Utilities for definitions |
| 47 | 43 |
| 48 function InstallFunction(object, name, func) { | 44 function InstallFunction(object, name, func) { |
| 49 InstallFunctions(object, DONT_ENUM, [name, func]); | 45 InstallFunctions(object, DONT_ENUM, [name, func]); |
| 50 } | 46 } |
| 51 | 47 |
| 52 | 48 |
| 53 function InstallConstructor(object, name, func) { | 49 function InstallConstructor(object, name, func) { |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 } | 238 } |
| 243 return TIMEZONE_NAME_LOCATION_PART_RE; | 239 return TIMEZONE_NAME_LOCATION_PART_RE; |
| 244 } | 240 } |
| 245 | 241 |
| 246 | 242 |
| 247 /** | 243 /** |
| 248 * Returns an intersection of locales and service supported locales. | 244 * Returns an intersection of locales and service supported locales. |
| 249 * Parameter locales is treated as a priority list. | 245 * Parameter locales is treated as a priority list. |
| 250 */ | 246 */ |
| 251 function supportedLocalesOf(service, locales, options) { | 247 function supportedLocalesOf(service, locales, options) { |
| 252 if (IS_NULL(InternalRegExpMatch(GetServiceRE(), service))) { | 248 if (IS_NULL(%regexp_internal_match(GetServiceRE(), service))) { |
| 253 throw %make_error(kWrongServiceType, service); | 249 throw %make_error(kWrongServiceType, service); |
| 254 } | 250 } |
| 255 | 251 |
| 256 // Provide defaults if matcher was not specified. | 252 // Provide defaults if matcher was not specified. |
| 257 if (IS_UNDEFINED(options)) { | 253 if (IS_UNDEFINED(options)) { |
| 258 options = {}; | 254 options = {}; |
| 259 } else { | 255 } else { |
| 260 options = TO_OBJECT(options); | 256 options = TO_OBJECT(options); |
| 261 } | 257 } |
| 262 | 258 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 290 | 286 |
| 291 /** | 287 /** |
| 292 * Returns the subset of the provided BCP 47 language priority list for which | 288 * 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. | 289 * 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. | 290 * Locales appear in the same order in the returned list as in the input list. |
| 295 */ | 291 */ |
| 296 function lookupSupportedLocalesOf(requestedLocales, availableLocales) { | 292 function lookupSupportedLocalesOf(requestedLocales, availableLocales) { |
| 297 var matchedLocales = new InternalArray(); | 293 var matchedLocales = new InternalArray(); |
| 298 for (var i = 0; i < requestedLocales.length; ++i) { | 294 for (var i = 0; i < requestedLocales.length; ++i) { |
| 299 // Remove -u- extension. | 295 // Remove -u- extension. |
| 300 var locale = InternalRegExpReplace( | 296 var locale = %regexp_internal_replace( |
| 301 GetUnicodeExtensionRE(), requestedLocales[i], ''); | 297 GetUnicodeExtensionRE(), requestedLocales[i], ''); |
| 302 do { | 298 do { |
| 303 if (!IS_UNDEFINED(availableLocales[locale])) { | 299 if (!IS_UNDEFINED(availableLocales[locale])) { |
| 304 // Push requested locale not the resolved one. | 300 // Push requested locale not the resolved one. |
| 305 %_Call(ArrayPush, matchedLocales, requestedLocales[i]); | 301 %_Call(ArrayPush, matchedLocales, requestedLocales[i]); |
| 306 break; | 302 break; |
| 307 } | 303 } |
| 308 // Truncate locale if possible, if not break. | 304 // Truncate locale if possible, if not break. |
| 309 var pos = %StringLastIndexOf(locale, '-'); | 305 var pos = %StringLastIndexOf(locale, '-'); |
| 310 if (pos === -1) { | 306 if (pos === -1) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 | 396 |
| 401 return resolved; | 397 return resolved; |
| 402 } | 398 } |
| 403 | 399 |
| 404 | 400 |
| 405 /** | 401 /** |
| 406 * Returns best matched supported locale and extension info using basic | 402 * Returns best matched supported locale and extension info using basic |
| 407 * lookup algorithm. | 403 * lookup algorithm. |
| 408 */ | 404 */ |
| 409 function lookupMatcher(service, requestedLocales) { | 405 function lookupMatcher(service, requestedLocales) { |
| 410 if (IS_NULL(InternalRegExpMatch(GetServiceRE(), service))) { | 406 if (IS_NULL(%regexp_internal_match(GetServiceRE(), service))) { |
| 411 throw %make_error(kWrongServiceType, service); | 407 throw %make_error(kWrongServiceType, service); |
| 412 } | 408 } |
| 413 | 409 |
| 414 // Cache these, they don't ever change per service. | 410 // Cache these, they don't ever change per service. |
| 415 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { | 411 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { |
| 416 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); | 412 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); |
| 417 } | 413 } |
| 418 | 414 |
| 419 for (var i = 0; i < requestedLocales.length; ++i) { | 415 for (var i = 0; i < requestedLocales.length; ++i) { |
| 420 // Remove all extensions. | 416 // Remove all extensions. |
| 421 var locale = InternalRegExpReplace( | 417 var locale = %regexp_internal_replace( |
| 422 GetAnyExtensionRE(), requestedLocales[i], ''); | 418 GetAnyExtensionRE(), requestedLocales[i], ''); |
| 423 do { | 419 do { |
| 424 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { | 420 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { |
| 425 // Return the resolved locale and extension. | 421 // Return the resolved locale and extension. |
| 426 var extensionMatch = InternalRegExpMatch( | 422 var extensionMatch = %regexp_internal_match( |
| 427 GetUnicodeExtensionRE(), requestedLocales[i]); | 423 GetUnicodeExtensionRE(), requestedLocales[i]); |
| 428 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; | 424 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; |
| 429 return {'locale': locale, 'extension': extension, 'position': i}; | 425 return {'locale': locale, 'extension': extension, 'position': i}; |
| 430 } | 426 } |
| 431 // Truncate locale if possible. | 427 // Truncate locale if possible. |
| 432 var pos = %StringLastIndexOf(locale, '-'); | 428 var pos = %StringLastIndexOf(locale, '-'); |
| 433 if (pos === -1) { | 429 if (pos === -1) { |
| 434 break; | 430 break; |
| 435 } | 431 } |
| 436 locale = %_Call(StringSubstring, locale, 0, pos); | 432 locale = %_Call(StringSubstring, locale, 0, pos); |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 614 return original; | 610 return original; |
| 615 } | 611 } |
| 616 | 612 |
| 617 var locales = %GetLanguageTagVariants([original, resolved]); | 613 var locales = %GetLanguageTagVariants([original, resolved]); |
| 618 if (locales[0].maximized !== locales[1].maximized) { | 614 if (locales[0].maximized !== locales[1].maximized) { |
| 619 return resolved; | 615 return resolved; |
| 620 } | 616 } |
| 621 | 617 |
| 622 // Preserve extensions of resolved locale, but swap base tags with original. | 618 // Preserve extensions of resolved locale, but swap base tags with original. |
| 623 var resolvedBase = new GlobalRegExp('^' + locales[1].base, 'g'); | 619 var resolvedBase = new GlobalRegExp('^' + locales[1].base, 'g'); |
| 624 return InternalRegExpReplace(resolvedBase, resolved, locales[0].base); | 620 return %regexp_internal_replace(resolvedBase, resolved, locales[0].base); |
| 625 } | 621 } |
| 626 | 622 |
| 627 | 623 |
| 628 /** | 624 /** |
| 629 * Returns an Object that contains all of supported locales for a given | 625 * Returns an Object that contains all of supported locales for a given |
| 630 * service. | 626 * service. |
| 631 * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ | 627 * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ |
| 632 * that is supported. This is required by the spec. | 628 * that is supported. This is required by the spec. |
| 633 */ | 629 */ |
| 634 function getAvailableLocalesOf(service) { | 630 function getAvailableLocalesOf(service) { |
| 635 var available = %AvailableLocalesOf(service); | 631 var available = %AvailableLocalesOf(service); |
| 636 | 632 |
| 637 for (var i in available) { | 633 for (var i in available) { |
| 638 if (HAS_OWN_PROPERTY(available, i)) { | 634 if (HAS_OWN_PROPERTY(available, i)) { |
| 639 var parts = InternalRegExpMatch( | 635 var parts = %regexp_internal_match( |
| 640 /^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/, i); | 636 /^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/, i); |
| 641 if (!IS_NULL(parts)) { | 637 if (!IS_NULL(parts)) { |
| 642 // Build xx-ZZ. We don't care about the actual value, | 638 // Build xx-ZZ. We don't care about the actual value, |
| 643 // as long it's not undefined. | 639 // as long it's not undefined. |
| 644 available[parts[1] + '-' + parts[3]] = null; | 640 available[parts[1] + '-' + parts[3]] = null; |
| 645 } | 641 } |
| 646 } | 642 } |
| 647 } | 643 } |
| 648 | 644 |
| 649 return available; | 645 return available; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 %StringToLowerCase(%_Call(StringSubstr, word, 1)); | 697 %StringToLowerCase(%_Call(StringSubstr, word, 1)); |
| 702 } | 698 } |
| 703 | 699 |
| 704 /** | 700 /** |
| 705 * Returns titlecased location, bueNos_airES -> Buenos_Aires | 701 * Returns titlecased location, bueNos_airES -> Buenos_Aires |
| 706 * or ho_cHi_minH -> Ho_Chi_Minh. It is locale-agnostic and only | 702 * or ho_cHi_minH -> Ho_Chi_Minh. It is locale-agnostic and only |
| 707 * deals with ASCII only characters. | 703 * deals with ASCII only characters. |
| 708 * 'of', 'au' and 'es' are special-cased and lowercased. | 704 * 'of', 'au' and 'es' are special-cased and lowercased. |
| 709 */ | 705 */ |
| 710 function toTitleCaseTimezoneLocation(location) { | 706 function toTitleCaseTimezoneLocation(location) { |
| 711 var match = InternalRegExpMatch(GetTimezoneNameLocationPartRE(), location) | 707 var match = %regexp_internal_match(GetTimezoneNameLocationPartRE(), location) |
| 712 if (IS_NULL(match)) throw %make_range_error(kExpectedLocation, location); | 708 if (IS_NULL(match)) throw %make_range_error(kExpectedLocation, location); |
| 713 | 709 |
| 714 var result = toTitleCaseWord(match[1]); | 710 var result = toTitleCaseWord(match[1]); |
| 715 if (!IS_UNDEFINED(match[2]) && 2 < match.length) { | 711 if (!IS_UNDEFINED(match[2]) && 2 < match.length) { |
| 716 // The first character is a separator, '_' or '-'. | 712 // The first character is a separator, '_' or '-'. |
| 717 // None of IANA zone names has both '_' and '-'. | 713 // None of IANA zone names has both '_' and '-'. |
| 718 var separator = %_Call(StringSubstring, match[2], 0, 1); | 714 var separator = %_Call(StringSubstring, match[2], 0, 1); |
| 719 var parts = %StringSplit(match[2], separator, kMaxUint32); | 715 var parts = %StringSplit(match[2], separator, kMaxUint32); |
| 720 for (var i = 1; i < parts.length; i++) { | 716 for (var i = 1; i < parts.length; i++) { |
| 721 var part = parts[i] | 717 var part = parts[i] |
| (...skipping 14 matching lines...) Expand all Loading... |
| 736 function canonicalizeLanguageTag(localeID) { | 732 function canonicalizeLanguageTag(localeID) { |
| 737 // null is typeof 'object' so we have to do extra check. | 733 // null is typeof 'object' so we have to do extra check. |
| 738 if ((!IS_STRING(localeID) && !IS_RECEIVER(localeID)) || | 734 if ((!IS_STRING(localeID) && !IS_RECEIVER(localeID)) || |
| 739 IS_NULL(localeID)) { | 735 IS_NULL(localeID)) { |
| 740 throw %make_type_error(kLanguageID); | 736 throw %make_type_error(kLanguageID); |
| 741 } | 737 } |
| 742 | 738 |
| 743 // Optimize for the most common case; a language code alone in | 739 // Optimize for the most common case; a language code alone in |
| 744 // the canonical form/lowercase (e.g. "en", "fil"). | 740 // the canonical form/lowercase (e.g. "en", "fil"). |
| 745 if (IS_STRING(localeID) && | 741 if (IS_STRING(localeID) && |
| 746 !IS_NULL(InternalRegExpMatch(/^[a-z]{2,3}$/, localeID))) { | 742 !IS_NULL(%regexp_internal_match(/^[a-z]{2,3}$/, localeID))) { |
| 747 return localeID; | 743 return localeID; |
| 748 } | 744 } |
| 749 | 745 |
| 750 var localeString = TO_STRING(localeID); | 746 var localeString = TO_STRING(localeID); |
| 751 | 747 |
| 752 if (isStructuallyValidLanguageTag(localeString) === false) { | 748 if (isStructuallyValidLanguageTag(localeString) === false) { |
| 753 throw %make_range_error(kInvalidLanguageTag, localeString); | 749 throw %make_range_error(kInvalidLanguageTag, localeString); |
| 754 } | 750 } |
| 755 | 751 |
| 756 // ECMA 402 6.2.3 | 752 // ECMA 402 6.2.3 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 814 * primary/extended language, script, region, variant are not checked | 810 * primary/extended language, script, region, variant are not checked |
| 815 * against the IANA language subtag registry. | 811 * against the IANA language subtag registry. |
| 816 * | 812 * |
| 817 * ICU is too permissible and lets invalid tags, like | 813 * ICU is too permissible and lets invalid tags, like |
| 818 * hant-cmn-cn, through. | 814 * hant-cmn-cn, through. |
| 819 * | 815 * |
| 820 * Returns false if the language tag is invalid. | 816 * Returns false if the language tag is invalid. |
| 821 */ | 817 */ |
| 822 function isStructuallyValidLanguageTag(locale) { | 818 function isStructuallyValidLanguageTag(locale) { |
| 823 // Check if it's well-formed, including grandfadered tags. | 819 // Check if it's well-formed, including grandfadered tags. |
| 824 if (IS_NULL(InternalRegExpMatch(GetLanguageTagRE(), locale))) { | 820 if (IS_NULL(%regexp_internal_match(GetLanguageTagRE(), locale))) { |
| 825 return false; | 821 return false; |
| 826 } | 822 } |
| 827 | 823 |
| 828 // Just return if it's a x- form. It's all private. | 824 // Just return if it's a x- form. It's all private. |
| 829 if (%StringIndexOf(locale, 'x-', 0) === 0) { | 825 if (%StringIndexOf(locale, 'x-', 0) === 0) { |
| 830 return true; | 826 return true; |
| 831 } | 827 } |
| 832 | 828 |
| 833 // Check if there are any duplicate variants or singletons (extensions). | 829 // Check if there are any duplicate variants or singletons (extensions). |
| 834 | 830 |
| 835 // Remove private use section. | 831 // Remove private use section. |
| 836 locale = %StringSplit(locale, '-x-', kMaxUint32)[0]; | 832 locale = %StringSplit(locale, '-x-', kMaxUint32)[0]; |
| 837 | 833 |
| 838 // Skip language since it can match variant regex, so we start from 1. | 834 // Skip language since it can match variant regex, so we start from 1. |
| 839 // We are matching i-klingon here, but that's ok, since i-klingon-klingon | 835 // We are matching i-klingon here, but that's ok, since i-klingon-klingon |
| 840 // is not valid and would fail LANGUAGE_TAG_RE test. | 836 // is not valid and would fail LANGUAGE_TAG_RE test. |
| 841 var variants = new InternalArray(); | 837 var variants = new InternalArray(); |
| 842 var extensions = new InternalArray(); | 838 var extensions = new InternalArray(); |
| 843 var parts = %StringSplit(locale, '-', kMaxUint32); | 839 var parts = %StringSplit(locale, '-', kMaxUint32); |
| 844 for (var i = 1; i < parts.length; i++) { | 840 for (var i = 1; i < parts.length; i++) { |
| 845 var value = parts[i]; | 841 var value = parts[i]; |
| 846 if (!IS_NULL(InternalRegExpMatch(GetLanguageVariantRE(), value)) && | 842 if (!IS_NULL(%regexp_internal_match(GetLanguageVariantRE(), value)) && |
| 847 extensions.length === 0) { | 843 extensions.length === 0) { |
| 848 if (%ArrayIndexOf(variants, value, 0) === -1) { | 844 if (%ArrayIndexOf(variants, value, 0) === -1) { |
| 849 %_Call(ArrayPush, variants, value); | 845 %_Call(ArrayPush, variants, value); |
| 850 } else { | 846 } else { |
| 851 return false; | 847 return false; |
| 852 } | 848 } |
| 853 } | 849 } |
| 854 | 850 |
| 855 if (!IS_NULL(InternalRegExpMatch(GetLanguageSingletonRE(), value))) { | 851 if (!IS_NULL(%regexp_internal_match(GetLanguageSingletonRE(), value))) { |
| 856 if (%ArrayIndexOf(extensions, value, 0) === -1) { | 852 if (%ArrayIndexOf(extensions, value, 0) === -1) { |
| 857 %_Call(ArrayPush, extensions, value); | 853 %_Call(ArrayPush, extensions, value); |
| 858 } else { | 854 } else { |
| 859 return false; | 855 return false; |
| 860 } | 856 } |
| 861 } | 857 } |
| 862 } | 858 } |
| 863 | 859 |
| 864 return true; | 860 return true; |
| 865 } | 861 } |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1114 | 1110 |
| 1115 AddBoundMethod(Intl.Collator, 'compare', compare, 2, 'collator'); | 1111 AddBoundMethod(Intl.Collator, 'compare', compare, 2, 'collator'); |
| 1116 | 1112 |
| 1117 /** | 1113 /** |
| 1118 * Verifies that the input is a well-formed ISO 4217 currency code. | 1114 * Verifies that the input is a well-formed ISO 4217 currency code. |
| 1119 * Don't uppercase to test. It could convert invalid code into a valid one. | 1115 * Don't uppercase to test. It could convert invalid code into a valid one. |
| 1120 * For example \u00DFP (Eszett+P) becomes SSP. | 1116 * For example \u00DFP (Eszett+P) becomes SSP. |
| 1121 */ | 1117 */ |
| 1122 function isWellFormedCurrencyCode(currency) { | 1118 function isWellFormedCurrencyCode(currency) { |
| 1123 return typeof currency == "string" && currency.length == 3 && | 1119 return typeof currency == "string" && currency.length == 3 && |
| 1124 IS_NULL(InternalRegExpMatch(/[^A-Za-z]/, currency)); | 1120 IS_NULL(%regexp_internal_match(/[^A-Za-z]/, currency)); |
| 1125 } | 1121 } |
| 1126 | 1122 |
| 1127 | 1123 |
| 1128 /** | 1124 /** |
| 1129 * Returns the valid digit count for a property, or throws RangeError on | 1125 * Returns the valid digit count for a property, or throws RangeError on |
| 1130 * a value out of the range. | 1126 * a value out of the range. |
| 1131 */ | 1127 */ |
| 1132 function getNumberOption(options, property, min, max, fallback) { | 1128 function getNumberOption(options, property, min, max, fallback) { |
| 1133 var value = options[property]; | 1129 var value = options[property]; |
| 1134 if (!IS_UNDEFINED(value)) { | 1130 if (!IS_UNDEFINED(value)) { |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1432 return ''; | 1428 return ''; |
| 1433 } | 1429 } |
| 1434 } | 1430 } |
| 1435 | 1431 |
| 1436 | 1432 |
| 1437 /** | 1433 /** |
| 1438 * Returns object that matches LDML representation of the date. | 1434 * Returns object that matches LDML representation of the date. |
| 1439 */ | 1435 */ |
| 1440 function fromLDMLString(ldmlString) { | 1436 function fromLDMLString(ldmlString) { |
| 1441 // First remove '' quoted text, so we lose 'Uhr' strings. | 1437 // First remove '' quoted text, so we lose 'Uhr' strings. |
| 1442 ldmlString = InternalRegExpReplace(GetQuotedStringRE(), ldmlString, ''); | 1438 ldmlString = %regexp_internal_replace(GetQuotedStringRE(), ldmlString, ''); |
| 1443 | 1439 |
| 1444 var options = {}; | 1440 var options = {}; |
| 1445 var match = InternalRegExpMatch(/E{3,5}/, ldmlString); | 1441 var match = %regexp_internal_match(/E{3,5}/, ldmlString); |
| 1446 options = appendToDateTimeObject( | 1442 options = appendToDateTimeObject( |
| 1447 options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'}); | 1443 options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'}); |
| 1448 | 1444 |
| 1449 match = InternalRegExpMatch(/G{3,5}/, ldmlString); | 1445 match = %regexp_internal_match(/G{3,5}/, ldmlString); |
| 1450 options = appendToDateTimeObject( | 1446 options = appendToDateTimeObject( |
| 1451 options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'}); | 1447 options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'}); |
| 1452 | 1448 |
| 1453 match = InternalRegExpMatch(/y{1,2}/, ldmlString); | 1449 match = %regexp_internal_match(/y{1,2}/, ldmlString); |
| 1454 options = appendToDateTimeObject( | 1450 options = appendToDateTimeObject( |
| 1455 options, 'year', match, {y: 'numeric', yy: '2-digit'}); | 1451 options, 'year', match, {y: 'numeric', yy: '2-digit'}); |
| 1456 | 1452 |
| 1457 match = InternalRegExpMatch(/M{1,5}/, ldmlString); | 1453 match = %regexp_internal_match(/M{1,5}/, ldmlString); |
| 1458 options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit', | 1454 options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit', |
| 1459 M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'}); | 1455 M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'}); |
| 1460 | 1456 |
| 1461 // Sometimes we get L instead of M for month - standalone name. | 1457 // Sometimes we get L instead of M for month - standalone name. |
| 1462 match = InternalRegExpMatch(/L{1,5}/, ldmlString); | 1458 match = %regexp_internal_match(/L{1,5}/, ldmlString); |
| 1463 options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit', | 1459 options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit', |
| 1464 L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'}); | 1460 L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'}); |
| 1465 | 1461 |
| 1466 match = InternalRegExpMatch(/d{1,2}/, ldmlString); | 1462 match = %regexp_internal_match(/d{1,2}/, ldmlString); |
| 1467 options = appendToDateTimeObject( | 1463 options = appendToDateTimeObject( |
| 1468 options, 'day', match, {d: 'numeric', dd: '2-digit'}); | 1464 options, 'day', match, {d: 'numeric', dd: '2-digit'}); |
| 1469 | 1465 |
| 1470 match = InternalRegExpMatch(/h{1,2}/, ldmlString); | 1466 match = %regexp_internal_match(/h{1,2}/, ldmlString); |
| 1471 if (match !== null) { | 1467 if (match !== null) { |
| 1472 options['hour12'] = true; | 1468 options['hour12'] = true; |
| 1473 } | 1469 } |
| 1474 options = appendToDateTimeObject( | 1470 options = appendToDateTimeObject( |
| 1475 options, 'hour', match, {h: 'numeric', hh: '2-digit'}); | 1471 options, 'hour', match, {h: 'numeric', hh: '2-digit'}); |
| 1476 | 1472 |
| 1477 match = InternalRegExpMatch(/H{1,2}/, ldmlString); | 1473 match = %regexp_internal_match(/H{1,2}/, ldmlString); |
| 1478 if (match !== null) { | 1474 if (match !== null) { |
| 1479 options['hour12'] = false; | 1475 options['hour12'] = false; |
| 1480 } | 1476 } |
| 1481 options = appendToDateTimeObject( | 1477 options = appendToDateTimeObject( |
| 1482 options, 'hour', match, {H: 'numeric', HH: '2-digit'}); | 1478 options, 'hour', match, {H: 'numeric', HH: '2-digit'}); |
| 1483 | 1479 |
| 1484 match = InternalRegExpMatch(/m{1,2}/, ldmlString); | 1480 match = %regexp_internal_match(/m{1,2}/, ldmlString); |
| 1485 options = appendToDateTimeObject( | 1481 options = appendToDateTimeObject( |
| 1486 options, 'minute', match, {m: 'numeric', mm: '2-digit'}); | 1482 options, 'minute', match, {m: 'numeric', mm: '2-digit'}); |
| 1487 | 1483 |
| 1488 match = InternalRegExpMatch(/s{1,2}/, ldmlString); | 1484 match = %regexp_internal_match(/s{1,2}/, ldmlString); |
| 1489 options = appendToDateTimeObject( | 1485 options = appendToDateTimeObject( |
| 1490 options, 'second', match, {s: 'numeric', ss: '2-digit'}); | 1486 options, 'second', match, {s: 'numeric', ss: '2-digit'}); |
| 1491 | 1487 |
| 1492 match = InternalRegExpMatch(/z|zzzz/, ldmlString); | 1488 match = %regexp_internal_match(/z|zzzz/, ldmlString); |
| 1493 options = appendToDateTimeObject( | 1489 options = appendToDateTimeObject( |
| 1494 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); | 1490 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); |
| 1495 | 1491 |
| 1496 return options; | 1492 return options; |
| 1497 } | 1493 } |
| 1498 | 1494 |
| 1499 | 1495 |
| 1500 function appendToDateTimeObject(options, option, match, pairs) { | 1496 function appendToDateTimeObject(options, option, match, pairs) { |
| 1501 if (IS_NULL(match)) { | 1497 if (IS_NULL(match)) { |
| 1502 if (!HAS_OWN_PROPERTY(options, option)) { | 1498 if (!HAS_OWN_PROPERTY(options, option)) { |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1811 var upperID = %StringToUpperCase(tzID); | 1807 var upperID = %StringToUpperCase(tzID); |
| 1812 if (upperID === 'UTC' || upperID === 'GMT' || | 1808 if (upperID === 'UTC' || upperID === 'GMT' || |
| 1813 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { | 1809 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { |
| 1814 return 'UTC'; | 1810 return 'UTC'; |
| 1815 } | 1811 } |
| 1816 | 1812 |
| 1817 // TODO(jshin): Add support for Etc/GMT[+-]([1-9]|1[0-2]) | 1813 // TODO(jshin): Add support for Etc/GMT[+-]([1-9]|1[0-2]) |
| 1818 | 1814 |
| 1819 // We expect only _, '-' and / beside ASCII letters. | 1815 // We expect only _, '-' and / beside ASCII letters. |
| 1820 // All inputs should conform to Area/Location(/Location)* from now on. | 1816 // All inputs should conform to Area/Location(/Location)* from now on. |
| 1821 var match = InternalRegExpMatch(GetTimezoneNameCheckRE(), tzID); | 1817 var match = %regexp_internal_match(GetTimezoneNameCheckRE(), tzID); |
| 1822 if (IS_NULL(match)) throw %make_range_error(kExpectedTimezoneID, tzID); | 1818 if (IS_NULL(match)) throw %make_range_error(kExpectedTimezoneID, tzID); |
| 1823 | 1819 |
| 1824 var result = toTitleCaseTimezoneLocation(match[1]) + '/' + | 1820 var result = toTitleCaseTimezoneLocation(match[1]) + '/' + |
| 1825 toTitleCaseTimezoneLocation(match[2]); | 1821 toTitleCaseTimezoneLocation(match[2]); |
| 1826 | 1822 |
| 1827 if (!IS_UNDEFINED(match[3]) && 3 < match.length) { | 1823 if (!IS_UNDEFINED(match[3]) && 3 < match.length) { |
| 1828 var locations = %StringSplit(match[3], '/', kMaxUint32); | 1824 var locations = %StringSplit(match[3], '/', kMaxUint32); |
| 1829 // The 1st element is empty. Starts with i=1. | 1825 // The 1st element is empty. Starts with i=1. |
| 1830 for (var i = 1; i < locations.length; i++) { | 1826 for (var i = 1; i < locations.length; i++) { |
| 1831 result = result + '/' + toTitleCaseTimezoneLocation(locations[i]); | 1827 result = result + '/' + toTitleCaseTimezoneLocation(locations[i]); |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2269 } | 2265 } |
| 2270 ); | 2266 ); |
| 2271 | 2267 |
| 2272 %FunctionRemovePrototype(FormatDateToParts); | 2268 %FunctionRemovePrototype(FormatDateToParts); |
| 2273 | 2269 |
| 2274 utils.Export(function(to) { | 2270 utils.Export(function(to) { |
| 2275 to.FormatDateToParts = FormatDateToParts; | 2271 to.FormatDateToParts = FormatDateToParts; |
| 2276 }); | 2272 }); |
| 2277 | 2273 |
| 2278 }) | 2274 }) |
| OLD | NEW |