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

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: fix Created 4 years, 9 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') | src/js/regexp.js » ('J')
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 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
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
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
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
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
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
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
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
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
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
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 })
OLDNEW
« no previous file with comments | « no previous file | src/js/regexp.js » ('j') | src/js/regexp.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698