builtins-intl.cc 45 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/js-segments-inl.h"
32
#include "src/objects/objects-inl.h"
33
#include "src/objects/option-utils.h"
34
#include "src/objects/property-descriptor.h"
35
#include "src/objects/smi.h"
36
#include "unicode/brkiter.h"
37

38 39 40
namespace v8 {
namespace internal {

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

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

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

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

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

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

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

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

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

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

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

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

  // 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));
}

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

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

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

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

  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,
145
                                       Object::ToNumber(isolate, args.at(1)));
146 147 148 149 150 151 152 153
  }

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

154 155
  RETURN_RESULT_OR_FAILURE(isolate, JSDateTimeFormat::FormatToParts(
                                        isolate, dtf, date_value, false));
156 157
}

158 159 160
// Common code for DateTimeFormatPrototypeFormtRange(|ToParts)
template <class T>
V8_WARN_UNUSED_RESULT Object DateTimeFormatRange(
161
    BuiltinArguments args, Isolate* isolate, const char* const method_name,
162 163 164 165
    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.
166
  CHECK_RECEIVER(JSObject, date_format_holder, method_name);
167 168 169 170 171 172 173 174

  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,
175
                              factory->NewStringFromAsciiChecked(method_name),
176 177 178 179 180
                              date_format_holder));
  }
  Handle<JSDateTimeFormat> dtf =
      Handle<JSDateTimeFormat>::cast(date_format_holder);

181
  // 4. If startDate is undefined or endDate is undefined, throw a TypeError
182 183 184 185 186
  // 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(
187
        isolate, NewTypeError(MessageTemplate::kInvalidTimeValue));
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
  }
  // 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) {
211
  const char* const method_name = "Intl.DateTimeFormat.prototype.formatRange";
212
  HandleScope handle_scope(isolate);
213
  return DateTimeFormatRange<String>(args, isolate, method_name,
214 215 216 217
                                     JSDateTimeFormat::FormatRange);
}

BUILTIN(DateTimeFormatPrototypeFormatRangeToParts) {
218 219
  const char* const method_name =
      "Intl.DateTimeFormat.prototype.formatRangeToParts";
220
  HandleScope handle_scope(isolate);
221
  return DateTimeFormatRange<JSArray>(args, isolate, method_name,
222 223 224
                                      JSDateTimeFormat::FormatRangeToParts);
}

225
namespace {
226

227
Handle<JSFunction> CreateBoundFunction(Isolate* isolate,
228 229
                                       Handle<JSObject> object, Builtin builtin,
                                       int len) {
230
  Handle<NativeContext> native_context(isolate->context().native_context(),
231 232 233 234 235 236 237 238
                                       isolate);
  Handle<Context> context = isolate->factory()->NewBuiltinContext(
      native_context,
      static_cast<int>(Intl::BoundFunctionContextSlot::kLength));

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

239 240
  Handle<SharedFunctionInfo> info =
      isolate->factory()->NewSharedFunctionInfoForBuiltin(
241
          isolate->factory()->empty_string(), builtin, kNormalFunction);
242
  info->set_internal_formal_parameter_count(JSParameterCount(len));
243 244
  info->set_length(len);

245 246 247
  return Factory::JSFunctionBuilder{isolate, info, context}
      .set_map(isolate->strict_function_without_prototype_map())
      .Build();
248
}
249 250 251 252 253 254

/**
 * Common code shared between DateTimeFormatConstructor and
 * NumberFormatConstrutor
 */
template <class T>
255 256
Object LegacyFormatConstructor(BuiltinArguments args, Isolate* isolate,
                               v8::Isolate::UseCounterFeature feature,
257 258
                               Handle<Object> constructor,
                               const char* method_name) {
259
  isolate->CountUsage(feature);
260 261 262 263 264 265 266 267 268 269 270 271 272 273
  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);

274 275
  // 2. Let format be ? OrdinaryCreateFromConstructor(newTarget,
  // "%<T>Prototype%", ...).
276
  Handle<Map> map;
277
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
278
      isolate, map, JSFunction::GetDerivedMap(isolate, target, new_target));
279

280
  // 3. Perform ? Initialize<T>(Format, locales, options).
281
  Handle<T> format;
282
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
283
      isolate, format, T::New(isolate, map, locales, options, method_name));
284
  // 4. Let this be the this value.
285 286
  if (args.new_target()->IsUndefined(isolate)) {
    Handle<Object> receiver = args.receiver();
287
    // 5. If NewTarget is undefined and ? OrdinaryHasInstance(%<T>%, this)
288 289
    // is true, then Look up the intrinsic value that has been stored on
    // the context.
290
    Handle<Object> ordinary_has_instance_obj;
291
    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
292 293 294
        isolate, ordinary_has_instance_obj,
        Object::OrdinaryHasInstance(isolate, constructor, receiver));
    if (ordinary_has_instance_obj->BooleanValue(isolate)) {
295 296
      if (!receiver->IsJSReceiver()) {
        THROW_NEW_ERROR_RETURN_FAILURE(
297 298 299 300
            isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
                                  isolate->factory()->NewStringFromAsciiChecked(
                                      method_name),
                                  receiver));
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
      }
      Handle<JSReceiver> rec = Handle<JSReceiver>::cast(receiver);
      // a. Perform ? DefinePropertyOrThrow(this,
      // %Intl%.[[FallbackSymbol]], PropertyDescriptor{ [[Value]]: format,
      // [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }).
      PropertyDescriptor desc;
      desc.set_value(format);
      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,
          Just(kThrowOnError));
      MAYBE_RETURN(success, ReadOnlyRoots(isolate).exception());
      CHECK(success.FromJust());
      // b. b. Return this.
      return *receiver;
318 319
    }
  }
320 321 322
  // 6. Return format.
  return *format;
}
323

324 325 326 327 328
/**
 * Common code shared by ListFormat, RelativeTimeFormat, PluralRules, and
 * Segmenter
 */
template <class T>
329 330
Object DisallowCallConstructor(BuiltinArguments args, Isolate* isolate,
                               v8::Isolate::UseCounterFeature feature,
331
                               const char* method_name) {
332 333 334 335 336
  isolate->CountUsage(feature);

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

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

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

354 355
  // 3. Return New<T>(t, locales, options).
  RETURN_RESULT_OR_FAILURE(isolate, T::New(isolate, map, locales, options));
356 357 358 359 360 361
}

/**
 * Common code shared by Collator and V8BreakIterator
 */
template <class T>
362
Object CallOrConstructConstructor(BuiltinArguments args, Isolate* isolate,
363
                                  const char* method_name) {
364 365 366 367 368 369 370 371 372 373 374 375 376 377
  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);

378
  Handle<Map> map;
379
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
380
      isolate, map, JSFunction::GetDerivedMap(isolate, target, new_target));
381

382
  RETURN_RESULT_OR_FAILURE(isolate,
383
                           T::New(isolate, map, locales, options, method_name));
384
}
385

386 387
}  // namespace

388 389 390 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
// 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

427 428
BUILTIN(NumberFormatConstructor) {
  HandleScope scope(isolate);
429

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

435 436
BUILTIN(NumberFormatPrototypeResolvedOptions) {
  HandleScope scope(isolate);
437
  const char* const method_name = "Intl.NumberFormat.prototype.resolvedOptions";
438 439 440

  // 1. Let nf be the this value.
  // 2. If Type(nf) is not Object, throw a TypeError exception.
441
  CHECK_RECEIVER(JSReceiver, number_format_holder, method_name);
442 443 444 445 446 447 448 449 450 451

  // 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);
}

452
BUILTIN(NumberFormatPrototypeFormatNumber) {
453
  const char* const method_name = "get Intl.NumberFormat.prototype.format";
454 455 456 457
  HandleScope scope(isolate);

  // 1. Let nf be the this value.
  // 2. If Type(nf) is not Object, throw a TypeError exception.
458
  CHECK_RECEIVER(JSReceiver, receiver, method_name);
459 460

  // 3. Let nf be ? UnwrapNumberFormat(nf).
461
  Handle<JSNumberFormat> number_format;
462
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
463 464
      isolate, number_format,
      JSNumberFormat::UnwrapNumberFormat(isolate, receiver));
465

466
  Handle<Object> bound_format(number_format->bound_format(), isolate);
467 468 469 470 471 472 473 474

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

475
  Handle<JSFunction> new_bound_format_function = CreateBoundFunction(
476
      isolate, number_format, Builtin::kNumberFormatInternalFormatNumber, 1);
477 478

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

  // 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.
493
  Handle<JSNumberFormat> number_format = Handle<JSNumberFormat>(
494 495
      JSNumberFormat::cast(context->get(
          static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
496
      isolate);
497 498 499 500

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

501 502
  // 4. Let x be ? ToNumeric(value).
  Handle<Object> numeric_obj;
503 504
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, numeric_obj,
                                     Object::ToNumeric(isolate, value));
505

506
  icu::number::LocalizedNumberFormatter* icu_localized_number_formatter =
507
      number_format->icu_number_formatter().raw();
508
  CHECK_NOT_NULL(icu_localized_number_formatter);
509

510
  // Return FormatNumber(nf, x).
511
  RETURN_RESULT_OR_FAILURE(
512 513
      isolate, JSNumberFormat::FormatNumeric(
                   isolate, *icu_localized_number_formatter, numeric_obj));
514 515
}

516 517
BUILTIN(DateTimeFormatConstructor) {
  HandleScope scope(isolate);
518

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

524
BUILTIN(DateTimeFormatPrototypeFormat) {
525
  const char* const method_name = "get Intl.DateTimeFormat.prototype.format";
526 527 528 529
  HandleScope scope(isolate);

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

  // 3. Let dtf be ? UnwrapDateTimeFormat(dtf).
533
  Handle<JSDateTimeFormat> format;
534
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
535 536
      isolate, format,
      JSDateTimeFormat::UnwrapDateTimeFormat(isolate, receiver));
537

538
  Handle<Object> bound_format = Handle<Object>(format->bound_format(), isolate);
539 540 541 542 543 544 545 546

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

547
  Handle<JSFunction> new_bound_format_function = CreateBoundFunction(
548
      isolate, format, Builtin::kDateTimeFormatInternalFormat, 1);
549 550

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

  // 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.
564 565 566 567
  Handle<JSDateTimeFormat> date_format_holder = Handle<JSDateTimeFormat>(
      JSDateTimeFormat::cast(context->get(
          static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
      isolate);
568 569 570

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

571 572
  RETURN_RESULT_OR_FAILURE(isolate, JSDateTimeFormat::DateTimeFormat(
                                        isolate, date_format_holder, date));
573 574
}

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

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

583 584 585 586 587 588 589
BUILTIN(IntlSupportedValuesOf) {
  HandleScope scope(isolate);
  Handle<Object> locales = args.atOrUndefined(isolate, 1);

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

590 591
BUILTIN(ListFormatConstructor) {
  HandleScope scope(isolate);
592

593 594 595
  return DisallowCallConstructor<JSListFormat>(
      args, isolate, v8::Isolate::UseCounterFeature::kListFormat,
      "Intl.ListFormat");
596 597
}

598 599 600 601 602 603 604
BUILTIN(ListFormatPrototypeResolvedOptions) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSListFormat, format_holder,
                 "Intl.ListFormat.prototype.resolvedOptions");
  return *JSListFormat::ResolvedOptions(isolate, format_holder);
}

605 606
BUILTIN(ListFormatSupportedLocalesOf) {
  HandleScope scope(isolate);
607 608 609
  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);

610
  RETURN_RESULT_OR_FAILURE(
611 612 613
      isolate, Intl::SupportedLocalesOf(
                   isolate, "Intl.ListFormat.supportedLocalesOf",
                   JSListFormat::GetAvailableLocales(), locales, options));
614 615
}

616 617 618 619 620 621
// Intl.Locale implementation
BUILTIN(LocaleConstructor) {
  HandleScope scope(isolate);

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

622
  const char* method_name = "Intl.Locale";
623 624
  if (args.new_target()->IsUndefined(isolate)) {  // [[Call]]
    THROW_NEW_ERROR_RETURN_FAILURE(
625 626 627
        isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
                              isolate->factory()->NewStringFromAsciiChecked(
                                  method_name)));
628 629 630 631 632 633 634
  }
  // [[Construct]]
  Handle<JSFunction> target = args.target();
  Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());

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

636
  Handle<Map> map;
637 638
  // 6. Let locale be ? OrdinaryCreateFromConstructor(NewTarget,
  // %LocalePrototype%, internalSlotsList).
639 640
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, map, JSFunction::GetDerivedMap(isolate, target, new_target));
641

642
  // 7. If Type(tag) is not String or Object, throw a TypeError exception.
643
  if (!tag->IsString() && !tag->IsJSReceiver()) {
644 645
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate, NewTypeError(MessageTemplate::kLocaleNotEmpty));
646
  }
647

648
  Handle<String> locale_string;
649 650
  // 8. If Type(tag) is Object and tag has an [[InitializedLocale]] internal
  // slot, then
651
  if (tag->IsJSLocale()) {
652
    // a. Let tag be tag.[[Locale]].
653
    locale_string = JSLocale::ToString(isolate, Handle<JSLocale>::cast(tag));
654 655
  } else {  // 9. Else,
    // a. Let tag be ? ToString(tag).
656 657
    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, locale_string,
                                       Object::ToString(isolate, tag));
658
  }
659

660
  // 10. Set options to ? CoerceOptionsToObject(options).
661
  Handle<JSReceiver> options_object;
662
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
663 664
      isolate, options_object,
      CoerceOptionsToObject(isolate, options, method_name));
665

666
  RETURN_RESULT_OR_FAILURE(
667
      isolate, JSLocale::New(isolate, map, locale_string, options_object));
668 669
}

670
BUILTIN(LocalePrototypeMaximize) {
671
  HandleScope scope(isolate);
672
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.maximize");
673
  RETURN_RESULT_OR_FAILURE(isolate, JSLocale::Maximize(isolate, locale));
674 675 676 677
}

BUILTIN(LocalePrototypeMinimize) {
  HandleScope scope(isolate);
678
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.minimize");
679
  RETURN_RESULT_OR_FAILURE(isolate, JSLocale::Minimize(isolate, locale));
680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
}

BUILTIN(LocalePrototypeCalendars) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.calendars");
  RETURN_RESULT_OR_FAILURE(isolate, JSLocale::Calendars(isolate, locale));
}

BUILTIN(LocalePrototypeCollations) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.collations");
  RETURN_RESULT_OR_FAILURE(isolate, JSLocale::Collations(isolate, locale));
}

BUILTIN(LocalePrototypeHourCycles) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.hourCycles");
  RETURN_RESULT_OR_FAILURE(isolate, JSLocale::HourCycles(isolate, locale));
}

BUILTIN(LocalePrototypeNumberingSystems) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.numberingSystems");
  RETURN_RESULT_OR_FAILURE(isolate,
                           JSLocale::NumberingSystems(isolate, locale));
}

BUILTIN(LocalePrototypeTextInfo) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.textInfo");
  RETURN_RESULT_OR_FAILURE(isolate, JSLocale::TextInfo(isolate, locale));
}

BUILTIN(LocalePrototypeTimeZones) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.timeZones");
  RETURN_RESULT_OR_FAILURE(isolate, JSLocale::TimeZones(isolate, locale));
}

BUILTIN(LocalePrototypeWeekInfo) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.weekInfo");
  RETURN_RESULT_OR_FAILURE(isolate, JSLocale::WeekInfo(isolate, locale));
723 724
}

725 726
BUILTIN(RelativeTimeFormatSupportedLocalesOf) {
  HandleScope scope(isolate);
727 728 729
  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);

730
  RETURN_RESULT_OR_FAILURE(
731 732 733 734
      isolate,
      Intl::SupportedLocalesOf(
          isolate, "Intl.RelativeTimeFormat.supportedLocalesOf",
          JSRelativeTimeFormat::GetAvailableLocales(), locales, options));
735 736
}

737 738 739 740 741 742 743 744
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");
745 746 747 748 749
  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,
750
                                            format_holder));
751 752 753 754 755 756 757 758 759 760
}

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");
761 762
  Handle<Object> value_obj = args.atOrUndefined(isolate, 1);
  Handle<Object> unit_obj = args.atOrUndefined(isolate, 2);
763 764 765
  RETURN_RESULT_OR_FAILURE(
      isolate, JSRelativeTimeFormat::FormatToParts(isolate, value_obj, unit_obj,
                                                   format_holder));
766 767
}

768 769 770 771
// Locale getters.
BUILTIN(LocalePrototypeLanguage) {
  HandleScope scope(isolate);
  // CHECK_RECEIVER will case locale_holder to JSLocale.
772
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.language");
773

774
  return *JSLocale::Language(isolate, locale);
775 776 777 778
}

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

781
  return *JSLocale::Script(isolate, locale);
782 783 784 785
}

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

788
  return *JSLocale::Region(isolate, locale);
789 790 791 792
}

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

795
  return *JSLocale::BaseName(isolate, locale);
796 797 798 799
}

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

802
  return *JSLocale::Calendar(isolate, locale);
803 804 805 806
}

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

809
  return *JSLocale::CaseFirst(isolate, locale);
810 811 812 813
}

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

816
  return *JSLocale::Collation(isolate, locale);
817 818 819 820
}

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

823
  return *JSLocale::HourCycle(isolate, locale);
824 825 826 827
}

BUILTIN(LocalePrototypeNumeric) {
  HandleScope scope(isolate);
828 829 830
  CHECK_RECEIVER(JSLocale, locale, "Intl.Locale.prototype.numeric");

  return *JSLocale::Numeric(isolate, locale);
831 832 833 834
}

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

837
  return *JSLocale::NumberingSystem(isolate, locale);
838 839 840 841
}

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

844
  return *JSLocale::ToString(isolate, locale);
845 846
}

847 848
BUILTIN(RelativeTimeFormatConstructor) {
  HandleScope scope(isolate);
849

850 851 852
  return DisallowCallConstructor<JSRelativeTimeFormat>(
      args, isolate, v8::Isolate::UseCounterFeature::kRelativeTimeFormat,
      "Intl.RelativeTimeFormat");
853 854 855 856 857 858 859 860 861
}

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

862 863
BUILTIN(StringPrototypeToLocaleLowerCase) {
  HandleScope scope(isolate);
864 865 866

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

867
  TO_THIS_STRING(string, "String.prototype.toLocaleLowerCase");
868

869 870 871 872 873 874 875
  RETURN_RESULT_OR_FAILURE(
      isolate, Intl::StringLocaleConvertCase(isolate, string, false,
                                             args.atOrUndefined(isolate, 1)));
}

BUILTIN(StringPrototypeToLocaleUpperCase) {
  HandleScope scope(isolate);
876 877 878

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

879
  TO_THIS_STRING(string, "String.prototype.toLocaleUpperCase");
880

881 882 883 884 885
  RETURN_RESULT_OR_FAILURE(
      isolate, Intl::StringLocaleConvertCase(isolate, string, true,
                                             args.atOrUndefined(isolate, 1)));
}

886 887 888
BUILTIN(PluralRulesConstructor) {
  HandleScope scope(isolate);

889 890 891
  return DisallowCallConstructor<JSPluralRules>(
      args, isolate, v8::Isolate::UseCounterFeature::kPluralRules,
      "Intl.PluralRules");
892 893
}

894 895 896 897 898 899 900
BUILTIN(PluralRulesPrototypeResolvedOptions) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSPluralRules, plural_rules_holder,
                 "Intl.PluralRules.prototype.resolvedOptions");
  return *JSPluralRules::ResolvedOptions(isolate, plural_rules_holder);
}

901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921
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));
}

922 923
BUILTIN(PluralRulesSupportedLocalesOf) {
  HandleScope scope(isolate);
924 925 926
  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);

927
  RETURN_RESULT_OR_FAILURE(
928 929 930
      isolate, Intl::SupportedLocalesOf(
                   isolate, "Intl.PluralRules.supportedLocalesOf",
                   JSPluralRules::GetAvailableLocales(), locales, options));
931 932
}

933 934
BUILTIN(CollatorConstructor) {
  HandleScope scope(isolate);
935 936 937

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

938
  return CallOrConstructConstructor<JSCollator>(args, isolate, "Intl.Collator");
939 940
}

941 942 943 944 945 946 947
BUILTIN(CollatorPrototypeResolvedOptions) {
  HandleScope scope(isolate);
  CHECK_RECEIVER(JSCollator, collator_holder,
                 "Intl.Collator.prototype.resolvedOptions");
  return *JSCollator::ResolvedOptions(isolate, collator_holder);
}

948 949
BUILTIN(CollatorSupportedLocalesOf) {
  HandleScope scope(isolate);
950 951 952 953
  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);

  RETURN_RESULT_OR_FAILURE(
954 955 956
      isolate, Intl::SupportedLocalesOf(
                   isolate, "Intl.Collator.supportedLocalesOf",
                   JSCollator::GetAvailableLocales(), locales, options));
957 958
}

959
BUILTIN(CollatorPrototypeCompare) {
960
  const char* const method_name = "get Intl.Collator.prototype.compare";
961 962 963 964 965 966
  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.
967
  CHECK_RECEIVER(JSCollator, collator, method_name);
968 969 970 971 972 973 974 975 976

  // 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;
  }

977
  Handle<JSFunction> new_bound_compare_function = CreateBoundFunction(
978
      isolate, collator, Builtin::kCollatorInternalCompare, 2);
979 980 981 982 983 984 985 986 987 988 989 990 991 992 993

  // 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.
994
  Handle<JSCollator> collator = Handle<JSCollator>(
995 996
      JSCollator::cast(context->get(
          static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
      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).
1014
  icu::Collator* icu_collator = collator->icu_collator().raw();
1015
  CHECK_NOT_NULL(icu_collator);
1016 1017
  return Smi::FromInt(
      Intl::CompareStrings(isolate, *icu_collator, string_x, string_y));
1018 1019
}

1020
// ecma402 #sec-%segmentiteratorprototype%.next
1021
BUILTIN(SegmentIteratorPrototypeNext) {
1022
  const char* const method_name = "%SegmentIterator.prototype%.next";
1023
  HandleScope scope(isolate);
1024
  CHECK_RECEIVER(JSSegmentIterator, segment_iterator, method_name);
1025 1026 1027 1028 1029

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

1030
// ecma402 #sec-intl.segmenter
1031 1032 1033
BUILTIN(SegmenterConstructor) {
  HandleScope scope(isolate);

1034 1035 1036
  return DisallowCallConstructor<JSSegmenter>(
      args, isolate, v8::Isolate::UseCounterFeature::kSegmenter,
      "Intl.Segmenter");
1037 1038
}

1039
// ecma402 #sec-intl.segmenter.supportedlocalesof
1040 1041
BUILTIN(SegmenterSupportedLocalesOf) {
  HandleScope scope(isolate);
1042 1043 1044
  Handle<Object> locales = args.atOrUndefined(isolate, 1);
  Handle<Object> options = args.atOrUndefined(isolate, 2);

1045
  RETURN_RESULT_OR_FAILURE(
1046 1047 1048
      isolate, Intl::SupportedLocalesOf(
                   isolate, "Intl.Segmenter.supportedLocalesOf",
                   JSSegmenter::GetAvailableLocales(), locales, options));
1049 1050
}

1051
// ecma402 #sec-intl.segmenter.prototype.resolvedoptions
1052 1053
BUILTIN(SegmenterPrototypeResolvedOptions) {
  HandleScope scope(isolate);
1054
  CHECK_RECEIVER(JSSegmenter, segmenter,
1055
                 "Intl.Segmenter.prototype.resolvedOptions");
1056
  return *JSSegmenter::ResolvedOptions(isolate, segmenter);
1057 1058
}

1059
// ecma402 #sec-intl.segmenter.prototype.segment
1060 1061
BUILTIN(SegmenterPrototypeSegment) {
  HandleScope scope(isolate);
1062
  CHECK_RECEIVER(JSSegmenter, segmenter, "Intl.Segmenter.prototype.segment");
1063 1064
  Handle<Object> input_text = args.atOrUndefined(isolate, 1);
  // 3. Let string be ? ToString(string).
1065 1066
  Handle<String> string;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string,
1067 1068
                                     Object::ToString(isolate, input_text));

1069 1070 1071 1072 1073 1074 1075
  // 4. Return ? CreateSegmentsObject(segmenter, string).
  RETURN_RESULT_OR_FAILURE(isolate,
                           JSSegments::Create(isolate, segmenter, string));
}

// ecma402 #sec-%segmentsprototype%.containing
BUILTIN(SegmentsPrototypeContaining) {
1076
  const char* const method_name = "%Segments.prototype%.containing";
1077
  HandleScope scope(isolate);
1078
  CHECK_RECEIVER(JSSegments, segments, method_name);
1079 1080 1081 1082 1083 1084 1085
  Handle<Object> index = args.atOrUndefined(isolate, 1);

  // 6. Let n be ? ToInteger(index).
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, index,
                                     Object::ToInteger(isolate, index));
  double const n = index->Number();

1086 1087
  RETURN_RESULT_OR_FAILURE(isolate,
                           JSSegments::Containing(isolate, segments, n));
1088 1089 1090 1091
}

// ecma402 #sec-%segmentsprototype%-@@iterator
BUILTIN(SegmentsPrototypeIterator) {
1092
  const char* const method_name = "%SegmentIsPrototype%[@@iterator]";
1093
  HandleScope scope(isolate);
1094
  CHECK_RECEIVER(JSSegments, segments, method_name);
1095
  RETURN_RESULT_OR_FAILURE(
1096 1097 1098
      isolate,
      JSSegmentIterator::Create(isolate, segments->icu_break_iterator().raw(),
                                segments->granularity()));
1099 1100
}

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
  const char* const method_name =
      "get Intl.v8BreakIterator.prototype.adoptText";
1118 1119
  HandleScope scope(isolate);

1120
  CHECK_RECEIVER(JSV8BreakIterator, break_iterator, method_name);
1121 1122

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

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

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

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

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

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

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

1156
  CHECK_RECEIVER(JSV8BreakIterator, break_iterator, method_name);
1157

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

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

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

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

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

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

1186
  CHECK_RECEIVER(JSV8BreakIterator, break_iterator, method_name);
1187

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

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

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

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

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

1215
  CHECK_RECEIVER(JSV8BreakIterator, break_iterator, method_name);
1216

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

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

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

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

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

1245
  CHECK_RECEIVER(JSV8BreakIterator, break_iterator, method_name);
1246

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

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

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

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

1270 1271
}  // namespace internal
}  // namespace v8