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