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