builtins-intl.cc 44.7 KB
Newer Older
1 2 3 4
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6 7
#ifndef V8_INTL_SUPPORT
#error Internationalization is expected to be enabled.
#endif  // V8_INTL_SUPPORT
8

9
#include <cmath>
10 11
#include <list>
#include <memory>
12

13
#include "src/builtins/builtins-utils-inl.h"
14
#include "src/builtins/builtins.h"
Yang Guo's avatar
Yang Guo committed
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/objects-inl.h"
32
#include "src/objects/property-descriptor.h"
33
#include "src/objects/smi.h"
34

35
#include "unicode/brkiter.h"
36

37 38 39
namespace v8 {
namespace internal {

40
BUILTIN(StringPrototypeToUpperCaseIntl) {
41 42
  HandleScope scope(isolate);
  TO_THIS_STRING(string, "String.prototype.toUpperCase");
43
  string = String::Flatten(isolate, string);
Frank Tang's avatar
Frank Tang committed
44
  RETURN_RESULT_OR_FAILURE(isolate, Intl::ConvertToUpper(isolate, string));
45 46
}

47
BUILTIN(StringPrototypeNormalizeIntl) {
48
  HandleScope handle_scope(isolate);
49
  isolate->CountUsage(v8::Isolate::UseCounterFeature::kStringNormalize);
50 51 52 53
  TO_THIS_STRING(string, "String.prototype.normalize");

  Handle<Object> form_input = args.atOrUndefined(isolate, 1);

54 55
  RETURN_RESULT_OR_FAILURE(isolate,
                           Intl::Normalize(isolate, string, form_input));
56 57
}

58
BUILTIN(V8BreakIteratorSupportedLocalesOf) {
59
  HandleScope scope(isolate);
60 61
  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);
62 63

  RETURN_RESULT_OR_FAILURE(
64 65 66
      isolate, Intl::SupportedLocalesOf(
                   isolate, "Intl.v8BreakIterator.supportedLocalesOf",
                   JSV8BreakIterator::GetAvailableLocales(), locales, options));
67 68 69 70
}

BUILTIN(NumberFormatSupportedLocalesOf) {
  HandleScope scope(isolate);
71 72 73
  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);

74
  RETURN_RESULT_OR_FAILURE(
Frank Tang's avatar
Frank Tang committed
75
      isolate, Intl::SupportedLocalesOf(
76 77
                   isolate, "Intl.NumberFormat.supportedLocalesOf",
                   JSNumberFormat::GetAvailableLocales(), locales, options));
78 79
}

80 81 82
BUILTIN(NumberFormatPrototypeFormatToParts) {
  const char* const method = "Intl.NumberFormat.prototype.formatToParts";
  HandleScope handle_scope(isolate);
83
  CHECK_RECEIVER(JSNumberFormat, number_format, method);
84 85

  Handle<Object> x;
86
  if (args.length() >= 2) {
87 88
    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x,
                                       Object::ToNumeric(isolate, args.at(1)));
89 90 91 92
  } else {
    x = isolate->factory()->nan_value();
  }

93 94
  RETURN_RESULT_OR_FAILURE(
      isolate, JSNumberFormat::FormatToParts(isolate, number_format, x));
95 96
}

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
BUILTIN(DateTimeFormatPrototypeResolvedOptions) {
  const char* const method = "Intl.DateTimeFormat.prototype.resolvedOptions";
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSReceiver, format_holder, method);

  // 3. Let dtf be ? UnwrapDateTimeFormat(dtf).
  Handle<JSDateTimeFormat> date_time_format;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, date_time_format,
      JSDateTimeFormat::UnwrapDateTimeFormat(isolate, format_holder));

  RETURN_RESULT_OR_FAILURE(
      isolate, JSDateTimeFormat::ResolvedOptions(isolate, date_time_format));
}

112 113
BUILTIN(DateTimeFormatSupportedLocalesOf) {
  HandleScope scope(isolate);
114 115 116
  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);

117
  RETURN_RESULT_OR_FAILURE(
118 119 120
      isolate, Intl::SupportedLocalesOf(
                   isolate, "Intl.DateTimeFormat.supportedLocalesOf",
                   JSDateTimeFormat::GetAvailableLocales(), locales, options));
121 122
}

123 124 125 126 127 128
BUILTIN(DateTimeFormatPrototypeFormatToParts) {
  const char* const method = "Intl.DateTimeFormat.prototype.formatToParts";
  HandleScope handle_scope(isolate);
  CHECK_RECEIVER(JSObject, date_format_holder, method);
  Factory* factory = isolate->factory();

129
  if (!date_format_holder->IsJSDateTimeFormat()) {
130 131 132 133 134
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
                              factory->NewStringFromAsciiChecked(method),
                              date_format_holder));
  }
135 136
  Handle<JSDateTimeFormat> dtf =
      Handle<JSDateTimeFormat>::cast(date_format_holder);
137 138 139 140 141 142

  Handle<Object> x = args.atOrUndefined(isolate, 1);
  if (x->IsUndefined(isolate)) {
    x = factory->NewNumber(JSDate::CurrentTimeValue(isolate));
  } else {
    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x,
143
                                       Object::ToNumber(isolate, args.at(1)));
144 145 146 147 148 149 150 151
  }

  double date_value = DateCache::TimeClip(x->Number());
  if (std::isnan(date_value)) {
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
  }

152 153
  RETURN_RESULT_OR_FAILURE(
      isolate, JSDateTimeFormat::FormatToParts(isolate, dtf, date_value));
154 155
}

156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
// Common code for DateTimeFormatPrototypeFormtRange(|ToParts)
template <class T>
V8_WARN_UNUSED_RESULT Object DateTimeFormatRange(
    BuiltinArguments args, Isolate* isolate, const char* const method,
    MaybeHandle<T> (*format)(Isolate*, Handle<JSDateTimeFormat>, double,
                             double)) {
  // 1. Let dtf be this value.
  // 2. If Type(dtf) is not Object, throw a TypeError exception.
  CHECK_RECEIVER(JSObject, date_format_holder, method);

  Factory* factory = isolate->factory();

  // 3. If dtf does not have an [[InitializedDateTimeFormat]] internal slot,
  //    throw a TypeError exception.
  if (!date_format_holder->IsJSDateTimeFormat()) {
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
                              factory->NewStringFromAsciiChecked(method),
                              date_format_holder));
  }
  Handle<JSDateTimeFormat> dtf =
      Handle<JSDateTimeFormat>::cast(date_format_holder);

  // 4. If startDate is undefined or endDate is undefined, throw a RangeError
  // exception.
  Handle<Object> start_date = args.atOrUndefined(isolate, 1);
  Handle<Object> end_date = args.atOrUndefined(isolate, 2);
  if (start_date->IsUndefined(isolate) || end_date->IsUndefined(isolate)) {
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
  }
  // 5. Let x be ? ToNumber(startDate).
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, start_date,
                                     Object::ToNumber(isolate, start_date));
  double x = start_date->Number();

  // 6. Let y be ? ToNumber(endDate).
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, end_date,
                                     Object::ToNumber(isolate, end_date));
  double y = end_date->Number();
  // 7. If x is greater than y, throw a RangeError exception.
  if (x > y) {
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
  }

  // 8. Return ? FormatDateTimeRange(dtf, x, y)
  // OR
  // 8. Return ? FormatDateTimeRangeToParts(dtf, x, y).
  RETURN_RESULT_OR_FAILURE(isolate, format(isolate, dtf, x, y));
}

BUILTIN(DateTimeFormatPrototypeFormatRange) {
  const char* const method = "Intl.DateTimeFormat.prototype.formatRange";
  HandleScope handle_scope(isolate);
  return DateTimeFormatRange<String>(args, isolate, method,
                                     JSDateTimeFormat::FormatRange);
}

BUILTIN(DateTimeFormatPrototypeFormatRangeToParts) {
  const char* const method = "Intl.DateTimeFormat.prototype.formatRangeToParts";
  HandleScope handle_scope(isolate);
  return DateTimeFormatRange<JSArray>(args, isolate, method,
                                      JSDateTimeFormat::FormatRangeToParts);
}

222 223 224
namespace {
Handle<JSFunction> CreateBoundFunction(Isolate* isolate,
                                       Handle<JSObject> object,
225
                                       Builtins::Name builtin_id, int len) {
226
  Handle<NativeContext> native_context(isolate->context().native_context(),
227 228 229 230 231 232 233 234
                                       isolate);
  Handle<Context> context = isolate->factory()->NewBuiltinContext(
      native_context,
      static_cast<int>(Intl::BoundFunctionContextSlot::kLength));

  context->set(static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction),
               *object);

235 236 237 238 239 240
  Handle<SharedFunctionInfo> info =
      isolate->factory()->NewSharedFunctionInfoForBuiltin(
          isolate->factory()->empty_string(), builtin_id, kNormalFunction);
  info->set_internal_formal_parameter_count(len);
  info->set_length(len);

241 242 243 244 245 246
  Handle<Map> map = isolate->strict_function_without_prototype_map();

  Handle<JSFunction> new_bound_function =
      isolate->factory()->NewFunctionFromSharedFunctionInfo(map, info, context);
  return new_bound_function;
}
247 248 249 250 251 252

/**
 * Common code shared between DateTimeFormatConstructor and
 * NumberFormatConstrutor
 */
template <class T>
253 254 255
Object LegacyFormatConstructor(BuiltinArguments args, Isolate* isolate,
                               v8::Isolate::UseCounterFeature feature,
                               Handle<Object> constructor, const char* method) {
256
  isolate->CountUsage(feature);
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
  Handle<JSReceiver> new_target;
  // 1. If NewTarget is undefined, let newTarget be the active
  // function object, else let newTarget be NewTarget.
  if (args.new_target()->IsUndefined(isolate)) {
    new_target = args.target();
  } else {
    new_target = Handle<JSReceiver>::cast(args.new_target());
  }

  // [[Construct]]
  Handle<JSFunction> target = args.target();

  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);

272 273
  // 2. Let format be ? OrdinaryCreateFromConstructor(newTarget,
  // "%<T>Prototype%", ...).
274

275
  Handle<Map> map;
276
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
277
      isolate, map, JSFunction::GetDerivedMap(isolate, target, new_target));
278

279
  // 3. Perform ? Initialize<T>(Format, locales, options).
280
  Handle<T> format;
281 282
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, format, T::New(isolate, map, locales, options, method));
283 284 285
  // 4. Let this be the this value.
  Handle<Object> receiver = args.receiver();

286
  // 5. If NewTarget is undefined and ? InstanceofOperator(this, %<T>%)
287 288 289 290 291 292 293
  // is true, then
  //
  // Look up the intrinsic value that has been stored on the context.
  // Call the instanceof function
  Handle<Object> is_instance_of_obj;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, is_instance_of_obj,
294
      Object::InstanceOf(isolate, receiver, constructor));
295 296 297 298 299 300 301

  // Get the boolean value of the result
  bool is_instance_of = is_instance_of_obj->BooleanValue(isolate);

  if (args.new_target()->IsUndefined(isolate) && is_instance_of) {
    if (!receiver->IsJSReceiver()) {
      THROW_NEW_ERROR_RETURN_FAILURE(
302 303 304 305
          isolate,
          NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
                       isolate->factory()->NewStringFromAsciiChecked(method),
                       receiver));
306 307 308
    }
    Handle<JSReceiver> rec = Handle<JSReceiver>::cast(receiver);
    // a. Perform ? DefinePropertyOrThrow(this,
309
    // %Intl%.[[FallbackSymbol]], PropertyDescriptor{ [[Value]]: format,
310 311
    // [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }).
    PropertyDescriptor desc;
312
    desc.set_value(format);
313 314 315 316 317
    desc.set_writable(false);
    desc.set_enumerable(false);
    desc.set_configurable(false);
    Maybe<bool> success = JSReceiver::DefineOwnProperty(
        isolate, rec, isolate->factory()->intl_fallback_symbol(), &desc,
318
        Just(kThrowOnError));
319 320 321 322 323
    MAYBE_RETURN(success, ReadOnlyRoots(isolate).exception());
    CHECK(success.FromJust());
    // b. b. Return this.
    return *receiver;
  }
324 325 326
  // 6. Return format.
  return *format;
}
327

328 329 330 331 332
/**
 * Common code shared by ListFormat, RelativeTimeFormat, PluralRules, and
 * Segmenter
 */
template <class T>
333 334 335
Object DisallowCallConstructor(BuiltinArguments args, Isolate* isolate,
                               v8::Isolate::UseCounterFeature feature,
                               const char* method) {
336 337 338 339 340 341 342 343 344 345 346 347 348
  isolate->CountUsage(feature);

  // 1. If NewTarget is undefined, throw a TypeError exception.
  if (args.new_target()->IsUndefined(isolate)) {  // [[Call]]
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate,
        NewTypeError(MessageTemplate::kConstructorNotFunction,
                     isolate->factory()->NewStringFromAsciiChecked(method)));
  }
  // [[Construct]]
  Handle<JSFunction> target = args.target();
  Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());

349
  Handle<Map> map;
350 351 352
  // 2. Let result be OrdinaryCreateFromConstructor(NewTarget,
  //    "%<T>Prototype%").
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
353
      isolate, map, JSFunction::GetDerivedMap(isolate, target, new_target));
354 355 356 357

  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);

358 359
  // 3. Return New<T>(t, locales, options).
  RETURN_RESULT_OR_FAILURE(isolate, T::New(isolate, map, locales, options));
360 361 362 363 364 365
}

/**
 * Common code shared by Collator and V8BreakIterator
 */
template <class T>
366 367
Object CallOrConstructConstructor(BuiltinArguments args, Isolate* isolate,
                                  const char* method) {
368 369 370 371 372 373 374 375 376 377 378 379 380 381
  Handle<JSReceiver> new_target;

  if (args.new_target()->IsUndefined(isolate)) {
    new_target = args.target();
  } else {
    new_target = Handle<JSReceiver>::cast(args.new_target());
  }

  // [[Construct]]
  Handle<JSFunction> target = args.target();

  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);

382
  Handle<Map> map;
383
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
384
      isolate, map, JSFunction::GetDerivedMap(isolate, target, new_target));
385

386 387
  RETURN_RESULT_OR_FAILURE(isolate,
                           T::New(isolate, map, locales, options, method));
388
}
389 390
}  // namespace

391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
// Intl.DisplayNames

BUILTIN(DisplayNamesConstructor) {
  HandleScope scope(isolate);

  return DisallowCallConstructor<JSDisplayNames>(
      args, isolate, v8::Isolate::UseCounterFeature::kDisplayNames,
      "Intl.DisplayNames");
}

BUILTIN(DisplayNamesPrototypeResolvedOptions) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSDisplayNames, holder,
                 "Intl.DisplayNames.prototype.resolvedOptions");
  return *JSDisplayNames::ResolvedOptions(isolate, holder);
}

BUILTIN(DisplayNamesSupportedLocalesOf) {
  HandleScope scope(isolate);
  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);

  RETURN_RESULT_OR_FAILURE(
      isolate, Intl::SupportedLocalesOf(
                   isolate, "Intl.DisplayNames.supportedLocalesOf",
                   JSDisplayNames::GetAvailableLocales(), locales, options));
}

BUILTIN(DisplayNamesPrototypeOf) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSDisplayNames, holder, "Intl.DisplayNames.prototype.of");
  Handle<Object> code_obj = args.atOrUndefined(isolate, 1);

  RETURN_RESULT_OR_FAILURE(isolate,
                           JSDisplayNames::Of(isolate, holder, code_obj));
}

// Intl.NumberFormat

430 431
BUILTIN(NumberFormatConstructor) {
  HandleScope scope(isolate);
432

433 434 435
  return LegacyFormatConstructor<JSNumberFormat>(
      args, isolate, v8::Isolate::UseCounterFeature::kNumberFormat,
      isolate->intl_number_format_function(), "Intl.NumberFormat");
436
}
437

438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
BUILTIN(NumberFormatPrototypeResolvedOptions) {
  HandleScope scope(isolate);
  const char* const method = "Intl.NumberFormat.prototype.resolvedOptions";

  // 1. Let nf be the this value.
  // 2. If Type(nf) is not Object, throw a TypeError exception.
  CHECK_RECEIVER(JSReceiver, number_format_holder, method);

  // 3. Let nf be ? UnwrapNumberFormat(nf)
  Handle<JSNumberFormat> number_format;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, number_format,
      JSNumberFormat::UnwrapNumberFormat(isolate, number_format_holder));

  return *JSNumberFormat::ResolvedOptions(isolate, number_format);
}

455 456 457 458 459 460
BUILTIN(NumberFormatPrototypeFormatNumber) {
  const char* const method = "get Intl.NumberFormat.prototype.format";
  HandleScope scope(isolate);

  // 1. Let nf be the this value.
  // 2. If Type(nf) is not Object, throw a TypeError exception.
461
  CHECK_RECEIVER(JSReceiver, receiver, method);
462 463

  // 3. Let nf be ? UnwrapNumberFormat(nf).
464
  Handle<JSNumberFormat> number_format;
465
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
466 467
      isolate, number_format,
      JSNumberFormat::UnwrapNumberFormat(isolate, receiver));
468

469
  Handle<Object> bound_format(number_format->bound_format(), isolate);
470 471 472 473 474 475 476 477

  // 4. If nf.[[BoundFormat]] is undefined, then
  if (!bound_format->IsUndefined(isolate)) {
    DCHECK(bound_format->IsJSFunction());
    // 5. Return nf.[[BoundFormat]].
    return *bound_format;
  }

478
  Handle<JSFunction> new_bound_format_function = CreateBoundFunction(
479
      isolate, number_format, Builtins::kNumberFormatInternalFormatNumber, 1);
480 481

  // 4. c. Set nf.[[BoundFormat]] to F.
482
  number_format->set_bound_format(*new_bound_format_function);
483 484 485 486 487 488 489 490 491 492 493 494 495

  // 5. Return nf.[[BoundFormat]].
  return *new_bound_format_function;
}

BUILTIN(NumberFormatInternalFormatNumber) {
  HandleScope scope(isolate);

  Handle<Context> context = Handle<Context>(isolate->context(), isolate);

  // 1. Let nf be F.[[NumberFormat]].
  // 2. Assert: Type(nf) is Object and nf has an
  //    [[InitializedNumberFormat]] internal slot.
496
  Handle<JSNumberFormat> number_format = Handle<JSNumberFormat>(
497 498
      JSNumberFormat::cast(context->get(
          static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
499
      isolate);
500 501 502 503

  // 3. If value is not provided, let value be undefined.
  Handle<Object> value = args.atOrUndefined(isolate, 1);

504 505
  // 4. Let x be ? ToNumeric(value).
  Handle<Object> numeric_obj;
506 507
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, numeric_obj,
                                     Object::ToNumeric(isolate, value));
508

509
  icu::number::LocalizedNumberFormatter* icu_localized_number_formatter =
510
      number_format->icu_number_formatter().raw();
511
  CHECK_NOT_NULL(icu_localized_number_formatter);
512

513
  // Return FormatNumber(nf, x).
514
  RETURN_RESULT_OR_FAILURE(
515 516
      isolate, JSNumberFormat::FormatNumeric(
                   isolate, *icu_localized_number_formatter, numeric_obj));
517 518
}

519 520
BUILTIN(DateTimeFormatConstructor) {
  HandleScope scope(isolate);
521

522 523 524
  return LegacyFormatConstructor<JSDateTimeFormat>(
      args, isolate, v8::Isolate::UseCounterFeature::kDateTimeFormat,
      isolate->intl_date_time_format_function(), "Intl.DateTimeFormat");
525 526
}

527 528 529 530 531 532 533 534 535
BUILTIN(DateTimeFormatPrototypeFormat) {
  const char* const method = "get Intl.DateTimeFormat.prototype.format";
  HandleScope scope(isolate);

  // 1. Let dtf be this value.
  // 2. If Type(dtf) is not Object, throw a TypeError exception.
  CHECK_RECEIVER(JSReceiver, receiver, method);

  // 3. Let dtf be ? UnwrapDateTimeFormat(dtf).
536
  Handle<JSDateTimeFormat> format;
537
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
538 539
      isolate, format,
      JSDateTimeFormat::UnwrapDateTimeFormat(isolate, receiver));
540

541
  Handle<Object> bound_format = Handle<Object>(format->bound_format(), isolate);
542 543 544 545 546 547 548 549

  // 4. If dtf.[[BoundFormat]] is undefined, then
  if (!bound_format->IsUndefined(isolate)) {
    DCHECK(bound_format->IsJSFunction());
    // 5. Return dtf.[[BoundFormat]].
    return *bound_format;
  }

550
  Handle<JSFunction> new_bound_format_function = CreateBoundFunction(
551
      isolate, format, Builtins::kDateTimeFormatInternalFormat, 1);
552 553

  // 4.c. Set dtf.[[BoundFormat]] to F.
554
  format->set_bound_format(*new_bound_format_function);
555 556 557 558 559 560 561 562 563 564 565 566

  // 5. Return dtf.[[BoundFormat]].
  return *new_bound_format_function;
}

BUILTIN(DateTimeFormatInternalFormat) {
  HandleScope scope(isolate);
  Handle<Context> context = Handle<Context>(isolate->context(), isolate);

  // 1. Let dtf be F.[[DateTimeFormat]].
  // 2. Assert: Type(dtf) is Object and dtf has an [[InitializedDateTimeFormat]]
  // internal slot.
567 568 569 570
  Handle<JSDateTimeFormat> date_format_holder = Handle<JSDateTimeFormat>(
      JSDateTimeFormat::cast(context->get(
          static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
      isolate);
571 572 573

  Handle<Object> date = args.atOrUndefined(isolate, 1);

574 575
  RETURN_RESULT_OR_FAILURE(isolate, JSDateTimeFormat::DateTimeFormat(
                                        isolate, date_format_holder, date));
576 577
}

578 579 580 581 582 583 584 585
BUILTIN(IntlGetCanonicalLocales) {
  HandleScope scope(isolate);
  Handle<Object> locales = args.atOrUndefined(isolate, 1);

  RETURN_RESULT_OR_FAILURE(isolate,
                           Intl::GetCanonicalLocales(isolate, locales));
}

586 587
BUILTIN(ListFormatConstructor) {
  HandleScope scope(isolate);
588

589 590 591
  return DisallowCallConstructor<JSListFormat>(
      args, isolate, v8::Isolate::UseCounterFeature::kListFormat,
      "Intl.ListFormat");
592 593
}

594 595 596 597 598 599 600
BUILTIN(ListFormatPrototypeResolvedOptions) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSListFormat, format_holder,
                 "Intl.ListFormat.prototype.resolvedOptions");
  return *JSListFormat::ResolvedOptions(isolate, format_holder);
}

601 602
BUILTIN(ListFormatSupportedLocalesOf) {
  HandleScope scope(isolate);
603 604 605
  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);

606
  RETURN_RESULT_OR_FAILURE(
607 608 609
      isolate, Intl::SupportedLocalesOf(
                   isolate, "Intl.ListFormat.supportedLocalesOf",
                   JSListFormat::GetAvailableLocales(), locales, options));
610 611
}

612
namespace {
613

614 615 616 617
MaybeHandle<JSLocale> CreateLocale(Isolate* isolate,
                                   Handle<JSFunction> constructor,
                                   Handle<JSReceiver> new_target,
                                   Handle<Object> tag, Handle<Object> options) {
618
  Handle<Map> map;
619 620
  // 6. Let locale be ? OrdinaryCreateFromConstructor(NewTarget,
  // %LocalePrototype%, internalSlotsList).
621
  ASSIGN_RETURN_ON_EXCEPTION(
622
      isolate, map, JSFunction::GetDerivedMap(isolate, constructor, new_target),
623
      JSLocale);
624

625
  // 7. If Type(tag) is not String or Object, throw a TypeError exception.
626
  if (!tag->IsString() && !tag->IsJSReceiver()) {
627 628 629
    THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kLocaleNotEmpty),
                    JSLocale);
  }
630

631
  Handle<String> locale_string;
632 633
  // 8. If Type(tag) is Object and tag has an [[InitializedLocale]] internal
  // slot, then
634
  if (tag->IsJSLocale()) {
635
    // a. Let tag be tag.[[Locale]].
636
    locale_string = JSLocale::ToString(isolate, Handle<JSLocale>::cast(tag));
637 638
  } else {  // 9. Else,
    // a. Let tag be ? ToString(tag).
639 640 641
    ASSIGN_RETURN_ON_EXCEPTION(isolate, locale_string,
                               Object::ToString(isolate, tag), JSLocale);
  }
642

643
  Handle<JSReceiver> options_object;
644 645 646
  // 10. If options is undefined, then
  if (options->IsUndefined(isolate)) {
    // a. Let options be ! ObjectCreate(null).
647
    options_object = isolate->factory()->NewJSObjectWithNullProto();
648 649
  } else {  // 11. Else
    // a. Let options be ? ToObject(options).
650 651
    ASSIGN_RETURN_ON_EXCEPTION(isolate, options_object,
                               Object::ToObject(isolate, options), JSLocale);
652
  }
653

654
  return JSLocale::New(isolate, map, locale_string, options_object);
655 656
}

657 658
}  // namespace

659
// Intl.Locale implementation
660
BUILTIN(LocaleConstructor) {
661
  HandleScope scope(isolate);
662 663 664

  isolate->CountUsage(v8::Isolate::UseCounterFeature::kLocale);

665 666 667
  if (args.new_target()->IsUndefined(isolate)) {  // [[Call]]
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
668 669
                              isolate->factory()->NewStringFromAsciiChecked(
                                  "Intl.Locale")));
670 671 672 673 674
  }
  // [[Construct]]
  Handle<JSFunction> target = args.target();
  Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());

675
  Handle<Object> tag = args.atOrUndefined(isolate, 1);
676 677 678
  Handle<Object> options = args.atOrUndefined(isolate, 2);

  RETURN_RESULT_OR_FAILURE(
679
      isolate, CreateLocale(isolate, target, new_target, tag, options));
680 681
}

682
BUILTIN(LocalePrototypeMaximize) {
683
  HandleScope scope(isolate);
684
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.maximize");
685 686
  Handle<JSFunction> constructor(
      isolate->native_context()->intl_locale_function(), isolate);
687
  Handle<String> locale_str = JSLocale::ToString(isolate, locale);
688
  RETURN_RESULT_OR_FAILURE(
689 690 691
      isolate, CreateLocale(isolate, constructor, constructor,
                            JSLocale::Maximize(isolate, *locale_str),
                            isolate->factory()->NewJSObjectWithNullProto()));
692 693 694 695
}

BUILTIN(LocalePrototypeMinimize) {
  HandleScope scope(isolate);
696
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.minimize");
697 698
  Handle<JSFunction> constructor(
      isolate->native_context()->intl_locale_function(), isolate);
699
  Handle<String> locale_str = JSLocale::ToString(isolate, locale);
700
  RETURN_RESULT_OR_FAILURE(
701 702 703
      isolate, CreateLocale(isolate, constructor, constructor,
                            JSLocale::Minimize(isolate, *locale_str),
                            isolate->factory()->NewJSObjectWithNullProto()));
704 705
}

706 707
BUILTIN(RelativeTimeFormatSupportedLocalesOf) {
  HandleScope scope(isolate);
708 709 710
  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);

711
  RETURN_RESULT_OR_FAILURE(
712 713 714 715
      isolate,
      Intl::SupportedLocalesOf(
          isolate, "Intl.RelativeTimeFormat.supportedLocalesOf",
          JSRelativeTimeFormat::GetAvailableLocales(), locales, options));
716 717
}

718 719 720 721 722 723 724 725
BUILTIN(RelativeTimeFormatPrototypeFormat) {
  HandleScope scope(isolate);
  // 1. Let relativeTimeFormat be the this value.
  // 2. If Type(relativeTimeFormat) is not Object or relativeTimeFormat does not
  //    have an [[InitializedRelativeTimeFormat]] internal slot whose value is
  //    true, throw a TypeError exception.
  CHECK_RECEIVER(JSRelativeTimeFormat, format_holder,
                 "Intl.RelativeTimeFormat.prototype.format");
726 727 728 729 730
  Handle<Object> value_obj = args.atOrUndefined(isolate, 1);
  Handle<Object> unit_obj = args.atOrUndefined(isolate, 2);

  RETURN_RESULT_OR_FAILURE(
      isolate, JSRelativeTimeFormat::Format(isolate, value_obj, unit_obj,
731
                                            format_holder));
732 733 734 735 736 737 738 739 740 741
}

BUILTIN(RelativeTimeFormatPrototypeFormatToParts) {
  HandleScope scope(isolate);
  // 1. Let relativeTimeFormat be the this value.
  // 2. If Type(relativeTimeFormat) is not Object or relativeTimeFormat does not
  //    have an [[InitializedRelativeTimeFormat]] internal slot whose value is
  //    true, throw a TypeError exception.
  CHECK_RECEIVER(JSRelativeTimeFormat, format_holder,
                 "Intl.RelativeTimeFormat.prototype.formatToParts");
742 743
  Handle<Object> value_obj = args.atOrUndefined(isolate, 1);
  Handle<Object> unit_obj = args.atOrUndefined(isolate, 2);
744 745 746
  RETURN_RESULT_OR_FAILURE(
      isolate, JSRelativeTimeFormat::FormatToParts(isolate, value_obj, unit_obj,
                                                   format_holder));
747 748
}

749 750 751 752
// Locale getters.
BUILTIN(LocalePrototypeLanguage) {
  HandleScope scope(isolate);
  // CHECK_RECEIVER will case locale_holder to JSLocale.
753
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.language");
754

755
  return *JSLocale::Language(isolate, locale);
756 757 758 759
}

BUILTIN(LocalePrototypeScript) {
  HandleScope scope(isolate);
760
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.script");
761

762
  return *JSLocale::Script(isolate, locale);
763 764 765 766
}

BUILTIN(LocalePrototypeRegion) {
  HandleScope scope(isolate);
767
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.region");
768

769
  return *JSLocale::Region(isolate, locale);
770 771 772 773
}

BUILTIN(LocalePrototypeBaseName) {
  HandleScope scope(isolate);
774
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.baseName");
775

776
  return *JSLocale::BaseName(isolate, locale);
777 778 779 780
}

BUILTIN(LocalePrototypeCalendar) {
  HandleScope scope(isolate);
781
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.calendar");
782

783
  return *JSLocale::Calendar(isolate, locale);
784 785 786 787
}

BUILTIN(LocalePrototypeCaseFirst) {
  HandleScope scope(isolate);
788
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.caseFirst");
789

790
  return *JSLocale::CaseFirst(isolate, locale);
791 792 793 794
}

BUILTIN(LocalePrototypeCollation) {
  HandleScope scope(isolate);
795
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.collation");
796

797
  return *JSLocale::Collation(isolate, locale);
798 799 800 801
}

BUILTIN(LocalePrototypeHourCycle) {
  HandleScope scope(isolate);
802
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.hourCycle");
803

804
  return *JSLocale::HourCycle(isolate, locale);
805 806 807 808
}

BUILTIN(LocalePrototypeNumeric) {
  HandleScope scope(isolate);
809 810 811
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.numeric");

  return *JSLocale::Numeric(isolate, locale);
812 813 814 815
}

BUILTIN(LocalePrototypeNumberingSystem) {
  HandleScope scope(isolate);
816
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.numberingSystem");
817

818
  return *JSLocale::NumberingSystem(isolate, locale);
819 820 821 822
}

BUILTIN(LocalePrototypeToString) {
  HandleScope scope(isolate);
823
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.toString");
824

825
  return *JSLocale::ToString(isolate, locale);
826 827
}

828 829
BUILTIN(RelativeTimeFormatConstructor) {
  HandleScope scope(isolate);
830

831 832 833
  return DisallowCallConstructor<JSRelativeTimeFormat>(
      args, isolate, v8::Isolate::UseCounterFeature::kRelativeTimeFormat,
      "Intl.RelativeTimeFormat");
834 835 836 837 838 839 840 841 842
}

BUILTIN(RelativeTimeFormatPrototypeResolvedOptions) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSRelativeTimeFormat, format_holder,
                 "Intl.RelativeTimeFormat.prototype.resolvedOptions");
  return *JSRelativeTimeFormat::ResolvedOptions(isolate, format_holder);
}

843 844
BUILTIN(StringPrototypeToLocaleLowerCase) {
  HandleScope scope(isolate);
845 846 847

  isolate->CountUsage(v8::Isolate::UseCounterFeature::kStringToLocaleLowerCase);

848
  TO_THIS_STRING(string, "String.prototype.toLocaleLowerCase");
849

850 851 852 853 854 855 856
  RETURN_RESULT_OR_FAILURE(
      isolate, Intl::StringLocaleConvertCase(isolate, string, false,
                                             args.atOrUndefined(isolate, 1)));
}

BUILTIN(StringPrototypeToLocaleUpperCase) {
  HandleScope scope(isolate);
857 858 859

  isolate->CountUsage(v8::Isolate::UseCounterFeature::kStringToLocaleUpperCase);

860
  TO_THIS_STRING(string, "String.prototype.toLocaleUpperCase");
861

862 863 864 865 866
  RETURN_RESULT_OR_FAILURE(
      isolate, Intl::StringLocaleConvertCase(isolate, string, true,
                                             args.atOrUndefined(isolate, 1)));
}

867 868 869
BUILTIN(PluralRulesConstructor) {
  HandleScope scope(isolate);

870 871 872
  return DisallowCallConstructor<JSPluralRules>(
      args, isolate, v8::Isolate::UseCounterFeature::kPluralRules,
      "Intl.PluralRules");
873 874
}

875 876 877 878 879 880 881
BUILTIN(PluralRulesPrototypeResolvedOptions) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSPluralRules, plural_rules_holder,
                 "Intl.PluralRules.prototype.resolvedOptions");
  return *JSPluralRules::ResolvedOptions(isolate, plural_rules_holder);
}

882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902
BUILTIN(PluralRulesPrototypeSelect) {
  HandleScope scope(isolate);

  // 1. Let pr be the this value.
  // 2. If Type(pr) is not Object, throw a TypeError exception.
  // 3. If pr does not have an [[InitializedPluralRules]] internal slot, throw a
  // TypeError exception.
  CHECK_RECEIVER(JSPluralRules, plural_rules,
                 "Intl.PluralRules.prototype.select");

  // 4. Let n be ? ToNumber(value).
  Handle<Object> number = args.atOrUndefined(isolate, 1);
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number,
                                     Object::ToNumber(isolate, number));
  double number_double = number->Number();

  // 5. Return ? ResolvePlural(pr, n).
  RETURN_RESULT_OR_FAILURE(isolate, JSPluralRules::ResolvePlural(
                                        isolate, plural_rules, number_double));
}

903 904
BUILTIN(PluralRulesSupportedLocalesOf) {
  HandleScope scope(isolate);
905 906 907
  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);

908
  RETURN_RESULT_OR_FAILURE(
909 910 911
      isolate, Intl::SupportedLocalesOf(
                   isolate, "Intl.PluralRules.supportedLocalesOf",
                   JSPluralRules::GetAvailableLocales(), locales, options));
912 913
}

914 915
BUILTIN(CollatorConstructor) {
  HandleScope scope(isolate);
916 917 918

  isolate->CountUsage(v8::Isolate::UseCounterFeature::kCollator);

919
  return CallOrConstructConstructor<JSCollator>(args, isolate, "Intl.Collator");
920 921
}

922 923 924 925 926 927 928
BUILTIN(CollatorPrototypeResolvedOptions) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSCollator, collator_holder,
                 "Intl.Collator.prototype.resolvedOptions");
  return *JSCollator::ResolvedOptions(isolate, collator_holder);
}

929 930
BUILTIN(CollatorSupportedLocalesOf) {
  HandleScope scope(isolate);
931 932 933 934
  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);

  RETURN_RESULT_OR_FAILURE(
935 936 937
      isolate, Intl::SupportedLocalesOf(
                   isolate, "Intl.Collator.supportedLocalesOf",
                   JSCollator::GetAvailableLocales(), locales, options));
938 939
}

940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957
BUILTIN(CollatorPrototypeCompare) {
  const char* const method = "get Intl.Collator.prototype.compare";
  HandleScope scope(isolate);

  // 1. Let collator be this value.
  // 2. If Type(collator) is not Object, throw a TypeError exception.
  // 3. If collator does not have an [[InitializedCollator]] internal slot,
  // throw a TypeError exception.
  CHECK_RECEIVER(JSCollator, collator, method);

  // 4. If collator.[[BoundCompare]] is undefined, then
  Handle<Object> bound_compare(collator->bound_compare(), isolate);
  if (!bound_compare->IsUndefined(isolate)) {
    DCHECK(bound_compare->IsJSFunction());
    // 5. Return collator.[[BoundCompare]].
    return *bound_compare;
  }

958
  Handle<JSFunction> new_bound_compare_function = CreateBoundFunction(
959
      isolate, collator, Builtins::kCollatorInternalCompare, 2);
960 961 962 963 964 965 966 967 968 969 970 971 972 973 974

  // 4.c. Set collator.[[BoundCompare]] to F.
  collator->set_bound_compare(*new_bound_compare_function);

  // 5. Return collator.[[BoundCompare]].
  return *new_bound_compare_function;
}

BUILTIN(CollatorInternalCompare) {
  HandleScope scope(isolate);
  Handle<Context> context = Handle<Context>(isolate->context(), isolate);

  // 1. Let collator be F.[[Collator]].
  // 2. Assert: Type(collator) is Object and collator has an
  // [[InitializedCollator]] internal slot.
975
  Handle<JSCollator> collator = Handle<JSCollator>(
976 977
      JSCollator::cast(context->get(
          static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994
      isolate);

  // 3. If x is not provided, let x be undefined.
  Handle<Object> x = args.atOrUndefined(isolate, 1);
  // 4. If y is not provided, let y be undefined.
  Handle<Object> y = args.atOrUndefined(isolate, 2);

  // 5. Let X be ? ToString(x).
  Handle<String> string_x;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string_x,
                                     Object::ToString(isolate, x));
  // 6. Let Y be ? ToString(y).
  Handle<String> string_y;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string_y,
                                     Object::ToString(isolate, y));

  // 7. Return CompareStrings(collator, X, Y).
995
  icu::Collator* icu_collator = collator->icu_collator().raw();
996 997
  CHECK_NOT_NULL(icu_collator);
  return *Intl::CompareStrings(isolate, *icu_collator, string_x, string_y);
998 999
}

1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
// ecma402 #sec-segment-iterator-prototype-breakType
BUILTIN(SegmentIteratorPrototypeBreakType) {
  const char* const method = "get %SegmentIteratorPrototype%.breakType";
  HandleScope scope(isolate);

  CHECK_RECEIVER(JSSegmentIterator, segment_iterator, method);
  return *segment_iterator->BreakType();
}

// ecma402 #sec-segment-iterator-prototype-following
BUILTIN(SegmentIteratorPrototypeFollowing) {
  const char* const method = "%SegmentIteratorPrototype%.following";
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSSegmentIterator, segment_iterator, method);

  Handle<Object> from = args.atOrUndefined(isolate, 1);

  Maybe<bool> success =
      JSSegmentIterator::Following(isolate, segment_iterator, from);
  MAYBE_RETURN(success, ReadOnlyRoots(isolate).exception());
  return *isolate->factory()->ToBoolean(success.FromJust());
}

// ecma402 #sec-segment-iterator-prototype-next
BUILTIN(SegmentIteratorPrototypeNext) {
  const char* const method = "%SegmentIteratorPrototype%.next";
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSSegmentIterator, segment_iterator, method);

  RETURN_RESULT_OR_FAILURE(isolate,
                           JSSegmentIterator::Next(isolate, segment_iterator));
}

// ecma402 #sec-segment-iterator-prototype-preceding
BUILTIN(SegmentIteratorPrototypePreceding) {
  const char* const method = "%SegmentIteratorPrototype%.preceding";
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSSegmentIterator, segment_iterator, method);

  Handle<Object> from = args.atOrUndefined(isolate, 1);

  Maybe<bool> success =
      JSSegmentIterator::Preceding(isolate, segment_iterator, from);
  MAYBE_RETURN(success, ReadOnlyRoots(isolate).exception());
  return *isolate->factory()->ToBoolean(success.FromJust());
}

1047 1048 1049
// ecma402 #sec-segment-iterator-prototype-index
BUILTIN(SegmentIteratorPrototypeIndex) {
  const char* const method = "get %SegmentIteratorPrototype%.index";
1050 1051 1052
  HandleScope scope(isolate);

  CHECK_RECEIVER(JSSegmentIterator, segment_iterator, method);
1053
  return *JSSegmentIterator::Index(isolate, segment_iterator);
1054 1055
}

1056 1057 1058
BUILTIN(SegmenterConstructor) {
  HandleScope scope(isolate);

1059 1060 1061
  return DisallowCallConstructor<JSSegmenter>(
      args, isolate, v8::Isolate::UseCounterFeature::kSegmenter,
      "Intl.Segmenter");
1062 1063 1064 1065
}

BUILTIN(SegmenterSupportedLocalesOf) {
  HandleScope scope(isolate);
1066 1067 1068
  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);

1069
  RETURN_RESULT_OR_FAILURE(
1070 1071 1072
      isolate, Intl::SupportedLocalesOf(
                   isolate, "Intl.Segmenter.supportedLocalesOf",
                   JSSegmenter::GetAvailableLocales(), locales, options));
1073 1074 1075 1076 1077 1078 1079 1080 1081
}

BUILTIN(SegmenterPrototypeResolvedOptions) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSSegmenter, segmenter_holder,
                 "Intl.Segmenter.prototype.resolvedOptions");
  return *JSSegmenter::ResolvedOptions(isolate, segmenter_holder);
}

1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096
// ecma402 #sec-Intl.Segmenter.prototype.segment
BUILTIN(SegmenterPrototypeSegment) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSSegmenter, segmenter_holder,
                 "Intl.Segmenter.prototype.segment");
  Handle<Object> input_text = args.atOrUndefined(isolate, 1);
  // 3. Let string be ? ToString(string).
  Handle<String> text;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, text,
                                     Object::ToString(isolate, input_text));

  // 4. Return ? CreateSegmentIterator(segment, string).
  RETURN_RESULT_OR_FAILURE(
      isolate,
      JSSegmentIterator::Create(
1097
          isolate, segmenter_holder->icu_break_iterator().raw()->clone(),
1098 1099 1100
          segmenter_holder->granularity(), text));
}

1101
BUILTIN(V8BreakIteratorConstructor) {
1102
  HandleScope scope(isolate);
1103

1104 1105
  return CallOrConstructConstructor<JSV8BreakIterator>(args, isolate,
                                                       "Intl.v8BreakIterator");
1106 1107
}

1108
BUILTIN(V8BreakIteratorPrototypeResolvedOptions) {
1109 1110 1111 1112 1113 1114
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSV8BreakIterator, break_iterator,
                 "Intl.v8BreakIterator.prototype.resolvedOptions");
  return *JSV8BreakIterator::ResolvedOptions(isolate, break_iterator);
}

1115
BUILTIN(V8BreakIteratorPrototypeAdoptText) {
1116 1117 1118 1119 1120 1121
  const char* const method = "get Intl.v8BreakIterator.prototype.adoptText";
  HandleScope scope(isolate);

  CHECK_RECEIVER(JSV8BreakIterator, break_iterator, method);

  Handle<Object> bound_adopt_text(break_iterator->bound_adopt_text(), isolate);
1122 1123 1124 1125 1126
  if (!bound_adopt_text->IsUndefined(isolate)) {
    DCHECK(bound_adopt_text->IsJSFunction());
    return *bound_adopt_text;
  }

1127
  Handle<JSFunction> new_bound_adopt_text_function = CreateBoundFunction(
1128
      isolate, break_iterator, Builtins::kV8BreakIteratorInternalAdoptText, 1);
1129
  break_iterator->set_bound_adopt_text(*new_bound_adopt_text_function);
1130 1131 1132
  return *new_bound_adopt_text_function;
}

1133
BUILTIN(V8BreakIteratorInternalAdoptText) {
1134 1135 1136
  HandleScope scope(isolate);
  Handle<Context> context = Handle<Context>(isolate->context(), isolate);

1137
  Handle<JSV8BreakIterator> break_iterator = Handle<JSV8BreakIterator>(
1138
      JSV8BreakIterator::cast(context->get(
1139
          static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
1140 1141 1142 1143 1144 1145 1146
      isolate);

  Handle<Object> input_text = args.atOrUndefined(isolate, 1);
  Handle<String> text;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, text,
                                     Object::ToString(isolate, input_text));

1147
  JSV8BreakIterator::AdoptText(isolate, break_iterator, text);
1148 1149 1150
  return ReadOnlyRoots(isolate).undefined_value();
}

1151
BUILTIN(V8BreakIteratorPrototypeFirst) {
1152 1153 1154
  const char* const method = "get Intl.v8BreakIterator.prototype.first";
  HandleScope scope(isolate);

1155
  CHECK_RECEIVER(JSV8BreakIterator, break_iterator, method);
1156

1157
  Handle<Object> bound_first(break_iterator->bound_first(), isolate);
1158 1159 1160 1161 1162
  if (!bound_first->IsUndefined(isolate)) {
    DCHECK(bound_first->IsJSFunction());
    return *bound_first;
  }

1163 1164 1165
  Handle<JSFunction> new_bound_first_function = CreateBoundFunction(
      isolate, break_iterator, Builtins::kV8BreakIteratorInternalFirst, 0);
  break_iterator->set_bound_first(*new_bound_first_function);
1166 1167 1168
  return *new_bound_first_function;
}

1169
BUILTIN(V8BreakIteratorInternalFirst) {
1170 1171 1172
  HandleScope scope(isolate);
  Handle<Context> context = Handle<Context>(isolate->context(), isolate);

1173
  Handle<JSV8BreakIterator> break_iterator = Handle<JSV8BreakIterator>(
1174
      JSV8BreakIterator::cast(context->get(
1175
          static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
1176 1177
      isolate);

1178
  return *JSV8BreakIterator::First(isolate, break_iterator);
1179 1180
}

1181
BUILTIN(V8BreakIteratorPrototypeNext) {
1182 1183 1184
  const char* const method = "get Intl.v8BreakIterator.prototype.next";
  HandleScope scope(isolate);

1185
  CHECK_RECEIVER(JSV8BreakIterator, break_iterator, method);
1186

1187
  Handle<Object> bound_next(break_iterator->bound_next(), isolate);
1188 1189 1190 1191 1192
  if (!bound_next->IsUndefined(isolate)) {
    DCHECK(bound_next->IsJSFunction());
    return *bound_next;
  }

1193 1194 1195
  Handle<JSFunction> new_bound_next_function = CreateBoundFunction(
      isolate, break_iterator, Builtins::kV8BreakIteratorInternalNext, 0);
  break_iterator->set_bound_next(*new_bound_next_function);
1196 1197 1198
  return *new_bound_next_function;
}

1199
BUILTIN(V8BreakIteratorInternalNext) {
1200 1201 1202
  HandleScope scope(isolate);
  Handle<Context> context = Handle<Context>(isolate->context(), isolate);

1203
  Handle<JSV8BreakIterator> break_iterator = Handle<JSV8BreakIterator>(
1204
      JSV8BreakIterator::cast(context->get(
1205
          static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
1206
      isolate);
1207
  return *JSV8BreakIterator::Next(isolate, break_iterator);
1208 1209
}

1210
BUILTIN(V8BreakIteratorPrototypeCurrent) {
1211 1212 1213
  const char* const method = "get Intl.v8BreakIterator.prototype.current";
  HandleScope scope(isolate);

1214
  CHECK_RECEIVER(JSV8BreakIterator, break_iterator, method);
1215

1216
  Handle<Object> bound_current(break_iterator->bound_current(), isolate);
1217 1218 1219 1220 1221
  if (!bound_current->IsUndefined(isolate)) {
    DCHECK(bound_current->IsJSFunction());
    return *bound_current;
  }

1222 1223 1224
  Handle<JSFunction> new_bound_current_function = CreateBoundFunction(
      isolate, break_iterator, Builtins::kV8BreakIteratorInternalCurrent, 0);
  break_iterator->set_bound_current(*new_bound_current_function);
1225 1226 1227
  return *new_bound_current_function;
}

1228
BUILTIN(V8BreakIteratorInternalCurrent) {
1229 1230 1231
  HandleScope scope(isolate);
  Handle<Context> context = Handle<Context>(isolate->context(), isolate);

1232
  Handle<JSV8BreakIterator> break_iterator = Handle<JSV8BreakIterator>(
1233
      JSV8BreakIterator::cast(context->get(
1234
          static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
1235
      isolate);
1236
  return *JSV8BreakIterator::Current(isolate, break_iterator);
1237 1238
}

1239
BUILTIN(V8BreakIteratorPrototypeBreakType) {
1240 1241 1242
  const char* const method = "get Intl.v8BreakIterator.prototype.breakType";
  HandleScope scope(isolate);

1243
  CHECK_RECEIVER(JSV8BreakIterator, break_iterator, method);
1244

1245
  Handle<Object> bound_break_type(break_iterator->bound_break_type(), isolate);
1246 1247 1248 1249 1250
  if (!bound_break_type->IsUndefined(isolate)) {
    DCHECK(bound_break_type->IsJSFunction());
    return *bound_break_type;
  }

1251 1252 1253
  Handle<JSFunction> new_bound_break_type_function = CreateBoundFunction(
      isolate, break_iterator, Builtins::kV8BreakIteratorInternalBreakType, 0);
  break_iterator->set_bound_break_type(*new_bound_break_type_function);
1254 1255 1256
  return *new_bound_break_type_function;
}

1257
BUILTIN(V8BreakIteratorInternalBreakType) {
1258 1259 1260
  HandleScope scope(isolate);
  Handle<Context> context = Handle<Context>(isolate->context(), isolate);

1261
  Handle<JSV8BreakIterator> break_iterator = Handle<JSV8BreakIterator>(
1262
      JSV8BreakIterator::cast(context->get(
1263
          static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
1264
      isolate);
1265
  return JSV8BreakIterator::BreakType(isolate, break_iterator);
1266 1267
}

1268 1269
}  // namespace internal
}  // namespace v8