V8 Project
runtime-i18n.cc
Go to the documentation of this file.
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 
6 #ifdef V8_I18N_SUPPORT
7 #include "src/v8.h"
8 
9 #include "src/arguments.h"
10 #include "src/i18n.h"
11 #include "src/runtime/runtime.h"
13 
14 #include "unicode/brkiter.h"
15 #include "unicode/calendar.h"
16 #include "unicode/coll.h"
17 #include "unicode/curramt.h"
18 #include "unicode/datefmt.h"
19 #include "unicode/dcfmtsym.h"
20 #include "unicode/decimfmt.h"
21 #include "unicode/dtfmtsym.h"
22 #include "unicode/dtptngen.h"
23 #include "unicode/locid.h"
24 #include "unicode/numfmt.h"
25 #include "unicode/numsys.h"
26 #include "unicode/rbbi.h"
27 #include "unicode/smpdtfmt.h"
28 #include "unicode/timezone.h"
29 #include "unicode/uchar.h"
30 #include "unicode/ucol.h"
31 #include "unicode/ucurr.h"
32 #include "unicode/uloc.h"
33 #include "unicode/unum.h"
34 #include "unicode/uversion.h"
35 
36 
37 namespace v8 {
38 namespace internal {
39 
40 RUNTIME_FUNCTION(Runtime_CanonicalizeLanguageTag) {
41  HandleScope scope(isolate);
42  Factory* factory = isolate->factory();
43 
44  DCHECK(args.length() == 1);
45  CONVERT_ARG_HANDLE_CHECKED(String, locale_id_str, 0);
46 
47  v8::String::Utf8Value locale_id(v8::Utils::ToLocal(locale_id_str));
48 
49  // Return value which denotes invalid language tag.
50  const char* const kInvalidTag = "invalid-tag";
51 
52  UErrorCode error = U_ZERO_ERROR;
53  char icu_result[ULOC_FULLNAME_CAPACITY];
54  int icu_length = 0;
55 
56  uloc_forLanguageTag(*locale_id, icu_result, ULOC_FULLNAME_CAPACITY,
57  &icu_length, &error);
58  if (U_FAILURE(error) || icu_length == 0) {
59  return *factory->NewStringFromAsciiChecked(kInvalidTag);
60  }
61 
62  char result[ULOC_FULLNAME_CAPACITY];
63 
64  // Force strict BCP47 rules.
65  uloc_toLanguageTag(icu_result, result, ULOC_FULLNAME_CAPACITY, TRUE, &error);
66 
67  if (U_FAILURE(error)) {
68  return *factory->NewStringFromAsciiChecked(kInvalidTag);
69  }
70 
71  return *factory->NewStringFromAsciiChecked(result);
72 }
73 
74 
75 RUNTIME_FUNCTION(Runtime_AvailableLocalesOf) {
76  HandleScope scope(isolate);
77  Factory* factory = isolate->factory();
78 
79  DCHECK(args.length() == 1);
80  CONVERT_ARG_HANDLE_CHECKED(String, service, 0);
81 
82  const icu::Locale* available_locales = NULL;
83  int32_t count = 0;
84 
85  if (service->IsUtf8EqualTo(CStrVector("collator"))) {
86  available_locales = icu::Collator::getAvailableLocales(count);
87  } else if (service->IsUtf8EqualTo(CStrVector("numberformat"))) {
88  available_locales = icu::NumberFormat::getAvailableLocales(count);
89  } else if (service->IsUtf8EqualTo(CStrVector("dateformat"))) {
90  available_locales = icu::DateFormat::getAvailableLocales(count);
91  } else if (service->IsUtf8EqualTo(CStrVector("breakiterator"))) {
92  available_locales = icu::BreakIterator::getAvailableLocales(count);
93  }
94 
95  UErrorCode error = U_ZERO_ERROR;
96  char result[ULOC_FULLNAME_CAPACITY];
97  Handle<JSObject> locales = factory->NewJSObject(isolate->object_function());
98 
99  for (int32_t i = 0; i < count; ++i) {
100  const char* icu_name = available_locales[i].getName();
101 
102  error = U_ZERO_ERROR;
103  // No need to force strict BCP47 rules.
104  uloc_toLanguageTag(icu_name, result, ULOC_FULLNAME_CAPACITY, FALSE, &error);
105  if (U_FAILURE(error)) {
106  // This shouldn't happen, but lets not break the user.
107  continue;
108  }
109 
112  locales, factory->NewStringFromAsciiChecked(result),
113  factory->NewNumber(i), NONE));
114  }
115 
116  return *locales;
117 }
118 
119 
120 RUNTIME_FUNCTION(Runtime_GetDefaultICULocale) {
121  HandleScope scope(isolate);
122  Factory* factory = isolate->factory();
123 
124  DCHECK(args.length() == 0);
125 
126  icu::Locale default_locale;
127 
128  // Set the locale
129  char result[ULOC_FULLNAME_CAPACITY];
130  UErrorCode status = U_ZERO_ERROR;
131  uloc_toLanguageTag(default_locale.getName(), result, ULOC_FULLNAME_CAPACITY,
132  FALSE, &status);
133  if (U_SUCCESS(status)) {
134  return *factory->NewStringFromAsciiChecked(result);
135  }
136 
137  return *factory->NewStringFromStaticChars("und");
138 }
139 
140 
141 RUNTIME_FUNCTION(Runtime_GetLanguageTagVariants) {
142  HandleScope scope(isolate);
143  Factory* factory = isolate->factory();
144 
145  DCHECK(args.length() == 1);
146 
147  CONVERT_ARG_HANDLE_CHECKED(JSArray, input, 0);
148 
149  uint32_t length = static_cast<uint32_t>(input->length()->Number());
150  // Set some limit to prevent fuzz tests from going OOM.
151  // Can be bumped when callers' requirements change.
152  RUNTIME_ASSERT(length < 100);
153  Handle<FixedArray> output = factory->NewFixedArray(length);
154  Handle<Name> maximized = factory->NewStringFromStaticChars("maximized");
155  Handle<Name> base = factory->NewStringFromStaticChars("base");
156  for (unsigned int i = 0; i < length; ++i) {
157  Handle<Object> locale_id;
158  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, locale_id,
159  Object::GetElement(isolate, input, i));
160  if (!locale_id->IsString()) {
161  return isolate->Throw(*factory->illegal_argument_string());
162  }
163 
164  v8::String::Utf8Value utf8_locale_id(
166 
167  UErrorCode error = U_ZERO_ERROR;
168 
169  // Convert from BCP47 to ICU format.
170  // de-DE-u-co-phonebk -> de_DE@collation=phonebook
171  char icu_locale[ULOC_FULLNAME_CAPACITY];
172  int icu_locale_length = 0;
173  uloc_forLanguageTag(*utf8_locale_id, icu_locale, ULOC_FULLNAME_CAPACITY,
174  &icu_locale_length, &error);
175  if (U_FAILURE(error) || icu_locale_length == 0) {
176  return isolate->Throw(*factory->illegal_argument_string());
177  }
178 
179  // Maximize the locale.
180  // de_DE@collation=phonebook -> de_Latn_DE@collation=phonebook
181  char icu_max_locale[ULOC_FULLNAME_CAPACITY];
182  uloc_addLikelySubtags(icu_locale, icu_max_locale, ULOC_FULLNAME_CAPACITY,
183  &error);
184 
185  // Remove extensions from maximized locale.
186  // de_Latn_DE@collation=phonebook -> de_Latn_DE
187  char icu_base_max_locale[ULOC_FULLNAME_CAPACITY];
188  uloc_getBaseName(icu_max_locale, icu_base_max_locale,
189  ULOC_FULLNAME_CAPACITY, &error);
190 
191  // Get original name without extensions.
192  // de_DE@collation=phonebook -> de_DE
193  char icu_base_locale[ULOC_FULLNAME_CAPACITY];
194  uloc_getBaseName(icu_locale, icu_base_locale, ULOC_FULLNAME_CAPACITY,
195  &error);
196 
197  // Convert from ICU locale format to BCP47 format.
198  // de_Latn_DE -> de-Latn-DE
199  char base_max_locale[ULOC_FULLNAME_CAPACITY];
200  uloc_toLanguageTag(icu_base_max_locale, base_max_locale,
201  ULOC_FULLNAME_CAPACITY, FALSE, &error);
202 
203  // de_DE -> de-DE
204  char base_locale[ULOC_FULLNAME_CAPACITY];
205  uloc_toLanguageTag(icu_base_locale, base_locale, ULOC_FULLNAME_CAPACITY,
206  FALSE, &error);
207 
208  if (U_FAILURE(error)) {
209  return isolate->Throw(*factory->illegal_argument_string());
210  }
211 
212  Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
213  Handle<String> value = factory->NewStringFromAsciiChecked(base_max_locale);
214  JSObject::AddProperty(result, maximized, value, NONE);
215  value = factory->NewStringFromAsciiChecked(base_locale);
216  JSObject::AddProperty(result, base, value, NONE);
217  output->set(i, *result);
218  }
219 
220  Handle<JSArray> result = factory->NewJSArrayWithElements(output);
221  result->set_length(Smi::FromInt(length));
222  return *result;
223 }
224 
225 
226 RUNTIME_FUNCTION(Runtime_IsInitializedIntlObject) {
227  HandleScope scope(isolate);
228 
229  DCHECK(args.length() == 1);
230 
232 
233  if (!input->IsJSObject()) return isolate->heap()->false_value();
234  Handle<JSObject> obj = Handle<JSObject>::cast(input);
235 
236  Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
237  Handle<Object> tag(obj->GetHiddenProperty(marker), isolate);
238  return isolate->heap()->ToBoolean(!tag->IsTheHole());
239 }
240 
241 
242 RUNTIME_FUNCTION(Runtime_IsInitializedIntlObjectOfType) {
243  HandleScope scope(isolate);
244 
245  DCHECK(args.length() == 2);
246 
248  CONVERT_ARG_HANDLE_CHECKED(String, expected_type, 1);
249 
250  if (!input->IsJSObject()) return isolate->heap()->false_value();
251  Handle<JSObject> obj = Handle<JSObject>::cast(input);
252 
253  Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
254  Handle<Object> tag(obj->GetHiddenProperty(marker), isolate);
255  return isolate->heap()->ToBoolean(tag->IsString() &&
256  String::cast(*tag)->Equals(*expected_type));
257 }
258 
259 
260 RUNTIME_FUNCTION(Runtime_MarkAsInitializedIntlObjectOfType) {
261  HandleScope scope(isolate);
262 
263  DCHECK(args.length() == 3);
264 
265  CONVERT_ARG_HANDLE_CHECKED(JSObject, input, 0);
266  CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
267  CONVERT_ARG_HANDLE_CHECKED(JSObject, impl, 2);
268 
269  Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
270  JSObject::SetHiddenProperty(input, marker, type);
271 
272  marker = isolate->factory()->intl_impl_object_string();
273  JSObject::SetHiddenProperty(input, marker, impl);
274 
275  return isolate->heap()->undefined_value();
276 }
277 
278 
279 RUNTIME_FUNCTION(Runtime_GetImplFromInitializedIntlObject) {
280  HandleScope scope(isolate);
281 
282  DCHECK(args.length() == 1);
283 
285 
286  if (!input->IsJSObject()) {
287  Vector<Handle<Object> > arguments = HandleVector(&input, 1);
289  NewTypeError("not_intl_object", arguments));
290  }
291 
292  Handle<JSObject> obj = Handle<JSObject>::cast(input);
293 
294  Handle<String> marker = isolate->factory()->intl_impl_object_string();
295  Handle<Object> impl(obj->GetHiddenProperty(marker), isolate);
296  if (impl->IsTheHole()) {
297  Vector<Handle<Object> > arguments = HandleVector(&obj, 1);
299  NewTypeError("not_intl_object", arguments));
300  }
301  return *impl;
302 }
303 
304 
305 RUNTIME_FUNCTION(Runtime_CreateDateTimeFormat) {
306  HandleScope scope(isolate);
307 
308  DCHECK(args.length() == 3);
309 
310  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
311  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
312  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
313 
314  Handle<ObjectTemplateInfo> date_format_template = I18N::GetTemplate(isolate);
315 
316  // Create an empty object wrapper.
317  Handle<JSObject> local_object;
319  isolate, local_object,
320  Execution::InstantiateObject(date_format_template));
321 
322  // Set date time formatter as internal field of the resulting JS object.
323  icu::SimpleDateFormat* date_format =
324  DateFormat::InitializeDateTimeFormat(isolate, locale, options, resolved);
325 
326  if (!date_format) return isolate->ThrowIllegalOperation();
327 
328  local_object->SetInternalField(0, reinterpret_cast<Smi*>(date_format));
329 
330  Factory* factory = isolate->factory();
331  Handle<String> key = factory->NewStringFromStaticChars("dateFormat");
332  Handle<String> value = factory->NewStringFromStaticChars("valid");
333  JSObject::AddProperty(local_object, key, value, NONE);
334 
335  // Make object handle weak so we can delete the data format once GC kicks in.
336  Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
337  GlobalHandles::MakeWeak(wrapper.location(),
338  reinterpret_cast<void*>(wrapper.location()),
340  return *local_object;
341 }
342 
343 
344 RUNTIME_FUNCTION(Runtime_InternalDateFormat) {
345  HandleScope scope(isolate);
346 
347  DCHECK(args.length() == 2);
348 
349  CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
350  CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
351 
352  Handle<Object> value;
353  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
354  Execution::ToNumber(isolate, date));
355 
356  icu::SimpleDateFormat* date_format =
357  DateFormat::UnpackDateFormat(isolate, date_format_holder);
358  if (!date_format) return isolate->ThrowIllegalOperation();
359 
360  icu::UnicodeString result;
361  date_format->format(value->Number(), result);
362 
363  Handle<String> result_str;
365  isolate, result_str,
366  isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
367  reinterpret_cast<const uint16_t*>(result.getBuffer()),
368  result.length())));
369  return *result_str;
370 }
371 
372 
373 RUNTIME_FUNCTION(Runtime_InternalDateParse) {
374  HandleScope scope(isolate);
375 
376  DCHECK(args.length() == 2);
377 
378  CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
379  CONVERT_ARG_HANDLE_CHECKED(String, date_string, 1);
380 
381  v8::String::Utf8Value utf8_date(v8::Utils::ToLocal(date_string));
382  icu::UnicodeString u_date(icu::UnicodeString::fromUTF8(*utf8_date));
383  icu::SimpleDateFormat* date_format =
384  DateFormat::UnpackDateFormat(isolate, date_format_holder);
385  if (!date_format) return isolate->ThrowIllegalOperation();
386 
387  UErrorCode status = U_ZERO_ERROR;
388  UDate date = date_format->parse(u_date, status);
389  if (U_FAILURE(status)) return isolate->heap()->undefined_value();
390 
391  Handle<Object> result;
393  isolate, result, Execution::NewDate(isolate, static_cast<double>(date)));
394  DCHECK(result->IsJSDate());
395  return *result;
396 }
397 
398 
399 RUNTIME_FUNCTION(Runtime_CreateNumberFormat) {
400  HandleScope scope(isolate);
401 
402  DCHECK(args.length() == 3);
403 
404  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
405  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
406  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
407 
408  Handle<ObjectTemplateInfo> number_format_template =
409  I18N::GetTemplate(isolate);
410 
411  // Create an empty object wrapper.
412  Handle<JSObject> local_object;
414  isolate, local_object,
415  Execution::InstantiateObject(number_format_template));
416 
417  // Set number formatter as internal field of the resulting JS object.
418  icu::DecimalFormat* number_format =
419  NumberFormat::InitializeNumberFormat(isolate, locale, options, resolved);
420 
421  if (!number_format) return isolate->ThrowIllegalOperation();
422 
423  local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
424 
425  Factory* factory = isolate->factory();
426  Handle<String> key = factory->NewStringFromStaticChars("numberFormat");
427  Handle<String> value = factory->NewStringFromStaticChars("valid");
428  JSObject::AddProperty(local_object, key, value, NONE);
429 
430  Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
431  GlobalHandles::MakeWeak(wrapper.location(),
432  reinterpret_cast<void*>(wrapper.location()),
434  return *local_object;
435 }
436 
437 
438 RUNTIME_FUNCTION(Runtime_InternalNumberFormat) {
439  HandleScope scope(isolate);
440 
441  DCHECK(args.length() == 2);
442 
443  CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
445 
446  Handle<Object> value;
447  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
448  Execution::ToNumber(isolate, number));
449 
450  icu::DecimalFormat* number_format =
451  NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
452  if (!number_format) return isolate->ThrowIllegalOperation();
453 
454  icu::UnicodeString result;
455  number_format->format(value->Number(), result);
456 
457  Handle<String> result_str;
459  isolate, result_str,
460  isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
461  reinterpret_cast<const uint16_t*>(result.getBuffer()),
462  result.length())));
463  return *result_str;
464 }
465 
466 
467 RUNTIME_FUNCTION(Runtime_InternalNumberParse) {
468  HandleScope scope(isolate);
469 
470  DCHECK(args.length() == 2);
471 
472  CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
473  CONVERT_ARG_HANDLE_CHECKED(String, number_string, 1);
474 
475  v8::String::Utf8Value utf8_number(v8::Utils::ToLocal(number_string));
476  icu::UnicodeString u_number(icu::UnicodeString::fromUTF8(*utf8_number));
477  icu::DecimalFormat* number_format =
478  NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
479  if (!number_format) return isolate->ThrowIllegalOperation();
480 
481  UErrorCode status = U_ZERO_ERROR;
482  icu::Formattable result;
483  // ICU 4.6 doesn't support parseCurrency call. We need to wait for ICU49
484  // to be part of Chrome.
485  // TODO(cira): Include currency parsing code using parseCurrency call.
486  // We need to check if the formatter parses all currencies or only the
487  // one it was constructed with (it will impact the API - how to return ISO
488  // code and the value).
489  number_format->parse(u_number, result, status);
490  if (U_FAILURE(status)) return isolate->heap()->undefined_value();
491 
492  switch (result.getType()) {
493  case icu::Formattable::kDouble:
494  return *isolate->factory()->NewNumber(result.getDouble());
495  case icu::Formattable::kLong:
496  return *isolate->factory()->NewNumberFromInt(result.getLong());
497  case icu::Formattable::kInt64:
498  return *isolate->factory()->NewNumber(
499  static_cast<double>(result.getInt64()));
500  default:
501  return isolate->heap()->undefined_value();
502  }
503 }
504 
505 
506 RUNTIME_FUNCTION(Runtime_CreateCollator) {
507  HandleScope scope(isolate);
508 
509  DCHECK(args.length() == 3);
510 
511  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
512  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
513  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
514 
515  Handle<ObjectTemplateInfo> collator_template = I18N::GetTemplate(isolate);
516 
517  // Create an empty object wrapper.
518  Handle<JSObject> local_object;
520  isolate, local_object, Execution::InstantiateObject(collator_template));
521 
522  // Set collator as internal field of the resulting JS object.
523  icu::Collator* collator =
524  Collator::InitializeCollator(isolate, locale, options, resolved);
525 
526  if (!collator) return isolate->ThrowIllegalOperation();
527 
528  local_object->SetInternalField(0, reinterpret_cast<Smi*>(collator));
529 
530  Factory* factory = isolate->factory();
531  Handle<String> key = factory->NewStringFromStaticChars("collator");
532  Handle<String> value = factory->NewStringFromStaticChars("valid");
533  JSObject::AddProperty(local_object, key, value, NONE);
534 
535  Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
536  GlobalHandles::MakeWeak(wrapper.location(),
537  reinterpret_cast<void*>(wrapper.location()),
539  return *local_object;
540 }
541 
542 
543 RUNTIME_FUNCTION(Runtime_InternalCompare) {
544  HandleScope scope(isolate);
545 
546  DCHECK(args.length() == 3);
547 
548  CONVERT_ARG_HANDLE_CHECKED(JSObject, collator_holder, 0);
549  CONVERT_ARG_HANDLE_CHECKED(String, string1, 1);
550  CONVERT_ARG_HANDLE_CHECKED(String, string2, 2);
551 
552  icu::Collator* collator = Collator::UnpackCollator(isolate, collator_holder);
553  if (!collator) return isolate->ThrowIllegalOperation();
554 
555  v8::String::Value string_value1(v8::Utils::ToLocal(string1));
556  v8::String::Value string_value2(v8::Utils::ToLocal(string2));
557  const UChar* u_string1 = reinterpret_cast<const UChar*>(*string_value1);
558  const UChar* u_string2 = reinterpret_cast<const UChar*>(*string_value2);
559  UErrorCode status = U_ZERO_ERROR;
560  UCollationResult result =
561  collator->compare(u_string1, string_value1.length(), u_string2,
562  string_value2.length(), status);
563  if (U_FAILURE(status)) return isolate->ThrowIllegalOperation();
564 
565  return *isolate->factory()->NewNumberFromInt(result);
566 }
567 
568 
569 RUNTIME_FUNCTION(Runtime_StringNormalize) {
570  HandleScope scope(isolate);
571  static const UNormalizationMode normalizationForms[] = {
572  UNORM_NFC, UNORM_NFD, UNORM_NFKC, UNORM_NFKD};
573 
574  DCHECK(args.length() == 2);
575 
576  CONVERT_ARG_HANDLE_CHECKED(String, stringValue, 0);
577  CONVERT_NUMBER_CHECKED(int, form_id, Int32, args[1]);
578  RUNTIME_ASSERT(form_id >= 0 &&
579  static_cast<size_t>(form_id) < arraysize(normalizationForms));
580 
581  v8::String::Value string_value(v8::Utils::ToLocal(stringValue));
582  const UChar* u_value = reinterpret_cast<const UChar*>(*string_value);
583 
584  // TODO(mnita): check Normalizer2 (not available in ICU 46)
585  UErrorCode status = U_ZERO_ERROR;
586  icu::UnicodeString result;
587  icu::Normalizer::normalize(u_value, normalizationForms[form_id], 0, result,
588  status);
589  if (U_FAILURE(status)) {
590  return isolate->heap()->undefined_value();
591  }
592 
593  Handle<String> result_str;
595  isolate, result_str,
596  isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
597  reinterpret_cast<const uint16_t*>(result.getBuffer()),
598  result.length())));
599  return *result_str;
600 }
601 
602 
603 RUNTIME_FUNCTION(Runtime_CreateBreakIterator) {
604  HandleScope scope(isolate);
605 
606  DCHECK(args.length() == 3);
607 
608  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
609  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
610  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
611 
612  Handle<ObjectTemplateInfo> break_iterator_template =
613  I18N::GetTemplate2(isolate);
614 
615  // Create an empty object wrapper.
616  Handle<JSObject> local_object;
618  isolate, local_object,
619  Execution::InstantiateObject(break_iterator_template));
620 
621  // Set break iterator as internal field of the resulting JS object.
622  icu::BreakIterator* break_iterator = BreakIterator::InitializeBreakIterator(
623  isolate, locale, options, resolved);
624 
625  if (!break_iterator) return isolate->ThrowIllegalOperation();
626 
627  local_object->SetInternalField(0, reinterpret_cast<Smi*>(break_iterator));
628  // Make sure that the pointer to adopted text is NULL.
629  local_object->SetInternalField(1, reinterpret_cast<Smi*>(NULL));
630 
631  Factory* factory = isolate->factory();
632  Handle<String> key = factory->NewStringFromStaticChars("breakIterator");
633  Handle<String> value = factory->NewStringFromStaticChars("valid");
634  JSObject::AddProperty(local_object, key, value, NONE);
635 
636  // Make object handle weak so we can delete the break iterator once GC kicks
637  // in.
638  Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
639  GlobalHandles::MakeWeak(wrapper.location(),
640  reinterpret_cast<void*>(wrapper.location()),
642  return *local_object;
643 }
644 
645 
646 RUNTIME_FUNCTION(Runtime_BreakIteratorAdoptText) {
647  HandleScope scope(isolate);
648 
649  DCHECK(args.length() == 2);
650 
651  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
652  CONVERT_ARG_HANDLE_CHECKED(String, text, 1);
653 
654  icu::BreakIterator* break_iterator =
655  BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
656  if (!break_iterator) return isolate->ThrowIllegalOperation();
657 
658  icu::UnicodeString* u_text = reinterpret_cast<icu::UnicodeString*>(
659  break_iterator_holder->GetInternalField(1));
660  delete u_text;
661 
662  v8::String::Value text_value(v8::Utils::ToLocal(text));
663  u_text = new icu::UnicodeString(reinterpret_cast<const UChar*>(*text_value),
664  text_value.length());
665  break_iterator_holder->SetInternalField(1, reinterpret_cast<Smi*>(u_text));
666 
667  break_iterator->setText(*u_text);
668 
669  return isolate->heap()->undefined_value();
670 }
671 
672 
673 RUNTIME_FUNCTION(Runtime_BreakIteratorFirst) {
674  HandleScope scope(isolate);
675 
676  DCHECK(args.length() == 1);
677 
678  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
679 
680  icu::BreakIterator* break_iterator =
681  BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
682  if (!break_iterator) return isolate->ThrowIllegalOperation();
683 
684  return *isolate->factory()->NewNumberFromInt(break_iterator->first());
685 }
686 
687 
688 RUNTIME_FUNCTION(Runtime_BreakIteratorNext) {
689  HandleScope scope(isolate);
690 
691  DCHECK(args.length() == 1);
692 
693  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
694 
695  icu::BreakIterator* break_iterator =
696  BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
697  if (!break_iterator) return isolate->ThrowIllegalOperation();
698 
699  return *isolate->factory()->NewNumberFromInt(break_iterator->next());
700 }
701 
702 
703 RUNTIME_FUNCTION(Runtime_BreakIteratorCurrent) {
704  HandleScope scope(isolate);
705 
706  DCHECK(args.length() == 1);
707 
708  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
709 
710  icu::BreakIterator* break_iterator =
711  BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
712  if (!break_iterator) return isolate->ThrowIllegalOperation();
713 
714  return *isolate->factory()->NewNumberFromInt(break_iterator->current());
715 }
716 
717 
718 RUNTIME_FUNCTION(Runtime_BreakIteratorBreakType) {
719  HandleScope scope(isolate);
720 
721  DCHECK(args.length() == 1);
722 
723  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
724 
725  icu::BreakIterator* break_iterator =
726  BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
727  if (!break_iterator) return isolate->ThrowIllegalOperation();
728 
729  // TODO(cira): Remove cast once ICU fixes base BreakIterator class.
730  icu::RuleBasedBreakIterator* rule_based_iterator =
731  static_cast<icu::RuleBasedBreakIterator*>(break_iterator);
732  int32_t status = rule_based_iterator->getRuleStatus();
733  // Keep return values in sync with JavaScript BreakType enum.
734  if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
735  return *isolate->factory()->NewStringFromStaticChars("none");
736  } else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
737  return *isolate->factory()->number_string();
738  } else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
739  return *isolate->factory()->NewStringFromStaticChars("letter");
740  } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
741  return *isolate->factory()->NewStringFromStaticChars("kana");
742  } else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
743  return *isolate->factory()->NewStringFromStaticChars("ideo");
744  } else {
745  return *isolate->factory()->NewStringFromStaticChars("unknown");
746  }
747 }
748 }
749 } // namespace v8::internal
750 
751 #endif // V8_I18N_SUPPORT
Converts an object to a UTF-8-encoded character array.
Definition: v8.h:2048
Converts an object to a two-byte string.
Definition: v8.h:2070
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
static icu::BreakIterator * UnpackBreakIterator(Isolate *isolate, Handle< JSObject > obj)
Definition: i18n.cc:911
static icu::BreakIterator * InitializeBreakIterator(Isolate *isolate, Handle< String > locale, Handle< JSObject > options, Handle< JSObject > resolved)
Definition: i18n.cc:871
static void DeleteBreakIterator(const v8::WeakCallbackData< v8::Value, void > &data)
Definition: i18n.cc:925
static icu::Collator * UnpackCollator(Isolate *isolate, Handle< JSObject > obj)
Definition: i18n.cc:851
static void DeleteCollator(const v8::WeakCallbackData< v8::Value, void > &data)
Definition: i18n.cc:864
static icu::Collator * InitializeCollator(Isolate *isolate, Handle< String > locale, Handle< JSObject > options, Handle< JSObject > resolved)
Definition: i18n.cc:814
static icu::SimpleDateFormat * UnpackDateFormat(Isolate *isolate, Handle< JSObject > obj)
Definition: i18n.cc:716
static void DeleteDateFormat(const v8::WeakCallbackData< v8::Value, void > &data)
Definition: i18n.cc:746
static icu::SimpleDateFormat * InitializeDateTimeFormat(Isolate *isolate, Handle< String > locale, Handle< JSObject > options, Handle< JSObject > resolved)
Definition: i18n.cc:678
static void MakeWeak(Object **location, void *parameter, WeakCallback weak_callback)
static Handle< T > cast(Handle< S > that)
Definition: handles.h:116
static Handle< ObjectTemplateInfo > GetTemplate(Isolate *isolate)
Definition: i18n.cc:666
static Handle< ObjectTemplateInfo > GetTemplate2(Isolate *isolate)
Definition: i18n.cc:672
static Handle< Object > SetHiddenProperty(Handle< JSObject > object, Handle< Name > key, Handle< Object > value)
Definition: objects.cc:4627
static void AddProperty(Handle< JSObject > object, Handle< Name > key, Handle< Object > value, PropertyAttributes attributes)
Definition: objects.cc:3786
static MUST_USE_RESULT MaybeHandle< Object > SetOwnPropertyIgnoreAttributes(Handle< JSObject > object, Handle< Name > key, Handle< Object > value, PropertyAttributes attributes, ExecutableAccessorInfoHandling handling=DEFAULT_HANDLING)
Definition: objects.cc:3808
static icu::DecimalFormat * InitializeNumberFormat(Isolate *isolate, Handle< String > locale, Handle< JSObject > options, Handle< JSObject > resolved)
Definition: i18n.cc:753
static icu::DecimalFormat * UnpackNumberFormat(Isolate *isolate, Handle< JSObject > obj)
Definition: i18n.cc:792
static void DeleteNumberFormat(const v8::WeakCallbackData< v8::Value, void > &data)
Definition: i18n.cc:807
static MUST_USE_RESULT MaybeHandle< Object > GetElement(Isolate *isolate, Handle< Object > object, uint32_t index)
Definition: objects-inl.h:1113
static Smi * FromInt(int value)
Definition: objects-inl.h:1321
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)
Definition: isolate.h:131
#define THROW_NEW_ERROR_RETURN_FAILURE(isolate, call)
Definition: isolate.h:146
#define RETURN_FAILURE_ON_EXCEPTION(isolate, call)
Definition: isolate.h:162
#define DCHECK(condition)
Definition: logging.h:205
#define arraysize(array)
Definition: macros.h:86
unsigned short uint16_t
Definition: unicode.cc:23
int int32_t
Definition: unicode.cc:24
Vector< const char > CStrVector(const char *data)
Definition: vector.h:158
int ToNumber(Register reg)
kSerializedDataOffset Object
Definition: objects-inl.h:5322
Vector< Handle< Object > > HandleVector(v8::internal::Handle< T > *elms, int length)
Definition: utils.h:1100
@ RUNTIME_FUNCTION
Definition: serialize.h:23
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
@ NONE
#define RUNTIME_ASSERT(value)
Definition: runtime-utils.h:12
#define CONVERT_ARG_HANDLE_CHECKED(Type, name, index)
Definition: runtime-utils.h:28
#define CONVERT_NUMBER_CHECKED(type, name, Type, obj)
Definition: runtime-utils.h:60