1// Copyright 2021 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_OBJECTS_OPTION_UTILS_H_ 6#define V8_OBJECTS_OPTION_UTILS_H_ 7 8#include "src/execution/isolate.h" 9#include "src/objects/objects.h" 10 11namespace v8 { 12namespace internal { 13 14// ecma402/#sec-getoptionsobject and temporal/#sec-getoptionsobject 15V8_WARN_UNUSED_RESULT MaybeHandle<JSReceiver> GetOptionsObject( 16 Isolate* isolate, Handle<Object> options, const char* method_name); 17 18// ecma402/#sec-coerceoptionstoobject 19V8_WARN_UNUSED_RESULT MaybeHandle<JSReceiver> CoerceOptionsToObject( 20 Isolate* isolate, Handle<Object> options, const char* method_name); 21 22// ECMA402 9.2.10. GetOption( options, property, type, values, fallback) 23// ecma402/#sec-getoption and temporal/#sec-getoption 24// 25// This is specialized for the case when type is string. 26// 27// Instead of passing undefined for the values argument as the spec 28// defines, pass in an empty vector. 29// 30// Returns true if options object has the property and stores the 31// result in value. Returns false if the value is not found. The 32// caller is required to use fallback value appropriately in this 33// case. 34// 35// method_name is a string denoting the method the call from; used when 36// printing the error message. 37V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Maybe<bool> GetStringOption( 38 Isolate* isolate, Handle<JSReceiver> options, const char* property, 39 std::vector<const char*> values, const char* method_name, 40 std::unique_ptr<char[]>* result); 41 42// A helper template to get string from option into a enum. 43// The enum in the enum_values is the corresponding value to the strings 44// in the str_values. If the option does not contains name, 45// default_value will be return. 46template <typename T> 47V8_WARN_UNUSED_RESULT static Maybe<T> GetStringOption( 48 Isolate* isolate, Handle<JSReceiver> options, const char* name, 49 const char* method_name, const std::vector<const char*>& str_values, 50 const std::vector<T>& enum_values, T default_value) { 51 DCHECK_EQ(str_values.size(), enum_values.size()); 52 std::unique_ptr<char[]> cstr; 53 Maybe<bool> found = 54 GetStringOption(isolate, options, name, str_values, method_name, &cstr); 55 MAYBE_RETURN(found, Nothing<T>()); 56 if (found.FromJust()) { 57 DCHECK_NOT_NULL(cstr.get()); 58 for (size_t i = 0; i < str_values.size(); i++) { 59 if (strcmp(cstr.get(), str_values[i]) == 0) { 60 return Just(enum_values[i]); 61 } 62 } 63 UNREACHABLE(); 64 } 65 return Just(default_value); 66} 67 68// A helper template to get string from option into a enum. 69// The enum in the enum_values is the corresponding value to the strings 70// in the str_values. If the option does not contains name, 71// default_value will be return. 72template <typename T> 73V8_WARN_UNUSED_RESULT static Maybe<T> GetStringOrBooleanOption( 74 Isolate* isolate, Handle<JSReceiver> options, const char* property, 75 const char* method, const std::vector<const char*>& str_values, 76 const std::vector<T>& enum_values, T true_value, T false_value, 77 T fallback_value) { 78 DCHECK_EQ(str_values.size(), enum_values.size()); 79 Handle<String> property_str = 80 isolate->factory()->NewStringFromAsciiChecked(property); 81 82 // 1. Let value be ? Get(options, property). 83 Handle<Object> value; 84 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 85 isolate, value, 86 Object::GetPropertyOrElement(isolate, options, property_str), 87 Nothing<T>()); 88 // 2. If value is undefined, then return fallback. 89 if (value->IsUndefined(isolate)) { 90 return Just(fallback_value); 91 } 92 // 3. If value is true, then return trueValue. 93 if (value->IsTrue(isolate)) { 94 return Just(true_value); 95 } 96 // 4. Let valueBoolean be ToBoolean(value). 97 bool valueBoolean = value->BooleanValue(isolate); 98 // 5. If valueBoolean is false, then return valueBoolean. 99 if (!valueBoolean) { 100 return Just(false_value); 101 } 102 103 Handle<String> value_str; 104 // 6. Let value be ? ToString(value). 105 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 106 isolate, value_str, Object::ToString(isolate, value), Nothing<T>()); 107 // 7. If values does not contain an element equal to value, throw a 108 // RangeError exception. 109 // 8. Return value. 110 value_str = String::Flatten(isolate, value_str); 111 { 112 DisallowGarbageCollection no_gc; 113 const String::FlatContent& flat = value_str->GetFlatContent(no_gc); 114 int32_t length = value_str->length(); 115 for (size_t i = 0; i < str_values.size(); i++) { 116 if (static_cast<int32_t>(strlen(str_values.at(i))) == length) { 117 if (flat.IsOneByte()) { 118 if (CompareCharsEqual(str_values.at(i), 119 flat.ToOneByteVector().begin(), length)) { 120 return Just(enum_values[i]); 121 } 122 } else { 123 if (CompareCharsEqual(str_values.at(i), flat.ToUC16Vector().begin(), 124 length)) { 125 return Just(enum_values[i]); 126 } 127 } 128 } 129 } 130 } // end of no_gc 131 THROW_NEW_ERROR_RETURN_VALUE( 132 isolate, 133 NewRangeError(MessageTemplate::kValueOutOfRange, value, 134 isolate->factory()->NewStringFromAsciiChecked(method), 135 property_str), 136 Nothing<T>()); 137} 138 139// ECMA402 9.2.10. GetOption( options, property, type, values, fallback) 140// ecma402/#sec-getoption 141// 142// This is specialized for the case when type is boolean. 143// 144// Returns true if options object has the property and stores the 145// result in value. Returns false if the value is not found. The 146// caller is required to use fallback value appropriately in this 147// case. 148// 149// method_name is a string denoting the method it called from; used when 150// printing the error message. 151V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Maybe<bool> GetBoolOption( 152 Isolate* isolate, Handle<JSReceiver> options, const char* property, 153 const char* method_name, bool* result); 154 155V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Maybe<int> GetNumberOption( 156 Isolate* isolate, Handle<JSReceiver> options, Handle<String> property, 157 int min, int max, int fallback); 158 159// ecma402/#sec-defaultnumberoption 160V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Maybe<int> DefaultNumberOption( 161 Isolate* isolate, Handle<Object> value, int min, int max, int fallback, 162 Handle<String> property); 163 164} // namespace internal 165} // namespace v8 166#endif // V8_OBJECTS_OPTION_UTILS_H_ 167