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