Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: src/js/i18n.js

Issue 1819313002: [regexp, intl] Intl should not cause side effects to the RegExp object. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: addressed comment Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/js/regexp.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 InternalRegExpMatch;
32 var InternalRegExpReplace
33 var IsFinite;
34 var IsNaN;
32 var MakeError; 35 var MakeError;
33 var MakeRangeError; 36 var MakeRangeError;
34 var MakeTypeError; 37 var MakeTypeError;
35 var ObjectDefineProperties = utils.ImportNow("ObjectDefineProperties"); 38 var ObjectDefineProperties = utils.ImportNow("ObjectDefineProperties");
36 var ObjectDefineProperty = utils.ImportNow("ObjectDefineProperty"); 39 var ObjectDefineProperty = utils.ImportNow("ObjectDefineProperty");
37 var ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty"); 40 var ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty");
38 var OverrideFunction = utils.OverrideFunction; 41 var OverrideFunction = utils.OverrideFunction;
39 var patternSymbol = utils.ImportNow("intl_pattern_symbol"); 42 var patternSymbol = utils.ImportNow("intl_pattern_symbol");
40 var RegExpTest;
41 var resolvedSymbol = utils.ImportNow("intl_resolved_symbol"); 43 var resolvedSymbol = utils.ImportNow("intl_resolved_symbol");
42 var SetFunctionName = utils.SetFunctionName; 44 var SetFunctionName = utils.SetFunctionName;
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 RegExpTest = from.RegExpTest; 60 InternalRegExpMatch = from.InternalRegExpMatch;
61 InternalRegExpReplace = from.InternalRegExpReplace;
61 StringIndexOf = from.StringIndexOf; 62 StringIndexOf = from.StringIndexOf;
62 StringLastIndexOf = from.StringLastIndexOf; 63 StringLastIndexOf = from.StringLastIndexOf;
63 StringMatch = from.StringMatch;
64 StringReplace = from.StringReplace;
65 StringSplit = from.StringSplit; 64 StringSplit = from.StringSplit;
66 StringSubstr = from.StringSubstr; 65 StringSubstr = from.StringSubstr;
67 StringSubstring = from.StringSubstring; 66 StringSubstring = from.StringSubstring;
68 }); 67 });
69 68
70 // Utilities for definitions 69 // Utilities for definitions
71 70
72 function InstallFunction(object, name, func) { 71 function InstallFunction(object, name, func) {
73 InstallFunctions(object, DONT_ENUM, [name, func]); 72 InstallFunctions(object, DONT_ENUM, [name, func]);
74 } 73 }
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 } 255 }
257 return TIMEZONE_NAME_LOCATION_PART_RE; 256 return TIMEZONE_NAME_LOCATION_PART_RE;
258 } 257 }
259 258
260 259
261 /** 260 /**
262 * Returns an intersection of locales and service supported locales. 261 * Returns an intersection of locales and service supported locales.
263 * Parameter locales is treated as a priority list. 262 * Parameter locales is treated as a priority list.
264 */ 263 */
265 function supportedLocalesOf(service, locales, options) { 264 function supportedLocalesOf(service, locales, options) {
266 if (IS_NULL(%_Call(StringMatch, service, GetServiceRE()))) { 265 if (IS_NULL(InternalRegExpMatch(GetServiceRE(), service))) {
267 throw MakeError(kWrongServiceType, service); 266 throw MakeError(kWrongServiceType, service);
268 } 267 }
269 268
270 // Provide defaults if matcher was not specified. 269 // Provide defaults if matcher was not specified.
271 if (IS_UNDEFINED(options)) { 270 if (IS_UNDEFINED(options)) {
272 options = {}; 271 options = {};
273 } else { 272 } else {
274 options = TO_OBJECT(options); 273 options = TO_OBJECT(options);
275 } 274 }
276 275
(...skipping 27 matching lines...) Expand all
304 303
305 /** 304 /**
306 * Returns the subset of the provided BCP 47 language priority list for which 305 * Returns the subset of the provided BCP 47 language priority list for which
307 * this service has a matching locale when using the BCP 47 Lookup algorithm. 306 * this service has a matching locale when using the BCP 47 Lookup algorithm.
308 * Locales appear in the same order in the returned list as in the input list. 307 * Locales appear in the same order in the returned list as in the input list.
309 */ 308 */
310 function lookupSupportedLocalesOf(requestedLocales, availableLocales) { 309 function lookupSupportedLocalesOf(requestedLocales, availableLocales) {
311 var matchedLocales = []; 310 var matchedLocales = [];
312 for (var i = 0; i < requestedLocales.length; ++i) { 311 for (var i = 0; i < requestedLocales.length; ++i) {
313 // Remove -u- extension. 312 // Remove -u- extension.
314 var locale = %_Call(StringReplace, 313 var locale = InternalRegExpReplace(
315 requestedLocales[i], 314 GetUnicodeExtensionRE(), requestedLocales[i], '');
316 GetUnicodeExtensionRE(),
317 '');
318 do { 315 do {
319 if (!IS_UNDEFINED(availableLocales[locale])) { 316 if (!IS_UNDEFINED(availableLocales[locale])) {
320 // Push requested locale not the resolved one. 317 // Push requested locale not the resolved one.
321 %_Call(ArrayPush, matchedLocales, requestedLocales[i]); 318 %_Call(ArrayPush, matchedLocales, requestedLocales[i]);
322 break; 319 break;
323 } 320 }
324 // Truncate locale if possible, if not break. 321 // Truncate locale if possible, if not break.
325 var pos = %_Call(StringLastIndexOf, locale, '-'); 322 var pos = %_Call(StringLastIndexOf, locale, '-');
326 if (pos === -1) { 323 if (pos === -1) {
327 break; 324 break;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 410
414 return resolved; 411 return resolved;
415 } 412 }
416 413
417 414
418 /** 415 /**
419 * Returns best matched supported locale and extension info using basic 416 * Returns best matched supported locale and extension info using basic
420 * lookup algorithm. 417 * lookup algorithm.
421 */ 418 */
422 function lookupMatcher(service, requestedLocales) { 419 function lookupMatcher(service, requestedLocales) {
423 if (IS_NULL(%_Call(StringMatch, service, GetServiceRE()))) { 420 if (IS_NULL(InternalRegExpMatch(GetServiceRE(), service))) {
424 throw MakeError(kWrongServiceType, service); 421 throw MakeError(kWrongServiceType, service);
425 } 422 }
426 423
427 // Cache these, they don't ever change per service. 424 // Cache these, they don't ever change per service.
428 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { 425 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) {
429 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); 426 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service);
430 } 427 }
431 428
432 for (var i = 0; i < requestedLocales.length; ++i) { 429 for (var i = 0; i < requestedLocales.length; ++i) {
433 // Remove all extensions. 430 // Remove all extensions.
434 var locale = %_Call(StringReplace, requestedLocales[i], 431 var locale = InternalRegExpReplace(
435 GetAnyExtensionRE(), ''); 432 GetAnyExtensionRE(), requestedLocales[i], '');
436 do { 433 do {
437 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { 434 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) {
438 // Return the resolved locale and extension. 435 // Return the resolved locale and extension.
439 var extensionMatch = 436 var extensionMatch = InternalRegExpMatch(
440 %_Call(StringMatch, requestedLocales[i], GetUnicodeExtensionRE()); 437 GetUnicodeExtensionRE(), requestedLocales[i]);
441 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; 438 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0];
442 return {'locale': locale, 'extension': extension, 'position': i}; 439 return {'locale': locale, 'extension': extension, 'position': i};
443 } 440 }
444 // Truncate locale if possible. 441 // Truncate locale if possible.
445 var pos = %_Call(StringLastIndexOf, locale, '-'); 442 var pos = %_Call(StringLastIndexOf, locale, '-');
446 if (pos === -1) { 443 if (pos === -1) {
447 break; 444 break;
448 } 445 }
449 locale = %_Call(StringSubstring, locale, 0, pos); 446 locale = %_Call(StringSubstring, locale, 0, pos);
450 } while (true); 447 } while (true);
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
604 if (original === resolved) { 601 if (original === resolved) {
605 return original; 602 return original;
606 } 603 }
607 604
608 var locales = %GetLanguageTagVariants([original, resolved]); 605 var locales = %GetLanguageTagVariants([original, resolved]);
609 if (locales[0].maximized !== locales[1].maximized) { 606 if (locales[0].maximized !== locales[1].maximized) {
610 return resolved; 607 return resolved;
611 } 608 }
612 609
613 // Preserve extensions of resolved locale, but swap base tags with original. 610 // Preserve extensions of resolved locale, but swap base tags with original.
614 var resolvedBase = new GlobalRegExp('^' + locales[1].base); 611 var resolvedBase = new GlobalRegExp('^' + locales[1].base, 'g');
615 return %_Call(StringReplace, resolved, resolvedBase, locales[0].base); 612 return InternalRegExpReplace(resolvedBase, resolved, locales[0].base);
616 } 613 }
617 614
618 615
619 /** 616 /**
620 * Returns an Object that contains all of supported locales for a given 617 * Returns an Object that contains all of supported locales for a given
621 * service. 618 * service.
622 * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ 619 * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ
623 * that is supported. This is required by the spec. 620 * that is supported. This is required by the spec.
624 */ 621 */
625 function getAvailableLocalesOf(service) { 622 function getAvailableLocalesOf(service) {
626 var available = %AvailableLocalesOf(service); 623 var available = %AvailableLocalesOf(service);
627 624
628 for (var i in available) { 625 for (var i in available) {
629 if (HAS_OWN_PROPERTY(available, i)) { 626 if (HAS_OWN_PROPERTY(available, i)) {
630 var parts = 627 var parts = InternalRegExpMatch(
631 %_Call(StringMatch, i, /^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/); 628 /^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/, i);
632 if (parts !== null) { 629 if (!IS_NULL(parts)) {
633 // Build xx-ZZ. We don't care about the actual value, 630 // Build xx-ZZ. We don't care about the actual value,
634 // as long it's not undefined. 631 // as long it's not undefined.
635 available[parts[1] + '-' + parts[3]] = null; 632 available[parts[1] + '-' + parts[3]] = null;
636 } 633 }
637 } 634 }
638 } 635 }
639 636
640 return available; 637 return available;
641 } 638 }
642 639
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
692 %StringToLowerCase(%_Call(StringSubstr, word, 1)); 689 %StringToLowerCase(%_Call(StringSubstr, word, 1));
693 } 690 }
694 691
695 /** 692 /**
696 * Returns titlecased location, bueNos_airES -> Buenos_Aires 693 * Returns titlecased location, bueNos_airES -> Buenos_Aires
697 * or ho_cHi_minH -> Ho_Chi_Minh. It is locale-agnostic and only 694 * or ho_cHi_minH -> Ho_Chi_Minh. It is locale-agnostic and only
698 * deals with ASCII only characters. 695 * deals with ASCII only characters.
699 * 'of', 'au' and 'es' are special-cased and lowercased. 696 * 'of', 'au' and 'es' are special-cased and lowercased.
700 */ 697 */
701 function toTitleCaseTimezoneLocation(location) { 698 function toTitleCaseTimezoneLocation(location) {
702 var match = %_Call(StringMatch, location, GetTimezoneNameLocationPartRE()); 699 var match = InternalRegExpMatch(GetTimezoneNameLocationPartRE(), location)
703 if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, location); 700 if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, location);
704 701
705 var result = toTitleCaseWord(match[1]); 702 var result = toTitleCaseWord(match[1]);
706 if (!IS_UNDEFINED(match[2]) && 2 < match.length) { 703 if (!IS_UNDEFINED(match[2]) && 2 < match.length) {
707 // The first character is a separator, '_' or '-'. 704 // The first character is a separator, '_' or '-'.
708 // None of IANA zone names has both '_' and '-'. 705 // None of IANA zone names has both '_' and '-'.
709 var separator = %_Call(StringSubstring, match[2], 0, 1); 706 var separator = %_Call(StringSubstring, match[2], 0, 1);
710 var parts = %_Call(StringSplit, match[2], separator); 707 var parts = %_Call(StringSplit, match[2], separator);
711 for (var i = 1; i < parts.length; i++) { 708 for (var i = 1; i < parts.length; i++) {
712 var part = parts[i] 709 var part = parts[i]
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 * Validates the language tag. Section 2.2.9 of the bcp47 spec 786 * Validates the language tag. Section 2.2.9 of the bcp47 spec
790 * defines a valid tag. 787 * defines a valid tag.
791 * 788 *
792 * ICU is too permissible and lets invalid tags, like 789 * ICU is too permissible and lets invalid tags, like
793 * hant-cmn-cn, through. 790 * hant-cmn-cn, through.
794 * 791 *
795 * Returns false if the language tag is invalid. 792 * Returns false if the language tag is invalid.
796 */ 793 */
797 function isValidLanguageTag(locale) { 794 function isValidLanguageTag(locale) {
798 // Check if it's well-formed, including grandfadered tags. 795 // Check if it's well-formed, including grandfadered tags.
799 if (!%_Call(RegExpTest, GetLanguageTagRE(), locale)) { 796 if (IS_NULL(InternalRegExpMatch(GetLanguageTagRE(), locale))) {
800 return false; 797 return false;
801 } 798 }
802 799
803 // Just return if it's a x- form. It's all private. 800 // Just return if it's a x- form. It's all private.
804 if (%_Call(StringIndexOf, locale, 'x-') === 0) { 801 if (%_Call(StringIndexOf, locale, 'x-') === 0) {
805 return true; 802 return true;
806 } 803 }
807 804
808 // Check if there are any duplicate variants or singletons (extensions). 805 // Check if there are any duplicate variants or singletons (extensions).
809 806
810 // Remove private use section. 807 // Remove private use section.
811 locale = %_Call(StringSplit, locale, /-x-/)[0]; 808 locale = %_Call(StringSplit, locale, '-x-')[0];
812 809
813 // Skip language since it can match variant regex, so we start from 1. 810 // Skip language since it can match variant regex, so we start from 1.
814 // We are matching i-klingon here, but that's ok, since i-klingon-klingon 811 // We are matching i-klingon here, but that's ok, since i-klingon-klingon
815 // is not valid and would fail LANGUAGE_TAG_RE test. 812 // is not valid and would fail LANGUAGE_TAG_RE test.
816 var variants = []; 813 var variants = [];
817 var extensions = []; 814 var extensions = [];
818 var parts = %_Call(StringSplit, locale, /-/); 815 var parts = %_Call(StringSplit, locale, '-');
819 for (var i = 1; i < parts.length; i++) { 816 for (var i = 1; i < parts.length; i++) {
820 var value = parts[i]; 817 var value = parts[i];
821 if (%_Call(RegExpTest, GetLanguageVariantRE(), value) && 818 if (!IS_NULL(InternalRegExpMatch(GetLanguageVariantRE(), value)) &&
822 extensions.length === 0) { 819 extensions.length === 0) {
823 if (%_Call(ArrayIndexOf, variants, value) === -1) { 820 if (%_Call(ArrayIndexOf, variants, value) === -1) {
824 %_Call(ArrayPush, variants, value); 821 %_Call(ArrayPush, variants, value);
825 } else { 822 } else {
826 return false; 823 return false;
827 } 824 }
828 } 825 }
829 826
830 if (%_Call(RegExpTest, GetLanguageSingletonRE(), value)) { 827 if (!IS_NULL(InternalRegExpMatch(GetLanguageSingletonRE(), value))) {
831 if (%_Call(ArrayIndexOf, extensions, value) === -1) { 828 if (%_Call(ArrayIndexOf, extensions, value) === -1) {
832 %_Call(ArrayPush, extensions, value); 829 %_Call(ArrayPush, extensions, value);
833 } else { 830 } else {
834 return false; 831 return false;
835 } 832 }
836 } 833 }
837 } 834 }
838 835
839 return true; 836 return true;
840 } 837 }
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
1076 1073
1077 1074
1078 AddBoundMethod(Intl.Collator, 'compare', compare, 2); 1075 AddBoundMethod(Intl.Collator, 'compare', compare, 2);
1079 1076
1080 /** 1077 /**
1081 * Verifies that the input is a well-formed ISO 4217 currency code. 1078 * Verifies that the input is a well-formed ISO 4217 currency code.
1082 * Don't uppercase to test. It could convert invalid code into a valid one. 1079 * Don't uppercase to test. It could convert invalid code into a valid one.
1083 * For example \u00DFP (Eszett+P) becomes SSP. 1080 * For example \u00DFP (Eszett+P) becomes SSP.
1084 */ 1081 */
1085 function isWellFormedCurrencyCode(currency) { 1082 function isWellFormedCurrencyCode(currency) {
1086 return typeof currency == "string" && 1083 return typeof currency == "string" && currency.length == 3 &&
1087 currency.length == 3 && 1084 IS_NULL(InternalRegExpMatch(/[^A-Za-z]/, currency));
1088 %_Call(StringMatch, currency, /[^A-Za-z]/) == null;
1089 } 1085 }
1090 1086
1091 1087
1092 /** 1088 /**
1093 * Returns the valid digit count for a property, or throws RangeError on 1089 * Returns the valid digit count for a property, or throws RangeError on
1094 * a value out of the range. 1090 * a value out of the range.
1095 */ 1091 */
1096 function getNumberOption(options, property, min, max, fallback) { 1092 function getNumberOption(options, property, min, max, fallback) {
1097 var value = options[property]; 1093 var value = options[property];
1098 if (!IS_UNDEFINED(value)) { 1094 if (!IS_UNDEFINED(value)) {
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
1408 return ''; 1404 return '';
1409 } 1405 }
1410 } 1406 }
1411 1407
1412 1408
1413 /** 1409 /**
1414 * Returns object that matches LDML representation of the date. 1410 * Returns object that matches LDML representation of the date.
1415 */ 1411 */
1416 function fromLDMLString(ldmlString) { 1412 function fromLDMLString(ldmlString) {
1417 // First remove '' quoted text, so we lose 'Uhr' strings. 1413 // First remove '' quoted text, so we lose 'Uhr' strings.
1418 ldmlString = %_Call(StringReplace, ldmlString, GetQuotedStringRE(), ''); 1414 ldmlString = InternalRegExpReplace(GetQuotedStringRE(), ldmlString, '');
1419 1415
1420 var options = {}; 1416 var options = {};
1421 var match = %_Call(StringMatch, ldmlString, /E{3,5}/g); 1417 var match = InternalRegExpMatch(/E{3,5}/, ldmlString);
1422 options = appendToDateTimeObject( 1418 options = appendToDateTimeObject(
1423 options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'}); 1419 options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'});
1424 1420
1425 match = %_Call(StringMatch, ldmlString, /G{3,5}/g); 1421 match = InternalRegExpMatch(/G{3,5}/, ldmlString);
1426 options = appendToDateTimeObject( 1422 options = appendToDateTimeObject(
1427 options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'}); 1423 options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'});
1428 1424
1429 match = %_Call(StringMatch, ldmlString, /y{1,2}/g); 1425 match = InternalRegExpMatch(/y{1,2}/, ldmlString);
1430 options = appendToDateTimeObject( 1426 options = appendToDateTimeObject(
1431 options, 'year', match, {y: 'numeric', yy: '2-digit'}); 1427 options, 'year', match, {y: 'numeric', yy: '2-digit'});
1432 1428
1433 match = %_Call(StringMatch, ldmlString, /M{1,5}/g); 1429 match = InternalRegExpMatch(/M{1,5}/, ldmlString);
1434 options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit', 1430 options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit',
1435 M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'}); 1431 M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'});
1436 1432
1437 // Sometimes we get L instead of M for month - standalone name. 1433 // Sometimes we get L instead of M for month - standalone name.
1438 match = %_Call(StringMatch, ldmlString, /L{1,5}/g); 1434 match = InternalRegExpMatch(/L{1,5}/, ldmlString);
1439 options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit', 1435 options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit',
1440 L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'}); 1436 L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'});
1441 1437
1442 match = %_Call(StringMatch, ldmlString, /d{1,2}/g); 1438 match = InternalRegExpMatch(/d{1,2}/, ldmlString);
1443 options = appendToDateTimeObject( 1439 options = appendToDateTimeObject(
1444 options, 'day', match, {d: 'numeric', dd: '2-digit'}); 1440 options, 'day', match, {d: 'numeric', dd: '2-digit'});
1445 1441
1446 match = %_Call(StringMatch, ldmlString, /h{1,2}/g); 1442 match = InternalRegExpMatch(/h{1,2}/, ldmlString);
1447 if (match !== null) { 1443 if (match !== null) {
1448 options['hour12'] = true; 1444 options['hour12'] = true;
1449 } 1445 }
1450 options = appendToDateTimeObject( 1446 options = appendToDateTimeObject(
1451 options, 'hour', match, {h: 'numeric', hh: '2-digit'}); 1447 options, 'hour', match, {h: 'numeric', hh: '2-digit'});
1452 1448
1453 match = %_Call(StringMatch, ldmlString, /H{1,2}/g); 1449 match = InternalRegExpMatch(/H{1,2}/, ldmlString);
1454 if (match !== null) { 1450 if (match !== null) {
1455 options['hour12'] = false; 1451 options['hour12'] = false;
1456 } 1452 }
1457 options = appendToDateTimeObject( 1453 options = appendToDateTimeObject(
1458 options, 'hour', match, {H: 'numeric', HH: '2-digit'}); 1454 options, 'hour', match, {H: 'numeric', HH: '2-digit'});
1459 1455
1460 match = %_Call(StringMatch, ldmlString, /m{1,2}/g); 1456 match = InternalRegExpMatch(/m{1,2}/, ldmlString);
1461 options = appendToDateTimeObject( 1457 options = appendToDateTimeObject(
1462 options, 'minute', match, {m: 'numeric', mm: '2-digit'}); 1458 options, 'minute', match, {m: 'numeric', mm: '2-digit'});
1463 1459
1464 match = %_Call(StringMatch, ldmlString, /s{1,2}/g); 1460 match = InternalRegExpMatch(/s{1,2}/, ldmlString);
1465 options = appendToDateTimeObject( 1461 options = appendToDateTimeObject(
1466 options, 'second', match, {s: 'numeric', ss: '2-digit'}); 1462 options, 'second', match, {s: 'numeric', ss: '2-digit'});
1467 1463
1468 match = %_Call(StringMatch, ldmlString, /z|zzzz/g); 1464 match = InternalRegExpMatch(/z|zzzz/, ldmlString);
1469 options = appendToDateTimeObject( 1465 options = appendToDateTimeObject(
1470 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); 1466 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'});
1471 1467
1472 return options; 1468 return options;
1473 } 1469 }
1474 1470
1475 1471
1476 function appendToDateTimeObject(options, option, match, pairs) { 1472 function appendToDateTimeObject(options, option, match, pairs) {
1477 if (IS_NULL(match)) { 1473 if (IS_NULL(match)) {
1478 if (!HAS_OWN_PROPERTY(options, option)) { 1474 if (!HAS_OWN_PROPERTY(options, option)) {
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
1785 var upperID = %StringToUpperCase(tzID); 1781 var upperID = %StringToUpperCase(tzID);
1786 if (upperID === 'UTC' || upperID === 'GMT' || 1782 if (upperID === 'UTC' || upperID === 'GMT' ||
1787 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { 1783 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') {
1788 return 'UTC'; 1784 return 'UTC';
1789 } 1785 }
1790 1786
1791 // TODO(jshin): Add support for Etc/GMT[+-]([1-9]|1[0-2]) 1787 // TODO(jshin): Add support for Etc/GMT[+-]([1-9]|1[0-2])
1792 1788
1793 // We expect only _, '-' and / beside ASCII letters. 1789 // We expect only _, '-' and / beside ASCII letters.
1794 // All inputs should conform to Area/Location(/Location)* from now on. 1790 // All inputs should conform to Area/Location(/Location)* from now on.
1795 var match = %_Call(StringMatch, tzID, GetTimezoneNameCheckRE()); 1791 var match = InternalRegExpMatch(GetTimezoneNameCheckRE(), tzID);
1796 if (IS_NULL(match)) throw MakeRangeError(kExpectedTimezoneID, tzID); 1792 if (IS_NULL(match)) throw MakeRangeError(kExpectedTimezoneID, tzID);
1797 1793
1798 var result = toTitleCaseTimezoneLocation(match[1]) + '/' + 1794 var result = toTitleCaseTimezoneLocation(match[1]) + '/' +
1799 toTitleCaseTimezoneLocation(match[2]); 1795 toTitleCaseTimezoneLocation(match[2]);
1800 1796
1801 if (!IS_UNDEFINED(match[3]) && 3 < match.length) { 1797 if (!IS_UNDEFINED(match[3]) && 3 < match.length) {
1802 var locations = %_Call(StringSplit, match[3], '/'); 1798 var locations = %_Call(StringSplit, match[3], '/');
1803 // The 1st element is empty. Starts with i=1. 1799 // The 1st element is empty. Starts with i=1.
1804 for (var i = 1; i < locations.length; i++) { 1800 for (var i = 1; i < locations.length; i++) {
1805 result = result + '/' + toTitleCaseTimezoneLocation(locations[i]); 1801 result = result + '/' + toTitleCaseTimezoneLocation(locations[i]);
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
2136 } 2132 }
2137 2133
2138 var locales = arguments[0]; 2134 var locales = arguments[0];
2139 var options = arguments[1]; 2135 var options = arguments[1];
2140 return toLocaleDateTime( 2136 return toLocaleDateTime(
2141 this, locales, options, 'time', 'time', 'dateformattime'); 2137 this, locales, options, 'time', 'time', 'dateformattime');
2142 } 2138 }
2143 ); 2139 );
2144 2140
2145 }) 2141 })
OLDNEW
« no previous file with comments | « no previous file | src/js/regexp.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698