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