OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // ECMAScript 402 API implementation. | 5 // ECMAScript 402 API implementation. |
6 | 6 |
7 /** | 7 /** |
8 * Intl object is a single object that has some named properties, | 8 * Intl object is a single object that has some named properties, |
9 * all of which are constructors. | 9 * all of which are constructors. |
10 */ | 10 */ |
11 (function(global, utils) { | 11 (function(global, utils) { |
12 | 12 |
13 "use strict"; | 13 "use strict"; |
14 | 14 |
15 %CheckIsBootstrapping(); | 15 %CheckIsBootstrapping(); |
16 | 16 |
17 // ------------------------------------------------------------------- | 17 // ------------------------------------------------------------------- |
18 // Imports | 18 // Imports |
19 | 19 |
20 var ArrayIndexOf; | 20 var ArrayIndexOf; |
21 var ArrayJoin; | 21 var ArrayJoin; |
22 var ArrayPush; | 22 var ArrayPush; |
23 var FLAG_intl_extra; | 23 var FLAG_intl_extra; |
24 var GlobalBoolean = global.Boolean; | |
25 var GlobalDate = global.Date; | 24 var GlobalDate = global.Date; |
26 var GlobalNumber = global.Number; | 25 var GlobalNumber = global.Number; |
27 var GlobalRegExp = global.RegExp; | 26 var GlobalRegExp = global.RegExp; |
28 var GlobalString = global.String; | 27 var GlobalString = global.String; |
29 var InstallFunctions = utils.InstallFunctions; | 28 var InstallFunctions = utils.InstallFunctions; |
30 var InstallGetter = utils.InstallGetter; | 29 var InstallGetter = utils.InstallGetter; |
31 var InternalArray = utils.InternalArray; | 30 var InternalArray = utils.InternalArray; |
32 var InternalRegExpMatch; | 31 var InternalRegExpMatch; |
33 var InternalRegExpReplace | 32 var InternalRegExpReplace |
34 var IsFinite; | |
35 var IsNaN; | 33 var IsNaN; |
36 var MakeError; | 34 var MakeError; |
37 var MakeRangeError; | 35 var MakeRangeError; |
38 var MakeTypeError; | 36 var MakeTypeError; |
39 var ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty"); | 37 var ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty"); |
40 var OverrideFunction = utils.OverrideFunction; | 38 var OverrideFunction = utils.OverrideFunction; |
41 var patternSymbol = utils.ImportNow("intl_pattern_symbol"); | 39 var patternSymbol = utils.ImportNow("intl_pattern_symbol"); |
42 var resolvedSymbol = utils.ImportNow("intl_resolved_symbol"); | 40 var resolvedSymbol = utils.ImportNow("intl_resolved_symbol"); |
43 var SetFunctionName = utils.SetFunctionName; | 41 var SetFunctionName = utils.SetFunctionName; |
44 var StringIndexOf; | 42 var StringIndexOf; |
45 var StringLastIndexOf; | 43 var StringLastIndexOf; |
46 var StringSplit; | 44 var StringSplit; |
47 var StringSubstr; | 45 var StringSubstr; |
48 var StringSubstring; | 46 var StringSubstring; |
49 | 47 |
50 utils.Import(function(from) { | 48 utils.Import(function(from) { |
51 ArrayIndexOf = from.ArrayIndexOf; | 49 ArrayIndexOf = from.ArrayIndexOf; |
52 ArrayJoin = from.ArrayJoin; | 50 ArrayJoin = from.ArrayJoin; |
53 ArrayPush = from.ArrayPush; | 51 ArrayPush = from.ArrayPush; |
54 IsFinite = from.IsFinite; | |
55 IsNaN = from.IsNaN; | 52 IsNaN = from.IsNaN; |
56 MakeError = from.MakeError; | 53 MakeError = from.MakeError; |
57 MakeRangeError = from.MakeRangeError; | 54 MakeRangeError = from.MakeRangeError; |
58 MakeTypeError = from.MakeTypeError; | 55 MakeTypeError = from.MakeTypeError; |
59 InternalRegExpMatch = from.InternalRegExpMatch; | 56 InternalRegExpMatch = from.InternalRegExpMatch; |
60 InternalRegExpReplace = from.InternalRegExpReplace; | 57 InternalRegExpReplace = from.InternalRegExpReplace; |
61 StringIndexOf = from.StringIndexOf; | 58 StringIndexOf = from.StringIndexOf; |
62 StringLastIndexOf = from.StringLastIndexOf; | 59 StringLastIndexOf = from.StringLastIndexOf; |
63 StringSplit = from.StringSplit; | 60 StringSplit = from.StringSplit; |
64 StringSubstr = from.StringSubstr; | 61 StringSubstr = from.StringSubstr; |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 | 275 |
279 // Provide defaults if matcher was not specified. | 276 // Provide defaults if matcher was not specified. |
280 if (IS_UNDEFINED(options)) { | 277 if (IS_UNDEFINED(options)) { |
281 options = {}; | 278 options = {}; |
282 } else { | 279 } else { |
283 options = TO_OBJECT(options); | 280 options = TO_OBJECT(options); |
284 } | 281 } |
285 | 282 |
286 var matcher = options.localeMatcher; | 283 var matcher = options.localeMatcher; |
287 if (!IS_UNDEFINED(matcher)) { | 284 if (!IS_UNDEFINED(matcher)) { |
288 matcher = GlobalString(matcher); | 285 matcher = TO_STRING(matcher); |
289 if (matcher !== 'lookup' && matcher !== 'best fit') { | 286 if (matcher !== 'lookup' && matcher !== 'best fit') { |
290 throw MakeRangeError(kLocaleMatcher, matcher); | 287 throw MakeRangeError(kLocaleMatcher, matcher); |
291 } | 288 } |
292 } else { | 289 } else { |
293 matcher = 'best fit'; | 290 matcher = 'best fit'; |
294 } | 291 } |
295 | 292 |
296 var requestedLocales = initializeLocaleList(locales); | 293 var requestedLocales = initializeLocaleList(locales); |
297 | 294 |
298 // Cache these, they don't ever change per service. | 295 // Cache these, they don't ever change per service. |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 * is out of range for that property it throws RangeError. | 356 * is out of range for that property it throws RangeError. |
360 */ | 357 */ |
361 function getGetOption(options, caller) { | 358 function getGetOption(options, caller) { |
362 if (IS_UNDEFINED(options)) throw MakeError(kDefaultOptionsMissing, caller); | 359 if (IS_UNDEFINED(options)) throw MakeError(kDefaultOptionsMissing, caller); |
363 | 360 |
364 var getOption = function getOption(property, type, values, defaultValue) { | 361 var getOption = function getOption(property, type, values, defaultValue) { |
365 if (!IS_UNDEFINED(options[property])) { | 362 if (!IS_UNDEFINED(options[property])) { |
366 var value = options[property]; | 363 var value = options[property]; |
367 switch (type) { | 364 switch (type) { |
368 case 'boolean': | 365 case 'boolean': |
369 value = GlobalBoolean(value); | 366 value = TO_BOOLEAN(value); |
370 break; | 367 break; |
371 case 'string': | 368 case 'string': |
372 value = GlobalString(value); | 369 value = TO_STRING(value); |
373 break; | 370 break; |
374 case 'number': | 371 case 'number': |
375 value = GlobalNumber(value); | 372 value = TO_NUMBER(value); |
376 break; | 373 break; |
377 default: | 374 default: |
378 throw MakeError(kWrongValueType); | 375 throw MakeError(kWrongValueType); |
379 } | 376 } |
380 | 377 |
381 if (!IS_UNDEFINED(values) && %_Call(ArrayIndexOf, values, value) === -1) { | 378 if (!IS_UNDEFINED(values) && %_Call(ArrayIndexOf, values, value) === -1) { |
382 throw MakeRangeError(kValueOutOfRange, value, caller, property); | 379 throw MakeRangeError(kValueOutOfRange, value, caller, property); |
383 } | 380 } |
384 | 381 |
385 return value; | 382 return value; |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 * Unicode extensions for passing parameters to ICU). | 513 * Unicode extensions for passing parameters to ICU). |
517 * It's used for extension-option pairs only, e.g. kn-normalization, but not | 514 * It's used for extension-option pairs only, e.g. kn-normalization, but not |
518 * for 'sensitivity' since it doesn't have extension equivalent. | 515 * for 'sensitivity' since it doesn't have extension equivalent. |
519 * Extensions like nu and ca don't have options equivalent, so we place | 516 * Extensions like nu and ca don't have options equivalent, so we place |
520 * undefined in the map.property to denote that. | 517 * undefined in the map.property to denote that. |
521 */ | 518 */ |
522 function setOptions(inOptions, extensionMap, keyValues, getOption, outOptions) { | 519 function setOptions(inOptions, extensionMap, keyValues, getOption, outOptions) { |
523 var extension = ''; | 520 var extension = ''; |
524 | 521 |
525 var updateExtension = function updateExtension(key, value) { | 522 var updateExtension = function updateExtension(key, value) { |
526 return '-' + key + '-' + GlobalString(value); | 523 return '-' + key + '-' + TO_STRING(value); |
527 } | 524 } |
528 | 525 |
529 var updateProperty = function updateProperty(property, type, value) { | 526 var updateProperty = function updateProperty(property, type, value) { |
530 if (type === 'boolean' && (typeof value === 'string')) { | 527 if (type === 'boolean' && (typeof value === 'string')) { |
531 value = (value === 'true') ? true : false; | 528 value = (value === 'true') ? true : false; |
532 } | 529 } |
533 | 530 |
534 if (!IS_UNDEFINED(property)) { | 531 if (!IS_UNDEFINED(property)) { |
535 defineWEProperty(outOptions, property, value); | 532 defineWEProperty(outOptions, property, value); |
536 } | 533 } |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
735 throw MakeTypeError(kLanguageID); | 732 throw MakeTypeError(kLanguageID); |
736 } | 733 } |
737 | 734 |
738 // Optimize for the most common case; a language code alone in | 735 // Optimize for the most common case; a language code alone in |
739 // the canonical form/lowercase (e.g. "en", "fil"). | 736 // the canonical form/lowercase (e.g. "en", "fil"). |
740 if (IS_STRING(localeID) && | 737 if (IS_STRING(localeID) && |
741 !IS_NULL(InternalRegExpMatch(/^[a-z]{2,3}$/, localeID))) { | 738 !IS_NULL(InternalRegExpMatch(/^[a-z]{2,3}$/, localeID))) { |
742 return localeID; | 739 return localeID; |
743 } | 740 } |
744 | 741 |
745 var localeString = GlobalString(localeID); | 742 var localeString = TO_STRING(localeID); |
746 | 743 |
747 if (isValidLanguageTag(localeString) === false) { | 744 if (isValidLanguageTag(localeString) === false) { |
748 throw MakeRangeError(kInvalidLanguageTag, localeString); | 745 throw MakeRangeError(kInvalidLanguageTag, localeString); |
749 } | 746 } |
750 | 747 |
751 var tag = %CanonicalizeLanguageTag(localeString); | 748 var tag = %CanonicalizeLanguageTag(localeString); |
752 if (tag === 'invalid-tag') { | 749 if (tag === 'invalid-tag') { |
753 throw MakeRangeError(kInvalidLanguageTag, localeString); | 750 throw MakeRangeError(kInvalidLanguageTag, localeString); |
754 } | 751 } |
755 | 752 |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1071 * Number other than NaN that represents the result of a locale-sensitive | 1068 * Number other than NaN that represents the result of a locale-sensitive |
1072 * String comparison of x with y. | 1069 * String comparison of x with y. |
1073 * The result is intended to order String values in the sort order specified | 1070 * The result is intended to order String values in the sort order specified |
1074 * by the effective locale and collation options computed during construction | 1071 * by the effective locale and collation options computed during construction |
1075 * of this Collator object, and will be negative, zero, or positive, depending | 1072 * of this Collator object, and will be negative, zero, or positive, depending |
1076 * on whether x comes before y in the sort order, the Strings are equal under | 1073 * on whether x comes before y in the sort order, the Strings are equal under |
1077 * the sort order, or x comes after y in the sort order, respectively. | 1074 * the sort order, or x comes after y in the sort order, respectively. |
1078 */ | 1075 */ |
1079 function compare(collator, x, y) { | 1076 function compare(collator, x, y) { |
1080 return %InternalCompare(%GetImplFromInitializedIntlObject(collator), | 1077 return %InternalCompare(%GetImplFromInitializedIntlObject(collator), |
1081 GlobalString(x), GlobalString(y)); | 1078 TO_STRING(x), TO_STRING(y)); |
1082 }; | 1079 }; |
1083 | 1080 |
1084 | 1081 |
1085 AddBoundMethod(Intl.Collator, 'compare', compare, 2, 'collator'); | 1082 AddBoundMethod(Intl.Collator, 'compare', compare, 2, 'collator'); |
1086 | 1083 |
1087 /** | 1084 /** |
1088 * Verifies that the input is a well-formed ISO 4217 currency code. | 1085 * Verifies that the input is a well-formed ISO 4217 currency code. |
1089 * Don't uppercase to test. It could convert invalid code into a valid one. | 1086 * Don't uppercase to test. It could convert invalid code into a valid one. |
1090 * For example \u00DFP (Eszett+P) becomes SSP. | 1087 * For example \u00DFP (Eszett+P) becomes SSP. |
1091 */ | 1088 */ |
1092 function isWellFormedCurrencyCode(currency) { | 1089 function isWellFormedCurrencyCode(currency) { |
1093 return typeof currency == "string" && currency.length == 3 && | 1090 return typeof currency == "string" && currency.length == 3 && |
1094 IS_NULL(InternalRegExpMatch(/[^A-Za-z]/, currency)); | 1091 IS_NULL(InternalRegExpMatch(/[^A-Za-z]/, currency)); |
1095 } | 1092 } |
1096 | 1093 |
1097 | 1094 |
1098 /** | 1095 /** |
1099 * Returns the valid digit count for a property, or throws RangeError on | 1096 * Returns the valid digit count for a property, or throws RangeError on |
1100 * a value out of the range. | 1097 * a value out of the range. |
1101 */ | 1098 */ |
1102 function getNumberOption(options, property, min, max, fallback) { | 1099 function getNumberOption(options, property, min, max, fallback) { |
1103 var value = options[property]; | 1100 var value = options[property]; |
1104 if (!IS_UNDEFINED(value)) { | 1101 if (!IS_UNDEFINED(value)) { |
1105 value = GlobalNumber(value); | 1102 value = TO_NUMBER(value); |
1106 if (IsNaN(value) || value < min || value > max) { | 1103 if (NUMBER_IS_NAN(value) || value < min || value > max) { |
1107 throw MakeRangeError(kPropertyValueOutOfRange, property); | 1104 throw MakeRangeError(kPropertyValueOutOfRange, property); |
1108 } | 1105 } |
1109 return %math_floor(value); | 1106 return %math_floor(value); |
1110 } | 1107 } |
1111 | 1108 |
1112 return fallback; | 1109 return fallback; |
1113 } | 1110 } |
1114 | 1111 |
1115 var patternAccessor = { | 1112 var patternAccessor = { |
1116 get() { | 1113 get() { |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1341 return %InternalNumberFormat(%GetImplFromInitializedIntlObject(formatter), | 1338 return %InternalNumberFormat(%GetImplFromInitializedIntlObject(formatter), |
1342 number); | 1339 number); |
1343 } | 1340 } |
1344 | 1341 |
1345 | 1342 |
1346 /** | 1343 /** |
1347 * Returns a Number that represents string value that was passed in. | 1344 * Returns a Number that represents string value that was passed in. |
1348 */ | 1345 */ |
1349 function IntlParseNumber(formatter, value) { | 1346 function IntlParseNumber(formatter, value) { |
1350 return %InternalNumberParse(%GetImplFromInitializedIntlObject(formatter), | 1347 return %InternalNumberParse(%GetImplFromInitializedIntlObject(formatter), |
1351 GlobalString(value)); | 1348 TO_STRING(value)); |
1352 } | 1349 } |
1353 | 1350 |
1354 AddBoundMethod(Intl.NumberFormat, 'format', formatNumber, 1, 'numberformat'); | 1351 AddBoundMethod(Intl.NumberFormat, 'format', formatNumber, 1, 'numberformat'); |
1355 | 1352 |
1356 /** | 1353 /** |
1357 * Returns a string that matches LDML representation of the options object. | 1354 * Returns a string that matches LDML representation of the options object. |
1358 */ | 1355 */ |
1359 function toLDMLString(options) { | 1356 function toLDMLString(options) { |
1360 var getOption = getGetOption(options, 'dateformat'); | 1357 var getOption = getGetOption(options, 'dateformat'); |
1361 | 1358 |
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1748 * DateTimeFormat. | 1745 * DateTimeFormat. |
1749 */ | 1746 */ |
1750 function formatDate(formatter, dateValue) { | 1747 function formatDate(formatter, dateValue) { |
1751 var dateMs; | 1748 var dateMs; |
1752 if (IS_UNDEFINED(dateValue)) { | 1749 if (IS_UNDEFINED(dateValue)) { |
1753 dateMs = %DateCurrentTime(); | 1750 dateMs = %DateCurrentTime(); |
1754 } else { | 1751 } else { |
1755 dateMs = TO_NUMBER(dateValue); | 1752 dateMs = TO_NUMBER(dateValue); |
1756 } | 1753 } |
1757 | 1754 |
1758 if (!IsFinite(dateMs)) throw MakeRangeError(kDateRange); | 1755 if (!NUMBER_IS_FINITE(dateMs)) throw MakeRangeError(kDateRange); |
1759 | 1756 |
1760 return %InternalDateFormat(%GetImplFromInitializedIntlObject(formatter), | 1757 return %InternalDateFormat(%GetImplFromInitializedIntlObject(formatter), |
1761 new GlobalDate(dateMs)); | 1758 new GlobalDate(dateMs)); |
1762 } | 1759 } |
1763 | 1760 |
1764 | 1761 |
1765 /** | 1762 /** |
1766 * Returns a Date object representing the result of calling ToString(value) | 1763 * Returns a Date object representing the result of calling ToString(value) |
1767 * according to the effective locale and the formatting options of this | 1764 * according to the effective locale and the formatting options of this |
1768 * DateTimeFormat. | 1765 * DateTimeFormat. |
1769 * Returns undefined if date string cannot be parsed. | 1766 * Returns undefined if date string cannot be parsed. |
1770 */ | 1767 */ |
1771 function IntlParseDate(formatter, value) { | 1768 function IntlParseDate(formatter, value) { |
1772 return %InternalDateParse(%GetImplFromInitializedIntlObject(formatter), | 1769 return %InternalDateParse(%GetImplFromInitializedIntlObject(formatter), |
1773 GlobalString(value)); | 1770 TO_STRING(value)); |
1774 } | 1771 } |
1775 | 1772 |
1776 | 1773 |
1777 // 0 because date is optional argument. | 1774 // 0 because date is optional argument. |
1778 AddBoundMethod(Intl.DateTimeFormat, 'format', formatDate, 0, 'dateformat'); | 1775 AddBoundMethod(Intl.DateTimeFormat, 'format', formatDate, 0, 'dateformat'); |
1779 | 1776 |
1780 | 1777 |
1781 /** | 1778 /** |
1782 * Returns canonical Area/Location(/Location) name, or throws an exception | 1779 * Returns canonical Area/Location(/Location) name, or throws an exception |
1783 * if the zone name is invalid IANA name. | 1780 * if the zone name is invalid IANA name. |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1920 } | 1917 } |
1921 ); | 1918 ); |
1922 | 1919 |
1923 | 1920 |
1924 /** | 1921 /** |
1925 * Adopts text to segment using the iterator. Old text, if present, | 1922 * Adopts text to segment using the iterator. Old text, if present, |
1926 * gets discarded. | 1923 * gets discarded. |
1927 */ | 1924 */ |
1928 function adoptText(iterator, text) { | 1925 function adoptText(iterator, text) { |
1929 %BreakIteratorAdoptText(%GetImplFromInitializedIntlObject(iterator), | 1926 %BreakIteratorAdoptText(%GetImplFromInitializedIntlObject(iterator), |
1930 GlobalString(text)); | 1927 TO_STRING(text)); |
1931 } | 1928 } |
1932 | 1929 |
1933 | 1930 |
1934 /** | 1931 /** |
1935 * Returns index of the first break in the string and moves current pointer. | 1932 * Returns index of the first break in the string and moves current pointer. |
1936 */ | 1933 */ |
1937 function first(iterator) { | 1934 function first(iterator) { |
1938 return %BreakIteratorFirst(%GetImplFromInitializedIntlObject(iterator)); | 1935 return %BreakIteratorFirst(%GetImplFromInitializedIntlObject(iterator)); |
1939 } | 1936 } |
1940 | 1937 |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2252 } | 2249 } |
2253 ); | 2250 ); |
2254 | 2251 |
2255 utils.Export(function(to) { | 2252 utils.Export(function(to) { |
2256 to.AddBoundMethod = AddBoundMethod; | 2253 to.AddBoundMethod = AddBoundMethod; |
2257 to.IntlParseDate = IntlParseDate; | 2254 to.IntlParseDate = IntlParseDate; |
2258 to.IntlParseNumber = IntlParseNumber; | 2255 to.IntlParseNumber = IntlParseNumber; |
2259 }); | 2256 }); |
2260 | 2257 |
2261 }) | 2258 }) |
OLD | NEW |