1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_INTL_SUPPORT
6 #error Internationalization is expected to be enabled.
7 #endif // V8_INTL_SUPPORT
8
9 #include <cmath>
10 #include <memory>
11
12 #include "src/api-inl.h"
13 #include "src/api-natives.h"
14 #include "src/arguments-inl.h"
15 #include "src/date.h"
16 #include "src/global-handles.h"
17 #include "src/heap/factory.h"
18 #include "src/intl.h"
19 #include "src/isolate-inl.h"
20 #include "src/messages.h"
21 #include "src/objects/intl-objects-inl.h"
22 #include "src/objects/intl-objects.h"
23 #include "src/objects/js-array-inl.h"
24 #include "src/objects/js-collator-inl.h"
25 #include "src/objects/js-list-format-inl.h"
26 #include "src/objects/js-list-format.h"
27 #include "src/objects/js-plural-rules-inl.h"
28 #include "src/objects/managed.h"
29 #include "src/runtime/runtime-utils.h"
30 #include "src/utils.h"
31
32 #include "unicode/brkiter.h"
33 #include "unicode/calendar.h"
34 #include "unicode/coll.h"
35 #include "unicode/curramt.h"
36 #include "unicode/datefmt.h"
37 #include "unicode/dcfmtsym.h"
38 #include "unicode/decimfmt.h"
39 #include "unicode/dtfmtsym.h"
40 #include "unicode/dtptngen.h"
41 #include "unicode/locid.h"
42 #include "unicode/numfmt.h"
43 #include "unicode/numsys.h"
44 #include "unicode/plurrule.h"
45 #include "unicode/rbbi.h"
46 #include "unicode/smpdtfmt.h"
47 #include "unicode/timezone.h"
48 #include "unicode/uchar.h"
49 #include "unicode/ucol.h"
50 #include "unicode/ucurr.h"
51 #include "unicode/uloc.h"
52 #include "unicode/unistr.h"
53 #include "unicode/unum.h"
54 #include "unicode/uversion.h"
55
56
57 namespace v8 {
58 namespace internal {
59
60 // ecma402 #sec-formatlist
RUNTIME_FUNCTION(Runtime_FormatList)61 RUNTIME_FUNCTION(Runtime_FormatList) {
62 HandleScope scope(isolate);
63 DCHECK_EQ(2, args.length());
64 CONVERT_ARG_HANDLE_CHECKED(JSListFormat, list_format, 0);
65 CONVERT_ARG_HANDLE_CHECKED(JSArray, list, 1);
66 RETURN_RESULT_OR_FAILURE(
67 isolate, JSListFormat::FormatList(isolate, list_format, list));
68 }
69
70 // ecma402 #sec-formatlisttoparts
RUNTIME_FUNCTION(Runtime_FormatListToParts)71 RUNTIME_FUNCTION(Runtime_FormatListToParts) {
72 HandleScope scope(isolate);
73 DCHECK_EQ(2, args.length());
74 CONVERT_ARG_HANDLE_CHECKED(JSListFormat, list_format, 0);
75 CONVERT_ARG_HANDLE_CHECKED(JSArray, list, 1);
76 RETURN_RESULT_OR_FAILURE(
77 isolate, JSListFormat::FormatListToParts(isolate, list_format, list));
78 }
79
RUNTIME_FUNCTION(Runtime_GetNumberOption)80 RUNTIME_FUNCTION(Runtime_GetNumberOption) {
81 HandleScope scope(isolate);
82 DCHECK_EQ(5, args.length());
83 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, options, 0);
84 CONVERT_ARG_HANDLE_CHECKED(String, property, 1);
85 CONVERT_SMI_ARG_CHECKED(min, 2);
86 CONVERT_SMI_ARG_CHECKED(max, 3);
87 CONVERT_SMI_ARG_CHECKED(fallback, 4);
88
89 Maybe<int> num =
90 Intl::GetNumberOption(isolate, options, property, min, max, fallback);
91 if (num.IsNothing()) {
92 return ReadOnlyRoots(isolate).exception();
93 }
94 return Smi::FromInt(num.FromJust());
95 }
96
RUNTIME_FUNCTION(Runtime_DefaultNumberOption)97 RUNTIME_FUNCTION(Runtime_DefaultNumberOption) {
98 HandleScope scope(isolate);
99 DCHECK_EQ(5, args.length());
100 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
101 CONVERT_SMI_ARG_CHECKED(min, 1);
102 CONVERT_SMI_ARG_CHECKED(max, 2);
103 CONVERT_SMI_ARG_CHECKED(fallback, 3);
104 CONVERT_ARG_HANDLE_CHECKED(String, property, 4);
105
106 Maybe<int> num =
107 Intl::DefaultNumberOption(isolate, value, min, max, fallback, property);
108 if (num.IsNothing()) {
109 return ReadOnlyRoots(isolate).exception();
110 }
111 return Smi::FromInt(num.FromJust());
112 }
113
114 // ECMA 402 6.2.3
RUNTIME_FUNCTION(Runtime_CanonicalizeLanguageTag)115 RUNTIME_FUNCTION(Runtime_CanonicalizeLanguageTag) {
116 HandleScope scope(isolate);
117
118 DCHECK_EQ(1, args.length());
119 CONVERT_ARG_HANDLE_CHECKED(Object, locale, 0);
120
121 std::string canonicalized;
122 if (!Intl::CanonicalizeLanguageTag(isolate, locale).To(&canonicalized)) {
123 return ReadOnlyRoots(isolate).exception();
124 }
125 return *isolate->factory()->NewStringFromAsciiChecked(canonicalized.c_str());
126 }
127
RUNTIME_FUNCTION(Runtime_AvailableLocalesOf)128 RUNTIME_FUNCTION(Runtime_AvailableLocalesOf) {
129 HandleScope scope(isolate);
130 DCHECK_EQ(1, args.length());
131 CONVERT_ARG_HANDLE_CHECKED(String, service, 0);
132 Handle<JSObject> locales;
133 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
134 isolate, locales, Intl::AvailableLocalesOf(isolate, service));
135 return *locales;
136 }
137
RUNTIME_FUNCTION(Runtime_GetDefaultICULocale)138 RUNTIME_FUNCTION(Runtime_GetDefaultICULocale) {
139 HandleScope scope(isolate);
140
141 DCHECK_EQ(0, args.length());
142 return *isolate->factory()->NewStringFromAsciiChecked(
143 Intl::DefaultLocale(isolate).c_str());
144 }
145
RUNTIME_FUNCTION(Runtime_IsWellFormedCurrencyCode)146 RUNTIME_FUNCTION(Runtime_IsWellFormedCurrencyCode) {
147 HandleScope scope(isolate);
148 DCHECK_EQ(1, args.length());
149 CONVERT_ARG_HANDLE_CHECKED(String, currency, 0);
150 return *(isolate->factory()->ToBoolean(
151 Intl::IsWellFormedCurrencyCode(isolate, currency)));
152 }
153
RUNTIME_FUNCTION(Runtime_DefineWEProperty)154 RUNTIME_FUNCTION(Runtime_DefineWEProperty) {
155 HandleScope scope(isolate);
156
157 DCHECK_EQ(3, args.length());
158 CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
159 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
160 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
161 Intl::DefineWEProperty(isolate, target, key, value);
162 return ReadOnlyRoots(isolate).undefined_value();
163 }
164
RUNTIME_FUNCTION(Runtime_IsInitializedIntlObjectOfType)165 RUNTIME_FUNCTION(Runtime_IsInitializedIntlObjectOfType) {
166 HandleScope scope(isolate);
167
168 DCHECK_EQ(2, args.length());
169
170 CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
171 CONVERT_SMI_ARG_CHECKED(expected_type_int, 1);
172
173 Intl::Type expected_type = Intl::TypeFromInt(expected_type_int);
174
175 return isolate->heap()->ToBoolean(
176 Intl::IsObjectOfType(isolate, input, expected_type));
177 }
178
RUNTIME_FUNCTION(Runtime_MarkAsInitializedIntlObjectOfType)179 RUNTIME_FUNCTION(Runtime_MarkAsInitializedIntlObjectOfType) {
180 HandleScope scope(isolate);
181
182 DCHECK_EQ(2, args.length());
183
184 CONVERT_ARG_HANDLE_CHECKED(JSObject, input, 0);
185 CONVERT_ARG_HANDLE_CHECKED(Smi, type, 1);
186
187 #ifdef DEBUG
188 // TypeFromSmi does correctness checks.
189 Intl::Type type_intl = Intl::TypeFromSmi(*type);
190 USE(type_intl);
191 #endif
192
193 Handle<Symbol> marker = isolate->factory()->intl_initialized_marker_symbol();
194 JSObject::SetProperty(isolate, input, marker, type, LanguageMode::kStrict)
195 .Assert();
196
197 return ReadOnlyRoots(isolate).undefined_value();
198 }
199
RUNTIME_FUNCTION(Runtime_CreateDateTimeFormat)200 RUNTIME_FUNCTION(Runtime_CreateDateTimeFormat) {
201 HandleScope scope(isolate);
202
203 DCHECK_EQ(3, args.length());
204
205 CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
206 CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
207 CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
208
209 Handle<JSFunction> constructor(
210 isolate->native_context()->intl_date_time_format_function(), isolate);
211
212 Handle<JSObject> local_object;
213 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, local_object,
214 JSObject::New(constructor, constructor));
215
216 // Set date time formatter as embedder field of the resulting JS object.
217 icu::SimpleDateFormat* date_format =
218 DateFormat::InitializeDateTimeFormat(isolate, locale, options, resolved);
219 CHECK_NOT_NULL(date_format);
220
221 local_object->SetEmbedderField(DateFormat::kSimpleDateFormatIndex,
222 reinterpret_cast<Smi*>(date_format));
223
224 // Make object handle weak so we can delete the data format once GC kicks in.
225 Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
226 GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(),
227 DateFormat::DeleteDateFormat,
228 WeakCallbackType::kInternalFields);
229 return *local_object;
230 }
231
RUNTIME_FUNCTION(Runtime_CreateNumberFormat)232 RUNTIME_FUNCTION(Runtime_CreateNumberFormat) {
233 HandleScope scope(isolate);
234
235 DCHECK_EQ(3, args.length());
236
237 CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
238 CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
239 CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
240 RETURN_RESULT_OR_FAILURE(
241 isolate, Intl::CreateNumberFormat(isolate, locale, options, resolved));
242 }
243
RUNTIME_FUNCTION(Runtime_CurrencyDigits)244 RUNTIME_FUNCTION(Runtime_CurrencyDigits) {
245 HandleScope scope(isolate);
246 DCHECK_EQ(1, args.length());
247 CONVERT_ARG_HANDLE_CHECKED(String, currency, 0);
248 return *Intl::CurrencyDigits(isolate, currency);
249 }
250
RUNTIME_FUNCTION(Runtime_CollatorResolvedOptions)251 RUNTIME_FUNCTION(Runtime_CollatorResolvedOptions) {
252 HandleScope scope(isolate);
253
254 DCHECK_EQ(1, args.length());
255 CONVERT_ARG_HANDLE_CHECKED(Object, collator_obj, 0);
256
257 // 3. If pr does not have an [[InitializedCollator]] internal
258 // slot, throw a TypeError exception.
259 if (!collator_obj->IsJSCollator()) {
260 Handle<String> method_str = isolate->factory()->NewStringFromStaticChars(
261 "Intl.Collator.prototype.resolvedOptions");
262 THROW_NEW_ERROR_RETURN_FAILURE(
263 isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
264 method_str, collator_obj));
265 }
266
267 Handle<JSCollator> collator = Handle<JSCollator>::cast(collator_obj);
268
269 return *JSCollator::ResolvedOptions(isolate, collator);
270 }
271
RUNTIME_FUNCTION(Runtime_PluralRulesResolvedOptions)272 RUNTIME_FUNCTION(Runtime_PluralRulesResolvedOptions) {
273 HandleScope scope(isolate);
274
275 DCHECK_EQ(1, args.length());
276 CONVERT_ARG_HANDLE_CHECKED(Object, plural_rules_obj, 0);
277
278 // 3. If pr does not have an [[InitializedPluralRules]] internal
279 // slot, throw a TypeError exception.
280 if (!plural_rules_obj->IsJSPluralRules()) {
281 Handle<String> method_str = isolate->factory()->NewStringFromStaticChars(
282 "Intl.PluralRules.prototype.resolvedOptions");
283 THROW_NEW_ERROR_RETURN_FAILURE(
284 isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
285 method_str, plural_rules_obj));
286 }
287
288 Handle<JSPluralRules> plural_rules =
289 Handle<JSPluralRules>::cast(plural_rules_obj);
290
291 return *JSPluralRules::ResolvedOptions(isolate, plural_rules);
292 }
293
RUNTIME_FUNCTION(Runtime_ParseExtension)294 RUNTIME_FUNCTION(Runtime_ParseExtension) {
295 Factory* factory = isolate->factory();
296 HandleScope scope(isolate);
297 DCHECK_EQ(1, args.length());
298 CONVERT_ARG_HANDLE_CHECKED(String, extension, 0);
299 std::map<std::string, std::string> map;
300 Intl::ParseExtension(isolate, std::string(extension->ToCString().get()), map);
301 Handle<JSObject> extension_map =
302 isolate->factory()->NewJSObjectWithNullProto();
303 for (std::map<std::string, std::string>::iterator it = map.begin();
304 it != map.end(); it++) {
305 JSObject::AddProperty(
306 isolate, extension_map,
307 factory->NewStringFromAsciiChecked(it->first.c_str()),
308 factory->NewStringFromAsciiChecked(it->second.c_str()), NONE);
309 }
310 return *extension_map;
311 }
312
RUNTIME_FUNCTION(Runtime_PluralRulesSelect)313 RUNTIME_FUNCTION(Runtime_PluralRulesSelect) {
314 HandleScope scope(isolate);
315
316 DCHECK_EQ(2, args.length());
317 CONVERT_ARG_HANDLE_CHECKED(Object, plural_rules_obj, 0);
318 CONVERT_ARG_HANDLE_CHECKED(Object, number, 1);
319
320 // 3. If pr does not have an [[InitializedPluralRules]] internal
321 // slot, throw a TypeError exception.
322 if (!plural_rules_obj->IsJSPluralRules()) {
323 Handle<String> method_str = isolate->factory()->NewStringFromStaticChars(
324 "Intl.PluralRules.prototype.select");
325 THROW_NEW_ERROR_RETURN_FAILURE(
326 isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
327 method_str, plural_rules_obj));
328 }
329
330 Handle<JSPluralRules> plural_rules =
331 Handle<JSPluralRules>::cast(plural_rules_obj);
332
333 // 4. Return ? ResolvePlural(pr, n).
334
335 RETURN_RESULT_OR_FAILURE(
336 isolate, JSPluralRules::ResolvePlural(isolate, plural_rules, number));
337 }
338
RUNTIME_FUNCTION(Runtime_CreateBreakIterator)339 RUNTIME_FUNCTION(Runtime_CreateBreakIterator) {
340 HandleScope scope(isolate);
341
342 DCHECK_EQ(3, args.length());
343
344 CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
345 CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
346 CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
347
348 Handle<JSFunction> constructor(
349 isolate->native_context()->intl_v8_break_iterator_function(), isolate);
350
351 Handle<JSObject> local_object;
352 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, local_object,
353 JSObject::New(constructor, constructor));
354
355 // Set break iterator as embedder field of the resulting JS object.
356 icu::BreakIterator* break_iterator = V8BreakIterator::InitializeBreakIterator(
357 isolate, locale, options, resolved);
358 CHECK_NOT_NULL(break_iterator);
359
360 if (!break_iterator) return isolate->ThrowIllegalOperation();
361
362 local_object->SetEmbedderField(V8BreakIterator::kBreakIteratorIndex,
363 reinterpret_cast<Smi*>(break_iterator));
364 // Make sure that the pointer to adopted text is nullptr.
365 local_object->SetEmbedderField(V8BreakIterator::kUnicodeStringIndex,
366 static_cast<Smi*>(nullptr));
367
368 // Make object handle weak so we can delete the break iterator once GC kicks
369 // in.
370 Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
371 GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(),
372 V8BreakIterator::DeleteBreakIterator,
373 WeakCallbackType::kInternalFields);
374 return *local_object;
375 }
376
RUNTIME_FUNCTION(Runtime_BreakIteratorFirst)377 RUNTIME_FUNCTION(Runtime_BreakIteratorFirst) {
378 HandleScope scope(isolate);
379
380 DCHECK_EQ(1, args.length());
381
382 CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
383
384 icu::BreakIterator* break_iterator =
385 V8BreakIterator::UnpackBreakIterator(break_iterator_holder);
386 CHECK_NOT_NULL(break_iterator);
387
388 return *isolate->factory()->NewNumberFromInt(break_iterator->first());
389 }
390
RUNTIME_FUNCTION(Runtime_BreakIteratorNext)391 RUNTIME_FUNCTION(Runtime_BreakIteratorNext) {
392 HandleScope scope(isolate);
393
394 DCHECK_EQ(1, args.length());
395
396 CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
397
398 icu::BreakIterator* break_iterator =
399 V8BreakIterator::UnpackBreakIterator(break_iterator_holder);
400 CHECK_NOT_NULL(break_iterator);
401
402 return *isolate->factory()->NewNumberFromInt(break_iterator->next());
403 }
404
RUNTIME_FUNCTION(Runtime_BreakIteratorCurrent)405 RUNTIME_FUNCTION(Runtime_BreakIteratorCurrent) {
406 HandleScope scope(isolate);
407
408 DCHECK_EQ(1, args.length());
409
410 CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
411
412 icu::BreakIterator* break_iterator =
413 V8BreakIterator::UnpackBreakIterator(break_iterator_holder);
414 CHECK_NOT_NULL(break_iterator);
415
416 return *isolate->factory()->NewNumberFromInt(break_iterator->current());
417 }
418
RUNTIME_FUNCTION(Runtime_BreakIteratorBreakType)419 RUNTIME_FUNCTION(Runtime_BreakIteratorBreakType) {
420 HandleScope scope(isolate);
421
422 DCHECK_EQ(1, args.length());
423
424 CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
425
426 icu::BreakIterator* break_iterator =
427 V8BreakIterator::UnpackBreakIterator(break_iterator_holder);
428 CHECK_NOT_NULL(break_iterator);
429
430 // TODO(cira): Remove cast once ICU fixes base BreakIterator class.
431 icu::RuleBasedBreakIterator* rule_based_iterator =
432 static_cast<icu::RuleBasedBreakIterator*>(break_iterator);
433 int32_t status = rule_based_iterator->getRuleStatus();
434 // Keep return values in sync with JavaScript BreakType enum.
435 if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
436 return *isolate->factory()->NewStringFromStaticChars("none");
437 } else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
438 return ReadOnlyRoots(isolate).number_string();
439 } else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
440 return *isolate->factory()->NewStringFromStaticChars("letter");
441 } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
442 return *isolate->factory()->NewStringFromStaticChars("kana");
443 } else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
444 return *isolate->factory()->NewStringFromStaticChars("ideo");
445 } else {
446 return *isolate->factory()->NewStringFromStaticChars("unknown");
447 }
448 }
449
RUNTIME_FUNCTION(Runtime_ToLocaleDateTime)450 RUNTIME_FUNCTION(Runtime_ToLocaleDateTime) {
451 HandleScope scope(isolate);
452
453 DCHECK_EQ(6, args.length());
454
455 CONVERT_ARG_HANDLE_CHECKED(Object, date, 0);
456 CONVERT_ARG_HANDLE_CHECKED(Object, locales, 1);
457 CONVERT_ARG_HANDLE_CHECKED(Object, options, 2);
458 CONVERT_ARG_HANDLE_CHECKED(String, required, 3);
459 CONVERT_ARG_HANDLE_CHECKED(String, defaults, 4);
460 CONVERT_ARG_HANDLE_CHECKED(String, service, 5);
461
462 RETURN_RESULT_OR_FAILURE(
463 isolate, DateFormat::ToLocaleDateTime(
464 isolate, date, locales, options, required->ToCString().get(),
465 defaults->ToCString().get(), service->ToCString().get()));
466 }
467
RUNTIME_FUNCTION(Runtime_ToDateTimeOptions)468 RUNTIME_FUNCTION(Runtime_ToDateTimeOptions) {
469 HandleScope scope(isolate);
470 DCHECK_EQ(args.length(), 3);
471 CONVERT_ARG_HANDLE_CHECKED(Object, options, 0);
472 CONVERT_ARG_HANDLE_CHECKED(String, required, 1);
473 CONVERT_ARG_HANDLE_CHECKED(String, defaults, 2);
474 RETURN_RESULT_OR_FAILURE(
475 isolate, DateFormat::ToDateTimeOptions(isolate, options,
476 required->ToCString().get(),
477 defaults->ToCString().get()));
478 }
479
RUNTIME_FUNCTION(Runtime_StringToLowerCaseIntl)480 RUNTIME_FUNCTION(Runtime_StringToLowerCaseIntl) {
481 HandleScope scope(isolate);
482 DCHECK_EQ(args.length(), 1);
483 CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
484 s = String::Flatten(isolate, s);
485 RETURN_RESULT_OR_FAILURE(isolate, ConvertToLower(s, isolate));
486 }
487
RUNTIME_FUNCTION(Runtime_StringToUpperCaseIntl)488 RUNTIME_FUNCTION(Runtime_StringToUpperCaseIntl) {
489 HandleScope scope(isolate);
490 DCHECK_EQ(args.length(), 1);
491 CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
492 s = String::Flatten(isolate, s);
493 RETURN_RESULT_OR_FAILURE(isolate, ConvertToUpper(s, isolate));
494 }
495
RUNTIME_FUNCTION(Runtime_DateCacheVersion)496 RUNTIME_FUNCTION(Runtime_DateCacheVersion) {
497 HandleScope scope(isolate);
498 DCHECK_EQ(0, args.length());
499 if (isolate->serializer_enabled())
500 return ReadOnlyRoots(isolate).undefined_value();
501 if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) {
502 Handle<FixedArray> date_cache_version =
503 isolate->factory()->NewFixedArray(1, TENURED);
504 date_cache_version->set(0, Smi::kZero);
505 isolate->eternal_handles()->CreateSingleton(
506 isolate, *date_cache_version, EternalHandles::DATE_CACHE_VERSION);
507 }
508 Handle<FixedArray> date_cache_version =
509 Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton(
510 EternalHandles::DATE_CACHE_VERSION));
511 return date_cache_version->get(0);
512 }
513
RUNTIME_FUNCTION(Runtime_IntlUnwrapReceiver)514 RUNTIME_FUNCTION(Runtime_IntlUnwrapReceiver) {
515 HandleScope scope(isolate);
516 DCHECK_EQ(5, args.length());
517 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
518 CONVERT_SMI_ARG_CHECKED(type_int, 1);
519 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 2);
520 CONVERT_ARG_HANDLE_CHECKED(String, method, 3);
521 CONVERT_BOOLEAN_ARG_CHECKED(check_legacy_constructor, 4);
522
523 RETURN_RESULT_OR_FAILURE(
524 isolate, Intl::UnwrapReceiver(isolate, receiver, constructor,
525 Intl::TypeFromInt(type_int), method,
526 check_legacy_constructor));
527 }
528
RUNTIME_FUNCTION(Runtime_SupportedLocalesOf)529 RUNTIME_FUNCTION(Runtime_SupportedLocalesOf) {
530 HandleScope scope(isolate);
531
532 DCHECK_EQ(args.length(), 3);
533
534 CONVERT_ARG_HANDLE_CHECKED(String, service, 0);
535 CONVERT_ARG_HANDLE_CHECKED(Object, locales, 1);
536 CONVERT_ARG_HANDLE_CHECKED(Object, options, 2);
537
538 RETURN_RESULT_OR_FAILURE(
539 isolate, Intl::SupportedLocalesOf(isolate, service, locales, options));
540 }
541
542 } // namespace internal
543 } // namespace v8
544