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

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

Issue 2239523002: Expose getCanonicalLocales() for Intl object (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: return array is mutable Created 4 years, 4 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/runtime/runtime-i18n.cc » ('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 549 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 } 560 }
561 561
562 return extension === ''? '' : '-u' + extension; 562 return extension === ''? '' : '-u' + extension;
563 } 563 }
564 564
565 565
566 /** 566 /**
567 * Given an array-like, outputs an Array with the numbered 567 * Given an array-like, outputs an Array with the numbered
568 * properties copied over and defined 568 * properties copied over and defined
569 * configurable: false, writable: false, enumerable: true. 569 * configurable: false, writable: false, enumerable: true.
570 * When |expandable| is true, the result array can be expanded.
jungshik at Google 2016/08/16 08:51:39 Ick. I'll get rid of this line.
570 */ 571 */
571 function freezeArray(input) { 572 function freezeArray(input) {
572 var array = []; 573 var array = [];
573 var l = input.length; 574 var l = input.length;
574 for (var i = 0; i < l; i++) { 575 for (var i = 0; i < l; i++) {
575 if (i in input) { 576 if (i in input) {
576 %object_define_property(array, i, {value: input[i], 577 %object_define_property(array, i, {value: input[i],
577 configurable: false, 578 configurable: false,
578 writable: false, 579 writable: false,
579 enumerable: true}); 580 enumerable: true});
580 } 581 }
581 } 582 }
582 583
583 %object_define_property(array, 'length', {value: l, writable: false}); 584 %object_define_property(array, 'length', {value: l, writable: false});
584 return array; 585 return array;
585 } 586 }
586 587
588 /* Make JS array[] out of InternalArray */
589 function makeArray(input) {
590 var array = [];
591 %MoveArrayContents(input, array);
592 return array;
593 }
587 594
588 /** 595 /**
589 * It's sometimes desireable to leave user requested locale instead of ICU 596 * It's sometimes desireable to leave user requested locale instead of ICU
590 * supported one (zh-TW is equivalent to zh-Hant-TW, so we should keep shorter 597 * supported one (zh-TW is equivalent to zh-Hant-TW, so we should keep shorter
591 * one, if that was what user requested). 598 * one, if that was what user requested).
592 * This function returns user specified tag if its maximized form matches ICU 599 * This function returns user specified tag if its maximized form matches ICU
593 * resolved locale. If not we return ICU result. 600 * resolved locale. If not we return ICU result.
594 */ 601 */
595 function getOptimalLanguageTag(original, resolved) { 602 function getOptimalLanguageTag(original, resolved) {
596 // Returns Array<Object>, where each object has maximized and base properties. 603 // Returns Array<Object>, where each object has maximized and base properties.
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 ((lowercasedPart !== 'es' && 718 ((lowercasedPart !== 'es' &&
712 lowercasedPart !== 'of' && lowercasedPart !== 'au') ? 719 lowercasedPart !== 'of' && lowercasedPart !== 'au') ?
713 toTitleCaseWord(part) : lowercasedPart); 720 toTitleCaseWord(part) : lowercasedPart);
714 } 721 }
715 } 722 }
716 return result; 723 return result;
717 } 724 }
718 725
719 /** 726 /**
720 * Canonicalizes the language tag, or throws in case the tag is invalid. 727 * Canonicalizes the language tag, or throws in case the tag is invalid.
728 * ECMA 402 9.2.1 steps 7.c ii ~ v.
721 */ 729 */
722 function canonicalizeLanguageTag(localeID) { 730 function canonicalizeLanguageTag(localeID) {
723 // null is typeof 'object' so we have to do extra check. 731 // null is typeof 'object' so we have to do extra check.
724 if ((!IS_STRING(localeID) && !IS_RECEIVER(localeID)) || 732 if ((!IS_STRING(localeID) && !IS_RECEIVER(localeID)) ||
725 IS_NULL(localeID)) { 733 IS_NULL(localeID)) {
726 throw %make_type_error(kLanguageID); 734 throw %make_type_error(kLanguageID);
727 } 735 }
728 736
729 // Optimize for the most common case; a language code alone in 737 // Optimize for the most common case; a language code alone in
730 // the canonical form/lowercase (e.g. "en", "fil"). 738 // the canonical form/lowercase (e.g. "en", "fil").
731 if (IS_STRING(localeID) && 739 if (IS_STRING(localeID) &&
732 !IS_NULL(InternalRegExpMatch(/^[a-z]{2,3}$/, localeID))) { 740 !IS_NULL(InternalRegExpMatch(/^[a-z]{2,3}$/, localeID))) {
733 return localeID; 741 return localeID;
734 } 742 }
735 743
736 var localeString = TO_STRING(localeID); 744 var localeString = TO_STRING(localeID);
737 745
738 if (isValidLanguageTag(localeString) === false) { 746 if (isStructuallyValidLanguageTag(localeString) === false) {
739 throw %make_range_error(kInvalidLanguageTag, localeString); 747 throw %make_range_error(kInvalidLanguageTag, localeString);
740 } 748 }
741 749
750 // ECMA 402 6.2.3
742 var tag = %CanonicalizeLanguageTag(localeString); 751 var tag = %CanonicalizeLanguageTag(localeString);
752 // TODO(jshin): This should not happen because the structual validity
753 // is already checked. If that's the case, remove this.
743 if (tag === 'invalid-tag') { 754 if (tag === 'invalid-tag') {
744 throw %make_range_error(kInvalidLanguageTag, localeString); 755 throw %make_range_error(kInvalidLanguageTag, localeString);
745 } 756 }
746 757
747 return tag; 758 return tag;
748 } 759 }
749 760
750 761
751 /** 762 /**
752 * Returns an array where all locales are canonicalized and duplicates removed. 763 * Returns an InternalArray where all locales are canonicalized and duplicates
764 * removed.
753 * Throws on locales that are not well formed BCP47 tags. 765 * Throws on locales that are not well formed BCP47 tags.
766 * ECMA 402 8.2.1 steps 1 (ECMA 402 9.2.1) and 2.
754 */ 767 */
755 function initializeLocaleList(locales) { 768 function canonicalizeLocaleList(locales) {
756 var seen = new InternalArray(); 769 var seen = new InternalArray();
757 if (!IS_UNDEFINED(locales)) { 770 if (!IS_UNDEFINED(locales)) {
758 // We allow single string localeID. 771 // We allow single string localeID.
759 if (typeof locales === 'string') { 772 if (typeof locales === 'string') {
760 %_Call(ArrayPush, seen, canonicalizeLanguageTag(locales)); 773 %_Call(ArrayPush, seen, canonicalizeLanguageTag(locales));
761 return freezeArray(seen); 774 return seen;
762 } 775 }
763 776
764 var o = TO_OBJECT(locales); 777 var o = TO_OBJECT(locales);
765 var len = TO_UINT32(o.length); 778 var len = TO_LENGTH(o.length);
766 779
767 for (var k = 0; k < len; k++) { 780 for (var k = 0; k < len; k++) {
768 if (k in o) { 781 if (k in o) {
769 var value = o[k]; 782 var value = o[k];
770 783
771 var tag = canonicalizeLanguageTag(value); 784 var tag = canonicalizeLanguageTag(value);
772 785
773 if (%_Call(ArrayIndexOf, seen, tag) === -1) { 786 if (%_Call(ArrayIndexOf, seen, tag) === -1) {
774 %_Call(ArrayPush, seen, tag); 787 %_Call(ArrayPush, seen, tag);
775 } 788 }
776 } 789 }
777 } 790 }
778 } 791 }
779 792
780 return freezeArray(seen); 793 return seen;
781 } 794 }
782 795
796 function initializeLocaleList(locales) {
797 return freezeArray(canonicalizeLocaleList(locales));
798 }
783 799
784 /** 800 /**
785 * Validates the language tag. Section 2.2.9 of the bcp47 spec 801 * Check the structual Validity of the language tag per ECMA 402 6.2.2:
786 * defines a valid tag. 802 * - Well-formed per RFC 5646 2.1
803 * - There are no duplicate variant subtags
804 * - There are no duplicate singletion (extension) subtags
805 *
806 * One extra-check is done (from RFC 5646 2.2.9): the tag is compared
807 * against the list of grandfathered tags. However, subtags for
808 * primary/extended language, script, region, variant are not checked
809 * against the IANA language subtag registry.
787 * 810 *
788 * ICU is too permissible and lets invalid tags, like 811 * ICU is too permissible and lets invalid tags, like
789 * hant-cmn-cn, through. 812 * hant-cmn-cn, through.
790 * 813 *
791 * Returns false if the language tag is invalid. 814 * Returns false if the language tag is invalid.
792 */ 815 */
793 function isValidLanguageTag(locale) { 816 function isStructuallyValidLanguageTag(locale) {
794 // Check if it's well-formed, including grandfadered tags. 817 // Check if it's well-formed, including grandfadered tags.
795 if (IS_NULL(InternalRegExpMatch(GetLanguageTagRE(), locale))) { 818 if (IS_NULL(InternalRegExpMatch(GetLanguageTagRE(), locale))) {
796 return false; 819 return false;
797 } 820 }
798 821
799 // Just return if it's a x- form. It's all private. 822 // Just return if it's a x- form. It's all private.
800 if (%_Call(StringIndexOf, locale, 'x-') === 0) { 823 if (%_Call(StringIndexOf, locale, 'x-') === 0) {
801 return true; 824 return true;
802 } 825 }
803 826
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
878 var resolvedAccessor = { 901 var resolvedAccessor = {
879 get() { 902 get() {
880 %IncrementUseCounter(kIntlResolved); 903 %IncrementUseCounter(kIntlResolved);
881 return this[resolvedSymbol]; 904 return this[resolvedSymbol];
882 }, 905 },
883 set(value) { 906 set(value) {
884 this[resolvedSymbol] = value; 907 this[resolvedSymbol] = value;
885 } 908 }
886 }; 909 };
887 910
911 // ECMA 402 section 8.2.1
912 InstallFunction(Intl, 'getCanonicalLocales', function(locales) {
913 if (!IS_UNDEFINED(new.target)) {
914 throw %make_type_error(kOrdinaryFunctionCalledAsConstructor);
915 }
916
917 return makeArray(canonicalizeLocaleList(locales));
918 }
919 );
920
888 /** 921 /**
889 * Initializes the given object so it's a valid Collator instance. 922 * Initializes the given object so it's a valid Collator instance.
890 * Useful for subclassing. 923 * Useful for subclassing.
891 */ 924 */
892 function initializeCollator(collator, locales, options) { 925 function initializeCollator(collator, locales, options) {
893 if (%IsInitializedIntlObject(collator)) { 926 if (%IsInitializedIntlObject(collator)) {
894 throw %make_type_error(kReinitializeIntl, "Collator"); 927 throw %make_type_error(kReinitializeIntl, "Collator");
895 } 928 }
896 929
897 if (IS_UNDEFINED(options)) { 930 if (IS_UNDEFINED(options)) {
(...skipping 1348 matching lines...) Expand 10 before | Expand all | Expand 10 after
2246 } 2279 }
2247 ); 2280 );
2248 2281
2249 utils.Export(function(to) { 2282 utils.Export(function(to) {
2250 to.AddBoundMethod = AddBoundMethod; 2283 to.AddBoundMethod = AddBoundMethod;
2251 to.IntlParseDate = IntlParseDate; 2284 to.IntlParseDate = IntlParseDate;
2252 to.IntlParseNumber = IntlParseNumber; 2285 to.IntlParseNumber = IntlParseNumber;
2253 }); 2286 });
2254 2287
2255 }) 2288 })
OLDNEW
« no previous file with comments | « no previous file | src/runtime/runtime-i18n.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698