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

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

Issue 1419813010: [runtime] Remove the very dangerous %_CallFunction intrinsic. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 1 month 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 | « src/js/generator.js ('k') | src/js/macros.py » ('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 */
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 configurable: true 242 configurable: true
243 }); 243 });
244 } 244 }
245 245
246 246
247 /** 247 /**
248 * Returns an intersection of locales and service supported locales. 248 * Returns an intersection of locales and service supported locales.
249 * Parameter locales is treated as a priority list. 249 * Parameter locales is treated as a priority list.
250 */ 250 */
251 function supportedLocalesOf(service, locales, options) { 251 function supportedLocalesOf(service, locales, options) {
252 if (IS_NULL(%_CallFunction(service, GetServiceRE(), StringMatch))) { 252 if (IS_NULL(%_Call(StringMatch, service, GetServiceRE()))) {
253 throw MakeError(kWrongServiceType, service); 253 throw MakeError(kWrongServiceType, service);
254 } 254 }
255 255
256 // Provide defaults if matcher was not specified. 256 // Provide defaults if matcher was not specified.
257 if (IS_UNDEFINED(options)) { 257 if (IS_UNDEFINED(options)) {
258 options = {}; 258 options = {};
259 } else { 259 } else {
260 options = TO_OBJECT(options); 260 options = TO_OBJECT(options);
261 } 261 }
262 262
(...skipping 27 matching lines...) Expand all
290 290
291 /** 291 /**
292 * Returns the subset of the provided BCP 47 language priority list for which 292 * Returns the subset of the provided BCP 47 language priority list for which
293 * this service has a matching locale when using the BCP 47 Lookup algorithm. 293 * this service has a matching locale when using the BCP 47 Lookup algorithm.
294 * Locales appear in the same order in the returned list as in the input list. 294 * Locales appear in the same order in the returned list as in the input list.
295 */ 295 */
296 function lookupSupportedLocalesOf(requestedLocales, availableLocales) { 296 function lookupSupportedLocalesOf(requestedLocales, availableLocales) {
297 var matchedLocales = []; 297 var matchedLocales = [];
298 for (var i = 0; i < requestedLocales.length; ++i) { 298 for (var i = 0; i < requestedLocales.length; ++i) {
299 // Remove -u- extension. 299 // Remove -u- extension.
300 var locale = %_CallFunction(requestedLocales[i], GetUnicodeExtensionRE(), 300 var locale = %_Call(StringReplace,
301 '', StringReplace); 301 requestedLocales[i],
302 GetUnicodeExtensionRE(),
303 '');
302 do { 304 do {
303 if (!IS_UNDEFINED(availableLocales[locale])) { 305 if (!IS_UNDEFINED(availableLocales[locale])) {
304 // Push requested locale not the resolved one. 306 // Push requested locale not the resolved one.
305 %_CallFunction(matchedLocales, requestedLocales[i], ArrayPush); 307 %_Call(ArrayPush, matchedLocales, requestedLocales[i]);
306 break; 308 break;
307 } 309 }
308 // Truncate locale if possible, if not break. 310 // Truncate locale if possible, if not break.
309 var pos = %_CallFunction(locale, '-', StringLastIndexOf); 311 var pos = %_Call(StringLastIndexOf, locale, '-');
310 if (pos === -1) { 312 if (pos === -1) {
311 break; 313 break;
312 } 314 }
313 locale = %_CallFunction(locale, 0, pos, StringSubstring); 315 locale = %_Call(StringSubstring, locale, 0, pos);
314 } while (true); 316 } while (true);
315 } 317 }
316 318
317 return matchedLocales; 319 return matchedLocales;
318 } 320 }
319 321
320 322
321 /** 323 /**
322 * Returns the subset of the provided BCP 47 language priority list for which 324 * Returns the subset of the provided BCP 47 language priority list for which
323 * this service has a matching locale when using the implementation 325 * this service has a matching locale when using the implementation
(...skipping 24 matching lines...) Expand all
348 case 'string': 350 case 'string':
349 value = GlobalString(value); 351 value = GlobalString(value);
350 break; 352 break;
351 case 'number': 353 case 'number':
352 value = GlobalNumber(value); 354 value = GlobalNumber(value);
353 break; 355 break;
354 default: 356 default:
355 throw MakeError(kWrongValueType); 357 throw MakeError(kWrongValueType);
356 } 358 }
357 359
358 if (!IS_UNDEFINED(values) && 360 if (!IS_UNDEFINED(values) && %_Call(ArrayIndexOf, values, value) === -1) {
359 %_CallFunction(values, value, ArrayIndexOf) === -1) {
360 throw MakeRangeError(kValueOutOfRange, value, caller, property); 361 throw MakeRangeError(kValueOutOfRange, value, caller, property);
361 } 362 }
362 363
363 return value; 364 return value;
364 } 365 }
365 366
366 return defaultValue; 367 return defaultValue;
367 } 368 }
368 369
369 return getOption; 370 return getOption;
(...skipping 28 matching lines...) Expand all
398 399
399 return resolved; 400 return resolved;
400 } 401 }
401 402
402 403
403 /** 404 /**
404 * Returns best matched supported locale and extension info using basic 405 * Returns best matched supported locale and extension info using basic
405 * lookup algorithm. 406 * lookup algorithm.
406 */ 407 */
407 function lookupMatcher(service, requestedLocales) { 408 function lookupMatcher(service, requestedLocales) {
408 if (IS_NULL(%_CallFunction(service, GetServiceRE(), StringMatch))) { 409 if (IS_NULL(%_Call(StringMatch, service, GetServiceRE()))) {
409 throw MakeError(kWrongServiceType, service); 410 throw MakeError(kWrongServiceType, service);
410 } 411 }
411 412
412 // Cache these, they don't ever change per service. 413 // Cache these, they don't ever change per service.
413 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) { 414 if (IS_UNDEFINED(AVAILABLE_LOCALES[service])) {
414 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service); 415 AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service);
415 } 416 }
416 417
417 for (var i = 0; i < requestedLocales.length; ++i) { 418 for (var i = 0; i < requestedLocales.length; ++i) {
418 // Remove all extensions. 419 // Remove all extensions.
419 var locale = %_CallFunction(requestedLocales[i], GetAnyExtensionRE(), '', 420 var locale = %_Call(StringReplace, requestedLocales[i],
420 StringReplace); 421 GetAnyExtensionRE(), '');
421 do { 422 do {
422 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) { 423 if (!IS_UNDEFINED(AVAILABLE_LOCALES[service][locale])) {
423 // Return the resolved locale and extension. 424 // Return the resolved locale and extension.
424 var extensionMatch = 425 var extensionMatch =
425 %_CallFunction(requestedLocales[i], GetUnicodeExtensionRE(), 426 %_Call(StringMatch, requestedLocales[i], GetUnicodeExtensionRE());
426 StringMatch);
427 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; 427 var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0];
428 return {'locale': locale, 'extension': extension, 'position': i}; 428 return {'locale': locale, 'extension': extension, 'position': i};
429 } 429 }
430 // Truncate locale if possible. 430 // Truncate locale if possible.
431 var pos = %_CallFunction(locale, '-', StringLastIndexOf); 431 var pos = %_Call(StringLastIndexOf, locale, '-');
432 if (pos === -1) { 432 if (pos === -1) {
433 break; 433 break;
434 } 434 }
435 locale = %_CallFunction(locale, 0, pos, StringSubstring); 435 locale = %_Call(StringSubstring, locale, 0, pos);
436 } while (true); 436 } while (true);
437 } 437 }
438 438
439 // Didn't find a match, return default. 439 // Didn't find a match, return default.
440 if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) { 440 if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) {
441 DEFAULT_ICU_LOCALE = %GetDefaultICULocale(); 441 DEFAULT_ICU_LOCALE = %GetDefaultICULocale();
442 } 442 }
443 443
444 return {'locale': DEFAULT_ICU_LOCALE, 'extension': '', 'position': -1}; 444 return {'locale': DEFAULT_ICU_LOCALE, 'extension': '', 'position': -1};
445 } 445 }
446 446
447 447
448 /** 448 /**
449 * Returns best matched supported locale and extension info using 449 * Returns best matched supported locale and extension info using
450 * implementation dependend algorithm. 450 * implementation dependend algorithm.
451 */ 451 */
452 function bestFitMatcher(service, requestedLocales) { 452 function bestFitMatcher(service, requestedLocales) {
453 // TODO(cira): implement better best fit algorithm. 453 // TODO(cira): implement better best fit algorithm.
454 return lookupMatcher(service, requestedLocales); 454 return lookupMatcher(service, requestedLocales);
455 } 455 }
456 456
457 457
458 /** 458 /**
459 * Parses Unicode extension into key - value map. 459 * Parses Unicode extension into key - value map.
460 * Returns empty object if the extension string is invalid. 460 * Returns empty object if the extension string is invalid.
461 * We are not concerned with the validity of the values at this point. 461 * We are not concerned with the validity of the values at this point.
462 */ 462 */
463 function parseExtension(extension) { 463 function parseExtension(extension) {
464 var extensionSplit = %_CallFunction(extension, '-', StringSplit); 464 var extensionSplit = %_Call(StringSplit, extension, '-');
465 465
466 // Assume ['', 'u', ...] input, but don't throw. 466 // Assume ['', 'u', ...] input, but don't throw.
467 if (extensionSplit.length <= 2 || 467 if (extensionSplit.length <= 2 ||
468 (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) { 468 (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) {
469 return {}; 469 return {};
470 } 470 }
471 471
472 // Key is {2}alphanum, value is {3,8}alphanum. 472 // Key is {2}alphanum, value is {3,8}alphanum.
473 // Some keys may not have explicit values (booleans). 473 // Some keys may not have explicit values (booleans).
474 var extensionMap = {}; 474 var extensionMap = {};
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 return original; 591 return original;
592 } 592 }
593 593
594 var locales = %GetLanguageTagVariants([original, resolved]); 594 var locales = %GetLanguageTagVariants([original, resolved]);
595 if (locales[0].maximized !== locales[1].maximized) { 595 if (locales[0].maximized !== locales[1].maximized) {
596 return resolved; 596 return resolved;
597 } 597 }
598 598
599 // Preserve extensions of resolved locale, but swap base tags with original. 599 // Preserve extensions of resolved locale, but swap base tags with original.
600 var resolvedBase = new GlobalRegExp('^' + locales[1].base); 600 var resolvedBase = new GlobalRegExp('^' + locales[1].base);
601 return %_CallFunction(resolved, resolvedBase, locales[0].base, StringReplace); 601 return %_Call(StringReplace, resolved, resolvedBase, locales[0].base);
602 } 602 }
603 603
604 604
605 /** 605 /**
606 * Returns an Object that contains all of supported locales for a given 606 * Returns an Object that contains all of supported locales for a given
607 * service. 607 * service.
608 * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ 608 * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ
609 * that is supported. This is required by the spec. 609 * that is supported. This is required by the spec.
610 */ 610 */
611 function getAvailableLocalesOf(service) { 611 function getAvailableLocalesOf(service) {
612 var available = %AvailableLocalesOf(service); 612 var available = %AvailableLocalesOf(service);
613 613
614 for (var i in available) { 614 for (var i in available) {
615 if (%HasOwnProperty(available, i)) { 615 if (%HasOwnProperty(available, i)) {
616 var parts = %_CallFunction(i, /^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/, 616 var parts =
617 StringMatch); 617 %_Call(StringMatch, i, /^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/);
618 if (parts !== null) { 618 if (parts !== null) {
619 // Build xx-ZZ. We don't care about the actual value, 619 // Build xx-ZZ. We don't care about the actual value,
620 // as long it's not undefined. 620 // as long it's not undefined.
621 available[parts[1] + '-' + parts[3]] = null; 621 available[parts[1] + '-' + parts[3]] = null;
622 } 622 }
623 } 623 }
624 } 624 }
625 625
626 return available; 626 return available;
627 } 627 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 if (!IS_UNDEFINED(value)) { 667 if (!IS_UNDEFINED(value)) {
668 defineWECProperty(object, property, value); 668 defineWECProperty(object, property, value);
669 } 669 }
670 } 670 }
671 671
672 672
673 /** 673 /**
674 * Returns titlecased word, aMeRricA -> America. 674 * Returns titlecased word, aMeRricA -> America.
675 */ 675 */
676 function toTitleCaseWord(word) { 676 function toTitleCaseWord(word) {
677 return %StringToUpperCase(%_CallFunction(word, 0, 1, StringSubstr)) + 677 return %StringToUpperCase(%_Call(StringSubstr, word, 0, 1)) +
678 %StringToLowerCase(%_CallFunction(word, 1, StringSubstr)); 678 %StringToLowerCase(%_Call(StringSubstr, word, 1));
679 } 679 }
680 680
681 /** 681 /**
682 * Canonicalizes the language tag, or throws in case the tag is invalid. 682 * Canonicalizes the language tag, or throws in case the tag is invalid.
683 */ 683 */
684 function canonicalizeLanguageTag(localeID) { 684 function canonicalizeLanguageTag(localeID) {
685 // null is typeof 'object' so we have to do extra check. 685 // null is typeof 'object' so we have to do extra check.
686 if (typeof localeID !== 'string' && typeof localeID !== 'object' || 686 if (typeof localeID !== 'string' && typeof localeID !== 'object' ||
687 IS_NULL(localeID)) { 687 IS_NULL(localeID)) {
688 throw MakeTypeError(kLanguageID); 688 throw MakeTypeError(kLanguageID);
(...skipping 23 matching lines...) Expand all
712 * Throws on locales that are not well formed BCP47 tags. 712 * Throws on locales that are not well formed BCP47 tags.
713 */ 713 */
714 function initializeLocaleList(locales) { 714 function initializeLocaleList(locales) {
715 var seen = []; 715 var seen = [];
716 if (IS_UNDEFINED(locales)) { 716 if (IS_UNDEFINED(locales)) {
717 // Constructor is called without arguments. 717 // Constructor is called without arguments.
718 seen = []; 718 seen = [];
719 } else { 719 } else {
720 // We allow single string localeID. 720 // We allow single string localeID.
721 if (typeof locales === 'string') { 721 if (typeof locales === 'string') {
722 %_CallFunction(seen, canonicalizeLanguageTag(locales), ArrayPush); 722 %_Call(ArrayPush, seen, canonicalizeLanguageTag(locales));
723 return freezeArray(seen); 723 return freezeArray(seen);
724 } 724 }
725 725
726 var o = TO_OBJECT(locales); 726 var o = TO_OBJECT(locales);
727 var len = TO_UINT32(o.length); 727 var len = TO_UINT32(o.length);
728 728
729 for (var k = 0; k < len; k++) { 729 for (var k = 0; k < len; k++) {
730 if (k in o) { 730 if (k in o) {
731 var value = o[k]; 731 var value = o[k];
732 732
733 var tag = canonicalizeLanguageTag(value); 733 var tag = canonicalizeLanguageTag(value);
734 734
735 if (%_CallFunction(seen, tag, ArrayIndexOf) === -1) { 735 if (%_Call(ArrayIndexOf, seen, tag) === -1) {
736 %_CallFunction(seen, tag, ArrayPush); 736 %_Call(ArrayPush, seen, tag);
737 } 737 }
738 } 738 }
739 } 739 }
740 } 740 }
741 741
742 return freezeArray(seen); 742 return freezeArray(seen);
743 } 743 }
744 744
745 745
746 /** 746 /**
747 * Validates the language tag. Section 2.2.9 of the bcp47 spec 747 * Validates the language tag. Section 2.2.9 of the bcp47 spec
748 * defines a valid tag. 748 * defines a valid tag.
749 * 749 *
750 * ICU is too permissible and lets invalid tags, like 750 * ICU is too permissible and lets invalid tags, like
751 * hant-cmn-cn, through. 751 * hant-cmn-cn, through.
752 * 752 *
753 * Returns false if the language tag is invalid. 753 * Returns false if the language tag is invalid.
754 */ 754 */
755 function isValidLanguageTag(locale) { 755 function isValidLanguageTag(locale) {
756 // Check if it's well-formed, including grandfadered tags. 756 // Check if it's well-formed, including grandfadered tags.
757 if (!%_CallFunction(GetLanguageTagRE(), locale, RegExpTest)) { 757 if (!%_Call(RegExpTest, GetLanguageTagRE(), locale)) {
758 return false; 758 return false;
759 } 759 }
760 760
761 // Just return if it's a x- form. It's all private. 761 // Just return if it's a x- form. It's all private.
762 if (%_CallFunction(locale, 'x-', StringIndexOf) === 0) { 762 if (%_Call(StringIndexOf, locale, 'x-') === 0) {
763 return true; 763 return true;
764 } 764 }
765 765
766 // Check if there are any duplicate variants or singletons (extensions). 766 // Check if there are any duplicate variants or singletons (extensions).
767 767
768 // Remove private use section. 768 // Remove private use section.
769 locale = %_CallFunction(locale, /-x-/, StringSplit)[0]; 769 locale = %_Call(StringSplit, locale, /-x-/)[0];
770 770
771 // Skip language since it can match variant regex, so we start from 1. 771 // Skip language since it can match variant regex, so we start from 1.
772 // We are matching i-klingon here, but that's ok, since i-klingon-klingon 772 // We are matching i-klingon here, but that's ok, since i-klingon-klingon
773 // is not valid and would fail LANGUAGE_TAG_RE test. 773 // is not valid and would fail LANGUAGE_TAG_RE test.
774 var variants = []; 774 var variants = [];
775 var extensions = []; 775 var extensions = [];
776 var parts = %_CallFunction(locale, /-/, StringSplit); 776 var parts = %_Call(StringSplit, locale, /-/);
777 for (var i = 1; i < parts.length; i++) { 777 for (var i = 1; i < parts.length; i++) {
778 var value = parts[i]; 778 var value = parts[i];
779 if (%_CallFunction(GetLanguageVariantRE(), value, RegExpTest) && 779 if (%_Call(RegExpTest, GetLanguageVariantRE(), value) &&
780 extensions.length === 0) { 780 extensions.length === 0) {
781 if (%_CallFunction(variants, value, ArrayIndexOf) === -1) { 781 if (%_Call(ArrayIndexOf, variants, value) === -1) {
782 %_CallFunction(variants, value, ArrayPush); 782 %_Call(ArrayPush, variants, value);
783 } else { 783 } else {
784 return false; 784 return false;
785 } 785 }
786 } 786 }
787 787
788 if (%_CallFunction(GetLanguageSingletonRE(), value, RegExpTest)) { 788 if (%_Call(RegExpTest, GetLanguageSingletonRE(), value)) {
789 if (%_CallFunction(extensions, value, ArrayIndexOf) === -1) { 789 if (%_Call(ArrayIndexOf, extensions, value) === -1) {
790 %_CallFunction(extensions, value, ArrayPush); 790 %_Call(ArrayPush, extensions, value);
791 } else { 791 } else {
792 return false; 792 return false;
793 } 793 }
794 } 794 }
795 } 795 }
796 796
797 return true; 797 return true;
798 } 798 }
799 799
800 800
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
894 894
895 /** 895 /**
896 * Allowed -u-co- values. List taken from: 896 * Allowed -u-co- values. List taken from:
897 * http://unicode.org/repos/cldr/trunk/common/bcp47/collation.xml 897 * http://unicode.org/repos/cldr/trunk/common/bcp47/collation.xml
898 */ 898 */
899 var ALLOWED_CO_VALUES = [ 899 var ALLOWED_CO_VALUES = [
900 'big5han', 'dict', 'direct', 'ducet', 'gb2312', 'phonebk', 'phonetic', 900 'big5han', 'dict', 'direct', 'ducet', 'gb2312', 'phonebk', 'phonetic',
901 'pinyin', 'reformed', 'searchjl', 'stroke', 'trad', 'unihan', 'zhuyin' 901 'pinyin', 'reformed', 'searchjl', 'stroke', 'trad', 'unihan', 'zhuyin'
902 ]; 902 ];
903 903
904 if (%_CallFunction(ALLOWED_CO_VALUES, extensionMap.co, ArrayIndexOf) !== 904 if (%_Call(ArrayIndexOf, ALLOWED_CO_VALUES, extensionMap.co) !== -1) {
905 -1) {
906 extension = '-u-co-' + extensionMap.co; 905 extension = '-u-co-' + extensionMap.co;
907 // ICU can't tell us what the collation is, so save user's input. 906 // ICU can't tell us what the collation is, so save user's input.
908 collation = extensionMap.co; 907 collation = extensionMap.co;
909 } 908 }
910 } else if (internalOptions.usage === 'search') { 909 } else if (internalOptions.usage === 'search') {
911 extension = '-u-co-search'; 910 extension = '-u-co-search';
912 } 911 }
913 defineWEProperty(internalOptions, 'collation', collation); 912 defineWEProperty(internalOptions, 'collation', collation);
914 913
915 var requestedLocale = locale.locale + extension; 914 var requestedLocale = locale.locale + extension;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1035 addBoundMethod(Intl.Collator, 'compare', compare, 2); 1034 addBoundMethod(Intl.Collator, 'compare', compare, 2);
1036 1035
1037 /** 1036 /**
1038 * Verifies that the input is a well-formed ISO 4217 currency code. 1037 * Verifies that the input is a well-formed ISO 4217 currency code.
1039 * Don't uppercase to test. It could convert invalid code into a valid one. 1038 * Don't uppercase to test. It could convert invalid code into a valid one.
1040 * For example \u00DFP (Eszett+P) becomes SSP. 1039 * For example \u00DFP (Eszett+P) becomes SSP.
1041 */ 1040 */
1042 function isWellFormedCurrencyCode(currency) { 1041 function isWellFormedCurrencyCode(currency) {
1043 return typeof currency == "string" && 1042 return typeof currency == "string" &&
1044 currency.length == 3 && 1043 currency.length == 3 &&
1045 %_CallFunction(currency, /[^A-Za-z]/, StringMatch) == null; 1044 %_Call(StringMatch, currency, /[^A-Za-z]/) == null;
1046 } 1045 }
1047 1046
1048 1047
1049 /** 1048 /**
1050 * Returns the valid digit count for a property, or throws RangeError on 1049 * Returns the valid digit count for a property, or throws RangeError on
1051 * a value out of the range. 1050 * a value out of the range.
1052 */ 1051 */
1053 function getNumberOption(options, property, min, max, fallback) { 1052 function getNumberOption(options, property, min, max, fallback) {
1054 var value = options[property]; 1053 var value = options[property];
1055 if (!IS_UNDEFINED(value)) { 1054 if (!IS_UNDEFINED(value)) {
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
1364 return ''; 1363 return '';
1365 } 1364 }
1366 } 1365 }
1367 1366
1368 1367
1369 /** 1368 /**
1370 * Returns object that matches LDML representation of the date. 1369 * Returns object that matches LDML representation of the date.
1371 */ 1370 */
1372 function fromLDMLString(ldmlString) { 1371 function fromLDMLString(ldmlString) {
1373 // First remove '' quoted text, so we lose 'Uhr' strings. 1372 // First remove '' quoted text, so we lose 'Uhr' strings.
1374 ldmlString = %_CallFunction(ldmlString, GetQuotedStringRE(), '', 1373 ldmlString = %_Call(StringReplace, ldmlString, GetQuotedStringRE(), '');
1375 StringReplace);
1376 1374
1377 var options = {}; 1375 var options = {};
1378 var match = %_CallFunction(ldmlString, /E{3,5}/g, StringMatch); 1376 var match = %_Call(StringMatch, ldmlString, /E{3,5}/g);
1379 options = appendToDateTimeObject( 1377 options = appendToDateTimeObject(
1380 options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'}); 1378 options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'});
1381 1379
1382 match = %_CallFunction(ldmlString, /G{3,5}/g, StringMatch); 1380 match = %_Call(StringMatch, ldmlString, /G{3,5}/g);
1383 options = appendToDateTimeObject( 1381 options = appendToDateTimeObject(
1384 options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'}); 1382 options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'});
1385 1383
1386 match = %_CallFunction(ldmlString, /y{1,2}/g, StringMatch); 1384 match = %_Call(StringMatch, ldmlString, /y{1,2}/g);
1387 options = appendToDateTimeObject( 1385 options = appendToDateTimeObject(
1388 options, 'year', match, {y: 'numeric', yy: '2-digit'}); 1386 options, 'year', match, {y: 'numeric', yy: '2-digit'});
1389 1387
1390 match = %_CallFunction(ldmlString, /M{1,5}/g, StringMatch); 1388 match = %_Call(StringMatch, ldmlString, /M{1,5}/g);
1391 options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit', 1389 options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit',
1392 M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'}); 1390 M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'});
1393 1391
1394 // Sometimes we get L instead of M for month - standalone name. 1392 // Sometimes we get L instead of M for month - standalone name.
1395 match = %_CallFunction(ldmlString, /L{1,5}/g, StringMatch); 1393 match = %_Call(StringMatch, ldmlString, /L{1,5}/g);
1396 options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit', 1394 options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit',
1397 L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'}); 1395 L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'});
1398 1396
1399 match = %_CallFunction(ldmlString, /d{1,2}/g, StringMatch); 1397 match = %_Call(StringMatch, ldmlString, /d{1,2}/g);
1400 options = appendToDateTimeObject( 1398 options = appendToDateTimeObject(
1401 options, 'day', match, {d: 'numeric', dd: '2-digit'}); 1399 options, 'day', match, {d: 'numeric', dd: '2-digit'});
1402 1400
1403 match = %_CallFunction(ldmlString, /h{1,2}/g, StringMatch); 1401 match = %_Call(StringMatch, ldmlString, /h{1,2}/g);
1404 if (match !== null) { 1402 if (match !== null) {
1405 options['hour12'] = true; 1403 options['hour12'] = true;
1406 } 1404 }
1407 options = appendToDateTimeObject( 1405 options = appendToDateTimeObject(
1408 options, 'hour', match, {h: 'numeric', hh: '2-digit'}); 1406 options, 'hour', match, {h: 'numeric', hh: '2-digit'});
1409 1407
1410 match = %_CallFunction(ldmlString, /H{1,2}/g, StringMatch); 1408 match = %_Call(StringMatch, ldmlString, /H{1,2}/g);
1411 if (match !== null) { 1409 if (match !== null) {
1412 options['hour12'] = false; 1410 options['hour12'] = false;
1413 } 1411 }
1414 options = appendToDateTimeObject( 1412 options = appendToDateTimeObject(
1415 options, 'hour', match, {H: 'numeric', HH: '2-digit'}); 1413 options, 'hour', match, {H: 'numeric', HH: '2-digit'});
1416 1414
1417 match = %_CallFunction(ldmlString, /m{1,2}/g, StringMatch); 1415 match = %_Call(StringMatch, ldmlString, /m{1,2}/g);
1418 options = appendToDateTimeObject( 1416 options = appendToDateTimeObject(
1419 options, 'minute', match, {m: 'numeric', mm: '2-digit'}); 1417 options, 'minute', match, {m: 'numeric', mm: '2-digit'});
1420 1418
1421 match = %_CallFunction(ldmlString, /s{1,2}/g, StringMatch); 1419 match = %_Call(StringMatch, ldmlString, /s{1,2}/g);
1422 options = appendToDateTimeObject( 1420 options = appendToDateTimeObject(
1423 options, 'second', match, {s: 'numeric', ss: '2-digit'}); 1421 options, 'second', match, {s: 'numeric', ss: '2-digit'});
1424 1422
1425 match = %_CallFunction(ldmlString, /z|zzzz/g, StringMatch); 1423 match = %_Call(StringMatch, ldmlString, /z|zzzz/g);
1426 options = appendToDateTimeObject( 1424 options = appendToDateTimeObject(
1427 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'}); 1425 options, 'timeZoneName', match, {z: 'short', zzzz: 'long'});
1428 1426
1429 return options; 1427 return options;
1430 } 1428 }
1431 1429
1432 1430
1433 function appendToDateTimeObject(options, option, match, pairs) { 1431 function appendToDateTimeObject(options, option, match, pairs) {
1434 if (IS_NULL(match)) { 1432 if (IS_NULL(match)) {
1435 if (!%HasOwnProperty(options, option)) { 1433 if (!%HasOwnProperty(options, option)) {
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
1748 1746
1749 // Special case handling (UTC, GMT). 1747 // Special case handling (UTC, GMT).
1750 var upperID = %StringToUpperCase(tzID); 1748 var upperID = %StringToUpperCase(tzID);
1751 if (upperID === 'UTC' || upperID === 'GMT' || 1749 if (upperID === 'UTC' || upperID === 'GMT' ||
1752 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') { 1750 upperID === 'ETC/UTC' || upperID === 'ETC/GMT') {
1753 return 'UTC'; 1751 return 'UTC';
1754 } 1752 }
1755 1753
1756 // We expect only _ and / beside ASCII letters. 1754 // We expect only _ and / beside ASCII letters.
1757 // All inputs should conform to Area/Location from now on. 1755 // All inputs should conform to Area/Location from now on.
1758 var match = %_CallFunction(tzID, GetTimezoneNameCheckRE(), StringMatch); 1756 var match = %_Call(StringMatch, tzID, GetTimezoneNameCheckRE());
1759 if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, tzID); 1757 if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, tzID);
1760 1758
1761 var result = toTitleCaseWord(match[1]) + '/' + toTitleCaseWord(match[2]); 1759 var result = toTitleCaseWord(match[1]) + '/' + toTitleCaseWord(match[2]);
1762 var i = 3; 1760 var i = 3;
1763 while (!IS_UNDEFINED(match[i]) && i < match.length) { 1761 while (!IS_UNDEFINED(match[i]) && i < match.length) {
1764 result = result + '_' + toTitleCaseWord(match[i]); 1762 result = result + '_' + toTitleCaseWord(match[i]);
1765 i++; 1763 i++;
1766 } 1764 }
1767 1765
1768 return result; 1766 return result;
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
2010 } 2008 }
2011 2009
2012 CHECK_OBJECT_COERCIBLE(this, "String.prototype.normalize"); 2010 CHECK_OBJECT_COERCIBLE(this, "String.prototype.normalize");
2013 var s = TO_STRING(this); 2011 var s = TO_STRING(this);
2014 2012
2015 var formArg = %_Arguments(0); 2013 var formArg = %_Arguments(0);
2016 var form = IS_UNDEFINED(formArg) ? 'NFC' : TO_STRING(formArg); 2014 var form = IS_UNDEFINED(formArg) ? 'NFC' : TO_STRING(formArg);
2017 2015
2018 var NORMALIZATION_FORMS = ['NFC', 'NFD', 'NFKC', 'NFKD']; 2016 var NORMALIZATION_FORMS = ['NFC', 'NFD', 'NFKC', 'NFKD'];
2019 2017
2020 var normalizationForm = 2018 var normalizationForm = %_Call(ArrayIndexOf, NORMALIZATION_FORMS, form);
2021 %_CallFunction(NORMALIZATION_FORMS, form, ArrayIndexOf);
2022 if (normalizationForm === -1) { 2019 if (normalizationForm === -1) {
2023 throw MakeRangeError(kNormalizationForm, 2020 throw MakeRangeError(kNormalizationForm,
2024 %_CallFunction(NORMALIZATION_FORMS, ', ', ArrayJoin)); 2021 %_Call(ArrayJoin, NORMALIZATION_FORMS, ', '));
2025 } 2022 }
2026 2023
2027 return %StringNormalize(s, normalizationForm); 2024 return %StringNormalize(s, normalizationForm);
2028 } 2025 }
2029 ); 2026 );
2030 2027
2031 2028
2032 /** 2029 /**
2033 * Formats a Number object (this) using locale and options values. 2030 * Formats a Number object (this) using locale and options values.
2034 * If locale or options are omitted, defaults are used. 2031 * If locale or options are omitted, defaults are used.
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
2116 } 2113 }
2117 2114
2118 var locales = %_Arguments(0); 2115 var locales = %_Arguments(0);
2119 var options = %_Arguments(1); 2116 var options = %_Arguments(1);
2120 return toLocaleDateTime( 2117 return toLocaleDateTime(
2121 this, locales, options, 'time', 'time', 'dateformattime'); 2118 this, locales, options, 'time', 'time', 'dateformattime');
2122 } 2119 }
2123 ); 2120 );
2124 2121
2125 }) 2122 })
OLDNEW
« no previous file with comments | « src/js/generator.js ('k') | src/js/macros.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698