#ifndef V8_OBJECTS_OPTION_UTILS_H_
#define V8_OBJECTS_OPTION_UTILS_H_
#include "src/common/globals.h"
#include "src/execution/isolate.h"
#include "src/objects/js-objects.h"
#include "src/objects/string.h"
namespace v8 {
namespace internal {
V8_WARN_UNUSED_RESULT MaybeDirectHandle<JSReceiver> GetOptionsObject(
Isolate* isolate, DirectHandle<Object> options, const char* method_name);
V8_WARN_UNUSED_RESULT MaybeDirectHandle<JSReceiver> CoerceOptionsToObject(
Isolate* isolate, DirectHandle<Object> options, const char* method_name);
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Maybe<bool> GetStringOption(
Isolate* isolate, DirectHandle<JSReceiver> options,
DirectHandle<String> property, const char* method_name,
DirectHandle<String>* result);
template <typename T>
V8_WARN_UNUSED_RESULT static Maybe<T> GetStringOption(
Isolate* isolate, DirectHandle<JSReceiver> options,
DirectHandle<String> property, const char* method_name,
const std::span<const std::string_view> str_values,
const std::span<const T> enum_values, std::optional<T> default_value) {
DCHECK_EQ(str_values.size(), enum_values.size());
DirectHandle<String> found_string;
Maybe<bool> found =
GetStringOption(isolate, options, property, method_name, &found_string);
MAYBE_RETURN(found, Nothing<T>());
if (found.FromJust()) {
for (size_t i = 0; i < str_values.size(); i++) {
if (found_string->IsEqualTo(str_values[i], isolate)) {
return Just(enum_values[i]);
}
}
} else if (default_value.has_value()) {
return Just(default_value.value());
}
if (found_string.is_null()) {
found_string = isolate->factory()->undefined_string();
}
DirectHandle<String> method_str =
isolate->factory()->NewStringFromAsciiChecked(method_name);
THROW_NEW_ERROR_RETURN_VALUE(
isolate,
NewRangeError(MessageTemplate::kValueOutOfRange, found_string, method_str,
property),
Nothing<T>());
}
template <typename T>
V8_WARN_UNUSED_RESULT static Maybe<T> GetStringOrBooleanOption(
Isolate* isolate, DirectHandle<JSReceiver> options, const char* property,
const char* method, const std::span<const std::string_view> str_values,
const std::span<const T> enum_values, T true_value, T false_value,
T fallback_value) {
DCHECK_EQ(str_values.size(), enum_values.size());
Factory* factory = isolate->factory();
DirectHandle<String> property_str =
factory->NewStringFromAsciiChecked(property);
DirectHandle<Object> value;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, value,
Object::GetPropertyOrElement(isolate, options, property_str));
if (IsUndefined(*value, isolate)) {
return Just(fallback_value);
}
if (IsTrue(*value, isolate)) {
return Just(true_value);
}
bool valueBoolean = Object::BooleanValue(*value, isolate);
if (!valueBoolean) {
return Just(false_value);
}
DirectHandle<String> value_str;
ASSIGN_RETURN_ON_EXCEPTION(isolate, value_str,
Object::ToString(isolate, value));
if (String::Equals(isolate, value_str, factory->true_string()) ||
String::Equals(isolate, value_str, factory->false_string())) {
return Just(fallback_value);
}
for (size_t i = 0; i < str_values.size(); i++) {
if (value_str->IsEqualTo(str_values[i], isolate)) {
return Just(enum_values[i]);
}
}
THROW_NEW_ERROR(
isolate,
NewRangeError(MessageTemplate::kValueOutOfRange, value,
factory->NewStringFromAsciiChecked(method), property_str));
}
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Maybe<bool> GetBoolOption(
Isolate* isolate, DirectHandle<JSReceiver> options,
DirectHandle<String> property, const char* method_name, bool* result);
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Maybe<int> GetNumberOption(
Isolate* isolate, DirectHandle<JSReceiver> options,
DirectHandle<String> property, int min, int max, int fallback);
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Maybe<double> GetNumberOptionAsDouble(
Isolate* isolate, DirectHandle<JSReceiver> options,
DirectHandle<String> property, double default_value);
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Maybe<int> DefaultNumberOption(
Isolate* isolate, DirectHandle<Object> value, int min, int max,
int fallback, DirectHandle<String> property);
}
}
#endif