| 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 |