LCOV - code coverage report
Current view: top level - src/runtime - runtime-intl.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 265 327 81.0 %
Date: 2017-04-26 Functions: 24 52 46.2 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_INTL_SUPPORT
       6             : #error Internationalization is expected to be enabled.
       7             : #endif  // V8_INTL_SUPPORT
       8             : 
       9             : #include "src/runtime/runtime-utils.h"
      10             : 
      11             : #include <memory>
      12             : 
      13             : #include "src/api-natives.h"
      14             : #include "src/api.h"
      15             : #include "src/arguments.h"
      16             : #include "src/factory.h"
      17             : #include "src/intl.h"
      18             : #include "src/isolate-inl.h"
      19             : #include "src/messages.h"
      20             : #include "src/objects/intl-objects-inl.h"
      21             : #include "src/objects/intl-objects.h"
      22             : #include "src/utils.h"
      23             : 
      24             : #include "unicode/brkiter.h"
      25             : #include "unicode/calendar.h"
      26             : #include "unicode/coll.h"
      27             : #include "unicode/curramt.h"
      28             : #include "unicode/datefmt.h"
      29             : #include "unicode/dcfmtsym.h"
      30             : #include "unicode/decimfmt.h"
      31             : #include "unicode/dtfmtsym.h"
      32             : #include "unicode/dtptngen.h"
      33             : #include "unicode/fieldpos.h"
      34             : #include "unicode/fpositer.h"
      35             : #include "unicode/locid.h"
      36             : #include "unicode/numfmt.h"
      37             : #include "unicode/numsys.h"
      38             : #include "unicode/rbbi.h"
      39             : #include "unicode/smpdtfmt.h"
      40             : #include "unicode/timezone.h"
      41             : #include "unicode/translit.h"
      42             : #include "unicode/uchar.h"
      43             : #include "unicode/ucol.h"
      44             : #include "unicode/ucurr.h"
      45             : #include "unicode/uloc.h"
      46             : #include "unicode/unistr.h"
      47             : #include "unicode/unum.h"
      48             : #include "unicode/ustring.h"
      49             : #include "unicode/uversion.h"
      50             : 
      51             : namespace v8 {
      52             : namespace internal {
      53             : 
      54             : // ECMA 402 6.2.3
      55        1982 : RUNTIME_FUNCTION(Runtime_CanonicalizeLanguageTag) {
      56         991 :   HandleScope scope(isolate);
      57         991 :   Factory* factory = isolate->factory();
      58             : 
      59             :   DCHECK_EQ(1, args.length());
      60        1982 :   CONVERT_ARG_HANDLE_CHECKED(String, locale_id_str, 0);
      61             : 
      62        2973 :   v8::String::Utf8Value locale_id(v8::Utils::ToLocal(locale_id_str));
      63             : 
      64             :   // Return value which denotes invalid language tag.
      65             :   // TODO(jshin): Can uloc_{for,to}TanguageTag fail even for structually valid
      66             :   // language tags? If not, just add CHECK instead of returning 'invalid-tag'.
      67             :   const char* const kInvalidTag = "invalid-tag";
      68             : 
      69         991 :   UErrorCode error = U_ZERO_ERROR;
      70             :   char icu_result[ULOC_FULLNAME_CAPACITY];
      71         991 :   int icu_length = 0;
      72             : 
      73         991 :   uloc_forLanguageTag(*locale_id, icu_result, ULOC_FULLNAME_CAPACITY,
      74         991 :                       &icu_length, &error);
      75         991 :   if (U_FAILURE(error) || icu_length == 0) {
      76           0 :     return *factory->NewStringFromAsciiChecked(kInvalidTag);
      77             :   }
      78             : 
      79             :   char result[ULOC_FULLNAME_CAPACITY];
      80             : 
      81             :   // Force strict BCP47 rules.
      82         991 :   uloc_toLanguageTag(icu_result, result, ULOC_FULLNAME_CAPACITY, TRUE, &error);
      83             : 
      84         991 :   if (U_FAILURE(error)) {
      85           0 :     return *factory->NewStringFromAsciiChecked(kInvalidTag);
      86             :   }
      87             : 
      88        2973 :   return *factory->NewStringFromAsciiChecked(result);
      89             : }
      90             : 
      91        6132 : RUNTIME_FUNCTION(Runtime_AvailableLocalesOf) {
      92        3066 :   HandleScope scope(isolate);
      93        3066 :   Factory* factory = isolate->factory();
      94             : 
      95             :   DCHECK_EQ(1, args.length());
      96        6132 :   CONVERT_ARG_HANDLE_CHECKED(String, service, 0);
      97             : 
      98             :   const icu::Locale* available_locales = NULL;
      99        3066 :   int32_t count = 0;
     100             : 
     101        6132 :   if (service->IsUtf8EqualTo(CStrVector("collator"))) {
     102         758 :     available_locales = icu::Collator::getAvailableLocales(count);
     103        4616 :   } else if (service->IsUtf8EqualTo(CStrVector("numberformat"))) {
     104         743 :     available_locales = icu::NumberFormat::getAvailableLocales(count);
     105        3130 :   } else if (service->IsUtf8EqualTo(CStrVector("dateformat"))) {
     106         844 :     available_locales = icu::DateFormat::getAvailableLocales(count);
     107        1442 :   } else if (service->IsUtf8EqualTo(CStrVector("breakiterator"))) {
     108         721 :     available_locales = icu::BreakIterator::getAvailableLocales(count);
     109             :   }
     110             : 
     111        3066 :   UErrorCode error = U_ZERO_ERROR;
     112             :   char result[ULOC_FULLNAME_CAPACITY];
     113        3066 :   Handle<JSObject> locales = factory->NewJSObject(isolate->object_function());
     114             : 
     115      354854 :   for (int32_t i = 0; i < count; ++i) {
     116      354854 :     const char* icu_name = available_locales[i].getName();
     117             : 
     118      354854 :     error = U_ZERO_ERROR;
     119             :     // No need to force strict BCP47 rules.
     120      354854 :     uloc_toLanguageTag(icu_name, result, ULOC_FULLNAME_CAPACITY, FALSE, &error);
     121      354854 :     if (U_FAILURE(error)) {
     122             :       // This shouldn't happen, but lets not break the user.
     123             :       continue;
     124             :     }
     125             : 
     126      709708 :     RETURN_FAILURE_ON_EXCEPTION(
     127             :         isolate, JSObject::SetOwnPropertyIgnoreAttributes(
     128             :                      locales, factory->NewStringFromAsciiChecked(result),
     129             :                      factory->NewNumber(i), NONE));
     130             :   }
     131             : 
     132        3066 :   return *locales;
     133             : }
     134             : 
     135        1626 : RUNTIME_FUNCTION(Runtime_GetDefaultICULocale) {
     136         813 :   HandleScope scope(isolate);
     137         813 :   Factory* factory = isolate->factory();
     138             : 
     139             :   DCHECK_EQ(0, args.length());
     140             : 
     141        1626 :   icu::Locale default_locale;
     142             : 
     143             :   // Set the locale
     144             :   char result[ULOC_FULLNAME_CAPACITY];
     145         813 :   UErrorCode status = U_ZERO_ERROR;
     146             :   uloc_toLanguageTag(default_locale.getName(), result, ULOC_FULLNAME_CAPACITY,
     147         813 :                      FALSE, &status);
     148         813 :   if (U_SUCCESS(status)) {
     149        1626 :     return *factory->NewStringFromAsciiChecked(result);
     150             :   }
     151             : 
     152         813 :   return *factory->NewStringFromStaticChars("und");
     153             : }
     154             : 
     155           0 : RUNTIME_FUNCTION(Runtime_GetLanguageTagVariants) {
     156           0 :   HandleScope scope(isolate);
     157           0 :   Factory* factory = isolate->factory();
     158             : 
     159             :   DCHECK_EQ(1, args.length());
     160             : 
     161           0 :   CONVERT_ARG_HANDLE_CHECKED(JSArray, input, 0);
     162             : 
     163           0 :   uint32_t length = static_cast<uint32_t>(input->length()->Number());
     164             :   // Set some limit to prevent fuzz tests from going OOM.
     165             :   // Can be bumped when callers' requirements change.
     166           0 :   if (length >= 100) return isolate->ThrowIllegalOperation();
     167           0 :   Handle<FixedArray> output = factory->NewFixedArray(length);
     168           0 :   Handle<Name> maximized = factory->NewStringFromStaticChars("maximized");
     169           0 :   Handle<Name> base = factory->NewStringFromStaticChars("base");
     170           0 :   for (unsigned int i = 0; i < length; ++i) {
     171             :     Handle<Object> locale_id;
     172           0 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     173             :         isolate, locale_id, JSReceiver::GetElement(isolate, input, i));
     174           0 :     if (!locale_id->IsString()) {
     175           0 :       return isolate->Throw(*factory->illegal_argument_string());
     176             :     }
     177             : 
     178             :     v8::String::Utf8Value utf8_locale_id(
     179           0 :         v8::Utils::ToLocal(Handle<String>::cast(locale_id)));
     180             : 
     181           0 :     UErrorCode error = U_ZERO_ERROR;
     182             : 
     183             :     // Convert from BCP47 to ICU format.
     184             :     // de-DE-u-co-phonebk -> de_DE@collation=phonebook
     185             :     char icu_locale[ULOC_FULLNAME_CAPACITY];
     186           0 :     int icu_locale_length = 0;
     187           0 :     uloc_forLanguageTag(*utf8_locale_id, icu_locale, ULOC_FULLNAME_CAPACITY,
     188           0 :                         &icu_locale_length, &error);
     189           0 :     if (U_FAILURE(error) || icu_locale_length == 0) {
     190           0 :       return isolate->Throw(*factory->illegal_argument_string());
     191             :     }
     192             : 
     193             :     // Maximize the locale.
     194             :     // de_DE@collation=phonebook -> de_Latn_DE@collation=phonebook
     195             :     char icu_max_locale[ULOC_FULLNAME_CAPACITY];
     196             :     uloc_addLikelySubtags(icu_locale, icu_max_locale, ULOC_FULLNAME_CAPACITY,
     197           0 :                           &error);
     198             : 
     199             :     // Remove extensions from maximized locale.
     200             :     // de_Latn_DE@collation=phonebook -> de_Latn_DE
     201             :     char icu_base_max_locale[ULOC_FULLNAME_CAPACITY];
     202             :     uloc_getBaseName(icu_max_locale, icu_base_max_locale,
     203           0 :                      ULOC_FULLNAME_CAPACITY, &error);
     204             : 
     205             :     // Get original name without extensions.
     206             :     // de_DE@collation=phonebook -> de_DE
     207             :     char icu_base_locale[ULOC_FULLNAME_CAPACITY];
     208             :     uloc_getBaseName(icu_locale, icu_base_locale, ULOC_FULLNAME_CAPACITY,
     209           0 :                      &error);
     210             : 
     211             :     // Convert from ICU locale format to BCP47 format.
     212             :     // de_Latn_DE -> de-Latn-DE
     213             :     char base_max_locale[ULOC_FULLNAME_CAPACITY];
     214             :     uloc_toLanguageTag(icu_base_max_locale, base_max_locale,
     215           0 :                        ULOC_FULLNAME_CAPACITY, FALSE, &error);
     216             : 
     217             :     // de_DE -> de-DE
     218             :     char base_locale[ULOC_FULLNAME_CAPACITY];
     219             :     uloc_toLanguageTag(icu_base_locale, base_locale, ULOC_FULLNAME_CAPACITY,
     220           0 :                        FALSE, &error);
     221             : 
     222           0 :     if (U_FAILURE(error)) {
     223           0 :       return isolate->Throw(*factory->illegal_argument_string());
     224             :     }
     225             : 
     226           0 :     Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
     227           0 :     Handle<String> value = factory->NewStringFromAsciiChecked(base_max_locale);
     228           0 :     JSObject::AddProperty(result, maximized, value, NONE);
     229           0 :     value = factory->NewStringFromAsciiChecked(base_locale);
     230           0 :     JSObject::AddProperty(result, base, value, NONE);
     231           0 :     output->set(i, *result);
     232           0 :   }
     233             : 
     234           0 :   Handle<JSArray> result = factory->NewJSArrayWithElements(output);
     235           0 :   result->set_length(Smi::FromInt(length));
     236           0 :   return *result;
     237             : }
     238             : 
     239           0 : RUNTIME_FUNCTION(Runtime_IsInitializedIntlObject) {
     240           0 :   HandleScope scope(isolate);
     241             : 
     242             :   DCHECK_EQ(1, args.length());
     243             : 
     244           0 :   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
     245             : 
     246           0 :   if (!input->IsJSObject()) return isolate->heap()->false_value();
     247           0 :   Handle<JSObject> obj = Handle<JSObject>::cast(input);
     248             : 
     249           0 :   Handle<Symbol> marker = isolate->factory()->intl_initialized_marker_symbol();
     250           0 :   Handle<Object> tag = JSReceiver::GetDataProperty(obj, marker);
     251           0 :   return isolate->heap()->ToBoolean(!tag->IsUndefined(isolate));
     252             : }
     253             : 
     254       35612 : RUNTIME_FUNCTION(Runtime_IsInitializedIntlObjectOfType) {
     255       17806 :   HandleScope scope(isolate);
     256             : 
     257             :   DCHECK_EQ(2, args.length());
     258             : 
     259       17806 :   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
     260       35612 :   CONVERT_ARG_HANDLE_CHECKED(String, expected_type, 1);
     261             : 
     262       17806 :   if (!input->IsJSObject()) return isolate->heap()->false_value();
     263       17735 :   Handle<JSObject> obj = Handle<JSObject>::cast(input);
     264             : 
     265       17735 :   Handle<Symbol> marker = isolate->factory()->intl_initialized_marker_symbol();
     266       17735 :   Handle<Object> tag = JSReceiver::GetDataProperty(obj, marker);
     267       34910 :   return isolate->heap()->ToBoolean(tag->IsString() &&
     268       34910 :                                     String::cast(*tag)->Equals(*expected_type));
     269             : }
     270             : 
     271       34248 : RUNTIME_FUNCTION(Runtime_MarkAsInitializedIntlObjectOfType) {
     272       17124 :   HandleScope scope(isolate);
     273             : 
     274             :   DCHECK_EQ(2, args.length());
     275             : 
     276       34248 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, input, 0);
     277       34248 :   CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
     278             : 
     279       17124 :   Handle<Symbol> marker = isolate->factory()->intl_initialized_marker_symbol();
     280       17124 :   JSObject::SetProperty(input, marker, type, STRICT).Assert();
     281             : 
     282       17124 :   return isolate->heap()->undefined_value();
     283             : }
     284             : 
     285        2266 : RUNTIME_FUNCTION(Runtime_CreateDateTimeFormat) {
     286        1133 :   HandleScope scope(isolate);
     287             : 
     288             :   DCHECK_EQ(3, args.length());
     289             : 
     290        2266 :   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
     291        2266 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
     292        2266 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
     293             : 
     294        2266 :   RETURN_RESULT_OR_FAILURE(
     295        1133 :       isolate, JSIntlDateTimeFormat::New(isolate, locale, options, resolved));
     296             : }
     297             : 
     298        1100 : RUNTIME_FUNCTION(Runtime_InternalDateFormat) {
     299         550 :   HandleScope scope(isolate);
     300             : 
     301             :   DCHECK_EQ(2, args.length());
     302             : 
     303        1100 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
     304        1100 :   CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
     305             : 
     306             :   Handle<Object> value;
     307        1100 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(date));
     308             : 
     309             :   Handle<JSIntlDateTimeFormat> dtf(
     310             :       reinterpret_cast<JSIntlDateTimeFormat*>(*date_format_holder));
     311             : 
     312         550 :   icu::SimpleDateFormat* date_format = dtf->simple_date_format();
     313         550 :   CHECK_NOT_NULL(date_format);
     314             : 
     315        1100 :   icu::UnicodeString result;
     316         550 :   date_format->format(value->Number(), result);
     317             : 
     318        1100 :   RETURN_RESULT_OR_FAILURE(
     319             :       isolate, isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
     320             :                    reinterpret_cast<const uint16_t*>(result.getBuffer()),
     321         550 :                    result.length())));
     322             : }
     323             : 
     324             : namespace {
     325             : // The list comes from third_party/icu/source/i18n/unicode/udat.h.
     326             : // They're mapped to DateTimeFormat components listed at
     327             : // https://tc39.github.io/ecma402/#sec-datetimeformat-abstracts .
     328             : 
     329         196 : Handle<String> IcuDateFieldIdToDateType(int32_t field_id, Isolate* isolate) {
     330         196 :   switch (field_id) {
     331             :     case -1:
     332             :       return isolate->factory()->literal_string();
     333             :     case UDAT_YEAR_FIELD:
     334             :     case UDAT_EXTENDED_YEAR_FIELD:
     335             :     case UDAT_YEAR_NAME_FIELD:
     336             :       return isolate->factory()->year_string();
     337             :     case UDAT_MONTH_FIELD:
     338             :     case UDAT_STANDALONE_MONTH_FIELD:
     339             :       return isolate->factory()->month_string();
     340             :     case UDAT_DATE_FIELD:
     341             :       return isolate->factory()->day_string();
     342             :     case UDAT_HOUR_OF_DAY1_FIELD:
     343             :     case UDAT_HOUR_OF_DAY0_FIELD:
     344             :     case UDAT_HOUR1_FIELD:
     345             :     case UDAT_HOUR0_FIELD:
     346             :       return isolate->factory()->hour_string();
     347             :     case UDAT_MINUTE_FIELD:
     348             :       return isolate->factory()->minute_string();
     349             :     case UDAT_SECOND_FIELD:
     350             :       return isolate->factory()->second_string();
     351             :     case UDAT_DAY_OF_WEEK_FIELD:
     352             :     case UDAT_DOW_LOCAL_FIELD:
     353             :     case UDAT_STANDALONE_DAY_FIELD:
     354             :       return isolate->factory()->weekday_string();
     355             :     case UDAT_AM_PM_FIELD:
     356             :       return isolate->factory()->dayperiod_string();
     357             :     case UDAT_TIMEZONE_FIELD:
     358             :     case UDAT_TIMEZONE_RFC_FIELD:
     359             :     case UDAT_TIMEZONE_GENERIC_FIELD:
     360             :     case UDAT_TIMEZONE_SPECIAL_FIELD:
     361             :     case UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD:
     362             :     case UDAT_TIMEZONE_ISO_FIELD:
     363             :     case UDAT_TIMEZONE_ISO_LOCAL_FIELD:
     364             :       return isolate->factory()->timeZoneName_string();
     365             :     case UDAT_ERA_FIELD:
     366             :       return isolate->factory()->era_string();
     367             :     default:
     368             :       // Other UDAT_*_FIELD's cannot show up because there is no way to specify
     369             :       // them via options of Intl.DateTimeFormat.
     370           0 :       UNREACHABLE();
     371             :       // To prevent MSVC from issuing C4715 warning.
     372             :       return Handle<String>();
     373             :   }
     374             : }
     375             : 
     376         196 : bool AddElement(Handle<JSArray> array, int index, int32_t field_id,
     377             :                 const icu::UnicodeString& formatted, int32_t begin, int32_t end,
     378             :                 Isolate* isolate) {
     379             :   HandleScope scope(isolate);
     380             :   Factory* factory = isolate->factory();
     381         196 :   Handle<JSObject> element = factory->NewJSObject(isolate->object_function());
     382         196 :   Handle<String> value = IcuDateFieldIdToDateType(field_id, isolate);
     383         196 :   JSObject::AddProperty(element, factory->type_string(), value, NONE);
     384             : 
     385         196 :   icu::UnicodeString field(formatted.tempSubStringBetween(begin, end));
     386         392 :   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     387             :       isolate, value,
     388             :       factory->NewStringFromTwoByte(Vector<const uint16_t>(
     389             :           reinterpret_cast<const uint16_t*>(field.getBuffer()),
     390             :           field.length())),
     391             :       false);
     392             : 
     393         196 :   JSObject::AddProperty(element, factory->value_string(), value, NONE);
     394         588 :   RETURN_ON_EXCEPTION_VALUE(
     395             :       isolate, JSObject::AddDataElement(array, index, element, NONE), false);
     396         196 :   return true;
     397             : }
     398             : 
     399             : }  // namespace
     400             : 
     401          28 : RUNTIME_FUNCTION(Runtime_InternalDateFormatToParts) {
     402          14 :   HandleScope scope(isolate);
     403          14 :   Factory* factory = isolate->factory();
     404             : 
     405             :   DCHECK_EQ(2, args.length());
     406             : 
     407          28 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
     408          28 :   CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
     409             : 
     410             :   Handle<Object> value;
     411          28 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(date));
     412             : 
     413             :   icu::SimpleDateFormat* date_format =
     414             :       reinterpret_cast<JSIntlDateTimeFormat*>(*date_format_holder)
     415          14 :           ->simple_date_format();
     416          14 :   CHECK_NOT_NULL(date_format);
     417             : 
     418          28 :   icu::UnicodeString formatted;
     419          28 :   icu::FieldPositionIterator fp_iter;
     420          28 :   icu::FieldPosition fp;
     421          14 :   UErrorCode status = U_ZERO_ERROR;
     422          14 :   date_format->format(value->Number(), formatted, &fp_iter, status);
     423          14 :   if (U_FAILURE(status)) return isolate->heap()->undefined_value();
     424             : 
     425          14 :   Handle<JSArray> result = factory->NewJSArray(0);
     426          14 :   int32_t length = formatted.length();
     427          14 :   if (length == 0) return *result;
     428             : 
     429             :   int index = 0;
     430             :   int32_t previous_end_pos = 0;
     431         126 :   while (fp_iter.next(fp)) {
     432         112 :     int32_t begin_pos = fp.getBeginIndex();
     433         112 :     int32_t end_pos = fp.getEndIndex();
     434             : 
     435         112 :     if (previous_end_pos < begin_pos) {
     436          84 :       if (!AddElement(result, index, -1, formatted, previous_end_pos, begin_pos,
     437          84 :                       isolate)) {
     438           0 :         return isolate->heap()->undefined_value();
     439             :       }
     440          84 :       ++index;
     441             :     }
     442         112 :     if (!AddElement(result, index, fp.getField(), formatted, begin_pos, end_pos,
     443         112 :                     isolate)) {
     444           0 :       return isolate->heap()->undefined_value();
     445             :     }
     446             :     previous_end_pos = end_pos;
     447         112 :     ++index;
     448             :   }
     449          14 :   if (previous_end_pos < length) {
     450           0 :     if (!AddElement(result, index, -1, formatted, previous_end_pos, length,
     451           0 :                     isolate)) {
     452           0 :       return isolate->heap()->undefined_value();
     453             :     }
     454             :   }
     455          14 :   JSObject::ValidateElements(result);
     456          14 :   return *result;
     457             : }
     458             : 
     459        1468 : RUNTIME_FUNCTION(Runtime_CreateNumberFormat) {
     460         734 :   HandleScope scope(isolate);
     461             : 
     462             :   DCHECK_EQ(3, args.length());
     463             : 
     464        1468 :   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
     465        1468 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
     466        1468 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
     467             : 
     468        1468 :   RETURN_RESULT_OR_FAILURE(
     469         734 :       isolate, JSIntlNumberFormat::New(isolate, locale, options, resolved));
     470             : }
     471             : 
     472        5256 : RUNTIME_FUNCTION(Runtime_InternalNumberFormat) {
     473        2628 :   HandleScope scope(isolate);
     474             : 
     475             :   DCHECK_EQ(2, args.length());
     476             : 
     477        5256 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
     478        2628 :   CONVERT_ARG_HANDLE_CHECKED(Object, number, 1);
     479             : 
     480             :   Handle<Object> value;
     481        5256 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(number));
     482             : 
     483             :   icu::DecimalFormat* number_format =
     484             :       reinterpret_cast<JSIntlNumberFormat*>(*number_format_holder)
     485        2628 :           ->decimal_format();
     486        2628 :   CHECK_NOT_NULL(number_format);
     487             : 
     488        5256 :   icu::UnicodeString result;
     489        2628 :   number_format->format(value->Number(), result);
     490             : 
     491        5256 :   RETURN_RESULT_OR_FAILURE(
     492             :       isolate, isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
     493             :                    reinterpret_cast<const uint16_t*>(result.getBuffer()),
     494        2628 :                    result.length())));
     495             : }
     496             : 
     497         196 : RUNTIME_FUNCTION(Runtime_CurrencyDigits) {
     498             :   DCHECK_EQ(1, args.length());
     499             : 
     500         196 :   CONVERT_ARG_HANDLE_CHECKED(String, currency, 0);
     501             : 
     502             :   // TODO(littledan): Avoid transcoding the string twice
     503         196 :   v8::String::Utf8Value currency_string(v8::Utils::ToLocal(currency));
     504             :   icu::UnicodeString currency_icu =
     505         196 :       icu::UnicodeString::fromUTF8(*currency_string);
     506             : 
     507             :   DisallowHeapAllocation no_gc;
     508          98 :   UErrorCode status = U_ZERO_ERROR;
     509             : #if U_ICU_VERSION_MAJOR_NUM >= 59
     510             :   uint32_t fraction_digits = ucurr_getDefaultFractionDigits(
     511             :       icu::toUCharPtr(currency_icu.getTerminatedBuffer()), &status);
     512             : #else
     513             :   uint32_t fraction_digits = ucurr_getDefaultFractionDigits(
     514          98 :       currency_icu.getTerminatedBuffer(), &status);
     515             : #endif
     516             :   // For missing currency codes, default to the most common, 2
     517          98 :   if (!U_SUCCESS(status)) fraction_digits = 2;
     518         196 :   return Smi::FromInt(fraction_digits);
     519             : }
     520             : 
     521       30192 : RUNTIME_FUNCTION(Runtime_CreateCollator) {
     522       15096 :   HandleScope scope(isolate);
     523             : 
     524             :   DCHECK_EQ(3, args.length());
     525             : 
     526       30192 :   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
     527       30192 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
     528       30192 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
     529             : 
     530       30192 :   RETURN_RESULT_OR_FAILURE(
     531       15096 :       isolate, JSIntlCollator::New(isolate, locale, options, resolved));
     532             : }
     533             : 
     534      285202 : RUNTIME_FUNCTION(Runtime_InternalCompare) {
     535      142601 :   HandleScope scope(isolate);
     536             : 
     537             :   DCHECK_EQ(3, args.length());
     538             : 
     539      285202 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, collator_holder, 0);
     540      285202 :   CONVERT_ARG_HANDLE_CHECKED(String, string1, 1);
     541      285202 :   CONVERT_ARG_HANDLE_CHECKED(String, string2, 2);
     542             : 
     543             :   icu::Collator* collator =
     544      142601 :       reinterpret_cast<JSIntlCollator*>(*collator_holder)->collator();
     545      142601 :   CHECK_NOT_NULL(collator);
     546             : 
     547      142601 :   string1 = String::Flatten(string1);
     548      142601 :   string2 = String::Flatten(string2);
     549             : 
     550             :   UCollationResult result;
     551      142601 :   UErrorCode status = U_ZERO_ERROR;
     552             :   {
     553             :     DisallowHeapAllocation no_gc;
     554      142601 :     int32_t length1 = string1->length();
     555      142601 :     int32_t length2 = string2->length();
     556      142601 :     String::FlatContent flat1 = string1->GetFlatContent();
     557      142601 :     String::FlatContent flat2 = string2->GetFlatContent();
     558      142601 :     std::unique_ptr<uc16[]> sap1;
     559      285202 :     std::unique_ptr<uc16[]> sap2;
     560             :     icu::UnicodeString string_val1(
     561      285202 :         FALSE, GetUCharBufferFromFlat(flat1, &sap1, length1), length1);
     562             :     icu::UnicodeString string_val2(
     563      285202 :         FALSE, GetUCharBufferFromFlat(flat2, &sap2, length2), length2);
     564      285202 :     result = collator->compare(string_val1, string_val2, status);
     565             :   }
     566      142601 :   if (U_FAILURE(status)) return isolate->ThrowIllegalOperation();
     567             : 
     568      285202 :   return *isolate->factory()->NewNumberFromInt(result);
     569             : }
     570             : 
     571         352 : RUNTIME_FUNCTION(Runtime_CreateBreakIterator) {
     572         176 :   HandleScope scope(isolate);
     573             : 
     574             :   DCHECK_EQ(3, args.length());
     575             : 
     576         352 :   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
     577         352 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
     578         352 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
     579             : 
     580         352 :   RETURN_RESULT_OR_FAILURE(
     581         176 :       isolate, JSIntlV8BreakIterator::New(isolate, locale, options, resolved));
     582             : }
     583             : 
     584          68 : RUNTIME_FUNCTION(Runtime_BreakIteratorAdoptText) {
     585          34 :   HandleScope scope(isolate);
     586             : 
     587             :   DCHECK_EQ(2, args.length());
     588             : 
     589          68 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
     590          68 :   CONVERT_ARG_HANDLE_CHECKED(String, text, 1);
     591             : 
     592             :   Handle<JSIntlV8BreakIterator> br(
     593             :       reinterpret_cast<JSIntlV8BreakIterator*>(*break_iterator_holder));
     594          34 :   icu::BreakIterator* break_iterator = br->break_iterator();
     595          34 :   CHECK_NOT_NULL(break_iterator);
     596             : 
     597          34 :   icu::UnicodeString* u_text = br->unicode_string();
     598          34 :   delete u_text;
     599             : 
     600          34 :   int length = text->length();
     601          34 :   text = String::Flatten(text);
     602             :   DisallowHeapAllocation no_gc;
     603          34 :   String::FlatContent flat = text->GetFlatContent();
     604          68 :   std::unique_ptr<uc16[]> sap;
     605          34 :   const UChar* text_value = GetUCharBufferFromFlat(flat, &sap, length);
     606          34 :   u_text = new icu::UnicodeString(text_value, length);
     607          34 :   br->set_unicode_string(u_text);
     608             : 
     609          34 :   break_iterator->setText(*u_text);
     610             : 
     611          68 :   return isolate->heap()->undefined_value();
     612             : }
     613             : 
     614          56 : RUNTIME_FUNCTION(Runtime_BreakIteratorFirst) {
     615          28 :   HandleScope scope(isolate);
     616             : 
     617             :   DCHECK_EQ(1, args.length());
     618             : 
     619          56 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
     620             : 
     621             :   Handle<JSIntlV8BreakIterator> br(
     622             :       reinterpret_cast<JSIntlV8BreakIterator*>(*break_iterator_holder));
     623          28 :   icu::BreakIterator* break_iterator = br->break_iterator();
     624          28 :   CHECK_NOT_NULL(break_iterator);
     625             : 
     626          56 :   return *isolate->factory()->NewNumberFromInt(break_iterator->first());
     627             : }
     628             : 
     629         948 : RUNTIME_FUNCTION(Runtime_BreakIteratorNext) {
     630         474 :   HandleScope scope(isolate);
     631             : 
     632             :   DCHECK_EQ(1, args.length());
     633             : 
     634         948 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
     635             : 
     636             :   Handle<JSIntlV8BreakIterator> br(
     637             :       reinterpret_cast<JSIntlV8BreakIterator*>(*break_iterator_holder));
     638         474 :   icu::BreakIterator* break_iterator = br->break_iterator();
     639         474 :   CHECK_NOT_NULL(break_iterator);
     640             : 
     641         948 :   return *isolate->factory()->NewNumberFromInt(break_iterator->next());
     642             : }
     643             : 
     644           0 : RUNTIME_FUNCTION(Runtime_BreakIteratorCurrent) {
     645           0 :   HandleScope scope(isolate);
     646             : 
     647             :   DCHECK_EQ(1, args.length());
     648             : 
     649           0 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
     650             : 
     651             :   Handle<JSIntlV8BreakIterator> br(
     652             :       reinterpret_cast<JSIntlV8BreakIterator*>(*break_iterator_holder));
     653           0 :   icu::BreakIterator* break_iterator = br->break_iterator();
     654           0 :   CHECK_NOT_NULL(break_iterator);
     655             : 
     656           0 :   return *isolate->factory()->NewNumberFromInt(break_iterator->current());
     657             : }
     658             : 
     659         868 : RUNTIME_FUNCTION(Runtime_BreakIteratorBreakType) {
     660         434 :   HandleScope scope(isolate);
     661             : 
     662             :   DCHECK_EQ(1, args.length());
     663             : 
     664         868 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
     665             : 
     666             :   Handle<JSIntlV8BreakIterator> br(
     667             :       reinterpret_cast<JSIntlV8BreakIterator*>(*break_iterator_holder));
     668         434 :   icu::BreakIterator* break_iterator = br->break_iterator();
     669         434 :   CHECK_NOT_NULL(break_iterator);
     670             : 
     671             :   // TODO(cira): Remove cast once ICU fixes base BreakIterator class.
     672             :   icu::RuleBasedBreakIterator* rule_based_iterator =
     673             :       static_cast<icu::RuleBasedBreakIterator*>(break_iterator);
     674         434 :   int32_t status = rule_based_iterator->getRuleStatus();
     675             :   // Keep return values in sync with JavaScript BreakType enum.
     676         434 :   if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
     677         420 :     return *isolate->factory()->NewStringFromStaticChars("none");
     678         224 :   } else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
     679           0 :     return isolate->heap()->number_string();
     680         224 :   } else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
     681         280 :     return *isolate->factory()->NewStringFromStaticChars("letter");
     682          84 :   } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
     683           0 :     return *isolate->factory()->NewStringFromStaticChars("kana");
     684          84 :   } else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
     685         168 :     return *isolate->factory()->NewStringFromStaticChars("ideo");
     686             :   } else {
     687           0 :     return *isolate->factory()->NewStringFromStaticChars("unknown");
     688         434 :   }
     689             : }
     690             : 
     691        4448 : RUNTIME_FUNCTION(Runtime_StringToLowerCaseIntl) {
     692        2224 :   HandleScope scope(isolate);
     693             :   DCHECK_EQ(args.length(), 1);
     694        4448 :   CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
     695        2224 :   s = String::Flatten(s);
     696        2224 :   return ConvertToLower(s, isolate);
     697             : }
     698             : 
     699        3048 : RUNTIME_FUNCTION(Runtime_StringToUpperCaseIntl) {
     700        1524 :   HandleScope scope(isolate);
     701             :   DCHECK_EQ(args.length(), 1);
     702        3048 :   CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
     703        1524 :   s = String::Flatten(s);
     704        1524 :   return ConvertToUpper(s, isolate);
     705             : }
     706             : 
     707        2324 : RUNTIME_FUNCTION(Runtime_StringLocaleConvertCase) {
     708        1162 :   HandleScope scope(isolate);
     709             :   DCHECK_EQ(args.length(), 3);
     710        2324 :   CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
     711        2324 :   CONVERT_BOOLEAN_ARG_CHECKED(is_upper, 1);
     712        2324 :   CONVERT_ARG_HANDLE_CHECKED(String, lang_arg, 2);
     713             : 
     714             :   // Primary language tag can be up to 8 characters long in theory.
     715             :   // https://tools.ietf.org/html/bcp47#section-2.2.1
     716             :   DCHECK(lang_arg->length() <= 8);
     717        1162 :   lang_arg = String::Flatten(lang_arg);
     718        1162 :   s = String::Flatten(s);
     719             : 
     720             :   // All the languages requiring special-handling have two-letter codes.
     721        1162 :   if (V8_UNLIKELY(lang_arg->length() > 2))
     722         182 :     return ConvertCase(s, is_upper, isolate);
     723             : 
     724             :   char c1, c2;
     725             :   {
     726             :     DisallowHeapAllocation no_gc;
     727         980 :     String::FlatContent lang = lang_arg->GetFlatContent();
     728         980 :     c1 = lang.Get(0);
     729         980 :     c2 = lang.Get(1);
     730             :   }
     731             :   // TODO(jshin): Consider adding a fast path for ASCII or Latin-1. The fastpath
     732             :   // in the root locale needs to be adjusted for az, lt and tr because even case
     733             :   // mapping of ASCII range characters are different in those locales.
     734             :   // Greek (el) does not require any adjustment.
     735         980 :   if (V8_UNLIKELY(c1 == 't' && c2 == 'r'))
     736         168 :     return LocaleConvertCase(s, isolate, is_upper, "tr");
     737         812 :   if (V8_UNLIKELY(c1 == 'e' && c2 == 'l'))
     738         350 :     return LocaleConvertCase(s, isolate, is_upper, "el");
     739         462 :   if (V8_UNLIKELY(c1 == 'l' && c2 == 't'))
     740          28 :     return LocaleConvertCase(s, isolate, is_upper, "lt");
     741         434 :   if (V8_UNLIKELY(c1 == 'a' && c2 == 'z'))
     742          56 :     return LocaleConvertCase(s, isolate, is_upper, "az");
     743             : 
     744         378 :   return ConvertCase(s, is_upper, isolate);
     745             : }
     746             : 
     747      570138 : RUNTIME_FUNCTION(Runtime_DateCacheVersion) {
     748      114008 :   HandleScope scope(isolate);
     749             :   DCHECK_EQ(0, args.length());
     750      114008 :   if (isolate->serializer_enabled()) return isolate->heap()->undefined_value();
     751      114008 :   if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) {
     752             :     Handle<FixedArray> date_cache_version =
     753          98 :         isolate->factory()->NewFixedArray(1, TENURED);
     754          98 :     date_cache_version->set(0, Smi::kZero);
     755             :     isolate->eternal_handles()->CreateSingleton(
     756          98 :         isolate, *date_cache_version, EternalHandles::DATE_CACHE_VERSION);
     757             :   }
     758             :   Handle<FixedArray> date_cache_version =
     759             :       Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton(
     760      114008 :           EternalHandles::DATE_CACHE_VERSION));
     761      114008 :   return date_cache_version->get(0);
     762             : }
     763             : 
     764             : }  // namespace internal
     765             : }  // namespace v8

Generated by: LCOV version 1.10