Commit 17330977 authored by Frank Tang's avatar Frank Tang Committed by V8 LUCI CQ

[Temporal] Preparation Refactor 2

Refactor generic option reading facility also used
by Temporal from intl-objects.* to option-util.*


See
https://tc39.es/proposal-temporal/#sec-getoptionsobject
https://tc39.es/proposal-temporal/#sec-getoptionsobject-deleted
https://tc39.es/ecma402/#sec-getoptionsobject

Bug: v8:11544
Change-Id: I8b27e8fa3515c1287217c2fbe225172fb8f69210
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3122501Reviewed-by: 's avatarShu-yu Guo <syg@chromium.org>
Commit-Queue: Frank Tang <ftang@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76824}
parent 3fb2ec7b
......@@ -1619,6 +1619,8 @@ filegroup(
"src/objects/objects-definitions.h",
"src/objects/oddball-inl.h",
"src/objects/oddball.h",
"src/objects/option-utils.h",
"src/objects/option-utils.cc",
"src/objects/ordered-hash-table-inl.h",
"src/objects/ordered-hash-table.cc",
"src/objects/ordered-hash-table.h",
......
......@@ -3029,6 +3029,7 @@ v8_header_set("v8_internal_headers") {
"src/objects/objects.h",
"src/objects/oddball-inl.h",
"src/objects/oddball.h",
"src/objects/option-utils.h",
"src/objects/ordered-hash-table-inl.h",
"src/objects/ordered-hash-table.h",
"src/objects/osr-optimized-code-cache-inl.h",
......@@ -4072,6 +4073,7 @@ v8_source_set("v8_base_without_compiler") {
"src/objects/module.cc",
"src/objects/object-type.cc",
"src/objects/objects.cc",
"src/objects/option-utils.cc",
"src/objects/ordered-hash-table.cc",
"src/objects/osr-optimized-code-cache.cc",
"src/objects/property-descriptor.cc",
......
......@@ -30,6 +30,7 @@
#include "src/objects/js-segmenter-inl.h"
#include "src/objects/js-segments-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/option-utils.h"
#include "src/objects/property-descriptor.h"
#include "src/objects/smi.h"
#include "unicode/brkiter.h"
......@@ -656,8 +657,7 @@ BUILTIN(LocaleConstructor) {
// 10. Set options to ? CoerceOptionsToObject(options).
Handle<JSReceiver> options_object;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, options_object,
Intl::CoerceOptionsToObject(isolate, options, method));
isolate, options_object, CoerceOptionsToObject(isolate, options, method));
RETURN_RESULT_OR_FAILURE(
isolate, JSLocale::New(isolate, map, locale_string, options_object));
......
......@@ -24,6 +24,7 @@
#include "src/objects/js-locale.h"
#include "src/objects/js-number-format-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/option-utils.h"
#include "src/objects/property-descriptor.h"
#include "src/objects/smi.h"
#include "src/objects/string.h"
......@@ -652,82 +653,6 @@ MaybeHandle<Object> Intl::LegacyUnwrapReceiver(Isolate* isolate,
return receiver;
}
Maybe<bool> Intl::GetStringOption(Isolate* isolate, Handle<JSReceiver> options,
const char* property,
std::vector<const char*> values,
const char* service,
std::unique_ptr<char[]>* result) {
Handle<String> property_str =
isolate->factory()->NewStringFromAsciiChecked(property);
// 1. Let value be ? Get(options, property).
Handle<Object> value;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, value,
Object::GetPropertyOrElement(isolate, options, property_str),
Nothing<bool>());
if (value->IsUndefined(isolate)) {
return Just(false);
}
// 2. c. Let value be ? ToString(value).
Handle<String> value_str;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, value_str, Object::ToString(isolate, value), Nothing<bool>());
std::unique_ptr<char[]> value_cstr = value_str->ToCString();
// 2. d. if values is not undefined, then
if (values.size() > 0) {
// 2. d. i. If values does not contain an element equal to value,
// throw a RangeError exception.
for (size_t i = 0; i < values.size(); i++) {
if (strcmp(values.at(i), value_cstr.get()) == 0) {
// 2. e. return value
*result = std::move(value_cstr);
return Just(true);
}
}
Handle<String> service_str =
isolate->factory()->NewStringFromAsciiChecked(service);
THROW_NEW_ERROR_RETURN_VALUE(
isolate,
NewRangeError(MessageTemplate::kValueOutOfRange, value, service_str,
property_str),
Nothing<bool>());
}
// 2. e. return value
*result = std::move(value_cstr);
return Just(true);
}
V8_WARN_UNUSED_RESULT Maybe<bool> Intl::GetBoolOption(
Isolate* isolate, Handle<JSReceiver> options, const char* property,
const char* service, bool* result) {
Handle<String> property_str =
isolate->factory()->NewStringFromAsciiChecked(property);
// 1. Let value be ? Get(options, property).
Handle<Object> value;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, value,
Object::GetPropertyOrElement(isolate, options, property_str),
Nothing<bool>());
// 2. If value is not undefined, then
if (!value->IsUndefined(isolate)) {
// 2. b. i. Let value be ToBoolean(value).
*result = value->BooleanValue(isolate);
// 2. e. return value
return Just(true);
}
return Just(false);
}
namespace {
bool IsTwoLetterLanguage(const std::string& locale) {
......@@ -1126,55 +1051,6 @@ MaybeHandle<String> Intl::NumberToLocaleString(Isolate* isolate,
numeric_obj);
}
namespace {
// ecma402/#sec-defaultnumberoption
Maybe<int> DefaultNumberOption(Isolate* isolate, Handle<Object> value, int min,
int max, int fallback, Handle<String> property) {
// 2. Else, return fallback.
if (value->IsUndefined()) return Just(fallback);
// 1. If value is not undefined, then
// a. Let value be ? ToNumber(value).
Handle<Object> value_num;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, value_num, Object::ToNumber(isolate, value), Nothing<int>());
DCHECK(value_num->IsNumber());
// b. If value is NaN or less than minimum or greater than maximum, throw a
// RangeError exception.
if (value_num->IsNaN() || value_num->Number() < min ||
value_num->Number() > max) {
THROW_NEW_ERROR_RETURN_VALUE(
isolate,
NewRangeError(MessageTemplate::kPropertyValueOutOfRange, property),
Nothing<int>());
}
// The max and min arguments are integers and the above check makes
// sure that we are within the integer range making this double to
// int conversion safe.
//
// c. Return floor(value).
return Just(FastD2I(floor(value_num->Number())));
}
} // namespace
// ecma402/#sec-getnumberoption
Maybe<int> Intl::GetNumberOption(Isolate* isolate, Handle<JSReceiver> options,
Handle<String> property, int min, int max,
int fallback) {
// 1. Let value be ? Get(options, property).
Handle<Object> value;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, value, JSReceiver::GetProperty(isolate, options, property),
Nothing<int>());
// Return ? DefaultNumberOption(value, minimum, maximum, fallback).
return DefaultNumberOption(isolate, value, min, max, fallback, property);
}
Maybe<Intl::NumberFormatDigitOptions> Intl::SetNumberFormatDigitOptions(
Isolate* isolate, Handle<JSReceiver> options, int mnfd_default,
int mxfd_default, bool notation_is_compact) {
......@@ -1184,8 +1060,8 @@ Maybe<Intl::NumberFormatDigitOptions> Intl::SetNumberFormatDigitOptions(
// 5. Let mnid be ? GetNumberOption(options, "minimumIntegerDigits,", 1, 21,
// 1).
int mnid = 1;
if (!Intl::GetNumberOption(isolate, options,
factory->minimumIntegerDigits_string(), 1, 21, 1)
if (!GetNumberOption(isolate, options, factory->minimumIntegerDigits_string(),
1, 21, 1)
.To(&mnid)) {
return Nothing<NumberFormatDigitOptions>();
}
......@@ -1612,9 +1488,9 @@ MaybeHandle<JSObject> SupportedLocales(
// 1. Set options to ? CoerceOptionsToObject(options).
Handle<JSReceiver> options_obj;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, options_obj,
Intl::CoerceOptionsToObject(isolate, options, method), JSObject);
ASSIGN_RETURN_ON_EXCEPTION(isolate, options_obj,
CoerceOptionsToObject(isolate, options, method),
JSObject);
// 2. Let matcher be ? GetOption(options, "localeMatcher", "string",
// « "lookup", "best fit" », "best fit").
......@@ -2222,7 +2098,7 @@ base::TimezoneCache* Intl::CreateTimeZoneCache() {
Maybe<Intl::MatcherOption> Intl::GetLocaleMatcher(Isolate* isolate,
Handle<JSReceiver> options,
const char* method) {
return Intl::GetStringOption<Intl::MatcherOption>(
return GetStringOption<Intl::MatcherOption>(
isolate, options, "localeMatcher", method, {"best fit", "lookup"},
{Intl::MatcherOption::kBestFit, Intl::MatcherOption::kLookup},
Intl::MatcherOption::kBestFit);
......@@ -2233,8 +2109,8 @@ Maybe<bool> Intl::GetNumberingSystem(Isolate* isolate,
const char* method,
std::unique_ptr<char[]>* result) {
const std::vector<const char*> empty_values = {};
Maybe<bool> maybe = Intl::GetStringOption(isolate, options, "numberingSystem",
empty_values, method, result);
Maybe<bool> maybe = GetStringOption(isolate, options, "numberingSystem",
empty_values, method, result);
MAYBE_RETURN(maybe, Nothing<bool>());
if (maybe.FromJust() && *result != nullptr) {
if (!IsWellFormedNumberingSystem(result->get())) {
......@@ -2343,41 +2219,6 @@ MaybeHandle<String> Intl::FormattedToString(
return Intl::ToString(isolate, result);
}
// ecma402/#sec-getoptionsobject
MaybeHandle<JSReceiver> Intl::GetOptionsObject(Isolate* isolate,
Handle<Object> options,
const char* service) {
// 1. If options is undefined, then
if (options->IsUndefined(isolate)) {
// a. Return ! ObjectCreate(null).
return isolate->factory()->NewJSObjectWithNullProto();
}
// 2. If Type(options) is Object, then
if (options->IsJSReceiver()) {
// a. Return options.
return Handle<JSReceiver>::cast(options);
}
// 3. Throw a TypeError exception.
THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kInvalidArgument),
JSReceiver);
}
// ecma402/#sec-coerceoptionstoobject
MaybeHandle<JSReceiver> Intl::CoerceOptionsToObject(Isolate* isolate,
Handle<Object> options,
const char* service) {
// 1. If options is undefined, then
if (options->IsUndefined(isolate)) {
// a. Return ! ObjectCreate(null).
return isolate->factory()->NewJSObjectWithNullProto();
}
// 2. Return ? ToObject(options).
ASSIGN_RETURN_ON_EXCEPTION(isolate, options,
Object::ToObject(isolate, options, service),
JSReceiver);
return Handle<JSReceiver>::cast(options);
}
MaybeHandle<JSArray> Intl::ToJSArray(
Isolate* isolate, const char* unicode_key,
icu::StringEnumeration* enumeration,
......
......@@ -66,72 +66,6 @@ class Intl {
const std::set<std::string>& available_locales, Handle<Object> locales_in,
Handle<Object> options_in);
// ECMA402 9.2.10. GetOption( options, property, type, values, fallback)
// ecma402/#sec-getoption
//
// This is specialized for the case when type is string.
//
// Instead of passing undefined for the values argument as the spec
// defines, pass in an empty vector.
//
// Returns true if options object has the property and stores the
// result in value. Returns false if the value is not found. The
// caller is required to use fallback value appropriately in this
// case.
//
// service is a string denoting the type of Intl object; used when
// printing the error message.
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static Maybe<bool> GetStringOption(
Isolate* isolate, Handle<JSReceiver> options, const char* property,
std::vector<const char*> values, const char* service,
std::unique_ptr<char[]>* result);
// A helper template to get string from option into a enum.
// The enum in the enum_values is the corresponding value to the strings
// in the str_values. If the option does not contains name,
// default_value will be return.
template <typename T>
V8_WARN_UNUSED_RESULT static Maybe<T> GetStringOption(
Isolate* isolate, Handle<JSReceiver> options, const char* name,
const char* method, const std::vector<const char*>& str_values,
const std::vector<T>& enum_values, T default_value) {
DCHECK_EQ(str_values.size(), enum_values.size());
std::unique_ptr<char[]> cstr;
Maybe<bool> found = Intl::GetStringOption(isolate, options, name,
str_values, method, &cstr);
MAYBE_RETURN(found, Nothing<T>());
if (found.FromJust()) {
DCHECK_NOT_NULL(cstr.get());
for (size_t i = 0; i < str_values.size(); i++) {
if (strcmp(cstr.get(), str_values[i]) == 0) {
return Just(enum_values[i]);
}
}
UNREACHABLE();
}
return Just(default_value);
}
// ECMA402 9.2.10. GetOption( options, property, type, values, fallback)
// ecma402/#sec-getoption
//
// This is specialized for the case when type is boolean.
//
// Returns true if options object has the property and stores the
// result in value. Returns false if the value is not found. The
// caller is required to use fallback value appropriately in this
// case.
//
// service is a string denoting the type of Intl object; used when
// printing the error message.
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static Maybe<bool> GetBoolOption(
Isolate* isolate, Handle<JSReceiver> options, const char* property,
const char* service, bool* result);
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static Maybe<int> GetNumberOption(
Isolate* isolate, Handle<JSReceiver> options, Handle<String> property,
int min, int max, int fallback);
// https://tc39.github.io/ecma402/#sec-canonicalizelocalelist
// {only_return_one_result} is an optimization for callers that only
// care about the first result.
......@@ -337,14 +271,6 @@ class Intl {
static const std::set<std::string>& GetAvailableLocalesForDateFormat();
// ecma402/#sec-getoptionsobject
V8_WARN_UNUSED_RESULT static MaybeHandle<JSReceiver> GetOptionsObject(
Isolate* isolate, Handle<Object> options, const char* service);
// ecma402/#sec-coerceoptionstoobject
V8_WARN_UNUSED_RESULT static MaybeHandle<JSReceiver> CoerceOptionsToObject(
Isolate* isolate, Handle<Object> options, const char* service);
V8_WARN_UNUSED_RESULT static MaybeHandle<JSArray> ToJSArray(
Isolate* isolate, const char* unicode_key,
icu::StringEnumeration* enumeration,
......
......@@ -10,6 +10,7 @@
#include "src/objects/intl-objects.h"
#include "src/objects/js-break-iterator-inl.h"
#include "src/objects/option-utils.h"
#include "unicode/brkiter.h"
namespace v8 {
......@@ -56,7 +57,7 @@ MaybeHandle<JSV8BreakIterator> JSV8BreakIterator::New(
Intl::ResolvedLocale r = maybe_resolve_locale.FromJust();
// Extract type from options
Maybe<Type> maybe_type = Intl::GetStringOption<Type>(
Maybe<Type> maybe_type = GetStringOption<Type>(
isolate, options, "type", service,
{"word", "character", "sentence", "line"},
{Type::WORD, Type::CHARACTER, Type::SENTENCE, Type::LINE}, Type::WORD);
......
......@@ -12,6 +12,7 @@
#include "src/objects/js-collator-inl.h"
#include "src/objects/js-locale.h"
#include "src/objects/objects-inl.h"
#include "src/objects/option-utils.h"
#include "unicode/coll.h"
#include "unicode/locid.h"
#include "unicode/strenum.h"
......@@ -43,7 +44,7 @@ enum class CaseFirst { kUndefined, kUpper, kLower, kFalse };
Maybe<CaseFirst> GetCaseFirst(Isolate* isolate, Handle<JSReceiver> options,
const char* method) {
return Intl::GetStringOption<CaseFirst>(
return GetStringOption<CaseFirst>(
isolate, options, "caseFirst", method, {"upper", "lower", "false"},
{CaseFirst::kUpper, CaseFirst::kLower, CaseFirst::kFalse},
CaseFirst::kUndefined);
......@@ -286,12 +287,12 @@ MaybeHandle<JSCollator> JSCollator::New(Isolate* isolate, Handle<Map> map,
// 2. Set options to ? CoerceOptionsToObject(options).
Handle<JSReceiver> options;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, options,
Intl::CoerceOptionsToObject(isolate, options_obj, service), JSCollator);
isolate, options, CoerceOptionsToObject(isolate, options_obj, service),
JSCollator);
// 4. Let usage be ? GetOption(options, "usage", "string", « "sort",
// "search" », "sort").
Maybe<Usage> maybe_usage = Intl::GetStringOption<Usage>(
Maybe<Usage> maybe_usage = GetStringOption<Usage>(
isolate, options, "usage", service, {"sort", "search"},
{Usage::SORT, Usage::SEARCH}, Usage::SORT);
MAYBE_RETURN(maybe_usage, MaybeHandle<JSCollator>());
......@@ -309,7 +310,7 @@ MaybeHandle<JSCollator> JSCollator::New(Isolate* isolate, Handle<Map> map,
// *undefined*, *undefined*).
std::unique_ptr<char[]> collation_str = nullptr;
const std::vector<const char*> empty_values = {};
Maybe<bool> maybe_collation = Intl::GetStringOption(
Maybe<bool> maybe_collation = GetStringOption(
isolate, options, "collation", empty_values, service, &collation_str);
MAYBE_RETURN(maybe_collation, MaybeHandle<JSCollator>());
// x. If _collation_ is not *undefined*, then
......@@ -334,13 +335,13 @@ MaybeHandle<JSCollator> JSCollator::New(Isolate* isolate, Handle<Map> map,
// a. Let numeric be ! ToString(numeric).
//
// Note: We omit the ToString(numeric) operation as it's not
// observable. Intl::GetBoolOption returns a Boolean and
// observable. GetBoolOption returns a Boolean and
// ToString(Boolean) is not side-effecting.
//
// 13. Set opt.[[kn]] to numeric.
bool numeric;
Maybe<bool> found_numeric =
Intl::GetBoolOption(isolate, options, "numeric", service, &numeric);
GetBoolOption(isolate, options, "numeric", service, &numeric);
MAYBE_RETURN(found_numeric, MaybeHandle<JSCollator>());
// 14. Let caseFirst be ? GetOption(options, "caseFirst", "string",
......@@ -477,12 +478,12 @@ MaybeHandle<JSCollator> JSCollator::New(Isolate* isolate, Handle<Map> map,
// 24. Let sensitivity be ? GetOption(options, "sensitivity",
// "string", « "base", "accent", "case", "variant" », undefined).
Maybe<Sensitivity> maybe_sensitivity = Intl::GetStringOption<Sensitivity>(
isolate, options, "sensitivity", service,
{"base", "accent", "case", "variant"},
{Sensitivity::kBase, Sensitivity::kAccent, Sensitivity::kCase,
Sensitivity::kVariant},
Sensitivity::kUndefined);
Maybe<Sensitivity> maybe_sensitivity =
GetStringOption<Sensitivity>(isolate, options, "sensitivity", service,
{"base", "accent", "case", "variant"},
{Sensitivity::kBase, Sensitivity::kAccent,
Sensitivity::kCase, Sensitivity::kVariant},
Sensitivity::kUndefined);
MAYBE_RETURN(maybe_sensitivity, MaybeHandle<JSCollator>());
Sensitivity sensitivity = maybe_sensitivity.FromJust();
......@@ -518,7 +519,7 @@ MaybeHandle<JSCollator> JSCollator::New(Isolate* isolate, Handle<Map> map,
// 27.Let ignorePunctuation be ? GetOption(options,
// "ignorePunctuation", "boolean", undefined, false).
bool ignore_punctuation;
Maybe<bool> found_ignore_punctuation = Intl::GetBoolOption(
Maybe<bool> found_ignore_punctuation = GetBoolOption(
isolate, options, "ignorePunctuation", service, &ignore_punctuation);
MAYBE_RETURN(found_ignore_punctuation, MaybeHandle<JSCollator>());
......
......@@ -20,7 +20,7 @@
#include "src/heap/factory.h"
#include "src/objects/intl-objects.h"
#include "src/objects/js-date-time-format-inl.h"
#include "src/objects/option-utils.h"
#include "unicode/calendar.h"
#include "unicode/dtitvfmt.h"
#include "unicode/dtptngen.h"
......@@ -77,7 +77,7 @@ JSDateTimeFormat::HourCycle ToHourCycle(UDateFormatHourCycle hc) {
Maybe<JSDateTimeFormat::HourCycle> GetHourCycle(Isolate* isolate,
Handle<JSReceiver> options,
const char* method) {
return Intl::GetStringOption<JSDateTimeFormat::HourCycle>(
return GetStringOption<JSDateTimeFormat::HourCycle>(
isolate, options, "hourCycle", method, {"h11", "h12", "h23", "h24"},
{JSDateTimeFormat::HourCycle::kH11, JSDateTimeFormat::HourCycle::kH12,
JSDateTimeFormat::HourCycle::kH23, JSDateTimeFormat::HourCycle::kH24},
......@@ -1499,7 +1499,7 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
const std::vector<const char*> empty_values = {};
// 6. Let calendar be ? GetOption(options, "calendar",
// "string", undefined, undefined).
Maybe<bool> maybe_calendar = Intl::GetStringOption(
Maybe<bool> maybe_calendar = GetStringOption(
isolate, options, "calendar", empty_values, service, &calendar_str);
MAYBE_RETURN(maybe_calendar, MaybeHandle<JSDateTimeFormat>());
if (maybe_calendar.FromJust() && calendar_str != nullptr) {
......@@ -1523,7 +1523,7 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
// undefined).
bool hour12;
Maybe<bool> maybe_get_hour12 =
Intl::GetBoolOption(isolate, options, "hour12", service, &hour12);
GetBoolOption(isolate, options, "hour12", service, &hour12);
MAYBE_RETURN(maybe_get_hour12, Handle<JSDateTimeFormat>());
// 7. Let hourCycle be ? GetOption(options, "hourCycle", "string", « "h11",
......@@ -1651,7 +1651,7 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
// 17. Let timeZone be ? Get(options, "timeZone").
std::unique_ptr<char[]> timezone = nullptr;
Maybe<bool> maybe_timezone = Intl::GetStringOption(
Maybe<bool> maybe_timezone = GetStringOption(
isolate, options, "timeZone", empty_values, service, &timezone);
MAYBE_RETURN(maybe_timezone, Handle<JSDateTimeFormat>());
......@@ -1689,7 +1689,7 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
if (item.property == "timeZoneName") {
// Let _value_ be ? GetNumberOption(options, "fractionalSecondDigits", 1,
// 3, *undefined*). The *undefined* is represented by value 0 here.
Maybe<int> maybe_fsd = Intl::GetNumberOption(
Maybe<int> maybe_fsd = GetNumberOption(
isolate, options, factory->fractionalSecondDigits_string(), 1, 3, 0);
MAYBE_RETURN(maybe_fsd, MaybeHandle<JSDateTimeFormat>());
// Convert fractionalSecondDigits to skeleton.
......@@ -1703,8 +1703,8 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
// ii. Let value be ? GetOption(options, prop, "string", « the strings
// given in the Values column of the row », undefined).
Maybe<bool> maybe_get_option =
Intl::GetStringOption(isolate, options, item.property.c_str(),
item.allowed_values, service, &input);
GetStringOption(isolate, options, item.property.c_str(),
item.allowed_values, service, &input);
MAYBE_RETURN(maybe_get_option, Handle<JSDateTimeFormat>());
if (maybe_get_option.FromJust()) {
if (item.property == "hour") {
......@@ -1724,7 +1724,7 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
// c. Let matcher be ? GetOption(options, "formatMatcher", "string",
// « "basic", "best fit" », "best fit").
Maybe<FormatMatcherOption> maybe_format_matcher =
Intl::GetStringOption<FormatMatcherOption>(
GetStringOption<FormatMatcherOption>(
isolate, options, "formatMatcher", service, {"best fit", "basic"},
{FormatMatcherOption::kBestFit, FormatMatcherOption::kBasic},
FormatMatcherOption::kBestFit);
......@@ -1734,7 +1734,7 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
// 32. Let dateStyle be ? GetOption(options, "dateStyle", "string", «
// "full", "long", "medium", "short" », undefined).
Maybe<DateTimeStyle> maybe_date_style = Intl::GetStringOption<DateTimeStyle>(
Maybe<DateTimeStyle> maybe_date_style = GetStringOption<DateTimeStyle>(
isolate, options, "dateStyle", service,
{"full", "long", "medium", "short"},
{DateTimeStyle::kFull, DateTimeStyle::kLong, DateTimeStyle::kMedium,
......@@ -1746,7 +1746,7 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
// 34. Let timeStyle be ? GetOption(options, "timeStyle", "string", «
// "full", "long", "medium", "short" »).
Maybe<DateTimeStyle> maybe_time_style = Intl::GetStringOption<DateTimeStyle>(
Maybe<DateTimeStyle> maybe_time_style = GetStringOption<DateTimeStyle>(
isolate, options, "timeStyle", service,
{"full", "long", "medium", "short"},
{DateTimeStyle::kFull, DateTimeStyle::kLong, DateTimeStyle::kMedium,
......
......@@ -17,6 +17,7 @@
#include "src/objects/js-display-names-inl.h"
#include "src/objects/managed.h"
#include "src/objects/objects-inl.h"
#include "src/objects/option-utils.h"
#include "unicode/dtfmtsym.h"
#include "unicode/dtptngen.h"
#include "unicode/localebuilder.h"
......@@ -372,9 +373,9 @@ MaybeHandle<JSDisplayNames> JSDisplayNames::New(Isolate* isolate,
maybe_requested_locales.FromJust();
// 4. Let options be ? GetOptionsObject(options).
ASSIGN_RETURN_ON_EXCEPTION(
isolate, options, Intl::GetOptionsObject(isolate, input_options, service),
JSDisplayNames);
ASSIGN_RETURN_ON_EXCEPTION(isolate, options,
GetOptionsObject(isolate, input_options, service),
JSDisplayNames);
// Note: No need to create a record. It's not observable.
// 5. Let opt be a new Record.
......@@ -409,7 +410,7 @@ MaybeHandle<JSDisplayNames> JSDisplayNames::New(Isolate* isolate,
// 10. Let s be ? GetOption(options, "style", "string",
// «"long", "short", "narrow"», "long").
Maybe<Style> maybe_style = Intl::GetStringOption<Style>(
Maybe<Style> maybe_style = GetStringOption<Style>(
isolate, options, "style", service, {"long", "short", "narrow"},
{Style::kLong, Style::kShort, Style::kNarrow}, Style::kLong);
MAYBE_RETURN(maybe_style, MaybeHandle<JSDisplayNames>());
......@@ -422,23 +423,22 @@ MaybeHandle<JSDisplayNames> JSDisplayNames::New(Isolate* isolate,
// undefined).
Maybe<Type> maybe_type =
FLAG_harmony_intl_displaynames_v2
? Intl::GetStringOption<Type>(
? GetStringOption<Type>(
isolate, options, "type", service,
{"language", "region", "script", "currency", "calendar",
"dateTimeField"},
{Type::kLanguage, Type::kRegion, Type::kScript, Type::kCurrency,
Type::kCalendar, Type::kDateTimeField},
Type::kUndefined)
: Intl::GetStringOption<Type>(
isolate, options, "type", service,
{"language", "region", "script", "currency"},
{
Type::kLanguage,
Type::kRegion,
Type::kScript,
Type::kCurrency,
},
Type::kUndefined);
: GetStringOption<Type>(isolate, options, "type", service,
{"language", "region", "script", "currency"},
{
Type::kLanguage,
Type::kRegion,
Type::kScript,
Type::kCurrency,
},
Type::kUndefined);
MAYBE_RETURN(maybe_type, MaybeHandle<JSDisplayNames>());
Type type_enum = maybe_type.FromJust();
......@@ -452,7 +452,7 @@ MaybeHandle<JSDisplayNames> JSDisplayNames::New(Isolate* isolate,
// 15. Let fallback be ? GetOption(options, "fallback", "string",
// « "code", "none" », "code").
Maybe<Fallback> maybe_fallback = Intl::GetStringOption<Fallback>(
Maybe<Fallback> maybe_fallback = GetStringOption<Fallback>(
isolate, options, "fallback", service, {"code", "none"},
{Fallback::kCode, Fallback::kNone}, Fallback::kCode);
MAYBE_RETURN(maybe_fallback, MaybeHandle<JSDisplayNames>());
......@@ -465,7 +465,7 @@ MaybeHandle<JSDisplayNames> JSDisplayNames::New(Isolate* isolate,
// 24. Let languageDisplay be ? GetOption(options, "languageDisplay",
// "string", « "dialect", "standard" », "dialect").
Maybe<LanguageDisplay> maybe_language_display =
Intl::GetStringOption<LanguageDisplay>(
GetStringOption<LanguageDisplay>(
isolate, options, "languageDisplay", service,
{"dialect", "standard"},
{LanguageDisplay::kDialect, LanguageDisplay::kStandard},
......
......@@ -20,6 +20,7 @@
#include "src/objects/js-list-format-inl.h"
#include "src/objects/managed.h"
#include "src/objects/objects-inl.h"
#include "src/objects/option-utils.h"
#include "unicode/fieldpos.h"
#include "unicode/fpositer.h"
#include "unicode/listformatter.h"
......@@ -69,9 +70,9 @@ MaybeHandle<JSListFormat> JSListFormat::New(Isolate* isolate, Handle<Map> map,
Handle<JSReceiver> options;
const char* service = "Intl.ListFormat";
// 4. Let options be GetOptionsObject(_options_).
ASSIGN_RETURN_ON_EXCEPTION(
isolate, options, Intl::GetOptionsObject(isolate, input_options, service),
JSListFormat);
ASSIGN_RETURN_ON_EXCEPTION(isolate, options,
GetOptionsObject(isolate, input_options, service),
JSListFormat);
// Note: No need to create a record. It's not observable.
// 6. Let opt be a new Record.
......@@ -100,7 +101,7 @@ MaybeHandle<JSListFormat> JSListFormat::New(Isolate* isolate, Handle<Map> map,
// 12. Let t be GetOption(options, "type", "string", «"conjunction",
// "disjunction", "unit"», "conjunction").
Maybe<Type> maybe_type = Intl::GetStringOption<Type>(
Maybe<Type> maybe_type = GetStringOption<Type>(
isolate, options, "type", service, {"conjunction", "disjunction", "unit"},
{Type::CONJUNCTION, Type::DISJUNCTION, Type::UNIT}, Type::CONJUNCTION);
MAYBE_RETURN(maybe_type, MaybeHandle<JSListFormat>());
......@@ -108,7 +109,7 @@ MaybeHandle<JSListFormat> JSListFormat::New(Isolate* isolate, Handle<Map> map,
// 14. Let s be ? GetOption(options, "style", "string",
// «"long", "short", "narrow"», "long").
Maybe<Style> maybe_style = Intl::GetStringOption<Style>(
Maybe<Style> maybe_style = GetStringOption<Style>(
isolate, options, "style", service, {"long", "short", "narrow"},
{Style::LONG, Style::SHORT, Style::NARROW}, Style::LONG);
MAYBE_RETURN(maybe_style, MaybeHandle<JSListFormat>());
......
......@@ -20,6 +20,7 @@
#include "src/objects/intl-objects.h"
#include "src/objects/js-locale-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/option-utils.h"
#include "unicode/calendar.h"
#include "unicode/char16ptr.h"
#include "unicode/coll.h"
......@@ -70,11 +71,11 @@ Maybe<bool> InsertOptionsIntoLocale(Isolate* isolate,
bool value_bool = false;
Maybe<bool> maybe_found =
option_to_bcp47.is_bool_value
? Intl::GetBoolOption(isolate, options, option_to_bcp47.name,
"locale", &value_bool)
: Intl::GetStringOption(isolate, options, option_to_bcp47.name,
*(option_to_bcp47.possible_values),
"locale", &value_str);
? GetBoolOption(isolate, options, option_to_bcp47.name, "locale",
&value_bool)
: GetStringOption(isolate, options, option_to_bcp47.name,
*(option_to_bcp47.possible_values), "locale",
&value_str);
MAYBE_RETURN(maybe_found, Nothing<bool>());
// TODO(cira): Use fallback value if value is not found to make
......@@ -266,8 +267,8 @@ Maybe<bool> ApplyOptionsToTag(Isolate* isolate, Handle<String> tag,
const std::vector<const char*> empty_values = {};
std::unique_ptr<char[]> language_str = nullptr;
Maybe<bool> maybe_language =
Intl::GetStringOption(isolate, options, "language", empty_values,
"ApplyOptionsToTag", &language_str);
GetStringOption(isolate, options, "language", empty_values,
"ApplyOptionsToTag", &language_str);
MAYBE_RETURN(maybe_language, Nothing<bool>());
// 4. If language is not undefined, then
if (maybe_language.FromJust()) {
......@@ -284,8 +285,8 @@ Maybe<bool> ApplyOptionsToTag(Isolate* isolate, Handle<String> tag,
// undefined).
std::unique_ptr<char[]> script_str = nullptr;
Maybe<bool> maybe_script =
Intl::GetStringOption(isolate, options, "script", empty_values,
"ApplyOptionsToTag", &script_str);
GetStringOption(isolate, options, "script", empty_values,
"ApplyOptionsToTag", &script_str);
MAYBE_RETURN(maybe_script, Nothing<bool>());
// 6. If script is not undefined, then
if (maybe_script.FromJust()) {
......@@ -301,8 +302,8 @@ Maybe<bool> ApplyOptionsToTag(Isolate* isolate, Handle<String> tag,
// undefined).
std::unique_ptr<char[]> region_str = nullptr;
Maybe<bool> maybe_region =
Intl::GetStringOption(isolate, options, "region", empty_values,
"ApplyOptionsToTag", &region_str);
GetStringOption(isolate, options, "region", empty_values,
"ApplyOptionsToTag", &region_str);
MAYBE_RETURN(maybe_region, Nothing<bool>());
// 8. If region is not undefined, then
if (maybe_region.FromJust()) {
......
......@@ -15,6 +15,7 @@
#include "src/objects/intl-objects.h"
#include "src/objects/js-number-format-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/option-utils.h"
#include "unicode/currunit.h"
#include "unicode/decimfmt.h"
#include "unicode/locid.h"
......@@ -816,8 +817,7 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
// 2. Set options to ? CoerceOptionsToObject(options).
Handle<JSReceiver> options;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, options,
Intl::CoerceOptionsToObject(isolate, options_obj, service),
isolate, options, CoerceOptionsToObject(isolate, options_obj, service),
JSNumberFormat);
// 4. Let opt be a new Record.
......@@ -899,7 +899,7 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
// 3. Let style be ? GetOption(options, "style", "string", « "decimal",
// "percent", "currency", "unit" », "decimal").
Maybe<Style> maybe_style = Intl::GetStringOption<Style>(
Maybe<Style> maybe_style = GetStringOption<Style>(
isolate, options, "style", service,
{"decimal", "percent", "currency", "unit"},
{Style::DECIMAL, Style::PERCENT, Style::CURRENCY, Style::UNIT},
......@@ -913,7 +913,7 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
// undefined).
std::unique_ptr<char[]> currency_cstr;
const std::vector<const char*> empty_values = {};
Maybe<bool> found_currency = Intl::GetStringOption(
Maybe<bool> found_currency = GetStringOption(
isolate, options, "currency", empty_values, service, &currency_cstr);
MAYBE_RETURN(found_currency, MaybeHandle<JSNumberFormat>());
......@@ -943,7 +943,7 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
// 8. Let currencyDisplay be ? GetOption(options, "currencyDisplay",
// "string", « "code", "symbol", "name", "narrowSymbol" », "symbol").
Maybe<CurrencyDisplay> maybe_currency_display =
Intl::GetStringOption<CurrencyDisplay>(
GetStringOption<CurrencyDisplay>(
isolate, options, "currencyDisplay", service,
{"code", "symbol", "name", "narrowSymbol"},
{CurrencyDisplay::CODE, CurrencyDisplay::SYMBOL,
......@@ -955,7 +955,7 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
CurrencySign currency_sign = CurrencySign::STANDARD;
// 9. Let currencySign be ? GetOption(options, "currencySign", "string", «
// "standard", "accounting" », "standard").
Maybe<CurrencySign> maybe_currency_sign = Intl::GetStringOption<CurrencySign>(
Maybe<CurrencySign> maybe_currency_sign = GetStringOption<CurrencySign>(
isolate, options, "currencySign", service, {"standard", "accounting"},
{CurrencySign::STANDARD, CurrencySign::ACCOUNTING},
CurrencySign::STANDARD);
......@@ -965,8 +965,8 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
// 10. Let unit be ? GetOption(options, "unit", "string", undefined,
// undefined).
std::unique_ptr<char[]> unit_cstr;
Maybe<bool> found_unit = Intl::GetStringOption(
isolate, options, "unit", empty_values, service, &unit_cstr);
Maybe<bool> found_unit = GetStringOption(isolate, options, "unit",
empty_values, service, &unit_cstr);
MAYBE_RETURN(found_unit, MaybeHandle<JSNumberFormat>());
std::pair<icu::MeasureUnit, icu::MeasureUnit> unit_pair;
......@@ -1001,7 +1001,7 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
// 13. Let unitDisplay be ? GetOption(options, "unitDisplay", "string", «
// "short", "narrow", "long" », "short").
Maybe<UnitDisplay> maybe_unit_display = Intl::GetStringOption<UnitDisplay>(
Maybe<UnitDisplay> maybe_unit_display = GetStringOption<UnitDisplay>(
isolate, options, "unitDisplay", service, {"short", "narrow", "long"},
{UnitDisplay::SHORT, UnitDisplay::NARROW, UnitDisplay::LONG},
UnitDisplay::SHORT);
......@@ -1097,7 +1097,7 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
Notation notation = Notation::STANDARD;
// 25. Let notation be ? GetOption(options, "notation", "string", «
// "standard", "scientific", "engineering", "compact" », "standard").
Maybe<Notation> maybe_notation = Intl::GetStringOption<Notation>(
Maybe<Notation> maybe_notation = GetStringOption<Notation>(
isolate, options, "notation", service,
{"standard", "scientific", "engineering", "compact"},
{Notation::STANDARD, Notation::SCIENTIFIC, Notation::ENGINEERING,
......@@ -1119,10 +1119,9 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
// 28. Let compactDisplay be ? GetOption(options, "compactDisplay",
// "string", « "short", "long" », "short").
Maybe<CompactDisplay> maybe_compact_display =
Intl::GetStringOption<CompactDisplay>(
isolate, options, "compactDisplay", service, {"short", "long"},
{CompactDisplay::SHORT, CompactDisplay::LONG}, CompactDisplay::SHORT);
Maybe<CompactDisplay> maybe_compact_display = GetStringOption<CompactDisplay>(
isolate, options, "compactDisplay", service, {"short", "long"},
{CompactDisplay::SHORT, CompactDisplay::LONG}, CompactDisplay::SHORT);
MAYBE_RETURN(maybe_compact_display, MaybeHandle<JSNumberFormat>());
CompactDisplay compact_display = maybe_compact_display.FromJust();
......@@ -1136,8 +1135,8 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
// 30. Let useGrouping be ? GetOption(options, "useGrouping", "boolean",
// undefined, true).
bool use_grouping = true;
Maybe<bool> found_use_grouping = Intl::GetBoolOption(
isolate, options, "useGrouping", service, &use_grouping);
Maybe<bool> found_use_grouping =
GetBoolOption(isolate, options, "useGrouping", service, &use_grouping);
MAYBE_RETURN(found_use_grouping, MaybeHandle<JSNumberFormat>());
// 31. Set numberFormat.[[UseGrouping]] to useGrouping.
if (!use_grouping) {
......@@ -1147,7 +1146,7 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
// 32. Let signDisplay be ? GetOption(options, "signDisplay", "string", «
// "auto", "never", "always", "exceptZero" », "auto").
Maybe<SignDisplay> maybe_sign_display = Intl::GetStringOption<SignDisplay>(
Maybe<SignDisplay> maybe_sign_display = GetStringOption<SignDisplay>(
isolate, options, "signDisplay", service,
{"auto", "never", "always", "exceptZero"},
{SignDisplay::AUTO, SignDisplay::NEVER, SignDisplay::ALWAYS,
......
......@@ -12,6 +12,7 @@
#include "src/objects/intl-objects.h"
#include "src/objects/js-number-format.h"
#include "src/objects/js-plural-rules-inl.h"
#include "src/objects/option-utils.h"
#include "unicode/locid.h"
#include "unicode/numberformatter.h"
#include "unicode/plurrule.h"
......@@ -74,8 +75,7 @@ MaybeHandle<JSPluralRules> JSPluralRules::New(Isolate* isolate, Handle<Map> map,
Handle<JSReceiver> options;
const char* service = "Intl.PluralRules";
ASSIGN_RETURN_ON_EXCEPTION(
isolate, options,
Intl::CoerceOptionsToObject(isolate, options_obj, service),
isolate, options, CoerceOptionsToObject(isolate, options_obj, service),
JSPluralRules);
// 5. Let matcher be ? GetOption(options, "localeMatcher", "string",
......@@ -88,7 +88,7 @@ MaybeHandle<JSPluralRules> JSPluralRules::New(Isolate* isolate, Handle<Map> map,
// 7. Let t be ? GetOption(options, "type", "string", « "cardinal",
// "ordinal" », "cardinal").
Maybe<Type> maybe_type = Intl::GetStringOption<Type>(
Maybe<Type> maybe_type = GetStringOption<Type>(
isolate, options, "type", service, {"cardinal", "ordinal"},
{Type::CARDINAL, Type::ORDINAL}, Type::CARDINAL);
MAYBE_RETURN(maybe_type, MaybeHandle<JSPluralRules>());
......
......@@ -18,6 +18,7 @@
#include "src/objects/js-number-format.h"
#include "src/objects/js-relative-time-format-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/option-utils.h"
#include "unicode/decimfmt.h"
#include "unicode/numfmt.h"
#include "unicode/reldatefmt.h"
......@@ -78,8 +79,7 @@ MaybeHandle<JSRelativeTimeFormat> JSRelativeTimeFormat::New(
Handle<JSReceiver> options;
const char* service = "Intl.RelativeTimeFormat";
ASSIGN_RETURN_ON_EXCEPTION(
isolate, options,
Intl::CoerceOptionsToObject(isolate, input_options, service),
isolate, options, CoerceOptionsToObject(isolate, input_options, service),
JSRelativeTimeFormat);
// 4. Let opt be a new Record.
......@@ -147,7 +147,7 @@ MaybeHandle<JSRelativeTimeFormat> JSRelativeTimeFormat::New(
// 16. Let s be ? GetOption(options, "style", "string",
// «"long", "short", "narrow"», "long").
Maybe<Style> maybe_style = Intl::GetStringOption<Style>(
Maybe<Style> maybe_style = GetStringOption<Style>(
isolate, options, "style", service, {"long", "short", "narrow"},
{Style::LONG, Style::SHORT, Style::NARROW}, Style::LONG);
MAYBE_RETURN(maybe_style, MaybeHandle<JSRelativeTimeFormat>());
......@@ -157,7 +157,7 @@ MaybeHandle<JSRelativeTimeFormat> JSRelativeTimeFormat::New(
// 18. Let numeric be ? GetOption(options, "numeric", "string",
// «"always", "auto"», "always").
Maybe<Numeric> maybe_numeric = Intl::GetStringOption<Numeric>(
Maybe<Numeric> maybe_numeric = GetStringOption<Numeric>(
isolate, options, "numeric", service, {"always", "auto"},
{Numeric::ALWAYS, Numeric::AUTO}, Numeric::ALWAYS);
MAYBE_RETURN(maybe_numeric, MaybeHandle<JSRelativeTimeFormat>());
......
......@@ -18,6 +18,7 @@
#include "src/objects/js-segmenter-inl.h"
#include "src/objects/managed.h"
#include "src/objects/objects-inl.h"
#include "src/objects/option-utils.h"
#include "unicode/brkiter.h"
namespace v8 {
......@@ -36,9 +37,9 @@ MaybeHandle<JSSegmenter> JSSegmenter::New(Isolate* isolate, Handle<Map> map,
Handle<JSReceiver> options;
const char* service = "Intl.Segmenter";
// 5. Let options be GetOptionsObject(_options_).
ASSIGN_RETURN_ON_EXCEPTION(
isolate, options, Intl::GetOptionsObject(isolate, input_options, service),
JSSegmenter);
ASSIGN_RETURN_ON_EXCEPTION(isolate, options,
GetOptionsObject(isolate, input_options, service),
JSSegmenter);
// 7. Let opt be a new Record.
// 8. Let matcher be ? GetOption(options, "localeMatcher", "string",
......@@ -68,7 +69,7 @@ MaybeHandle<JSSegmenter> JSSegmenter::New(Isolate* isolate, Handle<Map> map,
// 13. Let granularity be ? GetOption(options, "granularity", "string", «
// "grapheme", "word", "sentence" », "grapheme").
Maybe<Granularity> maybe_granularity = Intl::GetStringOption<Granularity>(
Maybe<Granularity> maybe_granularity = GetStringOption<Granularity>(
isolate, options, "granularity", service,
{"grapheme", "word", "sentence"},
{Granularity::GRAPHEME, Granularity::WORD, Granularity::SENTENCE},
......
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/objects/option-utils.h"
#include "src/numbers/conversions.h"
#include "src/objects/objects-inl.h"
namespace v8 {
namespace internal {
// ecma402/#sec-getoptionsobject
MaybeHandle<JSReceiver> GetOptionsObject(Isolate* isolate,
Handle<Object> options,
const char* method) {
// 1. If options is undefined, then
if (options->IsUndefined(isolate)) {
// a. Return ! ObjectCreate(null).
return isolate->factory()->NewJSObjectWithNullProto();
}
// 2. If Type(options) is Object, then
if (options->IsJSReceiver()) {
// a. Return options.
return Handle<JSReceiver>::cast(options);
}
// 3. Throw a TypeError exception.
THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kInvalidArgument),
JSReceiver);
}
// ecma402/#sec-coerceoptionstoobject
MaybeHandle<JSReceiver> CoerceOptionsToObject(Isolate* isolate,
Handle<Object> options,
const char* method) {
// 1. If options is undefined, then
if (options->IsUndefined(isolate)) {
// a. Return ! ObjectCreate(null).
return isolate->factory()->NewJSObjectWithNullProto();
}
// 2. Return ? ToObject(options).
ASSIGN_RETURN_ON_EXCEPTION(
isolate, options, Object::ToObject(isolate, options, method), JSReceiver);
return Handle<JSReceiver>::cast(options);
}
Maybe<bool> GetStringOption(Isolate* isolate, Handle<JSReceiver> options,
const char* property,
std::vector<const char*> values, const char* method,
std::unique_ptr<char[]>* result) {
Handle<String> property_str =
isolate->factory()->NewStringFromAsciiChecked(property);
// 1. Let value be ? Get(options, property).
Handle<Object> value;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, value,
Object::GetPropertyOrElement(isolate, options, property_str),
Nothing<bool>());
if (value->IsUndefined(isolate)) {
return Just(false);
}
// 2. c. Let value be ? ToString(value).
Handle<String> value_str;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, value_str, Object::ToString(isolate, value), Nothing<bool>());
std::unique_ptr<char[]> value_cstr = value_str->ToCString();
// 2. d. if values is not undefined, then
if (values.size() > 0) {
// 2. d. i. If values does not contain an element equal to value,
// throw a RangeError exception.
for (size_t i = 0; i < values.size(); i++) {
if (strcmp(values.at(i), value_cstr.get()) == 0) {
// 2. e. return value
*result = std::move(value_cstr);
return Just(true);
}
}
Handle<String> method_str =
isolate->factory()->NewStringFromAsciiChecked(method);
THROW_NEW_ERROR_RETURN_VALUE(
isolate,
NewRangeError(MessageTemplate::kValueOutOfRange, value, method_str,
property_str),
Nothing<bool>());
}
// 2. e. return value
*result = std::move(value_cstr);
return Just(true);
}
V8_WARN_UNUSED_RESULT Maybe<bool> GetBoolOption(Isolate* isolate,
Handle<JSReceiver> options,
const char* property,
const char* method,
bool* result) {
Handle<String> property_str =
isolate->factory()->NewStringFromAsciiChecked(property);
// 1. Let value be ? Get(options, property).
Handle<Object> value;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, value,
Object::GetPropertyOrElement(isolate, options, property_str),
Nothing<bool>());
// 2. If value is not undefined, then
if (!value->IsUndefined(isolate)) {
// 2. b. i. Let value be ToBoolean(value).
*result = value->BooleanValue(isolate);
// 2. e. return value
return Just(true);
}
return Just(false);
}
// ecma402/#sec-defaultnumberoption
Maybe<int> DefaultNumberOption(Isolate* isolate, Handle<Object> value, int min,
int max, int fallback, Handle<String> property) {
// 2. Else, return fallback.
if (value->IsUndefined()) return Just(fallback);
// 1. If value is not undefined, then
// a. Let value be ? ToNumber(value).
Handle<Object> value_num;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, value_num, Object::ToNumber(isolate, value), Nothing<int>());
DCHECK(value_num->IsNumber());
// b. If value is NaN or less than minimum or greater than maximum, throw a
// RangeError exception.
if (value_num->IsNaN() || value_num->Number() < min ||
value_num->Number() > max) {
THROW_NEW_ERROR_RETURN_VALUE(
isolate,
NewRangeError(MessageTemplate::kPropertyValueOutOfRange, property),
Nothing<int>());
}
// The max and min arguments are integers and the above check makes
// sure that we are within the integer range making this double to
// int conversion safe.
//
// c. Return floor(value).
return Just(FastD2I(floor(value_num->Number())));
}
// ecma402/#sec-getnumberoption
Maybe<int> GetNumberOption(Isolate* isolate, Handle<JSReceiver> options,
Handle<String> property, int min, int max,
int fallback) {
// 1. Let value be ? Get(options, property).
Handle<Object> value;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, value, JSReceiver::GetProperty(isolate, options, property),
Nothing<int>());
// Return ? DefaultNumberOption(value, minimum, maximum, fallback).
return DefaultNumberOption(isolate, value, min, max, fallback, property);
}
} // namespace internal
} // namespace v8
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_OBJECTS_OPTION_UTILS_H_
#define V8_OBJECTS_OPTION_UTILS_H_
#include "src/execution/isolate.h"
#include "src/objects/objects.h"
namespace v8 {
namespace internal {
// ecma402/#sec-getoptionsobject and temporal/#sec-getoptionsobject
V8_WARN_UNUSED_RESULT MaybeHandle<JSReceiver> GetOptionsObject(
Isolate* isolate, Handle<Object> options, const char* method);
// ecma402/#sec-coerceoptionstoobject
V8_WARN_UNUSED_RESULT MaybeHandle<JSReceiver> CoerceOptionsToObject(
Isolate* isolate, Handle<Object> options, const char* method);
// ECMA402 9.2.10. GetOption( options, property, type, values, fallback)
// ecma402/#sec-getoption and temporal/#sec-getoption
//
// This is specialized for the case when type is string.
//
// Instead of passing undefined for the values argument as the spec
// defines, pass in an empty vector.
//
// Returns true if options object has the property and stores the
// result in value. Returns false if the value is not found. The
// caller is required to use fallback value appropriately in this
// case.
//
// method is a string denoting the method the call from; used when
// printing the error message.
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Maybe<bool> GetStringOption(
Isolate* isolate, Handle<JSReceiver> options, const char* property,
std::vector<const char*> values, const char* method,
std::unique_ptr<char[]>* result);
// A helper template to get string from option into a enum.
// The enum in the enum_values is the corresponding value to the strings
// in the str_values. If the option does not contains name,
// default_value will be return.
template <typename T>
V8_WARN_UNUSED_RESULT static Maybe<T> GetStringOption(
Isolate* isolate, Handle<JSReceiver> options, const char* name,
const char* method, const std::vector<const char*>& str_values,
const std::vector<T>& enum_values, T default_value) {
DCHECK_EQ(str_values.size(), enum_values.size());
std::unique_ptr<char[]> cstr;
Maybe<bool> found =
GetStringOption(isolate, options, name, str_values, method, &cstr);
MAYBE_RETURN(found, Nothing<T>());
if (found.FromJust()) {
DCHECK_NOT_NULL(cstr.get());
for (size_t i = 0; i < str_values.size(); i++) {
if (strcmp(cstr.get(), str_values[i]) == 0) {
return Just(enum_values[i]);
}
}
UNREACHABLE();
}
return Just(default_value);
}
// ECMA402 9.2.10. GetOption( options, property, type, values, fallback)
// ecma402/#sec-getoption
//
// This is specialized for the case when type is boolean.
//
// Returns true if options object has the property and stores the
// result in value. Returns false if the value is not found. The
// caller is required to use fallback value appropriately in this
// case.
//
// method is a string denoting the method it called from; used when
// printing the error message.
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Maybe<bool> GetBoolOption(
Isolate* isolate, Handle<JSReceiver> options, const char* property,
const char* method, bool* result);
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Maybe<int> GetNumberOption(
Isolate* isolate, Handle<JSReceiver> options, Handle<String> property,
int min, int max, int fallback);
// ecma402/#sec-defaultnumberoption
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Maybe<int> DefaultNumberOption(
Isolate* isolate, Handle<Object> value, int min, int max, int fallback,
Handle<String> property);
} // namespace internal
} // namespace v8
#endif // V8_OBJECTS_OPTION_UTILS_H_
......@@ -4,7 +4,6 @@
#ifdef V8_INTL_SUPPORT
#include "src/objects/intl-objects.h"
#include "src/objects/js-break-iterator.h"
#include "src/objects/js-collator.h"
#include "src/objects/js-date-time-format.h"
......@@ -15,6 +14,7 @@
#include "src/objects/js-segmenter.h"
#include "src/objects/lookup.h"
#include "src/objects/objects-inl.h"
#include "src/objects/option-utils.h"
#include "test/cctest/cctest.h"
namespace v8 {
......@@ -123,8 +123,8 @@ TEST(GetStringOption) {
// No value found
std::unique_ptr<char[]> result = nullptr;
Maybe<bool> found =
Intl::GetStringOption(isolate, options, "foo",
std::vector<const char*>{}, "service", &result);
GetStringOption(isolate, options, "foo", std::vector<const char*>{},
"service", &result);
CHECK(!found.FromJust());
CHECK_NULL(result);
}
......@@ -140,8 +140,8 @@ TEST(GetStringOption) {
// Value found
std::unique_ptr<char[]> result = nullptr;
Maybe<bool> found =
Intl::GetStringOption(isolate, options, "foo",
std::vector<const char*>{}, "service", &result);
GetStringOption(isolate, options, "foo", std::vector<const char*>{},
"service", &result);
CHECK(found.FromJust());
CHECK_NOT_NULL(result);
CHECK_EQ(0, strcmp("42", result.get()));
......@@ -150,9 +150,9 @@ TEST(GetStringOption) {
{
// No expected value in values array
std::unique_ptr<char[]> result = nullptr;
Maybe<bool> found = Intl::GetStringOption(isolate, options, "foo",
std::vector<const char*>{"bar"},
"service", &result);
Maybe<bool> found =
GetStringOption(isolate, options, "foo",
std::vector<const char*>{"bar"}, "service", &result);
CHECK(isolate->has_pending_exception());
CHECK(found.IsNothing());
CHECK_NULL(result);
......@@ -162,9 +162,9 @@ TEST(GetStringOption) {
{
// Expected value in values array
std::unique_ptr<char[]> result = nullptr;
Maybe<bool> found = Intl::GetStringOption(isolate, options, "foo",
std::vector<const char*>{"42"},
"service", &result);
Maybe<bool> found =
GetStringOption(isolate, options, "foo", std::vector<const char*>{"42"},
"service", &result);
CHECK(found.FromJust());
CHECK_NOT_NULL(result);
CHECK_EQ(0, strcmp("42", result.get()));
......@@ -181,7 +181,7 @@ TEST(GetBoolOption) {
{
bool result = false;
Maybe<bool> found =
Intl::GetBoolOption(isolate, options, "foo", "service", &result);
GetBoolOption(isolate, options, "foo", "service", &result);
CHECK(!found.FromJust());
CHECK(!result);
}
......@@ -197,7 +197,7 @@ TEST(GetBoolOption) {
.Assert();
bool result = false;
Maybe<bool> found =
Intl::GetBoolOption(isolate, options, "foo", "service", &result);
GetBoolOption(isolate, options, "foo", "service", &result);
CHECK(found.FromJust());
CHECK(!result);
}
......@@ -212,7 +212,7 @@ TEST(GetBoolOption) {
.Assert();
bool result = false;
Maybe<bool> found =
Intl::GetBoolOption(isolate, options, "foo", "service", &result);
GetBoolOption(isolate, options, "foo", "service", &result);
CHECK(found.FromJust());
CHECK(result);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment