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