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
38namespace v8 {
39namespace internal {
40
41BUILTIN(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
48BUILTIN(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
59BUILTIN(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
70BUILTIN(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
81BUILTIN(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
105BUILTIN(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
121BUILTIN(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
132BUILTIN(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)
166template <class T, MaybeHandle<T> (*F)(Isolate*, Handle<JSDateTimeFormat>,
167                                       double, double)>
168V8_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
216BUILTIN(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
223BUILTIN(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
231namespace {
232
233Handle<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 */
261template <class T>
262Object 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 */
335template <class T>
336Object 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 */
368template <class T>
369Object 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
397BUILTIN(DisplayNamesConstructor) {
398  HandleScope scope(isolate);
399
400  return DisallowCallConstructor<JSDisplayNames>(
401      args, isolate, v8::Isolate::UseCounterFeature::kDisplayNames,
402      "Intl.DisplayNames");
403}
404
405BUILTIN(DisplayNamesPrototypeResolvedOptions) {
406  HandleScope scope(isolate);
407  CHECK_RECEIVER(JSDisplayNames, holder,
408                 "Intl.DisplayNames.prototype.resolvedOptions");
409  return *JSDisplayNames::ResolvedOptions(isolate, holder);
410}
411
412BUILTIN(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
423BUILTIN(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
434BUILTIN(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
442BUILTIN(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
459BUILTIN(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
492BUILTIN(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)
530template <class T, MaybeHandle<T> (*F)(Isolate*, Handle<JSNumberFormat>,
531                                       Handle<Object>, Handle<Object>)>
532V8_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
571BUILTIN(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
578BUILTIN(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
586BUILTIN(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
594BUILTIN(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
627BUILTIN(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
645BUILTIN(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
653BUILTIN(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
660BUILTIN(ListFormatConstructor) {
661  HandleScope scope(isolate);
662
663  return DisallowCallConstructor<JSListFormat>(
664      args, isolate, v8::Isolate::UseCounterFeature::kListFormat,
665      "Intl.ListFormat");
666}
667
668BUILTIN(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
675BUILTIN(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
687BUILTIN(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
740BUILTIN(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
746BUILTIN(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
752BUILTIN(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
758BUILTIN(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
764BUILTIN(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
770BUILTIN(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
777BUILTIN(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
783BUILTIN(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
789BUILTIN(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
795BUILTIN(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
807BUILTIN(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
823BUILTIN(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.
839BUILTIN(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
847BUILTIN(LocalePrototypeScript) {
848  HandleScope scope(isolate);
849  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.script");
850
851  return *JSLocale::Script(isolate, locale);
852}
853
854BUILTIN(LocalePrototypeRegion) {
855  HandleScope scope(isolate);
856  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.region");
857
858  return *JSLocale::Region(isolate, locale);
859}
860
861BUILTIN(LocalePrototypeBaseName) {
862  HandleScope scope(isolate);
863  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.baseName");
864
865  return *JSLocale::BaseName(isolate, locale);
866}
867
868BUILTIN(LocalePrototypeCalendar) {
869  HandleScope scope(isolate);
870  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.calendar");
871
872  return *JSLocale::Calendar(isolate, locale);
873}
874
875BUILTIN(LocalePrototypeCaseFirst) {
876  HandleScope scope(isolate);
877  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.caseFirst");
878
879  return *JSLocale::CaseFirst(isolate, locale);
880}
881
882BUILTIN(LocalePrototypeCollation) {
883  HandleScope scope(isolate);
884  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.collation");
885
886  return *JSLocale::Collation(isolate, locale);
887}
888
889BUILTIN(LocalePrototypeHourCycle) {
890  HandleScope scope(isolate);
891  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.hourCycle");
892
893  return *JSLocale::HourCycle(isolate, locale);
894}
895
896BUILTIN(LocalePrototypeNumeric) {
897  HandleScope scope(isolate);
898  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.numeric");
899
900  return *JSLocale::Numeric(isolate, locale);
901}
902
903BUILTIN(LocalePrototypeNumberingSystem) {
904  HandleScope scope(isolate);
905  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.numberingSystem");
906
907  return *JSLocale::NumberingSystem(isolate, locale);
908}
909
910BUILTIN(LocalePrototypeToString) {
911  HandleScope scope(isolate);
912  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.toString");
913
914  return *JSLocale::ToString(isolate, locale);
915}
916
917BUILTIN(RelativeTimeFormatConstructor) {
918  HandleScope scope(isolate);
919
920  return DisallowCallConstructor<JSRelativeTimeFormat>(
921      args, isolate, v8::Isolate::UseCounterFeature::kRelativeTimeFormat,
922      "Intl.RelativeTimeFormat");
923}
924
925BUILTIN(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
932BUILTIN(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
944BUILTIN(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
956BUILTIN(PluralRulesConstructor) {
957  HandleScope scope(isolate);
958
959  return DisallowCallConstructor<JSPluralRules>(
960      args, isolate, v8::Isolate::UseCounterFeature::kPluralRules,
961      "Intl.PluralRules");
962}
963
964BUILTIN(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
971BUILTIN(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
990BUILTIN(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
1048BUILTIN(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
1059BUILTIN(CollatorConstructor) {
1060  HandleScope scope(isolate);
1061
1062  isolate->CountUsage(v8::Isolate::UseCounterFeature::kCollator);
1063
1064  return CallOrConstructConstructor<JSCollator>(args, isolate, "Intl.Collator");
1065}
1066
1067BUILTIN(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
1074BUILTIN(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
1085BUILTIN(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
1113BUILTIN(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
1147BUILTIN(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
1157BUILTIN(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
1166BUILTIN(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
1178BUILTIN(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
1186BUILTIN(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
1201BUILTIN(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
1217BUILTIN(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
1227BUILTIN(V8BreakIteratorConstructor) {
1228  HandleScope scope(isolate);
1229
1230  return CallOrConstructConstructor<JSV8BreakIterator>(args, isolate,
1231                                                       "Intl.v8BreakIterator");
1232}
1233
1234BUILTIN(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
1241BUILTIN(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
1260BUILTIN(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
1278BUILTIN(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
1296BUILTIN(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
1308BUILTIN(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
1326BUILTIN(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
1337BUILTIN(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
1355BUILTIN(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
1366BUILTIN(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
1385BUILTIN(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