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