V8 Project
i18n.cc
Go to the documentation of this file.
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
3 // found in the LICENSE file.
4 // limitations under the License.
5 
6 #include "src/i18n.h"
7 
8 #include "unicode/brkiter.h"
9 #include "unicode/calendar.h"
10 #include "unicode/coll.h"
11 #include "unicode/curramt.h"
12 #include "unicode/dcfmtsym.h"
13 #include "unicode/decimfmt.h"
14 #include "unicode/dtfmtsym.h"
15 #include "unicode/dtptngen.h"
16 #include "unicode/locid.h"
17 #include "unicode/numfmt.h"
18 #include "unicode/numsys.h"
19 #include "unicode/rbbi.h"
20 #include "unicode/smpdtfmt.h"
21 #include "unicode/timezone.h"
22 #include "unicode/uchar.h"
23 #include "unicode/ucol.h"
24 #include "unicode/ucurr.h"
25 #include "unicode/unum.h"
26 #include "unicode/uversion.h"
27 
28 namespace v8 {
29 namespace internal {
30 
31 namespace {
32 
34  Handle<JSObject> options,
35  const char* key,
36  icu::UnicodeString* setting) {
37  Handle<String> str = isolate->factory()->NewStringFromAsciiChecked(key);
38  Handle<Object> object = Object::GetProperty(options, str).ToHandleChecked();
39  if (object->IsString()) {
40  v8::String::Utf8Value utf8_string(
42  *setting = icu::UnicodeString::fromUTF8(*utf8_string);
43  return true;
44  }
45  return false;
46 }
47 
48 
50  Handle<JSObject> options,
51  const char* key,
52  int32_t* value) {
53  Handle<String> str = isolate->factory()->NewStringFromAsciiChecked(key);
54  Handle<Object> object = Object::GetProperty(options, str).ToHandleChecked();
55  if (object->IsNumber()) {
56  object->ToInt32(value);
57  return true;
58  }
59  return false;
60 }
61 
62 
64  Handle<JSObject> options,
65  const char* key,
66  bool* value) {
67  Handle<String> str = isolate->factory()->NewStringFromAsciiChecked(key);
68  Handle<Object> object = Object::GetProperty(options, str).ToHandleChecked();
69  if (object->IsBoolean()) {
70  *value = object->BooleanValue();
71  return true;
72  }
73  return false;
74 }
75 
76 
77 icu::SimpleDateFormat* CreateICUDateFormat(
78  Isolate* isolate,
79  const icu::Locale& icu_locale,
80  Handle<JSObject> options) {
81  // Create time zone as specified by the user. We have to re-create time zone
82  // since calendar takes ownership.
83  icu::TimeZone* tz = NULL;
84  icu::UnicodeString timezone;
85  if (ExtractStringSetting(isolate, options, "timeZone", &timezone)) {
86  tz = icu::TimeZone::createTimeZone(timezone);
87  } else {
88  tz = icu::TimeZone::createDefault();
89  }
90 
91  // Create a calendar using locale, and apply time zone to it.
92  UErrorCode status = U_ZERO_ERROR;
93  icu::Calendar* calendar =
94  icu::Calendar::createInstance(tz, icu_locale, status);
95 
96  // Make formatter from skeleton. Calendar and numbering system are added
97  // to the locale as Unicode extension (if they were specified at all).
98  icu::SimpleDateFormat* date_format = NULL;
99  icu::UnicodeString skeleton;
100  if (ExtractStringSetting(isolate, options, "skeleton", &skeleton)) {
101  icu::DateTimePatternGenerator* generator =
102  icu::DateTimePatternGenerator::createInstance(icu_locale, status);
103  icu::UnicodeString pattern;
104  if (U_SUCCESS(status)) {
105  pattern = generator->getBestPattern(skeleton, status);
106  delete generator;
107  }
108 
109  date_format = new icu::SimpleDateFormat(pattern, icu_locale, status);
110  if (U_SUCCESS(status)) {
111  date_format->adoptCalendar(calendar);
112  }
113  }
114 
115  if (U_FAILURE(status)) {
116  delete calendar;
117  delete date_format;
118  date_format = NULL;
119  }
120 
121  return date_format;
122 }
123 
124 
126  const icu::Locale& icu_locale,
127  icu::SimpleDateFormat* date_format,
128  Handle<JSObject> resolved) {
129  Factory* factory = isolate->factory();
130  UErrorCode status = U_ZERO_ERROR;
131  icu::UnicodeString pattern;
132  date_format->toPattern(pattern);
134  resolved, factory->NewStringFromStaticChars("pattern"),
135  factory->NewStringFromTwoByte(
137  reinterpret_cast<const uint16_t*>(pattern.getBuffer()),
138  pattern.length())).ToHandleChecked(),
139  SLOPPY).Assert();
140 
141  // Set time zone and calendar.
142  const icu::Calendar* calendar = date_format->getCalendar();
143  const char* calendar_name = calendar->getType();
144  JSObject::SetProperty(resolved, factory->NewStringFromStaticChars("calendar"),
145  factory->NewStringFromAsciiChecked(calendar_name),
146  SLOPPY).Assert();
147 
148  const icu::TimeZone& tz = calendar->getTimeZone();
149  icu::UnicodeString time_zone;
150  tz.getID(time_zone);
151 
152  icu::UnicodeString canonical_time_zone;
153  icu::TimeZone::getCanonicalID(time_zone, canonical_time_zone, status);
154  if (U_SUCCESS(status)) {
155  if (canonical_time_zone == UNICODE_STRING_SIMPLE("Etc/GMT")) {
157  resolved, factory->NewStringFromStaticChars("timeZone"),
158  factory->NewStringFromStaticChars("UTC"), SLOPPY).Assert();
159  } else {
161  resolved, factory->NewStringFromStaticChars("timeZone"),
162  factory->NewStringFromTwoByte(
164  reinterpret_cast<const uint16_t*>(
165  canonical_time_zone.getBuffer()),
166  canonical_time_zone.length())).ToHandleChecked(),
167  SLOPPY).Assert();
168  }
169  }
170 
171  // Ugly hack. ICU doesn't expose numbering system in any way, so we have
172  // to assume that for given locale NumberingSystem constructor produces the
173  // same digits as NumberFormat/Calendar would.
174  status = U_ZERO_ERROR;
175  icu::NumberingSystem* numbering_system =
176  icu::NumberingSystem::createInstance(icu_locale, status);
177  if (U_SUCCESS(status)) {
178  const char* ns = numbering_system->getName();
180  resolved, factory->NewStringFromStaticChars("numberingSystem"),
181  factory->NewStringFromAsciiChecked(ns), SLOPPY).Assert();
182  } else {
183  JSObject::SetProperty(resolved,
184  factory->NewStringFromStaticChars("numberingSystem"),
185  factory->undefined_value(), SLOPPY).Assert();
186  }
187  delete numbering_system;
188 
189  // Set the locale
190  char result[ULOC_FULLNAME_CAPACITY];
191  status = U_ZERO_ERROR;
192  uloc_toLanguageTag(
193  icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
194  if (U_SUCCESS(status)) {
195  JSObject::SetProperty(resolved, factory->NewStringFromStaticChars("locale"),
196  factory->NewStringFromAsciiChecked(result),
197  SLOPPY).Assert();
198  } else {
199  // This would never happen, since we got the locale from ICU.
200  JSObject::SetProperty(resolved, factory->NewStringFromStaticChars("locale"),
201  factory->NewStringFromStaticChars("und"),
202  SLOPPY).Assert();
203  }
204 }
205 
206 
207 template<int internal_fields, EternalHandles::SingletonHandle field>
209  if (isolate->eternal_handles()->Exists(field)) {
211  isolate->eternal_handles()->GetSingleton(field));
212  }
213  v8::Local<v8::ObjectTemplate> raw_template =
214  v8::ObjectTemplate::New(reinterpret_cast<v8::Isolate*>(isolate));
215  raw_template->SetInternalFieldCount(internal_fields);
217  isolate->eternal_handles()->CreateSingleton(
218  isolate,
219  *v8::Utils::OpenHandle(*raw_template),
220  field));
221 }
222 
223 
224 icu::DecimalFormat* CreateICUNumberFormat(
225  Isolate* isolate,
226  const icu::Locale& icu_locale,
227  Handle<JSObject> options) {
228  // Make formatter from options. Numbering system is added
229  // to the locale as Unicode extension (if it was specified at all).
230  UErrorCode status = U_ZERO_ERROR;
231  icu::DecimalFormat* number_format = NULL;
232  icu::UnicodeString style;
233  icu::UnicodeString currency;
234  if (ExtractStringSetting(isolate, options, "style", &style)) {
235  if (style == UNICODE_STRING_SIMPLE("currency")) {
236  icu::UnicodeString display;
237  ExtractStringSetting(isolate, options, "currency", &currency);
238  ExtractStringSetting(isolate, options, "currencyDisplay", &display);
239 
240 #if (U_ICU_VERSION_MAJOR_NUM == 4) && (U_ICU_VERSION_MINOR_NUM <= 6)
241  icu::NumberFormat::EStyles format_style;
242  if (display == UNICODE_STRING_SIMPLE("code")) {
243  format_style = icu::NumberFormat::kIsoCurrencyStyle;
244  } else if (display == UNICODE_STRING_SIMPLE("name")) {
245  format_style = icu::NumberFormat::kPluralCurrencyStyle;
246  } else {
247  format_style = icu::NumberFormat::kCurrencyStyle;
248  }
249 #else // ICU version is 4.8 or above (we ignore versions below 4.0).
250  UNumberFormatStyle format_style;
251  if (display == UNICODE_STRING_SIMPLE("code")) {
252  format_style = UNUM_CURRENCY_ISO;
253  } else if (display == UNICODE_STRING_SIMPLE("name")) {
254  format_style = UNUM_CURRENCY_PLURAL;
255  } else {
256  format_style = UNUM_CURRENCY;
257  }
258 #endif
259 
260  number_format = static_cast<icu::DecimalFormat*>(
261  icu::NumberFormat::createInstance(icu_locale, format_style, status));
262  } else if (style == UNICODE_STRING_SIMPLE("percent")) {
263  number_format = static_cast<icu::DecimalFormat*>(
264  icu::NumberFormat::createPercentInstance(icu_locale, status));
265  if (U_FAILURE(status)) {
266  delete number_format;
267  return NULL;
268  }
269  // Make sure 1.1% doesn't go into 2%.
270  number_format->setMinimumFractionDigits(1);
271  } else {
272  // Make a decimal instance by default.
273  number_format = static_cast<icu::DecimalFormat*>(
274  icu::NumberFormat::createInstance(icu_locale, status));
275  }
276  }
277 
278  if (U_FAILURE(status)) {
279  delete number_format;
280  return NULL;
281  }
282 
283  // Set all options.
284  if (!currency.isEmpty()) {
285  number_format->setCurrency(currency.getBuffer(), status);
286  }
287 
288  int32_t digits;
290  isolate, options, "minimumIntegerDigits", &digits)) {
291  number_format->setMinimumIntegerDigits(digits);
292  }
293 
295  isolate, options, "minimumFractionDigits", &digits)) {
296  number_format->setMinimumFractionDigits(digits);
297  }
298 
300  isolate, options, "maximumFractionDigits", &digits)) {
301  number_format->setMaximumFractionDigits(digits);
302  }
303 
304  bool significant_digits_used = false;
306  isolate, options, "minimumSignificantDigits", &digits)) {
307  number_format->setMinimumSignificantDigits(digits);
308  significant_digits_used = true;
309  }
310 
312  isolate, options, "maximumSignificantDigits", &digits)) {
313  number_format->setMaximumSignificantDigits(digits);
314  significant_digits_used = true;
315  }
316 
317  number_format->setSignificantDigitsUsed(significant_digits_used);
318 
319  bool grouping;
320  if (ExtractBooleanSetting(isolate, options, "useGrouping", &grouping)) {
321  number_format->setGroupingUsed(grouping);
322  }
323 
324  // Set rounding mode.
325  number_format->setRoundingMode(icu::DecimalFormat::kRoundHalfUp);
326 
327  return number_format;
328 }
329 
330 
332  const icu::Locale& icu_locale,
333  icu::DecimalFormat* number_format,
334  Handle<JSObject> resolved) {
335  Factory* factory = isolate->factory();
336  icu::UnicodeString pattern;
337  number_format->toPattern(pattern);
339  resolved, factory->NewStringFromStaticChars("pattern"),
340  factory->NewStringFromTwoByte(
342  reinterpret_cast<const uint16_t*>(pattern.getBuffer()),
343  pattern.length())).ToHandleChecked(),
344  SLOPPY).Assert();
345 
346  // Set resolved currency code in options.currency if not empty.
347  icu::UnicodeString currency(number_format->getCurrency());
348  if (!currency.isEmpty()) {
350  resolved, factory->NewStringFromStaticChars("currency"),
351  factory->NewStringFromTwoByte(Vector<const uint16_t>(
352  reinterpret_cast<const uint16_t*>(
353  currency.getBuffer()),
354  currency.length())).ToHandleChecked(),
355  SLOPPY).Assert();
356  }
357 
358  // Ugly hack. ICU doesn't expose numbering system in any way, so we have
359  // to assume that for given locale NumberingSystem constructor produces the
360  // same digits as NumberFormat/Calendar would.
361  UErrorCode status = U_ZERO_ERROR;
362  icu::NumberingSystem* numbering_system =
363  icu::NumberingSystem::createInstance(icu_locale, status);
364  if (U_SUCCESS(status)) {
365  const char* ns = numbering_system->getName();
367  resolved, factory->NewStringFromStaticChars("numberingSystem"),
368  factory->NewStringFromAsciiChecked(ns), SLOPPY).Assert();
369  } else {
370  JSObject::SetProperty(resolved,
371  factory->NewStringFromStaticChars("numberingSystem"),
372  factory->undefined_value(), SLOPPY).Assert();
373  }
374  delete numbering_system;
375 
377  resolved, factory->NewStringFromStaticChars("useGrouping"),
378  factory->ToBoolean(number_format->isGroupingUsed()), SLOPPY).Assert();
379 
381  resolved, factory->NewStringFromStaticChars("minimumIntegerDigits"),
382  factory->NewNumberFromInt(number_format->getMinimumIntegerDigits()),
383  SLOPPY).Assert();
384 
386  resolved, factory->NewStringFromStaticChars("minimumFractionDigits"),
387  factory->NewNumberFromInt(number_format->getMinimumFractionDigits()),
388  SLOPPY).Assert();
389 
391  resolved, factory->NewStringFromStaticChars("maximumFractionDigits"),
392  factory->NewNumberFromInt(number_format->getMaximumFractionDigits()),
393  SLOPPY).Assert();
394 
395  Handle<String> key =
396  factory->NewStringFromStaticChars("minimumSignificantDigits");
398  CHECK(maybe.has_value);
399  if (maybe.value) {
401  resolved, factory->NewStringFromStaticChars("minimumSignificantDigits"),
402  factory->NewNumberFromInt(number_format->getMinimumSignificantDigits()),
403  SLOPPY).Assert();
404  }
405 
406  key = factory->NewStringFromStaticChars("maximumSignificantDigits");
407  maybe = JSReceiver::HasOwnProperty(resolved, key);
408  CHECK(maybe.has_value);
409  if (maybe.value) {
411  resolved, factory->NewStringFromStaticChars("maximumSignificantDigits"),
412  factory->NewNumberFromInt(number_format->getMaximumSignificantDigits()),
413  SLOPPY).Assert();
414  }
415 
416  // Set the locale
417  char result[ULOC_FULLNAME_CAPACITY];
418  status = U_ZERO_ERROR;
419  uloc_toLanguageTag(
420  icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
421  if (U_SUCCESS(status)) {
422  JSObject::SetProperty(resolved, factory->NewStringFromStaticChars("locale"),
423  factory->NewStringFromAsciiChecked(result),
424  SLOPPY).Assert();
425  } else {
426  // This would never happen, since we got the locale from ICU.
427  JSObject::SetProperty(resolved, factory->NewStringFromStaticChars("locale"),
428  factory->NewStringFromStaticChars("und"),
429  SLOPPY).Assert();
430  }
431 }
432 
433 
434 icu::Collator* CreateICUCollator(
435  Isolate* isolate,
436  const icu::Locale& icu_locale,
437  Handle<JSObject> options) {
438  // Make collator from options.
439  icu::Collator* collator = NULL;
440  UErrorCode status = U_ZERO_ERROR;
441  collator = icu::Collator::createInstance(icu_locale, status);
442 
443  if (U_FAILURE(status)) {
444  delete collator;
445  return NULL;
446  }
447 
448  // Set flags first, and then override them with sensitivity if necessary.
449  bool numeric;
450  if (ExtractBooleanSetting(isolate, options, "numeric", &numeric)) {
451  collator->setAttribute(
452  UCOL_NUMERIC_COLLATION, numeric ? UCOL_ON : UCOL_OFF, status);
453  }
454 
455  // Normalization is always on, by the spec. We are free to optimize
456  // if the strings are already normalized (but we don't have a way to tell
457  // that right now).
458  collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
459 
460  icu::UnicodeString case_first;
461  if (ExtractStringSetting(isolate, options, "caseFirst", &case_first)) {
462  if (case_first == UNICODE_STRING_SIMPLE("upper")) {
463  collator->setAttribute(UCOL_CASE_FIRST, UCOL_UPPER_FIRST, status);
464  } else if (case_first == UNICODE_STRING_SIMPLE("lower")) {
465  collator->setAttribute(UCOL_CASE_FIRST, UCOL_LOWER_FIRST, status);
466  } else {
467  // Default (false/off).
468  collator->setAttribute(UCOL_CASE_FIRST, UCOL_OFF, status);
469  }
470  }
471 
472  icu::UnicodeString sensitivity;
473  if (ExtractStringSetting(isolate, options, "sensitivity", &sensitivity)) {
474  if (sensitivity == UNICODE_STRING_SIMPLE("base")) {
475  collator->setStrength(icu::Collator::PRIMARY);
476  } else if (sensitivity == UNICODE_STRING_SIMPLE("accent")) {
477  collator->setStrength(icu::Collator::SECONDARY);
478  } else if (sensitivity == UNICODE_STRING_SIMPLE("case")) {
479  collator->setStrength(icu::Collator::PRIMARY);
480  collator->setAttribute(UCOL_CASE_LEVEL, UCOL_ON, status);
481  } else {
482  // variant (default)
483  collator->setStrength(icu::Collator::TERTIARY);
484  }
485  }
486 
487  bool ignore;
488  if (ExtractBooleanSetting(isolate, options, "ignorePunctuation", &ignore)) {
489  if (ignore) {
490  collator->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, status);
491  }
492  }
493 
494  return collator;
495 }
496 
497 
499  const icu::Locale& icu_locale,
500  icu::Collator* collator,
501  Handle<JSObject> resolved) {
502  Factory* factory = isolate->factory();
503  UErrorCode status = U_ZERO_ERROR;
504 
506  resolved, factory->NewStringFromStaticChars("numeric"),
507  factory->ToBoolean(
508  collator->getAttribute(UCOL_NUMERIC_COLLATION, status) == UCOL_ON),
509  SLOPPY).Assert();
510 
511  switch (collator->getAttribute(UCOL_CASE_FIRST, status)) {
512  case UCOL_LOWER_FIRST:
514  resolved, factory->NewStringFromStaticChars("caseFirst"),
515  factory->NewStringFromStaticChars("lower"), SLOPPY).Assert();
516  break;
517  case UCOL_UPPER_FIRST:
519  resolved, factory->NewStringFromStaticChars("caseFirst"),
520  factory->NewStringFromStaticChars("upper"), SLOPPY).Assert();
521  break;
522  default:
524  resolved, factory->NewStringFromStaticChars("caseFirst"),
525  factory->NewStringFromStaticChars("false"), SLOPPY).Assert();
526  }
527 
528  switch (collator->getAttribute(UCOL_STRENGTH, status)) {
529  case UCOL_PRIMARY: {
531  resolved, factory->NewStringFromStaticChars("strength"),
532  factory->NewStringFromStaticChars("primary"), SLOPPY).Assert();
533 
534  // case level: true + s1 -> case, s1 -> base.
535  if (UCOL_ON == collator->getAttribute(UCOL_CASE_LEVEL, status)) {
537  resolved, factory->NewStringFromStaticChars("sensitivity"),
538  factory->NewStringFromStaticChars("case"), SLOPPY).Assert();
539  } else {
541  resolved, factory->NewStringFromStaticChars("sensitivity"),
542  factory->NewStringFromStaticChars("base"), SLOPPY).Assert();
543  }
544  break;
545  }
546  case UCOL_SECONDARY:
548  resolved, factory->NewStringFromStaticChars("strength"),
549  factory->NewStringFromStaticChars("secondary"), SLOPPY).Assert();
551  resolved, factory->NewStringFromStaticChars("sensitivity"),
552  factory->NewStringFromStaticChars("accent"), SLOPPY).Assert();
553  break;
554  case UCOL_TERTIARY:
556  resolved, factory->NewStringFromStaticChars("strength"),
557  factory->NewStringFromStaticChars("tertiary"), SLOPPY).Assert();
559  resolved, factory->NewStringFromStaticChars("sensitivity"),
560  factory->NewStringFromStaticChars("variant"), SLOPPY).Assert();
561  break;
562  case UCOL_QUATERNARY:
563  // We shouldn't get quaternary and identical from ICU, but if we do
564  // put them into variant.
566  resolved, factory->NewStringFromStaticChars("strength"),
567  factory->NewStringFromStaticChars("quaternary"), SLOPPY).Assert();
569  resolved, factory->NewStringFromStaticChars("sensitivity"),
570  factory->NewStringFromStaticChars("variant"), SLOPPY).Assert();
571  break;
572  default:
574  resolved, factory->NewStringFromStaticChars("strength"),
575  factory->NewStringFromStaticChars("identical"), SLOPPY).Assert();
577  resolved, factory->NewStringFromStaticChars("sensitivity"),
578  factory->NewStringFromStaticChars("variant"), SLOPPY).Assert();
579  }
580 
582  resolved, factory->NewStringFromStaticChars("ignorePunctuation"),
583  factory->ToBoolean(collator->getAttribute(UCOL_ALTERNATE_HANDLING,
584  status) == UCOL_SHIFTED),
585  SLOPPY).Assert();
586 
587  // Set the locale
588  char result[ULOC_FULLNAME_CAPACITY];
589  status = U_ZERO_ERROR;
590  uloc_toLanguageTag(
591  icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
592  if (U_SUCCESS(status)) {
593  JSObject::SetProperty(resolved, factory->NewStringFromStaticChars("locale"),
594  factory->NewStringFromAsciiChecked(result),
595  SLOPPY).Assert();
596  } else {
597  // This would never happen, since we got the locale from ICU.
598  JSObject::SetProperty(resolved, factory->NewStringFromStaticChars("locale"),
599  factory->NewStringFromStaticChars("und"),
600  SLOPPY).Assert();
601  }
602 }
603 
604 
605 icu::BreakIterator* CreateICUBreakIterator(
606  Isolate* isolate,
607  const icu::Locale& icu_locale,
608  Handle<JSObject> options) {
609  UErrorCode status = U_ZERO_ERROR;
610  icu::BreakIterator* break_iterator = NULL;
611  icu::UnicodeString type;
612  if (!ExtractStringSetting(isolate, options, "type", &type)) return NULL;
613 
614  if (type == UNICODE_STRING_SIMPLE("character")) {
615  break_iterator =
616  icu::BreakIterator::createCharacterInstance(icu_locale, status);
617  } else if (type == UNICODE_STRING_SIMPLE("sentence")) {
618  break_iterator =
619  icu::BreakIterator::createSentenceInstance(icu_locale, status);
620  } else if (type == UNICODE_STRING_SIMPLE("line")) {
621  break_iterator =
622  icu::BreakIterator::createLineInstance(icu_locale, status);
623  } else {
624  // Defualt is word iterator.
625  break_iterator =
626  icu::BreakIterator::createWordInstance(icu_locale, status);
627  }
628 
629  if (U_FAILURE(status)) {
630  delete break_iterator;
631  return NULL;
632  }
633 
634  return break_iterator;
635 }
636 
637 
639  const icu::Locale& icu_locale,
640  icu::BreakIterator* break_iterator,
641  Handle<JSObject> resolved) {
642  Factory* factory = isolate->factory();
643  UErrorCode status = U_ZERO_ERROR;
644 
645  // Set the locale
646  char result[ULOC_FULLNAME_CAPACITY];
647  status = U_ZERO_ERROR;
648  uloc_toLanguageTag(
649  icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
650  if (U_SUCCESS(status)) {
651  JSObject::SetProperty(resolved, factory->NewStringFromStaticChars("locale"),
652  factory->NewStringFromAsciiChecked(result),
653  SLOPPY).Assert();
654  } else {
655  // This would never happen, since we got the locale from ICU.
656  JSObject::SetProperty(resolved, factory->NewStringFromStaticChars("locale"),
657  factory->NewStringFromStaticChars("und"),
658  SLOPPY).Assert();
659  }
660 }
661 
662 } // namespace
663 
664 
665 // static
667  return GetEternal<1, i::EternalHandles::I18N_TEMPLATE_ONE>(isolate);
668 }
669 
670 
671 // static
673  return GetEternal<2, i::EternalHandles::I18N_TEMPLATE_TWO>(isolate);
674 }
675 
676 
677 // static
679  Isolate* isolate,
680  Handle<String> locale,
681  Handle<JSObject> options,
682  Handle<JSObject> resolved) {
683  // Convert BCP47 into ICU locale format.
684  UErrorCode status = U_ZERO_ERROR;
685  icu::Locale icu_locale;
686  char icu_result[ULOC_FULLNAME_CAPACITY];
687  int icu_length = 0;
688  v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
689  if (bcp47_locale.length() != 0) {
690  uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
691  &icu_length, &status);
692  if (U_FAILURE(status) || icu_length == 0) {
693  return NULL;
694  }
695  icu_locale = icu::Locale(icu_result);
696  }
697 
698  icu::SimpleDateFormat* date_format = CreateICUDateFormat(
699  isolate, icu_locale, options);
700  if (!date_format) {
701  // Remove extensions and try again.
702  icu::Locale no_extension_locale(icu_locale.getBaseName());
703  date_format = CreateICUDateFormat(isolate, no_extension_locale, options);
704 
705  // Set resolved settings (pattern, numbering system, calendar).
707  isolate, no_extension_locale, date_format, resolved);
708  } else {
709  SetResolvedDateSettings(isolate, icu_locale, date_format, resolved);
710  }
711 
712  return date_format;
713 }
714 
715 
716 icu::SimpleDateFormat* DateFormat::UnpackDateFormat(
717  Isolate* isolate,
718  Handle<JSObject> obj) {
719  Handle<String> key =
720  isolate->factory()->NewStringFromStaticChars("dateFormat");
722  CHECK(maybe.has_value);
723  if (maybe.value) {
724  return reinterpret_cast<icu::SimpleDateFormat*>(
725  obj->GetInternalField(0));
726  }
727 
728  return NULL;
729 }
730 
731 
732 template<class T>
734  int index) {
736  delete reinterpret_cast<T*>(obj->GetAlignedPointerFromInternalField(index));
737 }
738 
739 
742  GlobalHandles::Destroy(reinterpret_cast<Object**>(data.GetParameter()));
743 }
744 
745 
748  DeleteNativeObjectAt<icu::SimpleDateFormat>(data, 0);
749  DestroyGlobalHandle(data);
750 }
751 
752 
754  Isolate* isolate,
755  Handle<String> locale,
756  Handle<JSObject> options,
757  Handle<JSObject> resolved) {
758  // Convert BCP47 into ICU locale format.
759  UErrorCode status = U_ZERO_ERROR;
760  icu::Locale icu_locale;
761  char icu_result[ULOC_FULLNAME_CAPACITY];
762  int icu_length = 0;
763  v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
764  if (bcp47_locale.length() != 0) {
765  uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
766  &icu_length, &status);
767  if (U_FAILURE(status) || icu_length == 0) {
768  return NULL;
769  }
770  icu_locale = icu::Locale(icu_result);
771  }
772 
773  icu::DecimalFormat* number_format =
774  CreateICUNumberFormat(isolate, icu_locale, options);
775  if (!number_format) {
776  // Remove extensions and try again.
777  icu::Locale no_extension_locale(icu_locale.getBaseName());
778  number_format = CreateICUNumberFormat(
779  isolate, no_extension_locale, options);
780 
781  // Set resolved settings (pattern, numbering system).
783  isolate, no_extension_locale, number_format, resolved);
784  } else {
785  SetResolvedNumberSettings(isolate, icu_locale, number_format, resolved);
786  }
787 
788  return number_format;
789 }
790 
791 
793  Isolate* isolate,
794  Handle<JSObject> obj) {
795  Handle<String> key =
796  isolate->factory()->NewStringFromStaticChars("numberFormat");
798  CHECK(maybe.has_value);
799  if (maybe.value) {
800  return reinterpret_cast<icu::DecimalFormat*>(obj->GetInternalField(0));
801  }
802 
803  return NULL;
804 }
805 
806 
809  DeleteNativeObjectAt<icu::DecimalFormat>(data, 0);
810  DestroyGlobalHandle(data);
811 }
812 
813 
815  Isolate* isolate,
816  Handle<String> locale,
817  Handle<JSObject> options,
818  Handle<JSObject> resolved) {
819  // Convert BCP47 into ICU locale format.
820  UErrorCode status = U_ZERO_ERROR;
821  icu::Locale icu_locale;
822  char icu_result[ULOC_FULLNAME_CAPACITY];
823  int icu_length = 0;
824  v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
825  if (bcp47_locale.length() != 0) {
826  uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
827  &icu_length, &status);
828  if (U_FAILURE(status) || icu_length == 0) {
829  return NULL;
830  }
831  icu_locale = icu::Locale(icu_result);
832  }
833 
834  icu::Collator* collator = CreateICUCollator(isolate, icu_locale, options);
835  if (!collator) {
836  // Remove extensions and try again.
837  icu::Locale no_extension_locale(icu_locale.getBaseName());
838  collator = CreateICUCollator(isolate, no_extension_locale, options);
839 
840  // Set resolved settings (pattern, numbering system).
842  isolate, no_extension_locale, collator, resolved);
843  } else {
844  SetResolvedCollatorSettings(isolate, icu_locale, collator, resolved);
845  }
846 
847  return collator;
848 }
849 
850 
851 icu::Collator* Collator::UnpackCollator(Isolate* isolate,
852  Handle<JSObject> obj) {
853  Handle<String> key = isolate->factory()->NewStringFromStaticChars("collator");
855  CHECK(maybe.has_value);
856  if (maybe.value) {
857  return reinterpret_cast<icu::Collator*>(obj->GetInternalField(0));
858  }
859 
860  return NULL;
861 }
862 
863 
866  DeleteNativeObjectAt<icu::Collator>(data, 0);
867  DestroyGlobalHandle(data);
868 }
869 
870 
872  Isolate* isolate,
873  Handle<String> locale,
874  Handle<JSObject> options,
875  Handle<JSObject> resolved) {
876  // Convert BCP47 into ICU locale format.
877  UErrorCode status = U_ZERO_ERROR;
878  icu::Locale icu_locale;
879  char icu_result[ULOC_FULLNAME_CAPACITY];
880  int icu_length = 0;
881  v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
882  if (bcp47_locale.length() != 0) {
883  uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
884  &icu_length, &status);
885  if (U_FAILURE(status) || icu_length == 0) {
886  return NULL;
887  }
888  icu_locale = icu::Locale(icu_result);
889  }
890 
891  icu::BreakIterator* break_iterator = CreateICUBreakIterator(
892  isolate, icu_locale, options);
893  if (!break_iterator) {
894  // Remove extensions and try again.
895  icu::Locale no_extension_locale(icu_locale.getBaseName());
896  break_iterator = CreateICUBreakIterator(
897  isolate, no_extension_locale, options);
898 
899  // Set resolved settings (locale).
901  isolate, no_extension_locale, break_iterator, resolved);
902  } else {
904  isolate, icu_locale, break_iterator, resolved);
905  }
906 
907  return break_iterator;
908 }
909 
910 
911 icu::BreakIterator* BreakIterator::UnpackBreakIterator(Isolate* isolate,
912  Handle<JSObject> obj) {
913  Handle<String> key =
914  isolate->factory()->NewStringFromStaticChars("breakIterator");
916  CHECK(maybe.has_value);
917  if (maybe.value) {
918  return reinterpret_cast<icu::BreakIterator*>(obj->GetInternalField(0));
919  }
920 
921  return NULL;
922 }
923 
924 
927  DeleteNativeObjectAt<icu::BreakIterator>(data, 0);
928  DeleteNativeObjectAt<icu::UnicodeString>(data, 1);
929  DestroyGlobalHandle(data);
930 }
931 
932 } } // namespace v8::internal
static Handle< T > Cast(Handle< S > that)
Definition: v8.h:277
Isolate represents an isolated instance of the V8 engine.
Definition: v8.h:4356
A light-weight stack-allocated object handle.
Definition: v8.h:334
static Local< ObjectTemplate > New()
Definition: api.cc:1244
Converts an object to a UTF-8-encoded character array.
Definition: v8.h:2048
int length() const
Definition: v8.h:2054
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
Definition: api.h:288
P * GetParameter() const
Definition: v8.h:423
Local< T > GetValue() const
Definition: v8.h:422
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
bool Exists(SingletonHandle singleton)
Handle< Object > CreateSingleton(Isolate *isolate, Object *object, SingletonHandle singleton)
Handle< Object > GetSingleton(SingletonHandle singleton)
static void Destroy(Object **location)
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
EternalHandles * eternal_handles()
Definition: isolate.h:919
Factory * factory()
Definition: isolate.h:982
static MUST_USE_RESULT Maybe< bool > HasOwnProperty(Handle< JSReceiver >, Handle< Name > name)
Definition: objects-inl.h:6658
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 > GetProperty(LookupIterator *it)
Definition: objects.cc:109
static MUST_USE_RESULT MaybeHandle< Object > SetProperty(Handle< Object > object, Handle< Name > key, Handle< Object > value, StrictMode strict_mode, StoreFromKeyed store_mode=MAY_BE_STORE_FROM_KEYED)
Definition: objects.cc:2798
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 CHECK(condition)
Definition: logging.h:36
unsigned short uint16_t
Definition: unicode.cc:23
int int32_t
Definition: unicode.cc:24
bool ExtractStringSetting(Isolate *isolate, Handle< JSObject > options, const char *key, icu::UnicodeString *setting)
Definition: i18n.cc:33
void SetResolvedCollatorSettings(Isolate *isolate, const icu::Locale &icu_locale, icu::Collator *collator, Handle< JSObject > resolved)
Definition: i18n.cc:498
void SetResolvedBreakIteratorSettings(Isolate *isolate, const icu::Locale &icu_locale, icu::BreakIterator *break_iterator, Handle< JSObject > resolved)
Definition: i18n.cc:638
bool ExtractIntegerSetting(Isolate *isolate, Handle< JSObject > options, const char *key, int32_t *value)
Definition: i18n.cc:49
void SetResolvedNumberSettings(Isolate *isolate, const icu::Locale &icu_locale, icu::DecimalFormat *number_format, Handle< JSObject > resolved)
Definition: i18n.cc:331
icu::BreakIterator * CreateICUBreakIterator(Isolate *isolate, const icu::Locale &icu_locale, Handle< JSObject > options)
Definition: i18n.cc:605
void SetResolvedDateSettings(Isolate *isolate, const icu::Locale &icu_locale, icu::SimpleDateFormat *date_format, Handle< JSObject > resolved)
Definition: i18n.cc:125
icu::SimpleDateFormat * CreateICUDateFormat(Isolate *isolate, const icu::Locale &icu_locale, Handle< JSObject > options)
Definition: i18n.cc:77
icu::Collator * CreateICUCollator(Isolate *isolate, const icu::Locale &icu_locale, Handle< JSObject > options)
Definition: i18n.cc:434
Handle< ObjectTemplateInfo > GetEternal(Isolate *isolate)
Definition: i18n.cc:208
icu::DecimalFormat * CreateICUNumberFormat(Isolate *isolate, const icu::Locale &icu_locale, Handle< JSObject > options)
Definition: i18n.cc:224
bool ExtractBooleanSetting(Isolate *isolate, Handle< JSObject > options, const char *key, bool *value)
Definition: i18n.cc:63
static void DestroyGlobalHandle(const v8::WeakCallbackData< v8::Value, void > &data)
Definition: i18n.cc:740
void DeleteNativeObjectAt(const v8::WeakCallbackData< v8::Value, void > &data, int index)
Definition: i18n.cc:733
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
Maybe< T > maybe(T t)
Definition: v8.h:902
A simple Maybe type, representing an object which may or may not have a value.
Definition: v8.h:890
#define T(name, string, precedence)
Definition: token.cc:25