v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
i18n.cc
Go to the documentation of this file.
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 // limitations under the License.
28 
29 #include "i18n.h"
30 
31 #include "unicode/brkiter.h"
32 #include "unicode/calendar.h"
33 #include "unicode/coll.h"
34 #include "unicode/curramt.h"
35 #include "unicode/dcfmtsym.h"
36 #include "unicode/decimfmt.h"
37 #include "unicode/dtfmtsym.h"
38 #include "unicode/dtptngen.h"
39 #include "unicode/locid.h"
40 #include "unicode/numfmt.h"
41 #include "unicode/numsys.h"
42 #include "unicode/rbbi.h"
43 #include "unicode/smpdtfmt.h"
44 #include "unicode/timezone.h"
45 #include "unicode/uchar.h"
46 #include "unicode/ucol.h"
47 #include "unicode/ucurr.h"
48 #include "unicode/unum.h"
49 #include "unicode/uversion.h"
50 
51 namespace v8 {
52 namespace internal {
53 
54 namespace {
55 
56 bool ExtractStringSetting(Isolate* isolate,
57  Handle<JSObject> options,
58  const char* key,
59  icu::UnicodeString* setting) {
60  Handle<String> str = isolate->factory()->NewStringFromAscii(CStrVector(key));
61  MaybeObject* maybe_object = options->GetProperty(*str);
62  Object* object;
63  if (maybe_object->ToObject(&object) && object->IsString()) {
64  v8::String::Utf8Value utf8_string(
65  v8::Utils::ToLocal(Handle<String>(String::cast(object))));
66  *setting = icu::UnicodeString::fromUTF8(*utf8_string);
67  return true;
68  }
69  return false;
70 }
71 
72 
73 bool ExtractIntegerSetting(Isolate* isolate,
74  Handle<JSObject> options,
75  const char* key,
76  int32_t* value) {
77  Handle<String> str = isolate->factory()->NewStringFromAscii(CStrVector(key));
78  MaybeObject* maybe_object = options->GetProperty(*str);
79  Object* object;
80  if (maybe_object->ToObject(&object) && object->IsNumber()) {
81  object->ToInt32(value);
82  return true;
83  }
84  return false;
85 }
86 
87 
88 bool ExtractBooleanSetting(Isolate* isolate,
89  Handle<JSObject> options,
90  const char* key,
91  bool* value) {
92  Handle<String> str = isolate->factory()->NewStringFromAscii(CStrVector(key));
93  MaybeObject* maybe_object = options->GetProperty(*str);
94  Object* object;
95  if (maybe_object->ToObject(&object) && object->IsBoolean()) {
96  *value = object->BooleanValue();
97  return true;
98  }
99  return false;
100 }
101 
102 
103 icu::SimpleDateFormat* CreateICUDateFormat(
104  Isolate* isolate,
105  const icu::Locale& icu_locale,
106  Handle<JSObject> options) {
107  // Create time zone as specified by the user. We have to re-create time zone
108  // since calendar takes ownership.
109  icu::TimeZone* tz = NULL;
110  icu::UnicodeString timezone;
111  if (ExtractStringSetting(isolate, options, "timeZone", &timezone)) {
112  tz = icu::TimeZone::createTimeZone(timezone);
113  } else {
114  tz = icu::TimeZone::createDefault();
115  }
116 
117  // Create a calendar using locale, and apply time zone to it.
118  UErrorCode status = U_ZERO_ERROR;
119  icu::Calendar* calendar =
120  icu::Calendar::createInstance(tz, icu_locale, status);
121 
122  // Make formatter from skeleton. Calendar and numbering system are added
123  // to the locale as Unicode extension (if they were specified at all).
124  icu::SimpleDateFormat* date_format = NULL;
125  icu::UnicodeString skeleton;
126  if (ExtractStringSetting(isolate, options, "skeleton", &skeleton)) {
127  icu::DateTimePatternGenerator* generator =
128  icu::DateTimePatternGenerator::createInstance(icu_locale, status);
129  icu::UnicodeString pattern;
130  if (U_SUCCESS(status)) {
131  pattern = generator->getBestPattern(skeleton, status);
132  delete generator;
133  }
134 
135  date_format = new icu::SimpleDateFormat(pattern, icu_locale, status);
136  if (U_SUCCESS(status)) {
137  date_format->adoptCalendar(calendar);
138  }
139  }
140 
141  if (U_FAILURE(status)) {
142  delete calendar;
143  delete date_format;
144  date_format = NULL;
145  }
146 
147  return date_format;
148 }
149 
150 
151 void SetResolvedDateSettings(Isolate* isolate,
152  const icu::Locale& icu_locale,
153  icu::SimpleDateFormat* date_format,
154  Handle<JSObject> resolved) {
155  UErrorCode status = U_ZERO_ERROR;
156  icu::UnicodeString pattern;
157  date_format->toPattern(pattern);
159  resolved,
160  isolate->factory()->NewStringFromAscii(CStrVector("pattern")),
161  isolate->factory()->NewStringFromTwoByte(
162  Vector<const uint16_t>(
163  reinterpret_cast<const uint16_t*>(pattern.getBuffer()),
164  pattern.length())),
165  NONE,
166  SLOPPY);
167 
168  // Set time zone and calendar.
169  const icu::Calendar* calendar = date_format->getCalendar();
170  const char* calendar_name = calendar->getType();
172  resolved,
173  isolate->factory()->NewStringFromAscii(CStrVector("calendar")),
174  isolate->factory()->NewStringFromAscii(CStrVector(calendar_name)),
175  NONE,
176  SLOPPY);
177 
178  const icu::TimeZone& tz = calendar->getTimeZone();
179  icu::UnicodeString time_zone;
180  tz.getID(time_zone);
181 
182  icu::UnicodeString canonical_time_zone;
183  icu::TimeZone::getCanonicalID(time_zone, canonical_time_zone, status);
184  if (U_SUCCESS(status)) {
185  if (canonical_time_zone == UNICODE_STRING_SIMPLE("Etc/GMT")) {
187  resolved,
188  isolate->factory()->NewStringFromAscii(CStrVector("timeZone")),
189  isolate->factory()->NewStringFromAscii(CStrVector("UTC")),
190  NONE,
191  SLOPPY);
192  } else {
194  resolved,
195  isolate->factory()->NewStringFromAscii(CStrVector("timeZone")),
196  isolate->factory()->NewStringFromTwoByte(
197  Vector<const uint16_t>(
198  reinterpret_cast<const uint16_t*>(
199  canonical_time_zone.getBuffer()),
200  canonical_time_zone.length())),
201  NONE,
202  SLOPPY);
203  }
204  }
205 
206  // Ugly hack. ICU doesn't expose numbering system in any way, so we have
207  // to assume that for given locale NumberingSystem constructor produces the
208  // same digits as NumberFormat/Calendar would.
209  status = U_ZERO_ERROR;
210  icu::NumberingSystem* numbering_system =
211  icu::NumberingSystem::createInstance(icu_locale, status);
212  if (U_SUCCESS(status)) {
213  const char* ns = numbering_system->getName();
215  resolved,
216  isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
217  isolate->factory()->NewStringFromAscii(CStrVector(ns)),
218  NONE,
219  SLOPPY);
220  } else {
222  resolved,
223  isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
224  isolate->factory()->undefined_value(),
225  NONE,
226  SLOPPY);
227  }
228  delete numbering_system;
229 
230  // Set the locale
231  char result[ULOC_FULLNAME_CAPACITY];
232  status = U_ZERO_ERROR;
233  uloc_toLanguageTag(
234  icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
235  if (U_SUCCESS(status)) {
237  resolved,
238  isolate->factory()->NewStringFromAscii(CStrVector("locale")),
239  isolate->factory()->NewStringFromAscii(CStrVector(result)),
240  NONE,
241  SLOPPY);
242  } else {
243  // This would never happen, since we got the locale from ICU.
245  resolved,
246  isolate->factory()->NewStringFromAscii(CStrVector("locale")),
247  isolate->factory()->NewStringFromAscii(CStrVector("und")),
248  NONE,
249  SLOPPY);
250  }
251 }
252 
253 
254 template<int internal_fields, EternalHandles::SingletonHandle field>
255 Handle<ObjectTemplateInfo> GetEternal(Isolate* isolate) {
256  if (isolate->eternal_handles()->Exists(field)) {
258  isolate->eternal_handles()->GetSingleton(field));
259  }
260  v8::Local<v8::ObjectTemplate> raw_template =
261  v8::ObjectTemplate::New(reinterpret_cast<v8::Isolate*>(isolate));
262  raw_template->SetInternalFieldCount(internal_fields);
264  isolate->eternal_handles()->CreateSingleton(
265  isolate,
266  *v8::Utils::OpenHandle(*raw_template),
267  field));
268 }
269 
270 
271 icu::DecimalFormat* CreateICUNumberFormat(
272  Isolate* isolate,
273  const icu::Locale& icu_locale,
274  Handle<JSObject> options) {
275  // Make formatter from options. Numbering system is added
276  // to the locale as Unicode extension (if it was specified at all).
277  UErrorCode status = U_ZERO_ERROR;
278  icu::DecimalFormat* number_format = NULL;
279  icu::UnicodeString style;
280  icu::UnicodeString currency;
281  if (ExtractStringSetting(isolate, options, "style", &style)) {
282  if (style == UNICODE_STRING_SIMPLE("currency")) {
283  icu::UnicodeString display;
284  ExtractStringSetting(isolate, options, "currency", &currency);
285  ExtractStringSetting(isolate, options, "currencyDisplay", &display);
286 
287 #if (U_ICU_VERSION_MAJOR_NUM == 4) && (U_ICU_VERSION_MINOR_NUM <= 6)
288  icu::NumberFormat::EStyles format_style;
289  if (display == UNICODE_STRING_SIMPLE("code")) {
290  format_style = icu::NumberFormat::kIsoCurrencyStyle;
291  } else if (display == UNICODE_STRING_SIMPLE("name")) {
292  format_style = icu::NumberFormat::kPluralCurrencyStyle;
293  } else {
294  format_style = icu::NumberFormat::kCurrencyStyle;
295  }
296 #else // ICU version is 4.8 or above (we ignore versions below 4.0).
297  UNumberFormatStyle format_style;
298  if (display == UNICODE_STRING_SIMPLE("code")) {
299  format_style = UNUM_CURRENCY_ISO;
300  } else if (display == UNICODE_STRING_SIMPLE("name")) {
301  format_style = UNUM_CURRENCY_PLURAL;
302  } else {
303  format_style = UNUM_CURRENCY;
304  }
305 #endif
306 
307  number_format = static_cast<icu::DecimalFormat*>(
308  icu::NumberFormat::createInstance(icu_locale, format_style, status));
309  } else if (style == UNICODE_STRING_SIMPLE("percent")) {
310  number_format = static_cast<icu::DecimalFormat*>(
311  icu::NumberFormat::createPercentInstance(icu_locale, status));
312  if (U_FAILURE(status)) {
313  delete number_format;
314  return NULL;
315  }
316  // Make sure 1.1% doesn't go into 2%.
317  number_format->setMinimumFractionDigits(1);
318  } else {
319  // Make a decimal instance by default.
320  number_format = static_cast<icu::DecimalFormat*>(
321  icu::NumberFormat::createInstance(icu_locale, status));
322  }
323  }
324 
325  if (U_FAILURE(status)) {
326  delete number_format;
327  return NULL;
328  }
329 
330  // Set all options.
331  if (!currency.isEmpty()) {
332  number_format->setCurrency(currency.getBuffer(), status);
333  }
334 
335  int32_t digits;
336  if (ExtractIntegerSetting(
337  isolate, options, "minimumIntegerDigits", &digits)) {
338  number_format->setMinimumIntegerDigits(digits);
339  }
340 
341  if (ExtractIntegerSetting(
342  isolate, options, "minimumFractionDigits", &digits)) {
343  number_format->setMinimumFractionDigits(digits);
344  }
345 
346  if (ExtractIntegerSetting(
347  isolate, options, "maximumFractionDigits", &digits)) {
348  number_format->setMaximumFractionDigits(digits);
349  }
350 
351  bool significant_digits_used = false;
352  if (ExtractIntegerSetting(
353  isolate, options, "minimumSignificantDigits", &digits)) {
354  number_format->setMinimumSignificantDigits(digits);
355  significant_digits_used = true;
356  }
357 
358  if (ExtractIntegerSetting(
359  isolate, options, "maximumSignificantDigits", &digits)) {
360  number_format->setMaximumSignificantDigits(digits);
361  significant_digits_used = true;
362  }
363 
364  number_format->setSignificantDigitsUsed(significant_digits_used);
365 
366  bool grouping;
367  if (ExtractBooleanSetting(isolate, options, "useGrouping", &grouping)) {
368  number_format->setGroupingUsed(grouping);
369  }
370 
371  // Set rounding mode.
372  number_format->setRoundingMode(icu::DecimalFormat::kRoundHalfUp);
373 
374  return number_format;
375 }
376 
377 
378 void SetResolvedNumberSettings(Isolate* isolate,
379  const icu::Locale& icu_locale,
380  icu::DecimalFormat* number_format,
381  Handle<JSObject> resolved) {
382  icu::UnicodeString pattern;
383  number_format->toPattern(pattern);
385  resolved,
386  isolate->factory()->NewStringFromAscii(CStrVector("pattern")),
387  isolate->factory()->NewStringFromTwoByte(
388  Vector<const uint16_t>(
389  reinterpret_cast<const uint16_t*>(pattern.getBuffer()),
390  pattern.length())),
391  NONE,
392  SLOPPY);
393 
394  // Set resolved currency code in options.currency if not empty.
395  icu::UnicodeString currency(number_format->getCurrency());
396  if (!currency.isEmpty()) {
398  resolved,
399  isolate->factory()->NewStringFromAscii(CStrVector("currency")),
400  isolate->factory()->NewStringFromTwoByte(
401  Vector<const uint16_t>(
402  reinterpret_cast<const uint16_t*>(currency.getBuffer()),
403  currency.length())),
404  NONE,
405  SLOPPY);
406  }
407 
408  // Ugly hack. ICU doesn't expose numbering system in any way, so we have
409  // to assume that for given locale NumberingSystem constructor produces the
410  // same digits as NumberFormat/Calendar would.
411  UErrorCode status = U_ZERO_ERROR;
412  icu::NumberingSystem* numbering_system =
413  icu::NumberingSystem::createInstance(icu_locale, status);
414  if (U_SUCCESS(status)) {
415  const char* ns = numbering_system->getName();
417  resolved,
418  isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
419  isolate->factory()->NewStringFromAscii(CStrVector(ns)),
420  NONE,
421  SLOPPY);
422  } else {
424  resolved,
425  isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
426  isolate->factory()->undefined_value(),
427  NONE,
428  SLOPPY);
429  }
430  delete numbering_system;
431 
433  resolved,
434  isolate->factory()->NewStringFromAscii(CStrVector("useGrouping")),
435  isolate->factory()->ToBoolean(number_format->isGroupingUsed()),
436  NONE,
437  SLOPPY);
438 
440  resolved,
441  isolate->factory()->NewStringFromAscii(
442  CStrVector("minimumIntegerDigits")),
443  isolate->factory()->NewNumberFromInt(
444  number_format->getMinimumIntegerDigits()),
445  NONE,
446  SLOPPY);
447 
449  resolved,
450  isolate->factory()->NewStringFromAscii(
451  CStrVector("minimumFractionDigits")),
452  isolate->factory()->NewNumberFromInt(
453  number_format->getMinimumFractionDigits()),
454  NONE,
455  SLOPPY);
456 
458  resolved,
459  isolate->factory()->NewStringFromAscii(
460  CStrVector("maximumFractionDigits")),
461  isolate->factory()->NewNumberFromInt(
462  number_format->getMaximumFractionDigits()),
463  NONE,
464  SLOPPY);
465 
466  Handle<String> key = isolate->factory()->NewStringFromAscii(
467  CStrVector("minimumSignificantDigits"));
468  if (JSReceiver::HasLocalProperty(resolved, key)) {
470  resolved,
471  isolate->factory()->NewStringFromAscii(
472  CStrVector("minimumSignificantDigits")),
473  isolate->factory()->NewNumberFromInt(
474  number_format->getMinimumSignificantDigits()),
475  NONE,
476  SLOPPY);
477  }
478 
479  key = isolate->factory()->NewStringFromAscii(
480  CStrVector("maximumSignificantDigits"));
481  if (JSReceiver::HasLocalProperty(resolved, key)) {
483  resolved,
484  isolate->factory()->NewStringFromAscii(
485  CStrVector("maximumSignificantDigits")),
486  isolate->factory()->NewNumberFromInt(
487  number_format->getMaximumSignificantDigits()),
488  NONE,
489  SLOPPY);
490  }
491 
492  // Set the locale
493  char result[ULOC_FULLNAME_CAPACITY];
494  status = U_ZERO_ERROR;
495  uloc_toLanguageTag(
496  icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
497  if (U_SUCCESS(status)) {
499  resolved,
500  isolate->factory()->NewStringFromAscii(CStrVector("locale")),
501  isolate->factory()->NewStringFromAscii(CStrVector(result)),
502  NONE,
503  SLOPPY);
504  } else {
505  // This would never happen, since we got the locale from ICU.
507  resolved,
508  isolate->factory()->NewStringFromAscii(CStrVector("locale")),
509  isolate->factory()->NewStringFromAscii(CStrVector("und")),
510  NONE,
511  SLOPPY);
512  }
513 }
514 
515 
516 icu::Collator* CreateICUCollator(
517  Isolate* isolate,
518  const icu::Locale& icu_locale,
519  Handle<JSObject> options) {
520  // Make collator from options.
521  icu::Collator* collator = NULL;
522  UErrorCode status = U_ZERO_ERROR;
523  collator = icu::Collator::createInstance(icu_locale, status);
524 
525  if (U_FAILURE(status)) {
526  delete collator;
527  return NULL;
528  }
529 
530  // Set flags first, and then override them with sensitivity if necessary.
531  bool numeric;
532  if (ExtractBooleanSetting(isolate, options, "numeric", &numeric)) {
533  collator->setAttribute(
534  UCOL_NUMERIC_COLLATION, numeric ? UCOL_ON : UCOL_OFF, status);
535  }
536 
537  // Normalization is always on, by the spec. We are free to optimize
538  // if the strings are already normalized (but we don't have a way to tell
539  // that right now).
540  collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
541 
542  icu::UnicodeString case_first;
543  if (ExtractStringSetting(isolate, options, "caseFirst", &case_first)) {
544  if (case_first == UNICODE_STRING_SIMPLE("upper")) {
545  collator->setAttribute(UCOL_CASE_FIRST, UCOL_UPPER_FIRST, status);
546  } else if (case_first == UNICODE_STRING_SIMPLE("lower")) {
547  collator->setAttribute(UCOL_CASE_FIRST, UCOL_LOWER_FIRST, status);
548  } else {
549  // Default (false/off).
550  collator->setAttribute(UCOL_CASE_FIRST, UCOL_OFF, status);
551  }
552  }
553 
554  icu::UnicodeString sensitivity;
555  if (ExtractStringSetting(isolate, options, "sensitivity", &sensitivity)) {
556  if (sensitivity == UNICODE_STRING_SIMPLE("base")) {
557  collator->setStrength(icu::Collator::PRIMARY);
558  } else if (sensitivity == UNICODE_STRING_SIMPLE("accent")) {
559  collator->setStrength(icu::Collator::SECONDARY);
560  } else if (sensitivity == UNICODE_STRING_SIMPLE("case")) {
561  collator->setStrength(icu::Collator::PRIMARY);
562  collator->setAttribute(UCOL_CASE_LEVEL, UCOL_ON, status);
563  } else {
564  // variant (default)
565  collator->setStrength(icu::Collator::TERTIARY);
566  }
567  }
568 
569  bool ignore;
570  if (ExtractBooleanSetting(isolate, options, "ignorePunctuation", &ignore)) {
571  if (ignore) {
572  collator->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, status);
573  }
574  }
575 
576  return collator;
577 }
578 
579 
580 void SetResolvedCollatorSettings(Isolate* isolate,
581  const icu::Locale& icu_locale,
582  icu::Collator* collator,
583  Handle<JSObject> resolved) {
584  UErrorCode status = U_ZERO_ERROR;
585 
587  resolved,
588  isolate->factory()->NewStringFromAscii(CStrVector("numeric")),
589  isolate->factory()->ToBoolean(
590  collator->getAttribute(UCOL_NUMERIC_COLLATION, status) == UCOL_ON),
591  NONE,
592  SLOPPY);
593 
594  switch (collator->getAttribute(UCOL_CASE_FIRST, status)) {
595  case UCOL_LOWER_FIRST:
597  resolved,
598  isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")),
599  isolate->factory()->NewStringFromAscii(CStrVector("lower")),
600  NONE,
601  SLOPPY);
602  break;
603  case UCOL_UPPER_FIRST:
605  resolved,
606  isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")),
607  isolate->factory()->NewStringFromAscii(CStrVector("upper")),
608  NONE,
609  SLOPPY);
610  break;
611  default:
613  resolved,
614  isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")),
615  isolate->factory()->NewStringFromAscii(CStrVector("false")),
616  NONE,
617  SLOPPY);
618  }
619 
620  switch (collator->getAttribute(UCOL_STRENGTH, status)) {
621  case UCOL_PRIMARY: {
623  resolved,
624  isolate->factory()->NewStringFromAscii(CStrVector("strength")),
625  isolate->factory()->NewStringFromAscii(CStrVector("primary")),
626  NONE,
627  SLOPPY);
628 
629  // case level: true + s1 -> case, s1 -> base.
630  if (UCOL_ON == collator->getAttribute(UCOL_CASE_LEVEL, status)) {
632  resolved,
633  isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
634  isolate->factory()->NewStringFromAscii(CStrVector("case")),
635  NONE,
636  SLOPPY);
637  } else {
639  resolved,
640  isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
641  isolate->factory()->NewStringFromAscii(CStrVector("base")),
642  NONE,
643  SLOPPY);
644  }
645  break;
646  }
647  case UCOL_SECONDARY:
649  resolved,
650  isolate->factory()->NewStringFromAscii(CStrVector("strength")),
651  isolate->factory()->NewStringFromAscii(CStrVector("secondary")),
652  NONE,
653  SLOPPY);
655  resolved,
656  isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
657  isolate->factory()->NewStringFromAscii(CStrVector("accent")),
658  NONE,
659  SLOPPY);
660  break;
661  case UCOL_TERTIARY:
663  resolved,
664  isolate->factory()->NewStringFromAscii(CStrVector("strength")),
665  isolate->factory()->NewStringFromAscii(CStrVector("tertiary")),
666  NONE,
667  SLOPPY);
669  resolved,
670  isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
671  isolate->factory()->NewStringFromAscii(CStrVector("variant")),
672  NONE,
673  SLOPPY);
674  break;
675  case UCOL_QUATERNARY:
676  // We shouldn't get quaternary and identical from ICU, but if we do
677  // put them into variant.
679  resolved,
680  isolate->factory()->NewStringFromAscii(CStrVector("strength")),
681  isolate->factory()->NewStringFromAscii(CStrVector("quaternary")),
682  NONE,
683  SLOPPY);
685  resolved,
686  isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
687  isolate->factory()->NewStringFromAscii(CStrVector("variant")),
688  NONE,
689  SLOPPY);
690  break;
691  default:
693  resolved,
694  isolate->factory()->NewStringFromAscii(CStrVector("strength")),
695  isolate->factory()->NewStringFromAscii(CStrVector("identical")),
696  NONE,
697  SLOPPY);
699  resolved,
700  isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
701  isolate->factory()->NewStringFromAscii(CStrVector("variant")),
702  NONE,
703  SLOPPY);
704  }
705 
707  resolved,
708  isolate->factory()->NewStringFromAscii(CStrVector("ignorePunctuation")),
709  isolate->factory()->ToBoolean(collator->getAttribute(
710  UCOL_ALTERNATE_HANDLING, status) == UCOL_SHIFTED),
711  NONE,
712  SLOPPY);
713 
714  // Set the locale
715  char result[ULOC_FULLNAME_CAPACITY];
716  status = U_ZERO_ERROR;
717  uloc_toLanguageTag(
718  icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
719  if (U_SUCCESS(status)) {
721  resolved,
722  isolate->factory()->NewStringFromAscii(CStrVector("locale")),
723  isolate->factory()->NewStringFromAscii(CStrVector(result)),
724  NONE,
725  SLOPPY);
726  } else {
727  // This would never happen, since we got the locale from ICU.
729  resolved,
730  isolate->factory()->NewStringFromAscii(CStrVector("locale")),
731  isolate->factory()->NewStringFromAscii(CStrVector("und")),
732  NONE,
733  SLOPPY);
734  }
735 }
736 
737 
738 icu::BreakIterator* CreateICUBreakIterator(
739  Isolate* isolate,
740  const icu::Locale& icu_locale,
741  Handle<JSObject> options) {
742  UErrorCode status = U_ZERO_ERROR;
743  icu::BreakIterator* break_iterator = NULL;
744  icu::UnicodeString type;
745  if (!ExtractStringSetting(isolate, options, "type", &type)) return NULL;
746 
747  if (type == UNICODE_STRING_SIMPLE("character")) {
748  break_iterator =
749  icu::BreakIterator::createCharacterInstance(icu_locale, status);
750  } else if (type == UNICODE_STRING_SIMPLE("sentence")) {
751  break_iterator =
752  icu::BreakIterator::createSentenceInstance(icu_locale, status);
753  } else if (type == UNICODE_STRING_SIMPLE("line")) {
754  break_iterator =
755  icu::BreakIterator::createLineInstance(icu_locale, status);
756  } else {
757  // Defualt is word iterator.
758  break_iterator =
759  icu::BreakIterator::createWordInstance(icu_locale, status);
760  }
761 
762  if (U_FAILURE(status)) {
763  delete break_iterator;
764  return NULL;
765  }
766 
767  return break_iterator;
768 }
769 
770 
771 void SetResolvedBreakIteratorSettings(Isolate* isolate,
772  const icu::Locale& icu_locale,
773  icu::BreakIterator* break_iterator,
774  Handle<JSObject> resolved) {
775  UErrorCode status = U_ZERO_ERROR;
776 
777  // Set the locale
778  char result[ULOC_FULLNAME_CAPACITY];
779  status = U_ZERO_ERROR;
780  uloc_toLanguageTag(
781  icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
782  if (U_SUCCESS(status)) {
784  resolved,
785  isolate->factory()->NewStringFromAscii(CStrVector("locale")),
786  isolate->factory()->NewStringFromAscii(CStrVector(result)),
787  NONE,
788  SLOPPY);
789  } else {
790  // This would never happen, since we got the locale from ICU.
792  resolved,
793  isolate->factory()->NewStringFromAscii(CStrVector("locale")),
794  isolate->factory()->NewStringFromAscii(CStrVector("und")),
795  NONE,
796  SLOPPY);
797  }
798 }
799 
800 } // namespace
801 
802 
803 // static
805  return GetEternal<1, i::EternalHandles::I18N_TEMPLATE_ONE>(isolate);
806 }
807 
808 
809 // static
811  return GetEternal<2, i::EternalHandles::I18N_TEMPLATE_TWO>(isolate);
812 }
813 
814 
815 // static
817  Isolate* isolate,
818  Handle<String> locale,
819  Handle<JSObject> options,
820  Handle<JSObject> resolved) {
821  // Convert BCP47 into ICU locale format.
822  UErrorCode status = U_ZERO_ERROR;
823  icu::Locale icu_locale;
824  char icu_result[ULOC_FULLNAME_CAPACITY];
825  int icu_length = 0;
826  v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
827  if (bcp47_locale.length() != 0) {
828  uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
829  &icu_length, &status);
830  if (U_FAILURE(status) || icu_length == 0) {
831  return NULL;
832  }
833  icu_locale = icu::Locale(icu_result);
834  }
835 
836  icu::SimpleDateFormat* date_format = CreateICUDateFormat(
837  isolate, icu_locale, options);
838  if (!date_format) {
839  // Remove extensions and try again.
840  icu::Locale no_extension_locale(icu_locale.getBaseName());
841  date_format = CreateICUDateFormat(isolate, no_extension_locale, options);
842 
843  // Set resolved settings (pattern, numbering system, calendar).
844  SetResolvedDateSettings(
845  isolate, no_extension_locale, date_format, resolved);
846  } else {
847  SetResolvedDateSettings(isolate, icu_locale, date_format, resolved);
848  }
849 
850  return date_format;
851 }
852 
853 
854 icu::SimpleDateFormat* DateFormat::UnpackDateFormat(
855  Isolate* isolate,
857  Handle<String> key =
858  isolate->factory()->NewStringFromAscii(CStrVector("dateFormat"));
859  if (JSReceiver::HasLocalProperty(obj, key)) {
860  return reinterpret_cast<icu::SimpleDateFormat*>(
861  obj->GetInternalField(0));
862  }
863 
864  return NULL;
865 }
866 
867 
868 template<class T>
870  int index) {
872  delete reinterpret_cast<T*>(obj->GetAlignedPointerFromInternalField(index));
873 }
874 
875 
876 static void DestroyGlobalHandle(
878  GlobalHandles::Destroy(reinterpret_cast<Object**>(data.GetParameter()));
879 }
880 
881 
884  DeleteNativeObjectAt<icu::SimpleDateFormat>(data, 0);
885  DestroyGlobalHandle(data);
886 }
887 
888 
890  Isolate* isolate,
891  Handle<String> locale,
892  Handle<JSObject> options,
893  Handle<JSObject> resolved) {
894  // Convert BCP47 into ICU locale format.
895  UErrorCode status = U_ZERO_ERROR;
896  icu::Locale icu_locale;
897  char icu_result[ULOC_FULLNAME_CAPACITY];
898  int icu_length = 0;
899  v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
900  if (bcp47_locale.length() != 0) {
901  uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
902  &icu_length, &status);
903  if (U_FAILURE(status) || icu_length == 0) {
904  return NULL;
905  }
906  icu_locale = icu::Locale(icu_result);
907  }
908 
909  icu::DecimalFormat* number_format =
910  CreateICUNumberFormat(isolate, icu_locale, options);
911  if (!number_format) {
912  // Remove extensions and try again.
913  icu::Locale no_extension_locale(icu_locale.getBaseName());
914  number_format = CreateICUNumberFormat(
915  isolate, no_extension_locale, options);
916 
917  // Set resolved settings (pattern, numbering system).
918  SetResolvedNumberSettings(
919  isolate, no_extension_locale, number_format, resolved);
920  } else {
921  SetResolvedNumberSettings(isolate, icu_locale, number_format, resolved);
922  }
923 
924  return number_format;
925 }
926 
927 
929  Isolate* isolate,
931  Handle<String> key =
932  isolate->factory()->NewStringFromAscii(CStrVector("numberFormat"));
933  if (JSReceiver::HasLocalProperty(obj, key)) {
934  return reinterpret_cast<icu::DecimalFormat*>(obj->GetInternalField(0));
935  }
936 
937  return NULL;
938 }
939 
940 
943  DeleteNativeObjectAt<icu::DecimalFormat>(data, 0);
944  DestroyGlobalHandle(data);
945 }
946 
947 
949  Isolate* isolate,
950  Handle<String> locale,
951  Handle<JSObject> options,
952  Handle<JSObject> resolved) {
953  // Convert BCP47 into ICU locale format.
954  UErrorCode status = U_ZERO_ERROR;
955  icu::Locale icu_locale;
956  char icu_result[ULOC_FULLNAME_CAPACITY];
957  int icu_length = 0;
958  v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
959  if (bcp47_locale.length() != 0) {
960  uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
961  &icu_length, &status);
962  if (U_FAILURE(status) || icu_length == 0) {
963  return NULL;
964  }
965  icu_locale = icu::Locale(icu_result);
966  }
967 
968  icu::Collator* collator = CreateICUCollator(isolate, icu_locale, options);
969  if (!collator) {
970  // Remove extensions and try again.
971  icu::Locale no_extension_locale(icu_locale.getBaseName());
972  collator = CreateICUCollator(isolate, no_extension_locale, options);
973 
974  // Set resolved settings (pattern, numbering system).
975  SetResolvedCollatorSettings(
976  isolate, no_extension_locale, collator, resolved);
977  } else {
978  SetResolvedCollatorSettings(isolate, icu_locale, collator, resolved);
979  }
980 
981  return collator;
982 }
983 
984 
985 icu::Collator* Collator::UnpackCollator(Isolate* isolate,
987  Handle<String> key =
988  isolate->factory()->NewStringFromAscii(CStrVector("collator"));
989  if (JSReceiver::HasLocalProperty(obj, key)) {
990  return reinterpret_cast<icu::Collator*>(obj->GetInternalField(0));
991  }
992 
993  return NULL;
994 }
995 
996 
999  DeleteNativeObjectAt<icu::Collator>(data, 0);
1000  DestroyGlobalHandle(data);
1001 }
1002 
1003 
1005  Isolate* isolate,
1006  Handle<String> locale,
1007  Handle<JSObject> options,
1008  Handle<JSObject> resolved) {
1009  // Convert BCP47 into ICU locale format.
1010  UErrorCode status = U_ZERO_ERROR;
1011  icu::Locale icu_locale;
1012  char icu_result[ULOC_FULLNAME_CAPACITY];
1013  int icu_length = 0;
1014  v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
1015  if (bcp47_locale.length() != 0) {
1016  uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
1017  &icu_length, &status);
1018  if (U_FAILURE(status) || icu_length == 0) {
1019  return NULL;
1020  }
1021  icu_locale = icu::Locale(icu_result);
1022  }
1023 
1024  icu::BreakIterator* break_iterator = CreateICUBreakIterator(
1025  isolate, icu_locale, options);
1026  if (!break_iterator) {
1027  // Remove extensions and try again.
1028  icu::Locale no_extension_locale(icu_locale.getBaseName());
1029  break_iterator = CreateICUBreakIterator(
1030  isolate, no_extension_locale, options);
1031 
1032  // Set resolved settings (locale).
1033  SetResolvedBreakIteratorSettings(
1034  isolate, no_extension_locale, break_iterator, resolved);
1035  } else {
1036  SetResolvedBreakIteratorSettings(
1037  isolate, icu_locale, break_iterator, resolved);
1038  }
1039 
1040  return break_iterator;
1041 }
1042 
1043 
1044 icu::BreakIterator* BreakIterator::UnpackBreakIterator(Isolate* isolate,
1046  Handle<String> key =
1047  isolate->factory()->NewStringFromAscii(CStrVector("breakIterator"));
1048  if (JSReceiver::HasLocalProperty(obj, key)) {
1049  return reinterpret_cast<icu::BreakIterator*>(obj->GetInternalField(0));
1050  }
1051 
1052  return NULL;
1053 }
1054 
1055 
1058  DeleteNativeObjectAt<icu::BreakIterator>(data, 0);
1059  DeleteNativeObjectAt<icu::UnicodeString>(data, 1);
1060  DestroyGlobalHandle(data);
1061 }
1062 
1063 } } // namespace v8::internal
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
static void Destroy(Object **location)
static icu::DecimalFormat * InitializeNumberFormat(Isolate *isolate, Handle< String > locale, Handle< JSObject > options, Handle< JSObject > resolved)
Definition: i18n.cc:889
static String * cast(Object *obj)
V8_INLINE void * GetAlignedPointerFromInternalField(int index)
Definition: v8.h:6158
static Handle< ObjectTemplateInfo > GetTemplate(Isolate *isolate)
Definition: i18n.cc:804
static Handle< T > cast(Handle< S > that)
Definition: handles.h:75
Handle< String > NewStringFromAscii(Vector< const char > str, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.h:141
static icu::DecimalFormat * UnpackNumberFormat(Isolate *isolate, Handle< JSObject > obj)
Definition: i18n.cc:928
kSerializedDataOffset Object
Definition: objects-inl.h:5016
int int32_t
Definition: unicode.cc:47
static void DeleteCollator(const v8::WeakCallbackData< v8::Value, void > &data)
Definition: i18n.cc:997
V8_INLINE Local< T > GetValue() const
Definition: v8.h:450
static void DeleteBreakIterator(const v8::WeakCallbackData< v8::Value, void > &data)
Definition: i18n.cc:1056
static icu::BreakIterator * InitializeBreakIterator(Isolate *isolate, Handle< String > locale, Handle< JSObject > options, Handle< JSObject > resolved)
Definition: i18n.cc:1004
Factory * factory()
Definition: isolate.h:995
static icu::SimpleDateFormat * InitializeDateTimeFormat(Isolate *isolate, Handle< String > locale, Handle< JSObject > options, Handle< JSObject > resolved)
Definition: i18n.cc:816
static icu::SimpleDateFormat * UnpackDateFormat(Isolate *isolate, Handle< JSObject > obj)
Definition: i18n.cc:854
static Handle< ObjectTemplateInfo > GetTemplate2(Isolate *isolate)
Definition: i18n.cc:810
static Local< ObjectTemplate > New()
Definition: api.cc:1286
void DeleteNativeObjectAt(const v8::WeakCallbackData< v8::Value, void > &data, int index)
Definition: i18n.cc:869
static icu::Collator * UnpackCollator(Isolate *isolate, Handle< JSObject > obj)
Definition: i18n.cc:985
static void DeleteDateFormat(const v8::WeakCallbackData< v8::Value, void > &data)
Definition: i18n.cc:882
void SetInternalFieldCount(int value)
Definition: api.cc:1552
static V8_INLINE Handle< T > Cast(Handle< S > that)
Definition: v8.h:297
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
Definition: api.h:308
Vector< const char > CStrVector(const char *data)
Definition: utils.h:574
V8_INLINE P * GetParameter() const
Definition: v8.h:451
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
#define T(name, string, precedence)
Definition: token.cc:48
static icu::BreakIterator * UnpackBreakIterator(Isolate *isolate, Handle< JSObject > obj)
Definition: i18n.cc:1044
static Handle< Object > SetProperty(Handle< JSReceiver > object, Handle< Name > key, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, StoreFromKeyed store_mode=MAY_BE_STORE_FROM_KEYED)
Definition: objects.cc:2858
int length() const
Definition: v8.h:1955
static icu::Collator * InitializeCollator(Isolate *isolate, Handle< String > locale, Handle< JSObject > options, Handle< JSObject > resolved)
Definition: i18n.cc:948
HeapObject * obj
static void DeleteNumberFormat(const v8::WeakCallbackData< v8::Value, void > &data)
Definition: i18n.cc:941
Definition: v8.h:124
static bool HasLocalProperty(Handle< JSReceiver >, Handle< Name > name)
Definition: objects-inl.h:6301