1 // Copyright 2017 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 <list>
11 #include <memory>
12 
13 #include "src/builtins/builtins-utils-inl.h"
14 #include "src/builtins/builtins.h"
15 #include "src/date/date.h"
16 #include "src/logging/counters.h"
17 #include "src/objects/elements.h"
18 #include "src/objects/intl-objects.h"
19 #include "src/objects/js-array-inl.h"
20 #include "src/objects/js-break-iterator-inl.h"
21 #include "src/objects/js-collator-inl.h"
22 #include "src/objects/js-date-time-format-inl.h"
23 #include "src/objects/js-display-names-inl.h"
24 #include "src/objects/js-list-format-inl.h"
25 #include "src/objects/js-locale-inl.h"
26 #include "src/objects/js-number-format-inl.h"
27 #include "src/objects/js-plural-rules-inl.h"
28 #include "src/objects/js-relative-time-format-inl.h"
29 #include "src/objects/js-segment-iterator-inl.h"
30 #include "src/objects/js-segmenter-inl.h"
31 #include "src/objects/js-segments-inl.h"
32 #include "src/objects/objects-inl.h"
33 #include "src/objects/option-utils.h"
34 #include "src/objects/property-descriptor.h"
35 #include "src/objects/smi.h"
36 #include "unicode/brkiter.h"
37 
38 namespace v8 {
39 namespace internal {
40 
BUILTIN(StringPrototypeToUpperCaseIntl)41 BUILTIN(StringPrototypeToUpperCaseIntl) {
42   HandleScope scope(isolate);
43   TO_THIS_STRING(string, "String.prototype.toUpperCase");
44   string = String::Flatten(isolate, string);
45   RETURN_RESULT_OR_FAILURE(isolate, Intl::ConvertToUpper(isolate, string));
46 }
47 
BUILTIN(StringPrototypeNormalizeIntl)48 BUILTIN(StringPrototypeNormalizeIntl) {
49   HandleScope handle_scope(isolate);
50   isolate->CountUsage(v8::Isolate::UseCounterFeature::kStringNormalize);
51   TO_THIS_STRING(string, "String.prototype.normalize");
52 
53   Handle<Object> form_input = args.atOrUndefined(isolate, 1);
54 
55   RETURN_RESULT_OR_FAILURE(isolate,
56                            Intl::Normalize(isolate, string, form_input));
57 }
58 
BUILTIN(V8BreakIteratorSupportedLocalesOf)59 BUILTIN(V8BreakIteratorSupportedLocalesOf) {
60   HandleScope scope(isolate);
61   Handle<Object> locales = args.atOrUndefined(isolate, 1);
62   Handle<Object> options = args.atOrUndefined(isolate, 2);
63 
64   RETURN_RESULT_OR_FAILURE(
65       isolate, Intl::SupportedLocalesOf(
66                    isolate, "Intl.v8BreakIterator.supportedLocalesOf",
67                    JSV8BreakIterator::GetAvailableLocales(), locales, options));
68 }
69 
BUILTIN(NumberFormatSupportedLocalesOf)70 BUILTIN(NumberFormatSupportedLocalesOf) {
71   HandleScope scope(isolate);
72   Handle<Object> locales = args.atOrUndefined(isolate, 1);
73   Handle<Object> options = args.atOrUndefined(isolate, 2);
74 
75   RETURN_RESULT_OR_FAILURE(
76       isolate, Intl::SupportedLocalesOf(
77                    isolate, "Intl.NumberFormat.supportedLocalesOf",
78                    JSNumberFormat::GetAvailableLocales(), locales, options));
79 }
80 
BUILTIN(NumberFormatPrototypeFormatToParts)81 BUILTIN(NumberFormatPrototypeFormatToParts) {
82   const char* const method_name = "Intl.NumberFormat.prototype.formatToParts";
83   HandleScope handle_scope(isolate);
84   CHECK_RECEIVER(JSNumberFormat, number_format, method_name);
85 
86   Handle<Object> x;
87   if (args.length() >= 2) {
88     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x,
89                                        Object::ToNumeric(isolate, args.at(1)));
90   } else {
91     x = isolate->factory()->nan_value();
92   }
93 
94   RETURN_RESULT_OR_FAILURE(
95       isolate, JSNumberFormat::FormatToParts(isolate, number_format, x));
96 }
97 
BUILTIN(DateTimeFormatPrototypeResolvedOptions)98 BUILTIN(DateTimeFormatPrototypeResolvedOptions) {
99   const char* const method_name =
100       "Intl.DateTimeFormat.prototype.resolvedOptions";
101   HandleScope scope(isolate);
102   CHECK_RECEIVER(JSReceiver, format_holder, method_name);
103 
104   // 3. Let dtf be ? UnwrapDateTimeFormat(dtf).
105   Handle<JSDateTimeFormat> date_time_format;
106   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
107       isolate, date_time_format,
108       JSDateTimeFormat::UnwrapDateTimeFormat(isolate, format_holder));
109 
110   RETURN_RESULT_OR_FAILURE(
111       isolate, JSDateTimeFormat::ResolvedOptions(isolate, date_time_format));
112 }
113 
BUILTIN(DateTimeFormatSupportedLocalesOf)114 BUILTIN(DateTimeFormatSupportedLocalesOf) {
115   HandleScope scope(isolate);
116   Handle<Object> locales = args.atOrUndefined(isolate, 1);
117   Handle<Object> options = args.atOrUndefined(isolate, 2);
118 
119   RETURN_RESULT_OR_FAILURE(
120       isolate, Intl::SupportedLocalesOf(
121                    isolate, "Intl.DateTimeFormat.supportedLocalesOf",
122                    JSDateTimeFormat::GetAvailableLocales(), locales, options));
123 }
124 
BUILTIN(DateTimeFormatPrototypeFormatToParts)125 BUILTIN(DateTimeFormatPrototypeFormatToParts) {
126   const char* const method_name = "Intl.DateTimeFormat.prototype.formatToParts";
127   HandleScope handle_scope(isolate);
128   CHECK_RECEIVER(JSObject, date_format_holder, method_name);
129   Factory* factory = isolate->factory();
130 
131   if (!date_format_holder->IsJSDateTimeFormat()) {
132     THROW_NEW_ERROR_RETURN_FAILURE(
133         isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
134                               factory->NewStringFromAsciiChecked(method_name),
135                               date_format_holder));
136   }
137   Handle<JSDateTimeFormat> dtf =
138       Handle<JSDateTimeFormat>::cast(date_format_holder);
139 
140   Handle<Object> x = args.atOrUndefined(isolate, 1);
141   if (x->IsUndefined(isolate)) {
142     x = factory->NewNumber(JSDate::CurrentTimeValue(isolate));
143   } else {
144     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x,
145                                        Object::ToNumber(isolate, args.at(1)));
146   }
147 
148   double date_value = DateCache::TimeClip(x->Number());
149   if (std::isnan(date_value)) {
150     THROW_NEW_ERROR_RETURN_FAILURE(
151         isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
152   }
153 
154   RETURN_RESULT_OR_FAILURE(isolate, JSDateTimeFormat::FormatToParts(
155                                         isolate, dtf, date_value, false));
156 }
157 
158 // Common code for DateTimeFormatPrototypeFormtRange(|ToParts)
159 template <class T>
DateTimeFormatRange(BuiltinArguments args,Isolate * isolate,const char * const method_name,MaybeHandle<T> (* format)(Isolate *,Handle<JSDateTimeFormat>,double,double))160 V8_WARN_UNUSED_RESULT Object DateTimeFormatRange(
161     BuiltinArguments args, Isolate* isolate, const char* const method_name,
162     MaybeHandle<T> (*format)(Isolate*, Handle<JSDateTimeFormat>, double,
163                              double)) {
164   // 1. Let dtf be this value.
165   // 2. If Type(dtf) is not Object, throw a TypeError exception.
166   CHECK_RECEIVER(JSObject, date_format_holder, method_name);
167 
168   Factory* factory = isolate->factory();
169 
170   // 3. If dtf does not have an [[InitializedDateTimeFormat]] internal slot,
171   //    throw a TypeError exception.
172   if (!date_format_holder->IsJSDateTimeFormat()) {
173     THROW_NEW_ERROR_RETURN_FAILURE(
174         isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
175                               factory->NewStringFromAsciiChecked(method_name),
176                               date_format_holder));
177   }
178   Handle<JSDateTimeFormat> dtf =
179       Handle<JSDateTimeFormat>::cast(date_format_holder);
180 
181   // 4. If startDate is undefined or endDate is undefined, throw a TypeError
182   // exception.
183   Handle<Object> start_date = args.atOrUndefined(isolate, 1);
184   Handle<Object> end_date = args.atOrUndefined(isolate, 2);
185   if (start_date->IsUndefined(isolate) || end_date->IsUndefined(isolate)) {
186     THROW_NEW_ERROR_RETURN_FAILURE(
187         isolate, NewTypeError(MessageTemplate::kInvalidTimeValue));
188   }
189   // 5. Let x be ? ToNumber(startDate).
190   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, start_date,
191                                      Object::ToNumber(isolate, start_date));
192   double x = start_date->Number();
193 
194   // 6. Let y be ? ToNumber(endDate).
195   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, end_date,
196                                      Object::ToNumber(isolate, end_date));
197   double y = end_date->Number();
198   // 7. If x is greater than y, throw a RangeError exception.
199   if (x > y) {
200     THROW_NEW_ERROR_RETURN_FAILURE(
201         isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
202   }
203 
204   // 8. Return ? FormatDateTimeRange(dtf, x, y)
205   // OR
206   // 8. Return ? FormatDateTimeRangeToParts(dtf, x, y).
207   RETURN_RESULT_OR_FAILURE(isolate, format(isolate, dtf, x, y));
208 }
209 
BUILTIN(DateTimeFormatPrototypeFormatRange)210 BUILTIN(DateTimeFormatPrototypeFormatRange) {
211   const char* const method_name = "Intl.DateTimeFormat.prototype.formatRange";
212   HandleScope handle_scope(isolate);
213   return DateTimeFormatRange<String>(args, isolate, method_name,
214                                      JSDateTimeFormat::FormatRange);
215 }
216 
BUILTIN(DateTimeFormatPrototypeFormatRangeToParts)217 BUILTIN(DateTimeFormatPrototypeFormatRangeToParts) {
218   const char* const method_name =
219       "Intl.DateTimeFormat.prototype.formatRangeToParts";
220   HandleScope handle_scope(isolate);
221   return DateTimeFormatRange<JSArray>(args, isolate, method_name,
222                                       JSDateTimeFormat::FormatRangeToParts);
223 }
224 
225 namespace {
226 
CreateBoundFunction(Isolate * isolate,Handle<JSObject> object,Builtin builtin,int len)227 Handle<JSFunction> CreateBoundFunction(Isolate* isolate,
228                                        Handle<JSObject> object, Builtin builtin,
229                                        int len) {
230   Handle<NativeContext> native_context(isolate->context().native_context(),
231                                        isolate);
232   Handle<Context> context = isolate->factory()->NewBuiltinContext(
233       native_context,
234       static_cast<int>(Intl::BoundFunctionContextSlot::kLength));
235 
236   context->set(static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction),
237                *object);
238 
239   Handle<SharedFunctionInfo> info =
240       isolate->factory()->NewSharedFunctionInfoForBuiltin(
241           isolate->factory()->empty_string(), builtin, kNormalFunction);
242   info->set_internal_formal_parameter_count(JSParameterCount(len));
243   info->set_length(len);
244 
245   return Factory::JSFunctionBuilder{isolate, info, context}
246       .set_map(isolate->strict_function_without_prototype_map())
247       .Build();
248 }
249 
250 /**
251  * Common code shared between DateTimeFormatConstructor and
252  * NumberFormatConstrutor
253  */
254 template <class T>
LegacyFormatConstructor(BuiltinArguments args,Isolate * isolate,v8::Isolate::UseCounterFeature feature,Handle<Object> constructor,const char * method_name)255 Object LegacyFormatConstructor(BuiltinArguments args, Isolate* isolate,
256                                v8::Isolate::UseCounterFeature feature,
257                                Handle<Object> constructor,
258                                const char* method_name) {
259   isolate->CountUsage(feature);
260   Handle<JSReceiver> new_target;
261   // 1. If NewTarget is undefined, let newTarget be the active
262   // function object, else let newTarget be NewTarget.
263   if (args.new_target()->IsUndefined(isolate)) {
264     new_target = args.target();
265   } else {
266     new_target = Handle<JSReceiver>::cast(args.new_target());
267   }
268 
269   // [[Construct]]
270   Handle<JSFunction> target = args.target();
271   Handle<Object> locales = args.atOrUndefined(isolate, 1);
272   Handle<Object> options = args.atOrUndefined(isolate, 2);
273 
274   // 2. Let format be ? OrdinaryCreateFromConstructor(newTarget,
275   // "%<T>Prototype%", ...).
276   Handle<Map> map;
277   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
278       isolate, map, JSFunction::GetDerivedMap(isolate, target, new_target));
279 
280   // 3. Perform ? Initialize<T>(Format, locales, options).
281   Handle<T> format;
282   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
283       isolate, format, T::New(isolate, map, locales, options, method_name));
284   // 4. Let this be the this value.
285   if (args.new_target()->IsUndefined(isolate)) {
286     Handle<Object> receiver = args.receiver();
287     // 5. If NewTarget is undefined and ? OrdinaryHasInstance(%<T>%, this)
288     // is true, then Look up the intrinsic value that has been stored on
289     // the context.
290     Handle<Object> ordinary_has_instance_obj;
291     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
292         isolate, ordinary_has_instance_obj,
293         Object::OrdinaryHasInstance(isolate, constructor, receiver));
294     if (ordinary_has_instance_obj->BooleanValue(isolate)) {
295       if (!receiver->IsJSReceiver()) {
296         THROW_NEW_ERROR_RETURN_FAILURE(
297             isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
298                                   isolate->factory()->NewStringFromAsciiChecked(
299                                       method_name),
300                                   receiver));
301       }
302       Handle<JSReceiver> rec = Handle<JSReceiver>::cast(receiver);
303       // a. Perform ? DefinePropertyOrThrow(this,
304       // %Intl%.[[FallbackSymbol]], PropertyDescriptor{ [[Value]]: format,
305       // [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }).
306       PropertyDescriptor desc;
307       desc.set_value(format);
308       desc.set_writable(false);
309       desc.set_enumerable(false);
310       desc.set_configurable(false);
311       Maybe<bool> success = JSReceiver::DefineOwnProperty(
312           isolate, rec, isolate->factory()->intl_fallback_symbol(), &desc,
313           Just(kThrowOnError));
314       MAYBE_RETURN(success, ReadOnlyRoots(isolate).exception());
315       CHECK(success.FromJust());
316       // b. b. Return this.
317       return *receiver;
318     }
319   }
320   // 6. Return format.
321   return *format;
322 }
323 
324 /**
325  * Common code shared by ListFormat, RelativeTimeFormat, PluralRules, and
326  * Segmenter
327  */
328 template <class T>
DisallowCallConstructor(BuiltinArguments args,Isolate * isolate,v8::Isolate::UseCounterFeature feature,const char * method_name)329 Object DisallowCallConstructor(BuiltinArguments args, Isolate* isolate,
330                                v8::Isolate::UseCounterFeature feature,
331                                const char* method_name) {
332   isolate->CountUsage(feature);
333 
334   // 1. If NewTarget is undefined, throw a TypeError exception.
335   if (args.new_target()->IsUndefined(isolate)) {  // [[Call]]
336     THROW_NEW_ERROR_RETURN_FAILURE(
337         isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
338                               isolate->factory()->NewStringFromAsciiChecked(
339                                   method_name)));
340   }
341   // [[Construct]]
342   Handle<JSFunction> target = args.target();
343   Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
344 
345   Handle<Map> map;
346   // 2. Let result be OrdinaryCreateFromConstructor(NewTarget,
347   //    "%<T>Prototype%").
348   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
349       isolate, map, JSFunction::GetDerivedMap(isolate, target, new_target));
350 
351   Handle<Object> locales = args.atOrUndefined(isolate, 1);
352   Handle<Object> options = args.atOrUndefined(isolate, 2);
353 
354   // 3. Return New<T>(t, locales, options).
355   RETURN_RESULT_OR_FAILURE(isolate, T::New(isolate, map, locales, options));
356 }
357 
358 /**
359  * Common code shared by Collator and V8BreakIterator
360  */
361 template <class T>
CallOrConstructConstructor(BuiltinArguments args,Isolate * isolate,const char * method_name)362 Object CallOrConstructConstructor(BuiltinArguments args, Isolate* isolate,
363                                   const char* method_name) {
364   Handle<JSReceiver> new_target;
365 
366   if (args.new_target()->IsUndefined(isolate)) {
367     new_target = args.target();
368   } else {
369     new_target = Handle<JSReceiver>::cast(args.new_target());
370   }
371 
372   // [[Construct]]
373   Handle<JSFunction> target = args.target();
374 
375   Handle<Object> locales = args.atOrUndefined(isolate, 1);
376   Handle<Object> options = args.atOrUndefined(isolate, 2);
377 
378   Handle<Map> map;
379   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
380       isolate, map, JSFunction::GetDerivedMap(isolate, target, new_target));
381 
382   RETURN_RESULT_OR_FAILURE(isolate,
383                            T::New(isolate, map, locales, options, method_name));
384 }
385 
386 }  // namespace
387 
388 // Intl.DisplayNames
389 
BUILTIN(DisplayNamesConstructor)390 BUILTIN(DisplayNamesConstructor) {
391   HandleScope scope(isolate);
392 
393   return DisallowCallConstructor<JSDisplayNames>(
394       args, isolate, v8::Isolate::UseCounterFeature::kDisplayNames,
395       "Intl.DisplayNames");
396 }
397 
BUILTIN(DisplayNamesPrototypeResolvedOptions)398 BUILTIN(DisplayNamesPrototypeResolvedOptions) {
399   HandleScope scope(isolate);
400   CHECK_RECEIVER(JSDisplayNames, holder,
401                  "Intl.DisplayNames.prototype.resolvedOptions");
402   return *JSDisplayNames::ResolvedOptions(isolate, holder);
403 }
404 
BUILTIN(DisplayNamesSupportedLocalesOf)405 BUILTIN(DisplayNamesSupportedLocalesOf) {
406   HandleScope scope(isolate);
407   Handle<Object> locales = args.atOrUndefined(isolate, 1);
408   Handle<Object> options = args.atOrUndefined(isolate, 2);
409 
410   RETURN_RESULT_OR_FAILURE(
411       isolate, Intl::SupportedLocalesOf(
412                    isolate, "Intl.DisplayNames.supportedLocalesOf",
413                    JSDisplayNames::GetAvailableLocales(), locales, options));
414 }
415 
BUILTIN(DisplayNamesPrototypeOf)416 BUILTIN(DisplayNamesPrototypeOf) {
417   HandleScope scope(isolate);
418   CHECK_RECEIVER(JSDisplayNames, holder, "Intl.DisplayNames.prototype.of");
419   Handle<Object> code_obj = args.atOrUndefined(isolate, 1);
420 
421   RETURN_RESULT_OR_FAILURE(isolate,
422                            JSDisplayNames::Of(isolate, holder, code_obj));
423 }
424 
425 // Intl.NumberFormat
426 
BUILTIN(NumberFormatConstructor)427 BUILTIN(NumberFormatConstructor) {
428   HandleScope scope(isolate);
429 
430   return LegacyFormatConstructor<JSNumberFormat>(
431       args, isolate, v8::Isolate::UseCounterFeature::kNumberFormat,
432       isolate->intl_number_format_function(), "Intl.NumberFormat");
433 }
434 
BUILTIN(NumberFormatPrototypeResolvedOptions)435 BUILTIN(NumberFormatPrototypeResolvedOptions) {
436   HandleScope scope(isolate);
437   const char* const method_name = "Intl.NumberFormat.prototype.resolvedOptions";
438 
439   // 1. Let nf be the this value.
440   // 2. If Type(nf) is not Object, throw a TypeError exception.
441   CHECK_RECEIVER(JSReceiver, number_format_holder, method_name);
442 
443   // 3. Let nf be ? UnwrapNumberFormat(nf)
444   Handle<JSNumberFormat> number_format;
445   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
446       isolate, number_format,
447       JSNumberFormat::UnwrapNumberFormat(isolate, number_format_holder));
448 
449   return *JSNumberFormat::ResolvedOptions(isolate, number_format);
450 }
451 
BUILTIN(NumberFormatPrototypeFormatNumber)452 BUILTIN(NumberFormatPrototypeFormatNumber) {
453   const char* const method_name = "get Intl.NumberFormat.prototype.format";
454   HandleScope scope(isolate);
455 
456   // 1. Let nf be the this value.
457   // 2. If Type(nf) is not Object, throw a TypeError exception.
458   CHECK_RECEIVER(JSReceiver, receiver, method_name);
459 
460   // 3. Let nf be ? UnwrapNumberFormat(nf).
461   Handle<JSNumberFormat> number_format;
462   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
463       isolate, number_format,
464       JSNumberFormat::UnwrapNumberFormat(isolate, receiver));
465 
466   Handle<Object> bound_format(number_format->bound_format(), isolate);
467 
468   // 4. If nf.[[BoundFormat]] is undefined, then
469   if (!bound_format->IsUndefined(isolate)) {
470     DCHECK(bound_format->IsJSFunction());
471     // 5. Return nf.[[BoundFormat]].
472     return *bound_format;
473   }
474 
475   Handle<JSFunction> new_bound_format_function = CreateBoundFunction(
476       isolate, number_format, Builtin::kNumberFormatInternalFormatNumber, 1);
477 
478   // 4. c. Set nf.[[BoundFormat]] to F.
479   number_format->set_bound_format(*new_bound_format_function);
480 
481   // 5. Return nf.[[BoundFormat]].
482   return *new_bound_format_function;
483 }
484 
BUILTIN(NumberFormatInternalFormatNumber)485 BUILTIN(NumberFormatInternalFormatNumber) {
486   HandleScope scope(isolate);
487 
488   Handle<Context> context = Handle<Context>(isolate->context(), isolate);
489 
490   // 1. Let nf be F.[[NumberFormat]].
491   // 2. Assert: Type(nf) is Object and nf has an
492   //    [[InitializedNumberFormat]] internal slot.
493   Handle<JSNumberFormat> number_format = Handle<JSNumberFormat>(
494       JSNumberFormat::cast(context->get(
495           static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
496       isolate);
497 
498   // 3. If value is not provided, let value be undefined.
499   Handle<Object> value = args.atOrUndefined(isolate, 1);
500 
501   // 4. Let x be ? ToNumeric(value).
502   Handle<Object> numeric_obj;
503   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, numeric_obj,
504                                      Object::ToNumeric(isolate, value));
505 
506   icu::number::LocalizedNumberFormatter* icu_localized_number_formatter =
507       number_format->icu_number_formatter().raw();
508   CHECK_NOT_NULL(icu_localized_number_formatter);
509 
510   // Return FormatNumber(nf, x).
511   RETURN_RESULT_OR_FAILURE(
512       isolate, JSNumberFormat::FormatNumeric(
513                    isolate, *icu_localized_number_formatter, numeric_obj));
514 }
515 
BUILTIN(DateTimeFormatConstructor)516 BUILTIN(DateTimeFormatConstructor) {
517   HandleScope scope(isolate);
518 
519   return LegacyFormatConstructor<JSDateTimeFormat>(
520       args, isolate, v8::Isolate::UseCounterFeature::kDateTimeFormat,
521       isolate->intl_date_time_format_function(), "Intl.DateTimeFormat");
522 }
523 
BUILTIN(DateTimeFormatPrototypeFormat)524 BUILTIN(DateTimeFormatPrototypeFormat) {
525   const char* const method_name = "get Intl.DateTimeFormat.prototype.format";
526   HandleScope scope(isolate);
527 
528   // 1. Let dtf be this value.
529   // 2. If Type(dtf) is not Object, throw a TypeError exception.
530   CHECK_RECEIVER(JSReceiver, receiver, method_name);
531 
532   // 3. Let dtf be ? UnwrapDateTimeFormat(dtf).
533   Handle<JSDateTimeFormat> format;
534   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
535       isolate, format,
536       JSDateTimeFormat::UnwrapDateTimeFormat(isolate, receiver));
537 
538   Handle<Object> bound_format = Handle<Object>(format->bound_format(), isolate);
539 
540   // 4. If dtf.[[BoundFormat]] is undefined, then
541   if (!bound_format->IsUndefined(isolate)) {
542     DCHECK(bound_format->IsJSFunction());
543     // 5. Return dtf.[[BoundFormat]].
544     return *bound_format;
545   }
546 
547   Handle<JSFunction> new_bound_format_function = CreateBoundFunction(
548       isolate, format, Builtin::kDateTimeFormatInternalFormat, 1);
549 
550   // 4.c. Set dtf.[[BoundFormat]] to F.
551   format->set_bound_format(*new_bound_format_function);
552 
553   // 5. Return dtf.[[BoundFormat]].
554   return *new_bound_format_function;
555 }
556 
BUILTIN(DateTimeFormatInternalFormat)557 BUILTIN(DateTimeFormatInternalFormat) {
558   HandleScope scope(isolate);
559   Handle<Context> context = Handle<Context>(isolate->context(), isolate);
560 
561   // 1. Let dtf be F.[[DateTimeFormat]].
562   // 2. Assert: Type(dtf) is Object and dtf has an [[InitializedDateTimeFormat]]
563   // internal slot.
564   Handle<JSDateTimeFormat> date_format_holder = Handle<JSDateTimeFormat>(
565       JSDateTimeFormat::cast(context->get(
566           static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
567       isolate);
568 
569   Handle<Object> date = args.atOrUndefined(isolate, 1);
570 
571   RETURN_RESULT_OR_FAILURE(isolate, JSDateTimeFormat::DateTimeFormat(
572                                         isolate, date_format_holder, date));
573 }
574 
BUILTIN(IntlGetCanonicalLocales)575 BUILTIN(IntlGetCanonicalLocales) {
576   HandleScope scope(isolate);
577   Handle<Object> locales = args.atOrUndefined(isolate, 1);
578 
579   RETURN_RESULT_OR_FAILURE(isolate,
580                            Intl::GetCanonicalLocales(isolate, locales));
581 }
582 
BUILTIN(IntlSupportedValuesOf)583 BUILTIN(IntlSupportedValuesOf) {
584   HandleScope scope(isolate);
585   Handle<Object> locales = args.atOrUndefined(isolate, 1);
586 
587   RETURN_RESULT_OR_FAILURE(isolate, Intl::SupportedValuesOf(isolate, locales));
588 }
589 
BUILTIN(ListFormatConstructor)590 BUILTIN(ListFormatConstructor) {
591   HandleScope scope(isolate);
592 
593   return DisallowCallConstructor<JSListFormat>(
594       args, isolate, v8::Isolate::UseCounterFeature::kListFormat,
595       "Intl.ListFormat");
596 }
597 
BUILTIN(ListFormatPrototypeResolvedOptions)598 BUILTIN(ListFormatPrototypeResolvedOptions) {
599   HandleScope scope(isolate);
600   CHECK_RECEIVER(JSListFormat, format_holder,
601                  "Intl.ListFormat.prototype.resolvedOptions");
602   return *JSListFormat::ResolvedOptions(isolate, format_holder);
603 }
604 
BUILTIN(ListFormatSupportedLocalesOf)605 BUILTIN(ListFormatSupportedLocalesOf) {
606   HandleScope scope(isolate);
607   Handle<Object> locales = args.atOrUndefined(isolate, 1);
608   Handle<Object> options = args.atOrUndefined(isolate, 2);
609 
610   RETURN_RESULT_OR_FAILURE(
611       isolate, Intl::SupportedLocalesOf(
612                    isolate, "Intl.ListFormat.supportedLocalesOf",
613                    JSListFormat::GetAvailableLocales(), locales, options));
614 }
615 
616 // Intl.Locale implementation
BUILTIN(LocaleConstructor)617 BUILTIN(LocaleConstructor) {
618   HandleScope scope(isolate);
619 
620   isolate->CountUsage(v8::Isolate::UseCounterFeature::kLocale);
621 
622   const char* method_name = "Intl.Locale";
623   if (args.new_target()->IsUndefined(isolate)) {  // [[Call]]
624     THROW_NEW_ERROR_RETURN_FAILURE(
625         isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
626                               isolate->factory()->NewStringFromAsciiChecked(
627                                   method_name)));
628   }
629   // [[Construct]]
630   Handle<JSFunction> target = args.target();
631   Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
632 
633   Handle<Object> tag = args.atOrUndefined(isolate, 1);
634   Handle<Object> options = args.atOrUndefined(isolate, 2);
635 
636   Handle<Map> map;
637   // 6. Let locale be ? OrdinaryCreateFromConstructor(NewTarget,
638   // %LocalePrototype%, internalSlotsList).
639   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
640       isolate, map, JSFunction::GetDerivedMap(isolate, target, new_target));
641 
642   // 7. If Type(tag) is not String or Object, throw a TypeError exception.
643   if (!tag->IsString() && !tag->IsJSReceiver()) {
644     THROW_NEW_ERROR_RETURN_FAILURE(
645         isolate, NewTypeError(MessageTemplate::kLocaleNotEmpty));
646   }
647 
648   Handle<String> locale_string;
649   // 8. If Type(tag) is Object and tag has an [[InitializedLocale]] internal
650   // slot, then
651   if (tag->IsJSLocale()) {
652     // a. Let tag be tag.[[Locale]].
653     locale_string = JSLocale::ToString(isolate, Handle<JSLocale>::cast(tag));
654   } else {  // 9. Else,
655     // a. Let tag be ? ToString(tag).
656     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, locale_string,
657                                        Object::ToString(isolate, tag));
658   }
659 
660   // 10. Set options to ? CoerceOptionsToObject(options).
661   Handle<JSReceiver> options_object;
662   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
663       isolate, options_object,
664       CoerceOptionsToObject(isolate, options, method_name));
665 
666   RETURN_RESULT_OR_FAILURE(
667       isolate, JSLocale::New(isolate, map, locale_string, options_object));
668 }
669 
BUILTIN(LocalePrototypeMaximize)670 BUILTIN(LocalePrototypeMaximize) {
671   HandleScope scope(isolate);
672   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.maximize");
673   RETURN_RESULT_OR_FAILURE(isolate, JSLocale::Maximize(isolate, locale));
674 }
675 
BUILTIN(LocalePrototypeMinimize)676 BUILTIN(LocalePrototypeMinimize) {
677   HandleScope scope(isolate);
678   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.minimize");
679   RETURN_RESULT_OR_FAILURE(isolate, JSLocale::Minimize(isolate, locale));
680 }
681 
BUILTIN(LocalePrototypeCalendars)682 BUILTIN(LocalePrototypeCalendars) {
683   HandleScope scope(isolate);
684   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.calendars");
685   RETURN_RESULT_OR_FAILURE(isolate, JSLocale::Calendars(isolate, locale));
686 }
687 
BUILTIN(LocalePrototypeCollations)688 BUILTIN(LocalePrototypeCollations) {
689   HandleScope scope(isolate);
690   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.collations");
691   RETURN_RESULT_OR_FAILURE(isolate, JSLocale::Collations(isolate, locale));
692 }
693 
BUILTIN(LocalePrototypeHourCycles)694 BUILTIN(LocalePrototypeHourCycles) {
695   HandleScope scope(isolate);
696   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.hourCycles");
697   RETURN_RESULT_OR_FAILURE(isolate, JSLocale::HourCycles(isolate, locale));
698 }
699 
BUILTIN(LocalePrototypeNumberingSystems)700 BUILTIN(LocalePrototypeNumberingSystems) {
701   HandleScope scope(isolate);
702   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.numberingSystems");
703   RETURN_RESULT_OR_FAILURE(isolate,
704                            JSLocale::NumberingSystems(isolate, locale));
705 }
706 
BUILTIN(LocalePrototypeTextInfo)707 BUILTIN(LocalePrototypeTextInfo) {
708   HandleScope scope(isolate);
709   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.textInfo");
710   RETURN_RESULT_OR_FAILURE(isolate, JSLocale::TextInfo(isolate, locale));
711 }
712 
BUILTIN(LocalePrototypeTimeZones)713 BUILTIN(LocalePrototypeTimeZones) {
714   HandleScope scope(isolate);
715   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.timeZones");
716   RETURN_RESULT_OR_FAILURE(isolate, JSLocale::TimeZones(isolate, locale));
717 }
718 
BUILTIN(LocalePrototypeWeekInfo)719 BUILTIN(LocalePrototypeWeekInfo) {
720   HandleScope scope(isolate);
721   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.weekInfo");
722   RETURN_RESULT_OR_FAILURE(isolate, JSLocale::WeekInfo(isolate, locale));
723 }
724 
BUILTIN(RelativeTimeFormatSupportedLocalesOf)725 BUILTIN(RelativeTimeFormatSupportedLocalesOf) {
726   HandleScope scope(isolate);
727   Handle<Object> locales = args.atOrUndefined(isolate, 1);
728   Handle<Object> options = args.atOrUndefined(isolate, 2);
729 
730   RETURN_RESULT_OR_FAILURE(
731       isolate,
732       Intl::SupportedLocalesOf(
733           isolate, "Intl.RelativeTimeFormat.supportedLocalesOf",
734           JSRelativeTimeFormat::GetAvailableLocales(), locales, options));
735 }
736 
BUILTIN(RelativeTimeFormatPrototypeFormat)737 BUILTIN(RelativeTimeFormatPrototypeFormat) {
738   HandleScope scope(isolate);
739   // 1. Let relativeTimeFormat be the this value.
740   // 2. If Type(relativeTimeFormat) is not Object or relativeTimeFormat does not
741   //    have an [[InitializedRelativeTimeFormat]] internal slot whose value is
742   //    true, throw a TypeError exception.
743   CHECK_RECEIVER(JSRelativeTimeFormat, format_holder,
744                  "Intl.RelativeTimeFormat.prototype.format");
745   Handle<Object> value_obj = args.atOrUndefined(isolate, 1);
746   Handle<Object> unit_obj = args.atOrUndefined(isolate, 2);
747 
748   RETURN_RESULT_OR_FAILURE(
749       isolate, JSRelativeTimeFormat::Format(isolate, value_obj, unit_obj,
750                                             format_holder));
751 }
752 
BUILTIN(RelativeTimeFormatPrototypeFormatToParts)753 BUILTIN(RelativeTimeFormatPrototypeFormatToParts) {
754   HandleScope scope(isolate);
755   // 1. Let relativeTimeFormat be the this value.
756   // 2. If Type(relativeTimeFormat) is not Object or relativeTimeFormat does not
757   //    have an [[InitializedRelativeTimeFormat]] internal slot whose value is
758   //    true, throw a TypeError exception.
759   CHECK_RECEIVER(JSRelativeTimeFormat, format_holder,
760                  "Intl.RelativeTimeFormat.prototype.formatToParts");
761   Handle<Object> value_obj = args.atOrUndefined(isolate, 1);
762   Handle<Object> unit_obj = args.atOrUndefined(isolate, 2);
763   RETURN_RESULT_OR_FAILURE(
764       isolate, JSRelativeTimeFormat::FormatToParts(isolate, value_obj, unit_obj,
765                                                    format_holder));
766 }
767 
768 // Locale getters.
BUILTIN(LocalePrototypeLanguage)769 BUILTIN(LocalePrototypeLanguage) {
770   HandleScope scope(isolate);
771   // CHECK_RECEIVER will case locale_holder to JSLocale.
772   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.language");
773 
774   return *JSLocale::Language(isolate, locale);
775 }
776 
BUILTIN(LocalePrototypeScript)777 BUILTIN(LocalePrototypeScript) {
778   HandleScope scope(isolate);
779   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.script");
780 
781   return *JSLocale::Script(isolate, locale);
782 }
783 
BUILTIN(LocalePrototypeRegion)784 BUILTIN(LocalePrototypeRegion) {
785   HandleScope scope(isolate);
786   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.region");
787 
788   return *JSLocale::Region(isolate, locale);
789 }
790 
BUILTIN(LocalePrototypeBaseName)791 BUILTIN(LocalePrototypeBaseName) {
792   HandleScope scope(isolate);
793   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.baseName");
794 
795   return *JSLocale::BaseName(isolate, locale);
796 }
797 
BUILTIN(LocalePrototypeCalendar)798 BUILTIN(LocalePrototypeCalendar) {
799   HandleScope scope(isolate);
800   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.calendar");
801 
802   return *JSLocale::Calendar(isolate, locale);
803 }
804 
BUILTIN(LocalePrototypeCaseFirst)805 BUILTIN(LocalePrototypeCaseFirst) {
806   HandleScope scope(isolate);
807   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.caseFirst");
808 
809   return *JSLocale::CaseFirst(isolate, locale);
810 }
811 
BUILTIN(LocalePrototypeCollation)812 BUILTIN(LocalePrototypeCollation) {
813   HandleScope scope(isolate);
814   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.collation");
815 
816   return *JSLocale::Collation(isolate, locale);
817 }
818 
BUILTIN(LocalePrototypeHourCycle)819 BUILTIN(LocalePrototypeHourCycle) {
820   HandleScope scope(isolate);
821   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.hourCycle");
822 
823   return *JSLocale::HourCycle(isolate, locale);
824 }
825 
BUILTIN(LocalePrototypeNumeric)826 BUILTIN(LocalePrototypeNumeric) {
827   HandleScope scope(isolate);
828   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.numeric");
829 
830   return *JSLocale::Numeric(isolate, locale);
831 }
832 
BUILTIN(LocalePrototypeNumberingSystem)833 BUILTIN(LocalePrototypeNumberingSystem) {
834   HandleScope scope(isolate);
835   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.numberingSystem");
836 
837   return *JSLocale::NumberingSystem(isolate, locale);
838 }
839 
BUILTIN(LocalePrototypeToString)840 BUILTIN(LocalePrototypeToString) {
841   HandleScope scope(isolate);
842   CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.toString");
843 
844   return *JSLocale::ToString(isolate, locale);
845 }
846 
BUILTIN(RelativeTimeFormatConstructor)847 BUILTIN(RelativeTimeFormatConstructor) {
848   HandleScope scope(isolate);
849 
850   return DisallowCallConstructor<JSRelativeTimeFormat>(
851       args, isolate, v8::Isolate::UseCounterFeature::kRelativeTimeFormat,
852       "Intl.RelativeTimeFormat");
853 }
854 
BUILTIN(RelativeTimeFormatPrototypeResolvedOptions)855 BUILTIN(RelativeTimeFormatPrototypeResolvedOptions) {
856   HandleScope scope(isolate);
857   CHECK_RECEIVER(JSRelativeTimeFormat, format_holder,
858                  "Intl.RelativeTimeFormat.prototype.resolvedOptions");
859   return *JSRelativeTimeFormat::ResolvedOptions(isolate, format_holder);
860 }
861 
BUILTIN(StringPrototypeToLocaleLowerCase)862 BUILTIN(StringPrototypeToLocaleLowerCase) {
863   HandleScope scope(isolate);
864 
865   isolate->CountUsage(v8::Isolate::UseCounterFeature::kStringToLocaleLowerCase);
866 
867   TO_THIS_STRING(string, "String.prototype.toLocaleLowerCase");
868 
869   RETURN_RESULT_OR_FAILURE(
870       isolate, Intl::StringLocaleConvertCase(isolate, string, false,
871                                              args.atOrUndefined(isolate, 1)));
872 }
873 
BUILTIN(StringPrototypeToLocaleUpperCase)874 BUILTIN(StringPrototypeToLocaleUpperCase) {
875   HandleScope scope(isolate);
876 
877   isolate->CountUsage(v8::Isolate::UseCounterFeature::kStringToLocaleUpperCase);
878 
879   TO_THIS_STRING(string, "String.prototype.toLocaleUpperCase");
880 
881   RETURN_RESULT_OR_FAILURE(
882       isolate, Intl::StringLocaleConvertCase(isolate, string, true,
883                                              args.atOrUndefined(isolate, 1)));
884 }
885 
BUILTIN(PluralRulesConstructor)886 BUILTIN(PluralRulesConstructor) {
887   HandleScope scope(isolate);
888 
889   return DisallowCallConstructor<JSPluralRules>(
890       args, isolate, v8::Isolate::UseCounterFeature::kPluralRules,
891       "Intl.PluralRules");
892 }
893 
BUILTIN(PluralRulesPrototypeResolvedOptions)894 BUILTIN(PluralRulesPrototypeResolvedOptions) {
895   HandleScope scope(isolate);
896   CHECK_RECEIVER(JSPluralRules, plural_rules_holder,
897                  "Intl.PluralRules.prototype.resolvedOptions");
898   return *JSPluralRules::ResolvedOptions(isolate, plural_rules_holder);
899 }
900 
BUILTIN(PluralRulesPrototypeSelect)901 BUILTIN(PluralRulesPrototypeSelect) {
902   HandleScope scope(isolate);
903 
904   // 1. Let pr be the this value.
905   // 2. If Type(pr) is not Object, throw a TypeError exception.
906   // 3. If pr does not have an [[InitializedPluralRules]] internal slot, throw a
907   // TypeError exception.
908   CHECK_RECEIVER(JSPluralRules, plural_rules,
909                  "Intl.PluralRules.prototype.select");
910 
911   // 4. Let n be ? ToNumber(value).
912   Handle<Object> number = args.atOrUndefined(isolate, 1);
913   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number,
914                                      Object::ToNumber(isolate, number));
915   double number_double = number->Number();
916 
917   // 5. Return ? ResolvePlural(pr, n).
918   RETURN_RESULT_OR_FAILURE(isolate, JSPluralRules::ResolvePlural(
919                                         isolate, plural_rules, number_double));
920 }
921 
BUILTIN(PluralRulesSupportedLocalesOf)922 BUILTIN(PluralRulesSupportedLocalesOf) {
923   HandleScope scope(isolate);
924   Handle<Object> locales = args.atOrUndefined(isolate, 1);
925   Handle<Object> options = args.atOrUndefined(isolate, 2);
926 
927   RETURN_RESULT_OR_FAILURE(
928       isolate, Intl::SupportedLocalesOf(
929                    isolate, "Intl.PluralRules.supportedLocalesOf",
930                    JSPluralRules::GetAvailableLocales(), locales, options));
931 }
932 
BUILTIN(CollatorConstructor)933 BUILTIN(CollatorConstructor) {
934   HandleScope scope(isolate);
935 
936   isolate->CountUsage(v8::Isolate::UseCounterFeature::kCollator);
937 
938   return CallOrConstructConstructor<JSCollator>(args, isolate, "Intl.Collator");
939 }
940 
BUILTIN(CollatorPrototypeResolvedOptions)941 BUILTIN(CollatorPrototypeResolvedOptions) {
942   HandleScope scope(isolate);
943   CHECK_RECEIVER(JSCollator, collator_holder,
944                  "Intl.Collator.prototype.resolvedOptions");
945   return *JSCollator::ResolvedOptions(isolate, collator_holder);
946 }
947 
BUILTIN(CollatorSupportedLocalesOf)948 BUILTIN(CollatorSupportedLocalesOf) {
949   HandleScope scope(isolate);
950   Handle<Object> locales = args.atOrUndefined(isolate, 1);
951   Handle<Object> options = args.atOrUndefined(isolate, 2);
952 
953   RETURN_RESULT_OR_FAILURE(
954       isolate, Intl::SupportedLocalesOf(
955                    isolate, "Intl.Collator.supportedLocalesOf",
956                    JSCollator::GetAvailableLocales(), locales, options));
957 }
958 
BUILTIN(CollatorPrototypeCompare)959 BUILTIN(CollatorPrototypeCompare) {
960   const char* const method_name = "get Intl.Collator.prototype.compare";
961   HandleScope scope(isolate);
962 
963   // 1. Let collator be this value.
964   // 2. If Type(collator) is not Object, throw a TypeError exception.
965   // 3. If collator does not have an [[InitializedCollator]] internal slot,
966   // throw a TypeError exception.
967   CHECK_RECEIVER(JSCollator, collator, method_name);
968 
969   // 4. If collator.[[BoundCompare]] is undefined, then
970   Handle<Object> bound_compare(collator->bound_compare(), isolate);
971   if (!bound_compare->IsUndefined(isolate)) {
972     DCHECK(bound_compare->IsJSFunction());
973     // 5. Return collator.[[BoundCompare]].
974     return *bound_compare;
975   }
976 
977   Handle<JSFunction> new_bound_compare_function = CreateBoundFunction(
978       isolate, collator, Builtin::kCollatorInternalCompare, 2);
979 
980   // 4.c. Set collator.[[BoundCompare]] to F.
981   collator->set_bound_compare(*new_bound_compare_function);
982 
983   // 5. Return collator.[[BoundCompare]].
984   return *new_bound_compare_function;
985 }
986 
BUILTIN(CollatorInternalCompare)987 BUILTIN(CollatorInternalCompare) {
988   HandleScope scope(isolate);
989   Handle<Context> context = Handle<Context>(isolate->context(), isolate);
990 
991   // 1. Let collator be F.[[Collator]].
992   // 2. Assert: Type(collator) is Object and collator has an
993   // [[InitializedCollator]] internal slot.
994   Handle<JSCollator> collator = Handle<JSCollator>(
995       JSCollator::cast(context->get(
996           static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
997       isolate);
998 
999   // 3. If x is not provided, let x be undefined.
1000   Handle<Object> x = args.atOrUndefined(isolate, 1);
1001   // 4. If y is not provided, let y be undefined.
1002   Handle<Object> y = args.atOrUndefined(isolate, 2);
1003 
1004   // 5. Let X be ? ToString(x).
1005   Handle<String> string_x;
1006   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string_x,
1007                                      Object::ToString(isolate, x));
1008   // 6. Let Y be ? ToString(y).
1009   Handle<String> string_y;
1010   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string_y,
1011                                      Object::ToString(isolate, y));
1012 
1013   // 7. Return CompareStrings(collator, X, Y).
1014   icu::Collator* icu_collator = collator->icu_collator().raw();
1015   CHECK_NOT_NULL(icu_collator);
1016   return Smi::FromInt(
1017       Intl::CompareStrings(isolate, *icu_collator, string_x, string_y));
1018 }
1019 
1020 // ecma402 #sec-%segmentiteratorprototype%.next
BUILTIN(SegmentIteratorPrototypeNext)1021 BUILTIN(SegmentIteratorPrototypeNext) {
1022   const char* const method_name = "%SegmentIterator.prototype%.next";
1023   HandleScope scope(isolate);
1024   CHECK_RECEIVER(JSSegmentIterator, segment_iterator, method_name);
1025 
1026   RETURN_RESULT_OR_FAILURE(isolate,
1027                            JSSegmentIterator::Next(isolate, segment_iterator));
1028 }
1029 
1030 // ecma402 #sec-intl.segmenter
BUILTIN(SegmenterConstructor)1031 BUILTIN(SegmenterConstructor) {
1032   HandleScope scope(isolate);
1033 
1034   return DisallowCallConstructor<JSSegmenter>(
1035       args, isolate, v8::Isolate::UseCounterFeature::kSegmenter,
1036       "Intl.Segmenter");
1037 }
1038 
1039 // ecma402 #sec-intl.segmenter.supportedlocalesof
BUILTIN(SegmenterSupportedLocalesOf)1040 BUILTIN(SegmenterSupportedLocalesOf) {
1041   HandleScope scope(isolate);
1042   Handle<Object> locales = args.atOrUndefined(isolate, 1);
1043   Handle<Object> options = args.atOrUndefined(isolate, 2);
1044 
1045   RETURN_RESULT_OR_FAILURE(
1046       isolate, Intl::SupportedLocalesOf(
1047                    isolate, "Intl.Segmenter.supportedLocalesOf",
1048                    JSSegmenter::GetAvailableLocales(), locales, options));
1049 }
1050 
1051 // ecma402 #sec-intl.segmenter.prototype.resolvedoptions
BUILTIN(SegmenterPrototypeResolvedOptions)1052 BUILTIN(SegmenterPrototypeResolvedOptions) {
1053   HandleScope scope(isolate);
1054   CHECK_RECEIVER(JSSegmenter, segmenter,
1055                  "Intl.Segmenter.prototype.resolvedOptions");
1056   return *JSSegmenter::ResolvedOptions(isolate, segmenter);
1057 }
1058 
1059 // ecma402 #sec-intl.segmenter.prototype.segment
BUILTIN(SegmenterPrototypeSegment)1060 BUILTIN(SegmenterPrototypeSegment) {
1061   HandleScope scope(isolate);
1062   CHECK_RECEIVER(JSSegmenter, segmenter, "Intl.Segmenter.prototype.segment");
1063   Handle<Object> input_text = args.atOrUndefined(isolate, 1);
1064   // 3. Let string be ? ToString(string).
1065   Handle<String> string;
1066   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string,
1067                                      Object::ToString(isolate, input_text));
1068 
1069   // 4. Return ? CreateSegmentsObject(segmenter, string).
1070   RETURN_RESULT_OR_FAILURE(isolate,
1071                            JSSegments::Create(isolate, segmenter, string));
1072 }
1073 
1074 // ecma402 #sec-%segmentsprototype%.containing
BUILTIN(SegmentsPrototypeContaining)1075 BUILTIN(SegmentsPrototypeContaining) {
1076   const char* const method_name = "%Segments.prototype%.containing";
1077   HandleScope scope(isolate);
1078   CHECK_RECEIVER(JSSegments, segments, method_name);
1079   Handle<Object> index = args.atOrUndefined(isolate, 1);
1080 
1081   // 6. Let n be ? ToInteger(index).
1082   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, index,
1083                                      Object::ToInteger(isolate, index));
1084   double const n = index->Number();
1085 
1086   RETURN_RESULT_OR_FAILURE(isolate,
1087                            JSSegments::Containing(isolate, segments, n));
1088 }
1089 
1090 // ecma402 #sec-%segmentsprototype%-@@iterator
BUILTIN(SegmentsPrototypeIterator)1091 BUILTIN(SegmentsPrototypeIterator) {
1092   const char* const method_name = "%SegmentIsPrototype%[@@iterator]";
1093   HandleScope scope(isolate);
1094   CHECK_RECEIVER(JSSegments, segments, method_name);
1095   RETURN_RESULT_OR_FAILURE(
1096       isolate,
1097       JSSegmentIterator::Create(isolate, segments->icu_break_iterator().raw(),
1098                                 segments->granularity()));
1099 }
1100 
BUILTIN(V8BreakIteratorConstructor)1101 BUILTIN(V8BreakIteratorConstructor) {
1102   HandleScope scope(isolate);
1103 
1104   return CallOrConstructConstructor<JSV8BreakIterator>(args, isolate,
1105                                                        "Intl.v8BreakIterator");
1106 }
1107 
BUILTIN(V8BreakIteratorPrototypeResolvedOptions)1108 BUILTIN(V8BreakIteratorPrototypeResolvedOptions) {
1109   HandleScope scope(isolate);
1110   CHECK_RECEIVER(JSV8BreakIterator, break_iterator,
1111                  "Intl.v8BreakIterator.prototype.resolvedOptions");
1112   return *JSV8BreakIterator::ResolvedOptions(isolate, break_iterator);
1113 }
1114 
BUILTIN(V8BreakIteratorPrototypeAdoptText)1115 BUILTIN(V8BreakIteratorPrototypeAdoptText) {
1116   const char* const method_name =
1117       "get Intl.v8BreakIterator.prototype.adoptText";
1118   HandleScope scope(isolate);
1119 
1120   CHECK_RECEIVER(JSV8BreakIterator, break_iterator, method_name);
1121 
1122   Handle<Object> bound_adopt_text(break_iterator->bound_adopt_text(), isolate);
1123   if (!bound_adopt_text->IsUndefined(isolate)) {
1124     DCHECK(bound_adopt_text->IsJSFunction());
1125     return *bound_adopt_text;
1126   }
1127 
1128   Handle<JSFunction> new_bound_adopt_text_function = CreateBoundFunction(
1129       isolate, break_iterator, Builtin::kV8BreakIteratorInternalAdoptText, 1);
1130   break_iterator->set_bound_adopt_text(*new_bound_adopt_text_function);
1131   return *new_bound_adopt_text_function;
1132 }
1133 
BUILTIN(V8BreakIteratorInternalAdoptText)1134 BUILTIN(V8BreakIteratorInternalAdoptText) {
1135   HandleScope scope(isolate);
1136   Handle<Context> context = Handle<Context>(isolate->context(), isolate);
1137 
1138   Handle<JSV8BreakIterator> break_iterator = Handle<JSV8BreakIterator>(
1139       JSV8BreakIterator::cast(context->get(
1140           static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
1141       isolate);
1142 
1143   Handle<Object> input_text = args.atOrUndefined(isolate, 1);
1144   Handle<String> text;
1145   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, text,
1146                                      Object::ToString(isolate, input_text));
1147 
1148   JSV8BreakIterator::AdoptText(isolate, break_iterator, text);
1149   return ReadOnlyRoots(isolate).undefined_value();
1150 }
1151 
BUILTIN(V8BreakIteratorPrototypeFirst)1152 BUILTIN(V8BreakIteratorPrototypeFirst) {
1153   const char* const method_name = "get Intl.v8BreakIterator.prototype.first";
1154   HandleScope scope(isolate);
1155 
1156   CHECK_RECEIVER(JSV8BreakIterator, break_iterator, method_name);
1157 
1158   Handle<Object> bound_first(break_iterator->bound_first(), isolate);
1159   if (!bound_first->IsUndefined(isolate)) {
1160     DCHECK(bound_first->IsJSFunction());
1161     return *bound_first;
1162   }
1163 
1164   Handle<JSFunction> new_bound_first_function = CreateBoundFunction(
1165       isolate, break_iterator, Builtin::kV8BreakIteratorInternalFirst, 0);
1166   break_iterator->set_bound_first(*new_bound_first_function);
1167   return *new_bound_first_function;
1168 }
1169 
BUILTIN(V8BreakIteratorInternalFirst)1170 BUILTIN(V8BreakIteratorInternalFirst) {
1171   HandleScope scope(isolate);
1172   Handle<Context> context = Handle<Context>(isolate->context(), isolate);
1173 
1174   Handle<JSV8BreakIterator> break_iterator = Handle<JSV8BreakIterator>(
1175       JSV8BreakIterator::cast(context->get(
1176           static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
1177       isolate);
1178 
1179   return *JSV8BreakIterator::First(isolate, break_iterator);
1180 }
1181 
BUILTIN(V8BreakIteratorPrototypeNext)1182 BUILTIN(V8BreakIteratorPrototypeNext) {
1183   const char* const method_name = "get Intl.v8BreakIterator.prototype.next";
1184   HandleScope scope(isolate);
1185 
1186   CHECK_RECEIVER(JSV8BreakIterator, break_iterator, method_name);
1187 
1188   Handle<Object> bound_next(break_iterator->bound_next(), isolate);
1189   if (!bound_next->IsUndefined(isolate)) {
1190     DCHECK(bound_next->IsJSFunction());
1191     return *bound_next;
1192   }
1193 
1194   Handle<JSFunction> new_bound_next_function = CreateBoundFunction(
1195       isolate, break_iterator, Builtin::kV8BreakIteratorInternalNext, 0);
1196   break_iterator->set_bound_next(*new_bound_next_function);
1197   return *new_bound_next_function;
1198 }
1199 
BUILTIN(V8BreakIteratorInternalNext)1200 BUILTIN(V8BreakIteratorInternalNext) {
1201   HandleScope scope(isolate);
1202   Handle<Context> context = Handle<Context>(isolate->context(), isolate);
1203 
1204   Handle<JSV8BreakIterator> break_iterator = Handle<JSV8BreakIterator>(
1205       JSV8BreakIterator::cast(context->get(
1206           static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
1207       isolate);
1208   return *JSV8BreakIterator::Next(isolate, break_iterator);
1209 }
1210 
BUILTIN(V8BreakIteratorPrototypeCurrent)1211 BUILTIN(V8BreakIteratorPrototypeCurrent) {
1212   const char* const method_name = "get Intl.v8BreakIterator.prototype.current";
1213   HandleScope scope(isolate);
1214 
1215   CHECK_RECEIVER(JSV8BreakIterator, break_iterator, method_name);
1216 
1217   Handle<Object> bound_current(break_iterator->bound_current(), isolate);
1218   if (!bound_current->IsUndefined(isolate)) {
1219     DCHECK(bound_current->IsJSFunction());
1220     return *bound_current;
1221   }
1222 
1223   Handle<JSFunction> new_bound_current_function = CreateBoundFunction(
1224       isolate, break_iterator, Builtin::kV8BreakIteratorInternalCurrent, 0);
1225   break_iterator->set_bound_current(*new_bound_current_function);
1226   return *new_bound_current_function;
1227 }
1228 
BUILTIN(V8BreakIteratorInternalCurrent)1229 BUILTIN(V8BreakIteratorInternalCurrent) {
1230   HandleScope scope(isolate);
1231   Handle<Context> context = Handle<Context>(isolate->context(), isolate);
1232 
1233   Handle<JSV8BreakIterator> break_iterator = Handle<JSV8BreakIterator>(
1234       JSV8BreakIterator::cast(context->get(
1235           static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
1236       isolate);
1237   return *JSV8BreakIterator::Current(isolate, break_iterator);
1238 }
1239 
BUILTIN(V8BreakIteratorPrototypeBreakType)1240 BUILTIN(V8BreakIteratorPrototypeBreakType) {
1241   const char* const method_name =
1242       "get Intl.v8BreakIterator.prototype.breakType";
1243   HandleScope scope(isolate);
1244 
1245   CHECK_RECEIVER(JSV8BreakIterator, break_iterator, method_name);
1246 
1247   Handle<Object> bound_break_type(break_iterator->bound_break_type(), isolate);
1248   if (!bound_break_type->IsUndefined(isolate)) {
1249     DCHECK(bound_break_type->IsJSFunction());
1250     return *bound_break_type;
1251   }
1252 
1253   Handle<JSFunction> new_bound_break_type_function = CreateBoundFunction(
1254       isolate, break_iterator, Builtin::kV8BreakIteratorInternalBreakType, 0);
1255   break_iterator->set_bound_break_type(*new_bound_break_type_function);
1256   return *new_bound_break_type_function;
1257 }
1258 
BUILTIN(V8BreakIteratorInternalBreakType)1259 BUILTIN(V8BreakIteratorInternalBreakType) {
1260   HandleScope scope(isolate);
1261   Handle<Context> context = Handle<Context>(isolate->context(), isolate);
1262 
1263   Handle<JSV8BreakIterator> break_iterator = Handle<JSV8BreakIterator>(
1264       JSV8BreakIterator::cast(context->get(
1265           static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
1266       isolate);
1267   return JSV8BreakIterator::BreakType(isolate, break_iterator);
1268 }
1269 
1270 }  // namespace internal
1271 }  // namespace v8
1272