| 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 */ |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 } | 377 } |
| 378 | 378 |
| 379 return defaultValue; | 379 return defaultValue; |
| 380 } | 380 } |
| 381 | 381 |
| 382 return getOption; | 382 return getOption; |
| 383 } | 383 } |
| 384 | 384 |
| 385 | 385 |
| 386 /** | 386 /** |
| 387 * Ecma 402 9.2.5 |
| 388 * TODO(jshin): relevantExtensionKeys and localeData need to be taken into |
| 389 * account per spec. |
| 387 * Compares a BCP 47 language priority list requestedLocales against the locales | 390 * Compares a BCP 47 language priority list requestedLocales against the locales |
| 388 * in availableLocales and determines the best available language to meet the | 391 * in availableLocales and determines the best available language to meet the |
| 389 * request. Two algorithms are available to match the locales: the Lookup | 392 * request. Two algorithms are available to match the locales: the Lookup |
| 390 * algorithm described in RFC 4647 section 3.4, and an implementation dependent | 393 * algorithm described in RFC 4647 section 3.4, and an implementation dependent |
| 391 * best-fit algorithm. Independent of the locale matching algorithm, options | 394 * best-fit algorithm. Independent of the locale matching algorithm, options |
| 392 * specified through Unicode locale extension sequences are negotiated | 395 * specified through Unicode locale extension sequences are negotiated |
| 393 * separately, taking the caller's relevant extension keys and locale data as | 396 * separately, taking the caller's relevant extension keys and locale data as |
| 394 * well as client-provided options into consideration. Returns an object with | 397 * well as client-provided options into consideration. Returns an object with |
| 395 * a locale property whose value is the language tag of the selected locale, | 398 * a locale property whose value is the language tag of the selected locale, |
| 396 * and properties for each key in relevantExtensionKeys providing the selected | 399 * and properties for each key in relevantExtensionKeys providing the selected |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 function bestFitMatcher(service, requestedLocales) { | 463 function bestFitMatcher(service, requestedLocales) { |
| 461 // TODO(cira): implement better best fit algorithm. | 464 // TODO(cira): implement better best fit algorithm. |
| 462 return lookupMatcher(service, requestedLocales); | 465 return lookupMatcher(service, requestedLocales); |
| 463 } | 466 } |
| 464 | 467 |
| 465 | 468 |
| 466 /** | 469 /** |
| 467 * Parses Unicode extension into key - value map. | 470 * Parses Unicode extension into key - value map. |
| 468 * Returns empty object if the extension string is invalid. | 471 * Returns empty object if the extension string is invalid. |
| 469 * We are not concerned with the validity of the values at this point. | 472 * We are not concerned with the validity of the values at this point. |
| 473 * 'attribute' in RFC 6047 is not supported. Keys without explicit |
| 474 * values are assigned UNDEFINED. |
| 475 * TODO(jshin): Fix the handling of 'attribute' (in RFC 6047, but none |
| 476 * has been defined so that it's not used) and boolean keys without |
| 477 * an explicit value. |
| 470 */ | 478 */ |
| 471 function parseExtension(extension) { | 479 function parseExtension(extension) { |
| 472 var extensionSplit = %StringSplit(extension, '-', kMaxUint32); | 480 var extensionSplit = %StringSplit(extension, '-', kMaxUint32); |
| 473 | 481 |
| 474 // Assume ['', 'u', ...] input, but don't throw. | 482 // Assume ['', 'u', ...] input, but don't throw. |
| 475 if (extensionSplit.length <= 2 || | 483 if (extensionSplit.length <= 2 || |
| 476 (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) { | 484 (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) { |
| 477 return {}; | 485 return {}; |
| 478 } | 486 } |
| 479 | 487 |
| 480 // Key is {2}alphanum, value is {3,8}alphanum. | 488 // Key is {2}alphanum, value is {3,8}alphanum. |
| 481 // Some keys may not have explicit values (booleans). | 489 // Some keys may not have explicit values (booleans). |
| 482 var extensionMap = {}; | 490 var extensionMap = {}; |
| 483 var previousKey = UNDEFINED; | 491 var key = UNDEFINED; |
| 492 var value = UNDEFINED; |
| 484 for (var i = 2; i < extensionSplit.length; ++i) { | 493 for (var i = 2; i < extensionSplit.length; ++i) { |
| 485 var length = extensionSplit[i].length; | 494 var length = extensionSplit[i].length; |
| 486 var element = extensionSplit[i]; | 495 var element = extensionSplit[i]; |
| 487 if (length === 2) { | 496 if (length === 2) { |
| 488 extensionMap[element] = UNDEFINED; | 497 if (!IS_UNDEFINED(key)) { |
| 489 previousKey = element; | 498 if (!(key in extensionMap)) { |
| 490 } else if (length >= 3 && length <=8 && !IS_UNDEFINED(previousKey)) { | 499 extensionMap[key] = value; |
| 491 extensionMap[previousKey] = element; | 500 } |
| 492 previousKey = UNDEFINED; | 501 value = UNDEFINED; |
| 502 } |
| 503 key = element; |
| 504 } else if (length >= 3 && length <= 8 && !IS_UNDEFINED(key)) { |
| 505 if (IS_UNDEFINED(value)) { |
| 506 value = element; |
| 507 } else { |
| 508 value = value + "-" + element; |
| 509 } |
| 493 } else { | 510 } else { |
| 494 // There is a value that's too long, or that doesn't have a key. | 511 // There is a value that's too long, or that doesn't have a key. |
| 495 return {}; | 512 return {}; |
| 496 } | 513 } |
| 497 } | 514 } |
| 515 if (!IS_UNDEFINED(key) && !(key in extensionMap)) { |
| 516 extensionMap[key] = value; |
| 517 } |
| 498 | 518 |
| 499 return extensionMap; | 519 return extensionMap; |
| 500 } | 520 } |
| 501 | 521 |
| 502 | 522 |
| 503 /** | 523 /** |
| 504 * Populates internalOptions object with boolean key-value pairs | 524 * Populates internalOptions object with boolean key-value pairs |
| 505 * from extensionMap and options. | 525 * from extensionMap and options. |
| 506 * Returns filtered extension (number and date format constructors use | 526 * Returns filtered extension (number and date format constructors use |
| 507 * Unicode extensions for passing parameters to ICU). | 527 * Unicode extensions for passing parameters to ICU). |
| (...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 910 if (IS_UNDEFINED(sensitivity) && internalOptions.usage === 'sort') { | 930 if (IS_UNDEFINED(sensitivity) && internalOptions.usage === 'sort') { |
| 911 sensitivity = 'variant'; | 931 sensitivity = 'variant'; |
| 912 } | 932 } |
| 913 defineWEProperty(internalOptions, 'sensitivity', sensitivity); | 933 defineWEProperty(internalOptions, 'sensitivity', sensitivity); |
| 914 | 934 |
| 915 defineWEProperty(internalOptions, 'ignorePunctuation', getOption( | 935 defineWEProperty(internalOptions, 'ignorePunctuation', getOption( |
| 916 'ignorePunctuation', 'boolean', UNDEFINED, false)); | 936 'ignorePunctuation', 'boolean', UNDEFINED, false)); |
| 917 | 937 |
| 918 var locale = resolveLocale('collator', locales, options); | 938 var locale = resolveLocale('collator', locales, options); |
| 919 | 939 |
| 940 // TODO(jshin): ICU now can take kb, kc, etc. Switch over to using ICU |
| 941 // directly. See Collator::InitializeCollator and |
| 942 // Collator::CreateICUCollator in src/i18n.cc |
| 920 // ICU can't take kb, kc... parameters through localeID, so we need to pass | 943 // ICU can't take kb, kc... parameters through localeID, so we need to pass |
| 921 // them as options. | 944 // them as options. |
| 922 // One exception is -co- which has to be part of the extension, but only for | 945 // One exception is -co- which has to be part of the extension, but only for |
| 923 // usage: sort, and its value can't be 'standard' or 'search'. | 946 // usage: sort, and its value can't be 'standard' or 'search'. |
| 924 var extensionMap = parseExtension(locale.extension); | 947 var extensionMap = parseExtension(locale.extension); |
| 925 | 948 |
| 926 /** | 949 /** |
| 927 * Map of Unicode extensions to option properties, and their values and types, | 950 * Map of Unicode extensions to option properties, and their values and types, |
| 928 * for a collator. | 951 * for a collator. |
| 929 */ | 952 */ |
| (...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1657 InstallFunction(Intl.DateTimeFormat.prototype, 'resolvedOptions', function() { | 1680 InstallFunction(Intl.DateTimeFormat.prototype, 'resolvedOptions', function() { |
| 1658 if (!IS_UNDEFINED(new.target)) { | 1681 if (!IS_UNDEFINED(new.target)) { |
| 1659 throw %make_type_error(kOrdinaryFunctionCalledAsConstructor); | 1682 throw %make_type_error(kOrdinaryFunctionCalledAsConstructor); |
| 1660 } | 1683 } |
| 1661 | 1684 |
| 1662 if (!%IsInitializedIntlObjectOfType(this, 'dateformat')) { | 1685 if (!%IsInitializedIntlObjectOfType(this, 'dateformat')) { |
| 1663 throw %make_type_error(kResolvedOptionsCalledOnNonObject, "DateTimeFormat"
); | 1686 throw %make_type_error(kResolvedOptionsCalledOnNonObject, "DateTimeFormat"
); |
| 1664 } | 1687 } |
| 1665 | 1688 |
| 1666 /** | 1689 /** |
| 1667 * Maps ICU calendar names into LDML type. | 1690 * Maps ICU calendar names to LDML/BCP47 types for key 'ca'. |
| 1691 * See typeMap section in third_party/icu/source/data/misc/keyTypeData.txt |
| 1692 * and |
| 1693 * http://www.unicode.org/repos/cldr/tags/latest/common/bcp47/calendar.xml |
| 1668 */ | 1694 */ |
| 1669 var ICU_CALENDAR_MAP = { | 1695 var ICU_CALENDAR_MAP = { |
| 1670 'gregorian': 'gregory', | 1696 'gregorian': 'gregory', |
| 1671 'japanese': 'japanese', | |
| 1672 'buddhist': 'buddhist', | |
| 1673 'roc': 'roc', | |
| 1674 'persian': 'persian', | |
| 1675 'islamic-civil': 'islamicc', | |
| 1676 'islamic': 'islamic', | |
| 1677 'hebrew': 'hebrew', | |
| 1678 'chinese': 'chinese', | |
| 1679 'indian': 'indian', | |
| 1680 'coptic': 'coptic', | |
| 1681 'ethiopic': 'ethiopic', | |
| 1682 'ethiopic-amete-alem': 'ethioaa' | 1697 'ethiopic-amete-alem': 'ethioaa' |
| 1683 }; | 1698 }; |
| 1684 | 1699 |
| 1685 var format = this; | 1700 var format = this; |
| 1686 var fromPattern = fromLDMLString(format[resolvedSymbol][patternSymbol]); | 1701 var fromPattern = fromLDMLString(format[resolvedSymbol][patternSymbol]); |
| 1687 var userCalendar = ICU_CALENDAR_MAP[format[resolvedSymbol].calendar]; | 1702 var userCalendar = ICU_CALENDAR_MAP[format[resolvedSymbol].calendar]; |
| 1688 if (IS_UNDEFINED(userCalendar)) { | 1703 if (IS_UNDEFINED(userCalendar)) { |
| 1689 // Use ICU name if we don't have a match. It shouldn't happen, but | 1704 // No match means that ICU's legacy name is identical to LDML/BCP type. |
| 1690 // it would be too strict to throw for this. | |
| 1691 userCalendar = format[resolvedSymbol].calendar; | 1705 userCalendar = format[resolvedSymbol].calendar; |
| 1692 } | 1706 } |
| 1693 | 1707 |
| 1694 var locale = getOptimalLanguageTag(format[resolvedSymbol].requestedLocale, | 1708 var locale = getOptimalLanguageTag(format[resolvedSymbol].requestedLocale, |
| 1695 format[resolvedSymbol].locale); | 1709 format[resolvedSymbol].locale); |
| 1696 | 1710 |
| 1697 var result = { | 1711 var result = { |
| 1698 locale: locale, | 1712 locale: locale, |
| 1699 numberingSystem: format[resolvedSymbol].numberingSystem, | 1713 numberingSystem: format[resolvedSymbol].numberingSystem, |
| 1700 calendar: userCalendar, | 1714 calendar: userCalendar, |
| (...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2246 } | 2260 } |
| 2247 ); | 2261 ); |
| 2248 | 2262 |
| 2249 utils.Export(function(to) { | 2263 utils.Export(function(to) { |
| 2250 to.AddBoundMethod = AddBoundMethod; | 2264 to.AddBoundMethod = AddBoundMethod; |
| 2251 to.IntlParseDate = IntlParseDate; | 2265 to.IntlParseDate = IntlParseDate; |
| 2252 to.IntlParseNumber = IntlParseNumber; | 2266 to.IntlParseNumber = IntlParseNumber; |
| 2253 }); | 2267 }); |
| 2254 | 2268 |
| 2255 }) | 2269 }) |
| OLD | NEW |