LibJS: Convert Object::get() to ThrowCompletionOr

To no one's surprise, this patch is pretty big - this is possibly the
most used AO of all of them. Definitely worth it though.
This commit is contained in:
Linus Groh 2021-10-02 23:52:27 +01:00
parent 9b6c09e2c4
commit b7e5f08e56
Notes: sideshowbarker 2024-07-18 03:07:41 +09:00
61 changed files with 326 additions and 686 deletions

View file

@ -1112,9 +1112,10 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
if (@js_name@@js_suffix@.is_nullish()) {
@member_name@ = JS::js_undefined();
} else {
@member_name@ = @js_name@@js_suffix@.as_object().get("@member_key@");
if (vm.exception())
auto @member_name@_or_error = @js_name@@js_suffix@.as_object().get("@member_key@");
if (@member_name@_or_error.is_error())
@return_statement@
@member_name@ = @member_name@_or_error.release_value();
}
)~~~");
if (member.required) {
@ -2956,7 +2957,7 @@ void @prototype_class@::initialize(JS::GlobalObject& global_object)
define_native_function(vm.names.keys, keys, 0, default_attributes);
define_native_function(vm.names.values, values, 0, default_attributes);
define_direct_property(*vm.well_known_symbol_iterator(), Object::get(vm.names.entries), JS::Attribute::Configurable | JS::Attribute::Writable);
define_direct_property(*vm.well_known_symbol_iterator(), get_without_side_effects(vm.names.entries), JS::Attribute::Configurable | JS::Attribute::Writable);
)~~~");
}

View file

@ -378,8 +378,8 @@ RefPtr<Sheet> Sheet::from_json(const JsonObject& object, Workbook& workbook)
sheet->add_column();
}
auto json = sheet->interpreter().global_object().get("JSON");
auto& parse_function = json.as_object().get("parse").as_function();
auto json = sheet->interpreter().global_object().get_without_side_effects("JSON");
auto& parse_function = json.as_object().get_without_side_effects("parse").as_function();
auto read_format = [](auto& format, const auto& obj) {
if (auto value = obj.get("foreground_color"); value.is_string())
@ -532,8 +532,8 @@ JsonObject Sheet::to_json() const
data.set("kind", it.value->kind() == Cell::Kind::Formula ? "Formula" : "LiteralString");
if (it.value->kind() == Cell::Formula) {
data.set("source", it.value->data());
auto json = interpreter().global_object().get("JSON");
auto stringified_or_error = interpreter().vm().call(json.as_object().get("stringify").as_function(), json, it.value->evaluated_data());
auto json = interpreter().global_object().get_without_side_effects("JSON");
auto stringified_or_error = interpreter().vm().call(json.as_object().get_without_side_effects("stringify").as_function(), json, it.value->evaluated_data());
VERIFY(!stringified_or_error.is_error());
data.set("value", stringified_or_error.release_value().to_string_without_side_effects());
} else {
@ -651,7 +651,7 @@ JsonObject Sheet::gather_documentation() const
const JS::PropertyName doc_name { "__documentation" };
auto add_docs_from = [&](auto& it, auto& global_object) {
auto value = global_object.get(it.key);
auto value = global_object.get(it.key).release_value();
if (!value.is_function() && !value.is_object())
return;
@ -660,7 +660,7 @@ JsonObject Sheet::gather_documentation() const
return;
dbgln("Found '{}'", it.key.to_display_string());
auto doc = value_object.get(doc_name);
auto doc = value_object.get(doc_name).release_value();
if (!doc.is_string())
return;

View file

@ -35,7 +35,7 @@ GUI::Variant SheetModel::data(const GUI::ModelIndex& index, GUI::ModelRole role)
if (value.is_object()) {
auto& object = value.as_object();
if (is<JS::Error>(object)) {
auto error = object.get("message").to_string_without_side_effects();
auto error = object.get_without_side_effects("message").to_string_without_side_effects();
builder.append(error);
return builder.to_string();
}

View file

@ -1216,9 +1216,7 @@ ThrowCompletionOr<Value> ClassExpression::class_definition_evaluation(Interprete
Object* super_constructor_prototype = nullptr;
if (!super_constructor.is_null()) {
auto super_constructor_prototype_value = super_constructor.as_object().get(vm.names.prototype);
if (auto* exception = interpreter.exception())
return throw_completion(exception->value());
auto super_constructor_prototype_value = TRY(super_constructor.as_object().get(vm.names.prototype));
if (!super_constructor_prototype_value.is_object() && !super_constructor_prototype_value.is_null())
return interpreter.vm().throw_completion<TypeError>(global_object, ErrorType::ClassExtendsValueInvalidPrototype, super_constructor_prototype_value.to_string_without_side_effects());
@ -1237,9 +1235,7 @@ ThrowCompletionOr<Value> ClassExpression::class_definition_evaluation(Interprete
TRY(class_constructor->internal_set_prototype_of(super_constructor.is_null() ? global_object.function_prototype() : &super_constructor.as_object()));
}
auto class_prototype = class_constructor->get(vm.names.prototype);
if (auto* exception = interpreter.exception())
return throw_completion(exception->value());
auto class_prototype = TRY(class_constructor->get(vm.names.prototype));
if (!class_prototype.is_object())
return interpreter.vm().throw_completion<TypeError>(global_object, ErrorType::NotAnObject, "Class prototype");
@ -2294,9 +2290,7 @@ Value ObjectExpression::execute(Interpreter& interpreter, GlobalObject& global_o
if (key.is_object() && is<Array>(key.as_object())) {
auto& array_to_spread = static_cast<Array&>(key.as_object());
for (auto& entry : array_to_spread.indexed_properties()) {
auto value = array_to_spread.get(entry.index());
if (interpreter.exception())
return {};
auto value = TRY_OR_DISCARD(array_to_spread.get(entry.index()));
object->indexed_properties().put(entry.index(), value);
if (interpreter.exception())
return {};
@ -2306,7 +2300,7 @@ Value ObjectExpression::execute(Interpreter& interpreter, GlobalObject& global_o
for (auto& it : obj_to_spread.shape().property_table_ordered()) {
if (it.value.attributes.is_enumerable()) {
object->define_direct_property(it.key, obj_to_spread.get(it.key), JS::default_attributes);
object->define_direct_property(it.key, TRY_OR_DISCARD(obj_to_spread.get(it.key)), JS::default_attributes);
if (interpreter.exception())
return {};
}

View file

@ -200,9 +200,10 @@ void CopyObjectExcludingProperties::execute_impl(Bytecode::Interpreter& interpre
for (auto& key : own_keys) {
if (!excluded_names.contains(key)) {
auto property_name = PropertyName(key.to_property_key(interpreter.global_object()));
auto property_value = from_object->get(property_name);
if (interpreter.vm().exception())
auto property_value_or_error = from_object->get(property_name);
if (property_value_or_error.is_error())
return;
auto property_value = property_value_or_error.release_value();
to_object->define_direct_property(property_name, property_value, JS::default_attributes);
}
}
@ -237,8 +238,12 @@ void SetVariable::execute_impl(Bytecode::Interpreter& interpreter) const
void GetById::execute_impl(Bytecode::Interpreter& interpreter) const
{
if (auto* object = interpreter.accumulator().to_object(interpreter.global_object()))
interpreter.accumulator() = object->get(interpreter.current_executable().get_string(m_property));
if (auto* object = interpreter.accumulator().to_object(interpreter.global_object())) {
auto value_or_error = object->get(interpreter.current_executable().get_string(m_property));
if (value_or_error.is_error())
return;
interpreter.accumulator() = value_or_error.release_value();
}
}
void PutById::execute_impl(Bytecode::Interpreter& interpreter) const
@ -429,7 +434,10 @@ void GetByValue::execute_impl(Bytecode::Interpreter& interpreter) const
auto property_key = interpreter.accumulator().to_property_key(interpreter.global_object());
if (interpreter.vm().exception())
return;
interpreter.accumulator() = object->get(property_key);
auto value_or_error = object->get(property_key);
if (value_or_error.is_error())
return;
interpreter.accumulator() = value_or_error.release_value();
}
}

View file

@ -99,7 +99,7 @@ void MarkupGenerator::array_to_html(const Array& array, StringBuilder& html_outp
html_output.append(wrap_string_in_style(", ", StyleType::Punctuation));
first = false;
// FIXME: Exception check
value_to_html(array.get(it.index()), html_output, seen_objects);
value_to_html(array.get(it.index()).release_value(), html_output, seen_objects);
}
html_output.append(wrap_string_in_style(" ]", StyleType::Punctuation));
}
@ -115,7 +115,7 @@ void MarkupGenerator::object_to_html(const Object& object, StringBuilder& html_o
html_output.append(wrap_string_in_style(String::number(entry.index()), StyleType::Number));
html_output.append(wrap_string_in_style(": ", StyleType::Punctuation));
// FIXME: Exception check
value_to_html(object.get(entry.index()), html_output, seen_objects);
value_to_html(object.get(entry.index()).release_value(), html_output, seen_objects);
}
if (!object.indexed_properties().is_empty() && object.shape().property_count())

View file

@ -46,9 +46,7 @@ ThrowCompletionOr<Value> require_object_coercible(GlobalObject& global_object, V
ThrowCompletionOr<size_t> length_of_array_like(GlobalObject& global_object, Object const& object)
{
auto& vm = global_object.vm();
auto result = object.get(vm.names.length);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto result = TRY(object.get(vm.names.length));
auto length = result.to_length(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
@ -82,9 +80,7 @@ ThrowCompletionOr<MarkedValueList> create_list_from_array_like(GlobalObject& glo
auto index_name = String::number(i);
// b. Let next be ? Get(obj, indexName).
auto next = array_like.get(index_name);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto next = TRY(array_like.get(index_name));
// c. If Type(next) is not an element of elementTypes, throw a TypeError exception.
if (check_value)
@ -104,9 +100,7 @@ ThrowCompletionOr<FunctionObject*> species_constructor(GlobalObject& global_obje
auto& vm = global_object.vm();
// 1. Let C be ? Get(O, "constructor").
auto constructor = object.get(vm.names.constructor);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto constructor = TRY(object.get(vm.names.constructor));
// 2. If C is undefined, return defaultConstructor.
if (constructor.is_undefined())
@ -117,9 +111,7 @@ ThrowCompletionOr<FunctionObject*> species_constructor(GlobalObject& global_obje
return vm.throw_completion<TypeError>(global_object, ErrorType::NotAConstructor, constructor.to_string_without_side_effects());
// 4. Let S be ? Get(C, @@species).
auto species = constructor.as_object().get(*vm.well_known_symbol_species());
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto species = TRY(constructor.as_object().get(*vm.well_known_symbol_species()));
// 5. If S is either undefined or null, return defaultConstructor.
if (species.is_nullish())
@ -340,9 +332,7 @@ ThrowCompletionOr<Object*> get_prototype_from_constructor(GlobalObject& global_o
// 1. Assert: intrinsicDefaultProto is this specification's name of an intrinsic object. The corresponding object must be an intrinsic that is intended to be used as the [[Prototype]] value of an object.
// 2. Let proto be ? Get(constructor, "prototype").
auto prototype = constructor.get(vm.names.prototype);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto prototype = TRY(constructor.get(vm.names.prototype));
// 3. If Type(proto) is not Object, then
if (!prototype.is_object()) {
@ -917,9 +907,7 @@ ThrowCompletionOr<String> get_substitution(GlobalObject& global_object, Utf16Vie
auto group_name_view = replace_view.substring_view(start_position, *end_position - start_position);
auto group_name = group_name_view.to_utf8(Utf16View::AllowInvalidCodeUnits::Yes);
auto capture = named_captures.as_object().get(group_name);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto capture = TRY(named_captures.as_object().get(group_name));
if (!capture.is_undefined()) {
auto capture_string = capture.to_string(global_object);

View file

@ -117,7 +117,7 @@ ThrowCompletionOr<Optional<PropertyDescriptor>> ArgumentsObject::internal_get_ow
// 5. If isMapped is true, then
if (is_mapped) {
// a. Set desc.[[Value]] to Get(map, P).
desc->value = m_parameter_map->get(property_name);
desc->value = TRY(m_parameter_map->get(property_name));
}
// 6. Return desc.
return desc;
@ -142,7 +142,7 @@ ThrowCompletionOr<bool> ArgumentsObject::internal_define_own_property(PropertyNa
// i. Set newArgDesc to a copy of Desc.
new_arg_desc = descriptor;
// ii. Set newArgDesc.[[Value]] to Get(map, P).
new_arg_desc.value = map.get(property_name);
new_arg_desc.value = TRY(map.get(property_name));
}
}

View file

@ -189,9 +189,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
auto& array_object = array.as_object();
for (size_t k = 0; k < length; ++k) {
auto k_value = array_like->get(k);
if (vm.exception())
return {};
auto k_value = TRY_OR_DISCARD(array_like->get(k));
Value mapped_value;
if (map_fn)
mapped_value = TRY_OR_DISCARD(vm.call(*map_fn, this_arg, k_value, Value(k)));

View file

@ -75,9 +75,8 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayIteratorPrototype::next)
if (iteration_kind == Object::PropertyKind::Key)
return create_iterator_result_object(global_object, Value(static_cast<i32>(index)), false);
auto value = array.get(index);
if (vm.exception())
return {};
auto value = TRY_OR_DISCARD(array.get(index));
if (iteration_kind == Object::PropertyKind::Value)
return create_iterator_result_object(global_object, value, false);

View file

@ -77,7 +77,7 @@ void ArrayPrototype::initialize(GlobalObject& global_object)
// Object.is(Array.prototype[Symbol.iterator], Array.prototype.values)
// evaluates to true
// 23.1.3.33 Array.prototype [ @@iterator ] ( ), https://tc39.es/ecma262/#sec-array.prototype-@@iterator
define_direct_property(*vm.well_known_symbol_iterator(), get(vm.names.values), attr);
define_direct_property(*vm.well_known_symbol_iterator(), get_without_side_effects(vm.names.values), attr);
// 23.1.3.34 Array.prototype [ @@unscopables ], https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
// With proposal, https://tc39.es/proposal-array-find-from-last/index.html#sec-array.prototype-@@unscopables
@ -116,9 +116,7 @@ static Object* array_species_create(GlobalObject& global_object, Object& origina
return array;
}
auto constructor = original_array.get(vm.names.constructor);
if (vm.exception())
return {};
auto constructor = TRY_OR_DISCARD(original_array.get(vm.names.constructor));
if (constructor.is_constructor()) {
auto& constructor_function = constructor.as_function();
auto* this_realm = vm.current_realm();
@ -130,9 +128,7 @@ static Object* array_species_create(GlobalObject& global_object, Object& origina
}
if (constructor.is_object()) {
constructor = constructor.as_object().get(*vm.well_known_symbol_species());
if (vm.exception())
return {};
constructor = TRY_OR_DISCARD(constructor.as_object().get(*vm.well_known_symbol_species()));
if (constructor.is_null())
constructor = js_undefined();
}
@ -201,9 +197,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::filter)
// c. If kPresent is true, then
if (k_present) {
// i. Let kValue be ? Get(O, Pk).
auto k_value = object->get(k);
if (vm.exception())
return {};
auto k_value = TRY_OR_DISCARD(object->get(k));
// ii. Let selected be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
auto selected = TRY_OR_DISCARD(vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
@ -259,9 +253,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::for_each)
// c. If kPresent is true, then
if (k_present) {
// i. Let kValue be ? Get(O, Pk).
auto k_value = object->get(property_name);
if (vm.exception())
return {};
auto k_value = TRY_OR_DISCARD(object->get(property_name));
// ii. Perform ? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »).
(void)vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object);
@ -315,9 +307,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::map)
// c. If kPresent is true, then
if (k_present) {
// i. Let kValue be ? Get(O, Pk).
auto k_value = object->get(property_name);
if (vm.exception())
return {};
auto k_value = TRY_OR_DISCARD(object->get(property_name));
// ii. Let mappedValue be ? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »).
auto mapped_value = TRY_OR_DISCARD(vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object));
@ -383,9 +373,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::unshift)
if (vm.exception())
return {};
if (from_present) {
auto from_value = this_object->get(from);
if (vm.exception())
return {};
auto from_value = TRY_OR_DISCARD(this_object->get(from));
this_object->set(to, from_value, Object::ShouldThrowExceptions::Yes);
if (vm.exception())
return {};
@ -421,9 +409,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::pop)
return js_undefined();
}
auto index = length - 1;
auto element = this_object->get(index);
if (vm.exception())
return {};
auto element = TRY_OR_DISCARD(this_object->get(index));
this_object->delete_property_or_throw(index);
if (vm.exception())
return {};
@ -446,10 +432,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::shift)
return {};
return js_undefined();
}
auto first = this_object->get(0);
if (vm.exception())
return {};
auto first = TRY_OR_DISCARD(this_object->get(0));
for (size_t k = 1; k < length; ++k) {
size_t from = k;
size_t to = k - 1;
@ -457,9 +440,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::shift)
if (vm.exception())
return {};
if (from_present) {
auto from_value = this_object->get(from);
if (vm.exception())
return {};
auto from_value = TRY_OR_DISCARD(this_object->get(from));
this_object->set(to, from_value, Object::ShouldThrowExceptions::Yes);
if (vm.exception())
return {};
@ -486,9 +467,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_string)
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
auto join_function = this_object->get(vm.names.join);
if (vm.exception())
return {};
auto join_function = TRY_OR_DISCARD(this_object->get(vm.names.join));
if (!join_function.is_function())
return ObjectPrototype::to_string(vm, global_object);
return TRY_OR_DISCARD(vm.call(join_function.as_function(), this_object));
@ -515,9 +494,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_locale_string)
for (size_t i = 0; i < length; ++i) {
if (i > 0)
builder.append(separator);
auto value = this_object->get(i);
if (vm.exception())
return {};
auto value = TRY_OR_DISCARD(this_object->get(i));
if (value.is_nullish())
continue;
auto locale_string_result = TRY_OR_DISCARD(value.invoke(global_object, vm.names.toLocaleString));
@ -557,9 +534,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::join)
for (size_t i = 0; i < length; ++i) {
if (i > 0)
builder.append(separator);
auto value = this_object->get(i);
if (vm.exception())
return {};
auto value = TRY_OR_DISCARD(this_object->get(i));
if (value.is_nullish())
continue;
auto string = value.to_string(global_object);
@ -593,10 +568,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::concat)
if (vm.exception())
return false;
auto spreadable = object->get(*vm.well_known_symbol_is_concat_spreadable());
if (vm.exception())
return false;
auto spreadable = TRY_OR_DISCARD(object->get(*vm.well_known_symbol_is_concat_spreadable()));
if (!spreadable.is_undefined())
return spreadable.to_boolean();
@ -625,9 +597,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::concat)
if (vm.exception())
return;
if (k_exists) {
auto k_value = obj.get(k);
if (vm.exception())
auto k_value_or_error = obj.get(k);
if (k_value_or_error.is_error())
return;
auto k_value = k_value_or_error.release_value();
new_array->create_data_property_or_throw(n, k_value);
if (vm.exception())
return;
@ -720,10 +693,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::slice)
return {};
if (present) {
auto value = this_object->get(k);
if (vm.exception())
return {};
auto value = TRY_OR_DISCARD(this_object->get(k));
new_array->create_data_property_or_throw(index, value);
if (vm.exception())
return {};
@ -801,9 +771,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::index_of)
// b. If kPresent is true, then
if (k_present) {
// i. Let elementK be ? Get(O, ! ToString(𝔽(k))).
auto element_k = object->get(property_name);
if (vm.exception())
return {};
auto element_k = TRY_OR_DISCARD(object->get(property_name));
// ii. Let same be IsStrictlyEqual(searchElement, elementK).
auto same = is_strictly_equal(search_element, element_k);
@ -875,9 +843,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce)
// iii. If kPresent is true, then
if (k_present) {
// 1. Set accumulator to ? Get(O, Pk).
accumulator = object->get(property_name);
if (vm.exception())
return {};
accumulator = TRY_OR_DISCARD(object->get(property_name));
}
// iv. Set k to k + 1.
@ -901,9 +867,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce)
// c. If kPresent is true, then
if (k_present) {
// i. Let kValue be ? Get(O, Pk).
auto k_value = object->get(property_name);
if (vm.exception())
return {};
auto k_value = TRY_OR_DISCARD(object->get(property_name));
// ii. Set accumulator to ? Call(callbackfn, undefined, « accumulator, kValue, 𝔽(k), O »).
accumulator = TRY_OR_DISCARD(vm.call(callback_function.as_function(), js_undefined(), accumulator, k_value, Value(k), object));
@ -971,9 +935,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce_right)
// iii. If kPresent is true, then
if (k_present) {
// 1. Set accumulator to ? Get(O, Pk).
accumulator = object->get(property_name);
if (vm.exception())
return {};
accumulator = TRY_OR_DISCARD(object->get(property_name));
}
// iv. Set k to k - 1.
@ -999,9 +961,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce_right)
// c. If kPresent is true, then
if (k_present) {
// i. Let kValue be ? Get(O, Pk).
auto k_value = object->get(property_name);
if (vm.exception())
return {};
auto k_value = TRY_OR_DISCARD(object->get(property_name));
// ii. Set accumulator to ? Call(callbackfn, undefined, « accumulator, kValue, 𝔽(k), O »).
accumulator = TRY_OR_DISCARD(vm.call(callback_function.as_function(), js_undefined(), accumulator, k_value, Value((size_t)k), object));
@ -1030,21 +990,15 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reverse)
if (vm.exception())
return {};
Value lower_value;
if (lower_exists) {
lower_value = this_object->get(lower);
if (vm.exception())
return {};
}
if (lower_exists)
lower_value = TRY_OR_DISCARD(this_object->get(lower));
auto upper_exists = this_object->has_property(upper);
if (vm.exception())
return {};
Value upper_value;
if (upper_exists) {
upper_value = this_object->get(upper);
if (vm.exception())
return {};
}
if (upper_exists)
upper_value = TRY_OR_DISCARD(this_object->get(upper));
if (lower_exists && upper_exists) {
this_object->set(lower, upper_value, Object::ShouldThrowExceptions::Yes);
@ -1204,10 +1158,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::sort)
return {};
if (k_present) {
auto k_value = object->get(k);
if (vm.exception())
return {};
auto k_value = TRY_OR_DISCARD(object->get(k));
items.append(k_value);
}
}
@ -1297,9 +1248,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::last_index_of)
// b. If kPresent is true, then
if (k_present) {
// i. Let elementK be ? Get(O, ! ToString(𝔽(k))).
auto element_k = object->get(property_name);
if (vm.exception())
return {};
auto element_k = TRY_OR_DISCARD(object->get(property_name));
// ii. Let same be IsStrictlyEqual(searchElement, elementK).
auto same = is_strictly_equal(search_element, element_k);
@ -1343,9 +1292,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::includes)
}
auto value_to_find = vm.argument(0);
for (u64 i = from_index; i < length; ++i) {
auto element = this_object->get(i);
if (vm.exception())
return {};
auto element = TRY_OR_DISCARD(this_object->get(i));
if (same_value_zero(element, value_to_find))
return Value(true);
}
@ -1379,9 +1326,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find)
auto property_name = PropertyName { k };
// b. Let kValue be ? Get(O, Pk).
auto k_value = object->get(property_name);
if (vm.exception())
return {};
auto k_value = TRY_OR_DISCARD(object->get(property_name));
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = TRY_OR_DISCARD(vm.call(predicate.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
@ -1424,9 +1369,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_index)
auto property_name = PropertyName { k };
// b. Let kValue be ? Get(O, Pk).
auto k_value = object->get(property_name);
if (vm.exception())
return {};
auto k_value = TRY_OR_DISCARD(object->get(property_name));
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = TRY_OR_DISCARD(vm.call(predicate.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
@ -1469,9 +1412,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_last)
auto property_name = PropertyName { k };
// b. Let kValue be ? Get(O, Pk).
auto k_value = object->get(property_name);
if (vm.exception())
return {};
auto k_value = TRY_OR_DISCARD(object->get(property_name));
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = TRY_OR_DISCARD(vm.call(predicate.as_function(), this_arg, k_value, Value((double)k), object)).to_boolean();
@ -1514,9 +1455,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_last_index)
auto property_name = PropertyName { k };
// b. Let kValue be ? Get(O, Pk).
auto k_value = object->get(property_name);
if (vm.exception())
return {};
auto k_value = TRY_OR_DISCARD(object->get(property_name));
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = TRY_OR_DISCARD(vm.call(predicate.as_function(), this_arg, k_value, Value((double)k), object)).to_boolean();
@ -1566,9 +1505,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::some)
// c. If kPresent is true, then
if (k_present) {
// i. Let kValue be ? Get(O, Pk).
auto k_value = object->get(property_name);
if (vm.exception())
return {};
auto k_value = TRY_OR_DISCARD(object->get(property_name));
// ii. Let testResult be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = TRY_OR_DISCARD(vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
@ -1619,9 +1556,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::every)
// c. If kPresent is true, then
if (k_present) {
// i. Let kValue be ? Get(O, Pk).
auto k_value = object->get(property_name);
if (vm.exception())
return {};
auto k_value = TRY_OR_DISCARD(object->get(property_name));
// ii. Let testResult be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = TRY_OR_DISCARD(vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
@ -1693,9 +1628,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice)
return {};
if (from_present) {
auto from_value = this_object->get(from);
if (vm.exception())
return {};
auto from_value = TRY_OR_DISCARD(this_object->get(from));
removed_elements->create_data_property_or_throw(i, from_value);
if (vm.exception())
@ -1717,10 +1650,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice)
return {};
if (from_present) {
auto from_value = this_object->get(from);
if (vm.exception())
return {};
auto from_value = TRY_OR_DISCARD(this_object->get(from));
this_object->set(to, from_value, Object::ShouldThrowExceptions::Yes);
} else {
this_object->delete_property_or_throw(to);
@ -1744,9 +1674,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice)
auto to = i + insert_count - 1;
if (from_present) {
auto from_value = this_object->get(from_index);
if (vm.exception())
return {};
auto from_value = TRY_OR_DISCARD(this_object->get(from_index));
this_object->set(to, from_value, Object::ShouldThrowExceptions::Yes);
} else {
this_object->delete_property_or_throw(to);
@ -1862,9 +1790,7 @@ static size_t flatten_into_array(GlobalObject& global_object, Object& new_array,
if (!value_exists)
continue;
auto value = array.get(j);
if (vm.exception())
return {};
auto value = TRY_OR_DISCARD(array.get(j));
if (mapper_func)
value = TRY_OR_DISCARD(vm.call(*mapper_func, this_arg, value, Value(j), &array));
@ -2019,9 +1945,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::copy_within)
return {};
if (from_present) {
auto from_value = this_object->get(from_i);
if (vm.exception())
return {};
auto from_value = TRY_OR_DISCARD(this_object->get(from_i));
this_object->set(to_i, from_value, Object::ShouldThrowExceptions::Yes);
if (vm.exception())
return {};
@ -2060,7 +1984,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::at)
}
if (index.has_overflow() || index.value() >= length)
return js_undefined();
return this_object->get(index.value());
return TRY_OR_DISCARD(this_object->get(index.value()));
}
}

View file

@ -85,7 +85,7 @@ void DatePrototype::initialize(GlobalObject& global_object)
// B.2.4.3 Date.prototype.toGMTString ( ), https://tc39.es/ecma262/#sec-date.prototype.togmtstring
// The function object that is the initial value of Date.prototype.toGMTString
// is the same function object that is the initial value of Date.prototype.toUTCString.
define_direct_property(vm.names.toGMTString, get(vm.names.toUTCString), attr);
define_direct_property(vm.names.toGMTString, get_without_side_effects(vm.names.toUTCString), attr);
}
DatePrototype::~DatePrototype()

View file

@ -43,9 +43,7 @@ ThrowCompletionOr<void> Error::install_error_cause(Value options)
return throw_completion(exception->value());
if (has_property) {
// a. Let cause be ? Get(options, "cause").
auto cause = options.as_object().get(vm.names.cause);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto cause = TRY(options.as_object().get(vm.names.cause));
// b. Perform ! CreateNonEnumerableDataPropertyOrThrow(O, "cause", cause).
create_non_enumerable_data_property_or_throw(vm.names.cause, cause);

View file

@ -40,9 +40,7 @@ JS_DEFINE_NATIVE_FUNCTION(ErrorPrototype::to_string)
auto& this_object = this_value.as_object();
String name = "Error";
auto name_property = this_object.get(vm.names.name);
if (vm.exception())
return {};
auto name_property = TRY_OR_DISCARD(this_object.get(vm.names.name));
if (!name_property.is_undefined()) {
name = name_property.to_string(global_object);
if (vm.exception())
@ -50,9 +48,7 @@ JS_DEFINE_NATIVE_FUNCTION(ErrorPrototype::to_string)
}
String message = "";
auto message_property = this_object.get(vm.names.message);
if (vm.exception())
return {};
auto message_property = TRY_OR_DISCARD(this_object.get(vm.names.message));
if (!message_property.is_undefined()) {
message = message_property.to_string(global_object);
if (vm.exception())

View file

@ -40,16 +40,12 @@ BoundFunction* FunctionObject::bind(Value bound_this_value, Vector<Value> argume
}();
i32 computed_length = 0;
auto length_property = get(vm.names.length);
if (vm.exception())
return nullptr;
auto length_property = TRY_OR_DISCARD(get(vm.names.length));
if (length_property.is_number())
computed_length = max(0, length_property.as_i32() - static_cast<i32>(arguments.size()));
Object* constructor_prototype = nullptr;
auto prototype_property = target_function.get(vm.names.prototype);
if (vm.exception())
return nullptr;
auto prototype_property = TRY_OR_DISCARD(target_function.get(vm.names.prototype));
if (prototype_property.is_object())
constructor_prototype = &prototype_property.as_object();

View file

@ -16,11 +16,12 @@ namespace JS {
GeneratorObject* GeneratorObject::create(GlobalObject& global_object, Value initial_value, ECMAScriptFunctionObject* generating_function, Environment* generating_scope, Bytecode::RegisterWindow frame)
{
// This is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
auto generating_function_proto_property = generating_function->get(global_object.vm().names.prototype).to_object(global_object);
if (!generating_function_proto_property)
auto generating_function_prototype = TRY_OR_DISCARD(generating_function->get(global_object.vm().names.prototype));
auto* generating_function_prototype_object = generating_function_prototype.to_object(global_object);
if (!generating_function_prototype_object)
return {};
auto object = global_object.heap().allocate<GeneratorObject>(global_object, global_object, *generating_function_proto_property);
auto object = global_object.heap().allocate<GeneratorObject>(global_object, global_object, *generating_function_prototype_object);
object->m_generating_function = generating_function;
object->m_environment = generating_scope;
object->m_frame = move(frame);
@ -54,15 +55,15 @@ Value GeneratorObject::next_impl(VM& vm, GlobalObject& global_object, Optional<V
auto bytecode_interpreter = Bytecode::Interpreter::current();
VERIFY(bytecode_interpreter);
auto generated_value = [](Value value) {
auto generated_value = [](Value value) -> Value {
if (value.is_object())
return value.as_object().get("result");
return TRY_OR_DISCARD(value.as_object().get("result"));
return value.is_empty() ? js_undefined() : value;
};
auto generated_continuation = [&](Value value) -> Bytecode::BasicBlock const* {
if (value.is_object())
return reinterpret_cast<Bytecode::BasicBlock const*>(static_cast<u64>(value.as_object().get("continuation").to_double(global_object)));
return reinterpret_cast<Bytecode::BasicBlock const*>(static_cast<u64>(TRY_OR_DISCARD(value.as_object().get("continuation")).to_double(global_object)));
return nullptr;
};

View file

@ -214,10 +214,7 @@ ThrowCompletionOr<Vector<String>> canonicalize_locale_list(GlobalObject& global_
}
// 5. Let len be ? ToLength(? Get(O, "length")).
auto length_value = object->get(vm.names.length);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto length = length_value.to_length(global_object);
auto length = TRY(object->get(vm.names.length)).to_length(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
@ -235,9 +232,7 @@ ThrowCompletionOr<Vector<String>> canonicalize_locale_list(GlobalObject& global_
// c. If kPresent is true, then
if (key_present) {
// i. Let kValue be ? Get(O, Pk).
auto key_value = object->get(property_key);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto key_value = TRY(object->get(property_key));
// ii. If Type(kValue) is not String or Object, throw a TypeError exception.
if (!key_value.is_string() && !key_value.is_object())
@ -619,10 +614,9 @@ ThrowCompletionOr<Value> get_option(GlobalObject& global_object, Object const& o
auto& vm = global_object.vm();
// 1. Assert: Type(options) is Object.
// 2. Let value be ? Get(options, property).
auto value = options.get(property);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto value = TRY(options.get(property));
// 3. If value is undefined, return fallback.
if (value.is_undefined()) {
@ -685,13 +679,10 @@ ThrowCompletionOr<Optional<int>> default_number_option(GlobalObject& global_obje
// 9.2.15 GetNumberOption ( options, property, minimum, maximum, fallback ), https://tc39.es/ecma402/#sec-getnumberoption
ThrowCompletionOr<Optional<int>> get_number_option(GlobalObject& global_object, Object const& options, PropertyName const& property, int minimum, int maximum, Optional<int> fallback)
{
auto& vm = global_object.vm();
// 1. Assert: Type(options) is Object.
// 2. Let value be ? Get(options, property).
auto value = options.get(property);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto value = TRY(options.get(property));
// 3. Return ? DefaultNumberOption(value, minimum, maximum, fallback).
return default_number_option(global_object, value, minimum, maximum, move(fallback));

View file

@ -252,24 +252,16 @@ ThrowCompletionOr<void> set_number_format_digit_options(GlobalObject& global_obj
auto min_integer_digits = TRY(get_number_option(global_object, options, vm.names.minimumIntegerDigits, 1, 21, 1));
// 6. Let mnfd be ? Get(options, "minimumFractionDigits").
auto min_fraction_digits = options.get(vm.names.minimumFractionDigits);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto min_fraction_digits = TRY(options.get(vm.names.minimumFractionDigits));
// 7. Let mxfd be ? Get(options, "maximumFractionDigits").
auto max_fraction_digits = options.get(vm.names.maximumFractionDigits);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto max_fraction_digits = TRY(options.get(vm.names.maximumFractionDigits));
// 8. Let mnsd be ? Get(options, "minimumSignificantDigits").
auto min_significant_digits = options.get(vm.names.minimumSignificantDigits);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto min_significant_digits = TRY(options.get(vm.names.minimumSignificantDigits));
// 9. Let mxsd be ? Get(options, "maximumSignificantDigits").
auto max_significant_digits = options.get(vm.names.maximumSignificantDigits);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto max_significant_digits = TRY(options.get(vm.names.maximumSignificantDigits));
// 10. Set intlObj.[[MinimumIntegerDigits]] to mnid.
intl_object.set_min_integer_digits(*min_integer_digits);

View file

@ -21,9 +21,7 @@ Object* get_iterator(GlobalObject& global_object, Value value, IteratorHint hint
auto object = value.to_object(global_object);
if (!object)
return {};
method = object->get(*vm.well_known_symbol_iterator());
if (vm.exception())
return {};
method = TRY_OR_DISCARD(object->get(*vm.well_known_symbol_iterator()));
}
if (!method.is_function()) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotIterable, value.to_string_without_side_effects());
@ -40,12 +38,11 @@ Object* get_iterator(GlobalObject& global_object, Value value, IteratorHint hint
// 7.4.2 IteratorNext ( iteratorRecord [ , value ] ), https://tc39.es/ecma262/#sec-iteratornext
Object* iterator_next(Object& iterator, Value value)
{
// FIXME: Implement using iterator records, not ordinary objects
auto& vm = iterator.vm();
auto& global_object = iterator.global_object();
auto next_method = iterator.get(vm.names.next);
if (vm.exception())
return {};
auto next_method = TRY_OR_DISCARD(iterator.get(vm.names.next));
if (!next_method.is_function()) {
vm.throw_exception<TypeError>(global_object, ErrorType::IterableNextNotAFunction);
@ -70,20 +67,18 @@ Object* iterator_next(Object& iterator, Value value)
bool iterator_complete(GlobalObject& global_object, Object& iterator_result)
{
auto& vm = global_object.vm();
auto done = iterator_result.get(vm.names.done);
if (vm.exception())
return {};
return done.to_boolean();
// 1. Return ! ToBoolean(? Get(iterResult, "done")).
return TRY_OR_DISCARD(iterator_result.get(vm.names.done)).to_boolean();
}
// 7.4.4 IteratorValue ( iterResult ), https://tc39.es/ecma262/#sec-iteratorvalue
Value iterator_value(GlobalObject& global_object, Object& iterator_result)
{
auto& vm = global_object.vm();
auto value = iterator_result.get(vm.names.value);
if (vm.exception())
return {};
return value;
// 1. Return ? Get(iterResult, "value").
return TRY_OR_DISCARD(iterator_result.get(vm.names.value));
}
// 7.4.5 IteratorStep ( iteratorRecord ), https://tc39.es/ecma262/#sec-iteratorstep
@ -186,18 +181,18 @@ void get_iterator_values(GlobalObject& global_object, Value value, Function<Iter
if (!next_object)
return;
auto done_property = next_object->get(vm.names.done);
if (vm.exception())
auto done_property_or_error = next_object->get(vm.names.done);
if (done_property_or_error.is_error())
return;
if (!done_property.is_empty() && done_property.to_boolean())
if (done_property_or_error.release_value().to_boolean())
return;
auto next_value = next_object->get(vm.names.value);
if (vm.exception())
auto next_value_or_error = next_object->get(vm.names.value);
if (next_value_or_error.is_error())
return;
auto result = callback(next_value);
auto result = callback(next_value_or_error.release_value());
if (result == IterationDecision::Break) {
if (close_on_abrupt == CloseOnAbrupt::Yes)
iterator_close(*iterator);

View file

@ -60,9 +60,7 @@ String JSONObject::stringify_impl(GlobalObject& global_object, Value value, Valu
auto replacer_length = TRY_OR_DISCARD(length_of_array_like(global_object, replacer_object));
Vector<String> list;
for (size_t i = 0; i < replacer_length; ++i) {
auto replacer_value = replacer_object.get(i);
if (vm.exception())
return {};
auto replacer_value = TRY_OR_DISCARD(replacer_object.get(i));
String item;
if (replacer_value.is_string()) {
item = replacer_value.as_string().string();
@ -142,16 +140,12 @@ JS_DEFINE_NATIVE_FUNCTION(JSONObject::stringify)
String JSONObject::serialize_json_property(GlobalObject& global_object, StringifyState& state, const PropertyName& key, Object* holder)
{
auto& vm = global_object.vm();
auto value = holder->get(key);
if (vm.exception())
return {};
auto value = TRY_OR_DISCARD(holder->get(key));
if (value.is_object() || value.is_bigint()) {
auto* value_object = value.to_object(global_object);
if (vm.exception())
return {};
auto to_json = value_object->get(vm.names.toJSON);
if (vm.exception())
return {};
auto to_json = TRY_OR_DISCARD(value_object->get(vm.names.toJSON));
if (to_json.is_function())
value = TRY_OR_DISCARD(vm.call(to_json.as_function(), value, js_string(vm, key.to_string())));
}
@ -465,9 +459,7 @@ Array* JSONObject::parse_json_array(GlobalObject& global_object, const JsonArray
Value JSONObject::internalize_json_property(GlobalObject& global_object, Object* holder, PropertyName const& name, FunctionObject& reviver)
{
auto& vm = global_object.vm();
auto value = holder->get(name);
if (vm.exception())
return {};
auto value = TRY_OR_DISCARD(holder->get(name));
if (value.is_object()) {
auto is_array = TRY_OR_DISCARD(value.is_array(global_object));

View file

@ -54,9 +54,7 @@ Value MapConstructor::construct(FunctionObject& new_target)
if (vm.argument(0).is_nullish())
return map;
auto adder = map->get(vm.names.set);
if (vm.exception())
return {};
auto adder = TRY_OR_DISCARD(map->get(vm.names.set));
if (!adder.is_function()) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, "'set' property of Map");
return {};
@ -68,12 +66,14 @@ Value MapConstructor::construct(FunctionObject& new_target)
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, String::formatted("Iterator value {}", iterator_value.to_string_without_side_effects()));
return IterationDecision::Break;
}
auto key = iterator_value.as_object().get(0);
if (vm.exception())
auto key_or_error = iterator_value.as_object().get(0);
if (key_or_error.is_error())
return IterationDecision::Break;
auto value = iterator_value.as_object().get(1);
if (vm.exception())
auto key = key_or_error.release_value();
auto value_or_error = iterator_value.as_object().get(1);
if (value_or_error.is_error())
return IterationDecision::Break;
auto value = value_or_error.release_value();
(void)vm.call(adder.as_function(), Value(map), key, value);
return vm.exception() ? IterationDecision::Break : IterationDecision::Continue;
});

View file

@ -34,7 +34,7 @@ void MapPrototype::initialize(GlobalObject& global_object)
define_native_accessor(vm.names.size, size_getter, {}, Attribute::Configurable);
define_direct_property(*vm.well_known_symbol_iterator(), Object::get(vm.names.entries), attr);
define_direct_property(*vm.well_known_symbol_iterator(), get_without_side_effects(vm.names.entries), attr);
define_direct_property(*vm.well_known_symbol_to_string_tag(), js_string(global_object.heap(), vm.names.Map.as_string()), Attribute::Configurable);
}

View file

@ -41,8 +41,8 @@ void NumberConstructor::initialize(GlobalObject& global_object)
define_native_function(vm.names.isInteger, is_integer, 1, attr);
define_native_function(vm.names.isNaN, is_nan, 1, attr);
define_native_function(vm.names.isSafeInteger, is_safe_integer, 1, attr);
define_direct_property(vm.names.parseInt, global_object.get(vm.names.parseInt), attr);
define_direct_property(vm.names.parseFloat, global_object.get(vm.names.parseFloat), attr);
define_direct_property(vm.names.parseInt, global_object.get_without_side_effects(vm.names.parseInt), attr);
define_direct_property(vm.names.parseFloat, global_object.get_without_side_effects(vm.names.parseFloat), attr);
define_direct_property(vm.names.EPSILON, Value(EPSILON_VALUE), 0);
define_direct_property(vm.names.MAX_VALUE, Value(NumericLimits<double>::max()), 0);
define_direct_property(vm.names.MIN_VALUE, Value(NumericLimits<double>::min()), 0);

View file

@ -77,7 +77,7 @@ ThrowCompletionOr<bool> Object::is_extensible() const
// 7.3 Operations on Objects, https://tc39.es/ecma262/#sec-operations-on-objects
// 7.3.2 Get ( O, P ), https://tc39.es/ecma262/#sec-get-o-p
Value Object::get(PropertyName const& property_name) const
ThrowCompletionOr<Value> Object::get(PropertyName const& property_name) const
{
// 1. Assert: Type(O) is Object.
@ -85,7 +85,7 @@ Value Object::get(PropertyName const& property_name) const
VERIFY(property_name.is_valid());
// 3. Return ? O.[[Get]](P, O).
return TRY_OR_DISCARD(internal_get(property_name, this));
return TRY(internal_get(property_name, this));
}
// 7.3.3 GetV ( V, P ) is defined as Value::get().
@ -401,7 +401,6 @@ MarkedValueList Object::enumerable_own_property_names(PropertyKind kind) const
// NOTE: This has been flattened for readability, so some `else` branches in the
// spec text have been replaced with `continue`s in the loop below.
auto& vm = this->vm();
auto& global_object = this->global_object();
// 1. Assert: Type(O) is Object.
@ -438,9 +437,10 @@ MarkedValueList Object::enumerable_own_property_names(PropertyKind kind) const
// 2. Else,
// a. Let value be ? Get(O, key).
auto value = get(property_name);
if (vm.exception())
auto value_or_error = get(property_name);
if (value_or_error.is_error())
return MarkedValueList { heap() };
auto value = value_or_error.release_value();
// b. If kind is value, append value to properties.
if (kind == PropertyKind::Value) {
@ -481,9 +481,7 @@ ThrowCompletionOr<Object*> Object::copy_data_properties(Value source, HashTable<
auto desc = TRY(from_object->internal_get_own_property(next_key));
if (desc.has_value() && desc->attributes().is_enumerable()) {
auto prop_value = from_object->get(next_key);
if (auto* thrown_exception = vm().exception())
return JS::throw_completion(thrown_exception->value());
auto prop_value = TRY(from_object->get(next_key));
create_data_property_or_throw(next_key, prop_value);
if (auto* thrown_exception = vm().exception())
return JS::throw_completion(thrown_exception->value());
@ -1096,9 +1094,7 @@ Object* Object::define_properties(Value properties)
// b. If propDesc is not undefined and propDesc.[[Enumerable]] is true, then
if (property_descriptor.has_value() && *property_descriptor->enumerable) {
// i. Let descObj be ? Get(props, nextKey).
auto descriptor_object = props->get(property_name);
if (vm.exception())
return {};
auto descriptor_object = TRY_OR_DISCARD(props->get(property_name));
// ii. Let desc be ? ToPropertyDescriptor(descObj).
auto descriptor = to_property_descriptor(global_object, descriptor_object);
@ -1159,9 +1155,7 @@ ThrowCompletionOr<Value> Object::ordinary_to_primitive(Value::PreferredType pref
// 3. For each element name of methodNames, do
for (auto& method_name : method_names) {
// a. Let method be ? Get(O, name).
auto method = get(method_name);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto method = TRY(get(method_name));
// b. If IsCallable(method) is true, then
if (method.is_function()) {

View file

@ -75,7 +75,7 @@ public:
// 7.3 Operations on Objects, https://tc39.es/ecma262/#sec-operations-on-objects
Value get(PropertyName const&) const;
ThrowCompletionOr<Value> get(PropertyName const&) const;
bool set(PropertyName const&, Value, ShouldThrowExceptions);
bool create_data_property(PropertyName const&, Value);
bool create_method_property(PropertyName const&, Value);

View file

@ -245,12 +245,14 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::from_entries)
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, String::formatted("Iterator value {}", iterator_value.to_string_without_side_effects()));
return IterationDecision::Break;
}
auto key = iterator_value.as_object().get(0);
if (vm.exception())
auto key_or_error = iterator_value.as_object().get(0);
if (key_or_error.is_error())
return IterationDecision::Break;
auto value = iterator_value.as_object().get(1);
if (vm.exception())
auto key = key_or_error.release_value();
auto value_or_error = iterator_value.as_object().get(1);
if (value_or_error.is_error())
return IterationDecision::Break;
auto value = value_or_error.release_value();
auto property_key = key.to_property_key(global_object);
if (vm.exception())
return IterationDecision::Break;
@ -484,9 +486,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::assign)
continue;
// a. Let propValue be ? Get(from, nextKey).
auto prop_value = from->get(property_name);
if (vm.exception())
return {};
auto prop_value = TRY_OR_DISCARD(from->get(property_name));
// b. Perform ? Set(to, nextKey, propValue, true).
to->set(property_name, prop_value, Object::ShouldThrowExceptions::Yes);

View file

@ -35,13 +35,9 @@ bool ObjectEnvironment::has_binding(FlyString const& name) const
return false;
if (!m_with_environment)
return true;
auto unscopables = m_binding_object.get(*vm.well_known_symbol_unscopables());
if (vm.exception())
return {};
auto unscopables = TRY_OR_DISCARD(m_binding_object.get(*vm.well_known_symbol_unscopables()));
if (unscopables.is_object()) {
auto blocked = unscopables.as_object().get(name);
if (vm.exception())
return {};
auto blocked = TRY_OR_DISCARD(unscopables.as_object().get(name));
if (blocked.to_boolean())
return false;
}
@ -110,7 +106,7 @@ Value ObjectEnvironment::get_binding_value(GlobalObject& global_object, FlyStrin
global_object.vm().throw_exception<ReferenceError>(global_object, ErrorType::UnknownIdentifier, name);
return {};
}
return m_binding_object.get(name);
return TRY_OR_DISCARD(m_binding_object.get(name));
}
// 9.1.1.2.7 DeleteBinding ( N ), https://tc39.es/ecma262/#sec-object-environment-records-deletebinding-n

View file

@ -124,9 +124,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_string)
builtin_tag = "Object";
// 15. Let tag be ? Get(O, @@toStringTag).
auto to_string_tag = object->get(*vm.well_known_symbol_to_string_tag());
if (vm.exception())
return {};
auto to_string_tag = TRY_OR_DISCARD(object->get(*vm.well_known_symbol_to_string_tag()));
// Optimization: Instead of creating another PrimitiveString from builtin_tag, we separate tag and to_string_tag and add an additional branch to step 16.
String tag;

View file

@ -23,9 +23,7 @@ Object* promise_resolve(GlobalObject& global_object, Object& constructor, Value
{
auto& vm = global_object.vm();
if (value.is_object() && is<Promise>(value.as_object())) {
auto value_constructor = value.as_object().get(vm.names.constructor);
if (vm.exception())
return nullptr;
auto value_constructor = TRY_OR_DISCARD(value.as_object().get(vm.names.constructor));
if (same_value(value_constructor, &constructor))
return &static_cast<Promise&>(value.as_object());
}
@ -72,14 +70,14 @@ Promise::ResolvingFunctions Promise::create_resolving_functions()
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / PromiseResolvingFunction]: Resolution is not an object, fulfilling with {}", &promise, resolution);
return promise.fulfill(resolution);
}
auto then_action = resolution.as_object().get(vm.names.then);
if (vm.exception()) {
auto then = resolution.as_object().get(vm.names.then);
if (then.is_throw_completion()) {
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / PromiseResolvingFunction]: Exception while getting 'then' property, rejecting with error", &promise);
auto error = vm.exception()->value();
vm.clear_exception();
vm.stop_unwind();
return promise.reject(error);
return promise.reject(then.throw_completion().value());
}
auto then_action = then.release_value();
if (!then_action.is_function()) {
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / PromiseResolvingFunction]: Then action is not a function, fulfilling with {}", &promise, resolution);
return promise.fulfill(resolution);

View file

@ -88,45 +88,35 @@ PropertyDescriptor to_property_descriptor(GlobalObject& global_object, Value arg
if (vm.exception())
return {};
if (has_enumerable) {
auto enumerable = object.get(vm.names.enumerable);
if (vm.exception())
return {};
auto enumerable = TRY_OR_DISCARD(object.get(vm.names.enumerable));
descriptor.enumerable = enumerable.to_boolean();
}
auto has_configurable = object.has_property(vm.names.configurable);
if (vm.exception())
return {};
if (has_configurable) {
auto configurable = object.get(vm.names.configurable);
if (vm.exception())
return {};
auto configurable = TRY_OR_DISCARD(object.get(vm.names.configurable));
descriptor.configurable = configurable.to_boolean();
}
auto has_value = object.has_property(vm.names.value);
if (vm.exception())
return {};
if (has_value) {
auto value = object.get(vm.names.value);
if (vm.exception())
return {};
auto value = TRY_OR_DISCARD(object.get(vm.names.value));
descriptor.value = value;
}
auto has_writable = object.has_property(vm.names.writable);
if (vm.exception())
return {};
if (has_writable) {
auto writable = object.get(vm.names.writable);
if (vm.exception())
return {};
auto writable = TRY_OR_DISCARD(object.get(vm.names.writable));
descriptor.writable = writable.to_boolean();
}
auto has_get = object.has_property(vm.names.get);
if (vm.exception())
return {};
if (has_get) {
auto getter = object.get(vm.names.get);
if (vm.exception())
return {};
auto getter = TRY_OR_DISCARD(object.get(vm.names.get));
if (!getter.is_function() && !getter.is_undefined()) {
vm.throw_exception<TypeError>(global_object, ErrorType::AccessorBadField, "get");
return {};
@ -137,9 +127,7 @@ PropertyDescriptor to_property_descriptor(GlobalObject& global_object, Value arg
if (vm.exception())
return {};
if (has_set) {
auto setter = object.get(vm.names.set);
if (vm.exception())
return {};
auto setter = TRY_OR_DISCARD(object.get(vm.names.set));
if (!setter.is_function() && !setter.is_undefined()) {
vm.throw_exception<TypeError>(global_object, ErrorType::AccessorBadField, "set");
return {};

View file

@ -72,7 +72,7 @@ Value Reference::get_value(GlobalObject& global_object) const
auto* base_obj = m_base_value.to_object(global_object);
if (!base_obj)
return {};
return base_obj->get(m_name);
return TRY_OR_DISCARD(base_obj->get(m_name));
}
VERIFY(m_base_type == BaseType::Environment);

View file

@ -45,10 +45,7 @@ Value RegExpConstructor::call()
bool pattern_is_regexp = TRY_OR_DISCARD(pattern.is_regexp(global_object));
if (pattern_is_regexp && flags.is_undefined()) {
auto pattern_constructor = pattern.as_object().get(vm.names.constructor);
if (vm.exception())
return {};
auto pattern_constructor = TRY_OR_DISCARD(pattern.as_object().get(vm.names.constructor));
if (same_value(this, pattern_constructor))
return pattern;
}
@ -79,14 +76,10 @@ Value RegExpConstructor::construct(FunctionObject&)
else
flags_value = flags;
} else if (pattern_is_regexp) {
pattern_value = pattern.as_object().get(vm.names.source);
if (vm.exception())
return {};
pattern_value = TRY_OR_DISCARD(pattern.as_object().get(vm.names.source));
if (flags.is_undefined()) {
flags_value = pattern.as_object().get(vm.names.flags);
if (vm.exception())
return {};
flags_value = TRY_OR_DISCARD(pattern.as_object().get(vm.names.flags));
} else {
flags_value = flags;
}

View file

@ -78,19 +78,19 @@ size_t advance_string_index(Utf16View const& string, size_t index, bool unicode)
return index + code_point.code_unit_count;
}
static void increment_last_index(GlobalObject& global_object, Object& regexp_object, Utf16View const& string, bool unicode)
static ThrowCompletionOr<void> increment_last_index(GlobalObject& global_object, Object& regexp_object, Utf16View const& string, bool unicode)
{
auto& vm = global_object.vm();
auto last_index_value = regexp_object.get(vm.names.lastIndex);
if (vm.exception())
return;
auto last_index = last_index_value.to_length(global_object);
if (vm.exception())
return;
auto last_index = TRY(regexp_object.get(vm.names.lastIndex)).to_length(global_object);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
last_index = advance_string_index(string, last_index, unicode);
regexp_object.set(vm.names.lastIndex, Value(last_index), Object::ShouldThrowExceptions::Yes);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
return {};
}
// 1.1.2.1 Match Records, https://tc39.es/proposal-regexp-match-indices/#sec-match-records
@ -172,10 +172,7 @@ static Value regexp_builtin_exec(GlobalObject& global_object, RegExpObject& rege
// FIXME: This should try using internal slots [[RegExpMatcher]], [[OriginalFlags]], etc.
auto& vm = global_object.vm();
auto last_index_value = regexp_object.get(vm.names.lastIndex);
if (vm.exception())
return {};
auto last_index = last_index_value.to_length(global_object);
auto last_index = TRY_OR_DISCARD(regexp_object.get(vm.names.lastIndex)).to_length(global_object);
if (vm.exception())
return {};
@ -287,10 +284,7 @@ Value regexp_exec(GlobalObject& global_object, Object& regexp_object, Utf16Strin
{
auto& vm = global_object.vm();
auto exec = regexp_object.get(vm.names.exec);
if (vm.exception())
return {};
auto exec = TRY_OR_DISCARD(regexp_object.get(vm.names.exec));
if (exec.is_function()) {
auto result = TRY_OR_DISCARD(vm.call(exec.as_function(), &regexp_object, js_string(vm, move(string))));
@ -344,11 +338,9 @@ JS_DEFINE_NATIVE_GETTER(RegExpPrototype::flags)
StringBuilder builder(8);
#define __JS_ENUMERATE(flagName, flag_name, flag_char) \
auto flag_##flag_name = regexp_object->get(vm.names.flagName); \
if (vm.exception()) \
return {}; \
if (flag_##flag_name.to_boolean()) \
#define __JS_ENUMERATE(flagName, flag_name, flag_char) \
auto flag_##flag_name = TRY_OR_DISCARD(regexp_object->get(vm.names.flagName)); \
if (flag_##flag_name.to_boolean()) \
builder.append(#flag_char);
JS_ENUMERATE_REGEXP_FLAGS
#undef __JS_ENUMERATE
@ -412,16 +404,12 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::to_string)
if (!regexp_object)
return {};
auto source_attr = regexp_object->get(vm.names.source);
if (vm.exception())
return {};
auto source_attr = TRY_OR_DISCARD(regexp_object->get(vm.names.source));
auto pattern = source_attr.to_string(global_object);
if (vm.exception())
return {};
auto flags_attr = regexp_object->get(vm.names.flags);
if (vm.exception())
return {};
auto flags_attr = TRY_OR_DISCARD(regexp_object->get(vm.names.flags));
auto flags = flags_attr.to_string(global_object);
if (vm.exception())
return {};
@ -440,10 +428,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match)
if (vm.exception())
return {};
auto global_value = regexp_object->get(vm.names.global);
if (vm.exception())
return {};
bool global = global_value.to_boolean();
bool global = TRY_OR_DISCARD(regexp_object->get(vm.names.global)).to_boolean();
if (!global) {
auto result = regexp_exec(global_object, *regexp_object, move(string));
@ -460,10 +445,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match)
if (vm.exception())
return {};
auto unicode_value = regexp_object->get(vm.names.unicode);
if (vm.exception())
return {};
bool unicode = unicode_value.to_boolean();
bool unicode = TRY_OR_DISCARD(regexp_object->get(vm.names.unicode)).to_boolean();
size_t n = 0;
@ -481,9 +463,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match)
auto* result_object = result.to_object(global_object);
if (!result_object)
return {};
auto match_object = result_object->get(0);
if (vm.exception())
return {};
auto match_object = TRY_OR_DISCARD(result_object->get(0));
auto match_str = match_object.to_string(global_object);
if (vm.exception())
return {};
@ -492,11 +472,8 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match)
if (vm.exception())
return {};
if (match_str.is_empty()) {
increment_last_index(global_object, *regexp_object, string.view(), unicode);
if (vm.exception())
return {};
}
if (match_str.is_empty())
TRY_OR_DISCARD(increment_last_index(global_object, *regexp_object, string.view(), unicode));
++n;
}
@ -515,10 +492,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match_all)
auto* constructor = TRY_OR_DISCARD(species_constructor(global_object, *regexp_object, *global_object.regexp_constructor()));
auto flags_value = regexp_object->get(vm.names.flags);
if (vm.exception())
return {};
auto flags = flags_value.to_string(global_object);
auto flags = TRY_OR_DISCARD(regexp_object->get(vm.names.flags)).to_string(global_object);
if (vm.exception())
return {};
@ -535,10 +509,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match_all)
if (!matcher)
return {};
auto last_index_value = regexp_object->get(vm.names.lastIndex);
if (vm.exception())
return {};
auto last_index = last_index_value.to_length(global_object);
auto last_index = TRY_OR_DISCARD(regexp_object->get(vm.names.lastIndex)).to_length(global_object);
if (vm.exception())
return {};
@ -573,18 +544,11 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_replace)
return {};
}
auto global_value = regexp_object->get(vm.names.global);
if (vm.exception())
return {};
bool global = global_value.to_boolean();
bool global = TRY_OR_DISCARD(regexp_object->get(vm.names.global)).to_boolean();
bool unicode = false;
if (global) {
auto unicode_value = regexp_object->get(vm.names.unicode);
if (vm.exception())
return {};
unicode = unicode_value.to_boolean();
unicode = TRY_OR_DISCARD(regexp_object->get(vm.names.unicode)).to_boolean();
regexp_object->set(vm.names.lastIndex, Value(0), Object::ShouldThrowExceptions::Yes);
if (vm.exception())
@ -608,18 +572,13 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_replace)
if (!global)
break;
auto match_object = result_object->get(0);
if (vm.exception())
return {};
auto match_object = TRY_OR_DISCARD(result_object->get(0));
String match_str = match_object.to_string(global_object);
if (vm.exception())
return {};
if (match_str.is_empty()) {
increment_last_index(global_object, *regexp_object, string_view, unicode);
if (vm.exception())
return {};
}
if (match_str.is_empty())
TRY_OR_DISCARD(increment_last_index(global_object, *regexp_object, string_view, unicode));
}
StringBuilder accumulated_result;
@ -630,18 +589,13 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_replace)
size_t result_length = TRY_OR_DISCARD(length_of_array_like(global_object, result));
size_t n_captures = result_length == 0 ? 0 : result_length - 1;
auto matched_value = result.get(0);
if (vm.exception())
return {};
auto matched_value = TRY_OR_DISCARD(result.get(0));
auto matched = matched_value.to_utf16_string(global_object);
if (vm.exception())
return {};
auto matched_length = matched.length_in_code_units();
auto position_value = result.get(vm.names.index);
if (vm.exception())
return {};
auto position_value = TRY_OR_DISCARD(result.get(vm.names.index));
double position = position_value.to_integer_or_infinity(global_object);
if (vm.exception())
return {};
@ -650,10 +604,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_replace)
MarkedValueList captures(vm.heap());
for (size_t n = 1; n <= n_captures; ++n) {
auto capture = result.get(n);
if (vm.exception())
return {};
auto capture = TRY_OR_DISCARD(result.get(n));
if (!capture.is_undefined()) {
auto capture_string = capture.to_string(global_object);
if (vm.exception())
@ -667,9 +618,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_replace)
captures.append(move(capture));
}
auto named_captures = result.get(vm.names.groups);
if (vm.exception())
return {};
auto named_captures = TRY_OR_DISCARD(result.get(vm.names.groups));
String replacement;
@ -728,9 +677,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_search)
if (vm.exception())
return {};
auto previous_last_index = regexp_object->get(vm.names.lastIndex);
if (vm.exception())
return {};
auto previous_last_index = TRY_OR_DISCARD(regexp_object->get(vm.names.lastIndex));
if (!same_value(previous_last_index, Value(0))) {
regexp_object->set(vm.names.lastIndex, Value(0), Object::ShouldThrowExceptions::Yes);
if (vm.exception())
@ -741,9 +688,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_search)
if (vm.exception())
return {};
auto current_last_index = regexp_object->get(vm.names.lastIndex);
if (vm.exception())
return {};
auto current_last_index = TRY_OR_DISCARD(regexp_object->get(vm.names.lastIndex));
if (!same_value(current_last_index, previous_last_index)) {
regexp_object->set(vm.names.lastIndex, previous_last_index, Object::ShouldThrowExceptions::Yes);
if (vm.exception())
@ -757,11 +702,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_search)
if (!result_object)
return {};
auto index = result_object->get(vm.names.index);
if (vm.exception())
return {};
return index;
return TRY_OR_DISCARD(result_object->get(vm.names.index));
}
// 22.2.5.13 RegExp.prototype [ @@split ] ( string, limit ), https://tc39.es/ecma262/#sec-regexp.prototype-@@split
@ -778,10 +719,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split)
auto* constructor = TRY_OR_DISCARD(species_constructor(global_object, *regexp_object, *global_object.regexp_constructor()));
auto flags_object = regexp_object->get(vm.names.flags);
if (vm.exception())
return {};
auto flags = flags_object.to_string(global_object);
auto flags = TRY_OR_DISCARD(regexp_object->get(vm.names.flags)).to_string(global_object);
if (vm.exception())
return {};
@ -836,10 +774,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split)
continue;
}
auto last_index_value = splitter->get(vm.names.lastIndex);
if (vm.exception())
return {};
auto last_index = last_index_value.to_length(global_object); // 'e' in the spec.
auto last_index = TRY_OR_DISCARD(splitter->get(vm.names.lastIndex)).to_length(global_object); // 'e' in the spec.
if (vm.exception())
return {};
last_index = min(last_index, string_view.length_in_code_units());
@ -865,10 +800,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split)
--number_of_captures;
for (size_t i = 1; i <= number_of_captures; ++i) {
auto next_capture = result_object->get(i);
if (vm.exception())
return {};
auto next_capture = TRY_OR_DISCARD(result_object->get(i));
array->create_data_property_or_throw(array_length, next_capture);
if (++array_length == limit)
return array;

View file

@ -57,18 +57,13 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpStringIteratorPrototype::next)
auto* match_object = match.to_object(global_object);
if (!match_object)
return {};
auto match_string_value = match_object->get(0);
if (vm.exception())
return {};
auto match_string_value = TRY_OR_DISCARD(match_object->get(0));
auto match_string = match_string_value.to_string(global_object);
if (vm.exception())
return {};
if (match_string.is_empty()) {
auto last_index_value = iterator->regexp_object().get(vm.names.lastIndex);
if (vm.exception())
return {};
auto last_index = last_index_value.to_length(global_object);
auto last_index = TRY_OR_DISCARD(iterator->regexp_object().get(vm.names.lastIndex)).to_length(global_object);
if (vm.exception())
return {};

View file

@ -54,9 +54,7 @@ Value SetConstructor::construct(FunctionObject& new_target)
if (vm.argument(0).is_nullish())
return set;
auto adder = set->get(vm.names.add);
if (vm.exception())
return {};
auto adder = TRY_OR_DISCARD(set->get(vm.names.add));
if (!adder.is_function()) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, "'add' property of Set");
return {};

View file

@ -31,10 +31,10 @@ void SetPrototype::initialize(GlobalObject& global_object)
define_native_function(vm.names.values, values, 0, attr);
define_native_accessor(vm.names.size, size_getter, {}, Attribute::Configurable);
define_direct_property(vm.names.keys, get(vm.names.values), attr);
define_direct_property(vm.names.keys, get_without_side_effects(vm.names.values), attr);
// 24.2.3.11 Set.prototype [ @@iterator ] ( ), https://tc39.es/ecma262/#sec-set.prototype-@@iterator
define_direct_property(*vm.well_known_symbol_iterator(), get(vm.names.values), attr);
define_direct_property(*vm.well_known_symbol_iterator(), get_without_side_effects(vm.names.values), attr);
// 24.2.3.12 Set.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-set.prototype-@@tostringtag
define_direct_property(*vm.well_known_symbol_to_string_tag(), js_string(vm, vm.names.Set.as_string()), Attribute::Configurable);

View file

@ -78,11 +78,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringConstructor::raw)
if (vm.exception())
return {};
auto raw_value = cooked->get(vm.names.raw);
if (vm.exception())
return {};
auto* raw = raw_value.to_object(global_object);
auto* raw = TRY_OR_DISCARD(cooked->get(vm.names.raw)).to_object(global_object);
if (vm.exception())
return {};
@ -98,10 +94,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringConstructor::raw)
StringBuilder builder;
for (size_t i = 0; i < literal_segments; ++i) {
auto next_key = String::number(i);
auto next_segment_value = raw->get(next_key);
if (vm.exception())
return {};
auto next_segment = next_segment_value.to_string(global_object);
auto next_segment = TRY_OR_DISCARD(raw->get(next_key)).to_string(global_object);
if (vm.exception())
return {};

View file

@ -880,9 +880,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::match_all)
if (!regexp.is_nullish()) {
auto is_regexp = TRY_OR_DISCARD(regexp.is_regexp(global_object));
if (is_regexp) {
auto flags = regexp.as_object().get("flags");
if (vm.exception())
return {};
auto flags = TRY_OR_DISCARD(regexp.as_object().get("flags"));
auto flags_object = TRY_OR_DISCARD(require_object_coercible(global_object, flags));
auto flags_string = flags_object.to_string(global_object);
if (vm.exception())
@ -970,9 +968,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::replace_all)
bool is_regexp = TRY_OR_DISCARD(search_value.is_regexp(global_object));
if (is_regexp) {
auto flags = search_value.as_object().get(vm.names.flags);
if (vm.exception())
return {};
auto flags = TRY_OR_DISCARD(search_value.as_object().get(vm.names.flags));
auto flags_object = TRY_OR_DISCARD(require_object_coercible(global_object, flags));
auto flags_string = flags_object.to_string(global_object);
if (vm.exception())

View file

@ -113,9 +113,7 @@ ThrowCompletionOr<Value> get_option(GlobalObject& global_object, Object const& o
// 2. Assert: Each element of types is Boolean, String, or Number.
// 3. Let value be ? Get(options, property).
auto value = options.get(property);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto value = TRY(options.get(property));
// 4. If value is undefined, return fallback.
if (value.is_undefined())
@ -1051,9 +1049,7 @@ ThrowCompletionOr<Object*> prepare_temporal_fields(GlobalObject& global_object,
// 3. For each value property of fieldNames, do
for (auto& property : field_names) {
// a. Let value be ? Get(fields, property).
auto value = fields.get(property);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto value = TRY(fields.get(property));
// b. If value is undefined, then
if (value.is_undefined()) {

View file

@ -332,9 +332,7 @@ ThrowCompletionOr<Object*> to_temporal_calendar(GlobalObject& global_object, Val
return &temporal_calendar_like_object;
// c. Set temporalCalendarLike to ? Get(temporalCalendarLike, "calendar").
temporal_calendar_like = temporal_calendar_like_object.get(vm.names.calendar);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
temporal_calendar_like = TRY(temporal_calendar_like_object.get(vm.names.calendar));
// d. If Type(temporalCalendarLike) is Object and ? HasProperty(temporalCalendarLike, "calendar") is false, return temporalCalendarLike.
if (temporal_calendar_like.is_object()) {
@ -394,9 +392,7 @@ ThrowCompletionOr<Object*> get_temporal_calendar_with_iso_default(GlobalObject&
return &static_cast<ZonedDateTime&>(item).calendar();
// 2. Let calendar be ? Get(item, "calendar").
auto calendar = item.get(vm.names.calendar);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto calendar = TRY(item.get(vm.names.calendar));
// 3. Return ? ToTemporalCalendarWithISODefault(calendar).
return to_temporal_calendar_with_iso_default(global_object, calendar);
@ -690,14 +686,10 @@ ThrowCompletionOr<double> resolve_iso_month(GlobalObject& global_object, Object
auto& vm = global_object.vm();
// 1. Let month be ? Get(fields, "month").
auto month = fields.get(vm.names.month);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto month = TRY(fields.get(vm.names.month));
// 2. Let monthCode be ? Get(fields, "monthCode").
auto month_code = fields.get(vm.names.monthCode);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto month_code = TRY(fields.get(vm.names.monthCode));
// 3. If monthCode is undefined, then
if (month_code.is_undefined()) {
@ -760,9 +752,7 @@ ThrowCompletionOr<ISODate> iso_date_from_fields(GlobalObject& global_object, Obj
auto* prepared_fields = TRY(prepare_temporal_fields(global_object, fields, { "day", "month", "monthCode", "year" }, {}));
// 4. Let year be ? Get(fields, "year").
auto year = prepared_fields->get(vm.names.year);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto year = TRY(prepared_fields->get(vm.names.year));
// 5. If year is undefined, throw a TypeError exception.
if (year.is_undefined())
@ -772,9 +762,7 @@ ThrowCompletionOr<ISODate> iso_date_from_fields(GlobalObject& global_object, Obj
auto month = TRY(resolve_iso_month(global_object, *prepared_fields));
// 7. Let day be ? Get(fields, "day").
auto day = prepared_fields->get(vm.names.day);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto day = TRY(prepared_fields->get(vm.names.day));
// 8. If day is undefined, throw a TypeError exception.
if (day.is_undefined())
@ -798,9 +786,7 @@ ThrowCompletionOr<ISOYearMonth> iso_year_month_from_fields(GlobalObject& global_
auto* prepared_fields = TRY(prepare_temporal_fields(global_object, fields, { "month"sv, "monthCode"sv, "year"sv }, {}));
// 4. Let year be ? Get(fields, "year").
auto year = prepared_fields->get(vm.names.year);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto year = TRY(prepared_fields->get(vm.names.year));
// 5. If year is undefined, throw a TypeError exception.
if (year.is_undefined())
@ -830,19 +816,13 @@ ThrowCompletionOr<ISOMonthDay> iso_month_day_from_fields(GlobalObject& global_ob
auto* prepared_fields = TRY(prepare_temporal_fields(global_object, fields, { "day"sv, "month"sv, "monthCode"sv, "year"sv }, {}));
// 4. Let month be ? Get(fields, "month").
auto month_value = prepared_fields->get(vm.names.month);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto month_value = TRY(prepared_fields->get(vm.names.month));
// 5. Let monthCode be ? Get(fields, "monthCode").
auto month_code = prepared_fields->get(vm.names.monthCode);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto month_code = TRY(prepared_fields->get(vm.names.monthCode));
// 6. Let year be ? Get(fields, "year").
auto year = prepared_fields->get(vm.names.year);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto year = TRY(prepared_fields->get(vm.names.year));
// 7. If month is not undefined, and monthCode and year are both undefined, then
if (!month_value.is_undefined() && month_code.is_undefined() && year.is_undefined()) {
@ -854,9 +834,7 @@ ThrowCompletionOr<ISOMonthDay> iso_month_day_from_fields(GlobalObject& global_ob
auto month = TRY(resolve_iso_month(global_object, *prepared_fields));
// 9. Let day be ? Get(fields, "day").
auto day = prepared_fields->get(vm.names.day);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto day = TRY(prepared_fields->get(vm.names.day));
// 10. If day is undefined, throw a TypeError exception.
if (day.is_undefined())
@ -974,9 +952,7 @@ ThrowCompletionOr<Object*> default_merge_fields(GlobalObject& global_object, Obj
auto property_name = PropertyName::from_value(global_object, next_key);
// i. Let propValue be ? Get(fields, nextKey).
auto prop_value = fields.get(property_name);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto prop_value = TRY(fields.get(property_name));
// ii. If propValue is not undefined, then
if (!prop_value.is_undefined()) {
@ -999,9 +975,7 @@ ThrowCompletionOr<Object*> default_merge_fields(GlobalObject& global_object, Obj
auto property_name = PropertyName::from_value(global_object, next_key);
// a. Let propValue be ? Get(additionalFields, nextKey).
auto prop_value = additional_fields.get(property_name);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto prop_value = TRY(additional_fields.get(property_name));
// b. If propValue is not undefined, then
if (!prop_value.is_undefined()) {
@ -1016,9 +990,7 @@ ThrowCompletionOr<Object*> default_merge_fields(GlobalObject& global_object, Obj
// 6. If newKeys does not contain either "month" or "monthCode", then
if (!new_keys_contains_month_or_month_code_property) {
// a. Let month be ? Get(fields, "month").
auto month = fields.get(vm.names.month);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto month = TRY(fields.get(vm.names.month));
// b. If month is not undefined, then
if (!month.is_undefined()) {
@ -1027,9 +999,7 @@ ThrowCompletionOr<Object*> default_merge_fields(GlobalObject& global_object, Obj
}
// c. Let monthCode be ? Get(fields, "monthCode").
auto month_code = fields.get(vm.names.monthCode);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto month_code = TRY(fields.get(vm.names.monthCode));
// d. If monthCode is not undefined, then
if (!month_code.is_undefined()) {

View file

@ -89,9 +89,7 @@ ThrowCompletionOr<TemporalDuration> to_temporal_duration_record(GlobalObject& gl
// a. Let prop be the Property value of the current row.
// b. Let val be ? Get(temporalDurationLike, prop).
auto value = temporal_duration_like.get(property);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto value = TRY(temporal_duration_like.get(property));
// c. If val is undefined, then
if (value.is_undefined()) {
@ -194,9 +192,7 @@ ThrowCompletionOr<PartialDuration> to_partial_duration(GlobalObject& global_obje
// a. Let property be the Property value of the current row.
// b. Let value be ? Get(temporalDurationLike, property).
auto value = temporal_duration_like.as_object().get(property);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto value = TRY(temporal_duration_like.as_object().get(property));
// c. If value is not undefined, then
if (!value.is_undefined()) {

View file

@ -373,9 +373,7 @@ JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::to_string)
auto* options = TRY_OR_DISCARD(get_options_object(global_object, vm.argument(0)));
// 4. Let timeZone be ? Get(options, "timeZone").
auto time_zone = options->get(vm.names.timeZone);
if (vm.exception())
return {};
auto time_zone = TRY_OR_DISCARD(options->get(vm.names.timeZone));
// 5. If timeZone is not undefined, then
if (!time_zone.is_undefined()) {
@ -455,9 +453,7 @@ JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::to_zoned_date_time)
}
// 4. Let calendarLike be ? Get(item, "calendar").
auto calendar_like = item.as_object().get(vm.names.calendar);
if (vm.exception())
return {};
auto calendar_like = TRY_OR_DISCARD(item.as_object().get(vm.names.calendar));
// 5. If calendarLike is undefined, then
if (calendar_like.is_undefined()) {
@ -470,9 +466,7 @@ JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::to_zoned_date_time)
auto* calendar = TRY_OR_DISCARD(to_temporal_calendar(global_object, calendar_like));
// 7. Let temporalTimeZoneLike be ? Get(item, "timeZone").
auto temporal_time_zone_like = item.as_object().get(vm.names.timeZone);
if (vm.exception())
return {};
auto temporal_time_zone_like = TRY_OR_DISCARD(item.as_object().get(vm.names.timeZone));
// 8. If temporalTimeZoneLike is undefined, then
if (temporal_time_zone_like.is_undefined()) {
@ -502,9 +496,7 @@ JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::to_zoned_date_time_iso)
// 3. If Type(item) is Object, then
if (item.is_object()) {
// a. Let timeZoneProperty be ? Get(item, "timeZone").
auto time_zone_property = item.as_object().get(vm.names.timeZone);
if (vm.exception())
return {};
auto time_zone_property = TRY_OR_DISCARD(item.as_object().get(vm.names.timeZone));
// b. If timeZoneProperty is not undefined, then
if (!time_zone_property.is_undefined()) {

View file

@ -81,9 +81,7 @@ ThrowCompletionOr<PlainMonthDay*> to_temporal_month_day(GlobalObject& global_obj
calendar_absent = false;
} else {
// i. Let calendar be ? Get(item, "calendar").
auto calendar_value = item_object.get(vm.names.calendar);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto calendar_value = TRY(item_object.get(vm.names.calendar));
// ii. If calendar is undefined, then
// 1. Let calendarAbsent be true.
@ -102,19 +100,13 @@ ThrowCompletionOr<PlainMonthDay*> to_temporal_month_day(GlobalObject& global_obj
auto* fields = TRY(prepare_temporal_fields(global_object, item_object, field_names, {}));
// f. Let month be ? Get(fields, "month").
auto month = fields->get(vm.names.month);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto month = TRY(fields->get(vm.names.month));
// g. Let monthCode be ? Get(fields, "monthCode").
auto month_code = fields->get(vm.names.monthCode);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto month_code = TRY(fields->get(vm.names.monthCode));
// h. Let year be ? Get(fields, "year").
auto year = fields->get(vm.names.year);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto year = TRY(fields->get(vm.names.year));
// i. If calendarAbsent is true, and month is not undefined, and monthCode is undefined and year is undefined, then
if (calendar_absent && !month.is_undefined() && month_code.is_undefined() && year.is_undefined()) {

View file

@ -140,9 +140,7 @@ ThrowCompletionOr<PartialUnregulatedTemporalTime> to_partial_time(GlobalObject&
// a. Let property be the Property value of the current row.
// b. Let value be ? Get(temporalTimeLike, property).
auto value = temporal_time_like.get(property);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto value = TRY(temporal_time_like.get(property));
// c. If value is not undefined, then
if (!value.is_undefined()) {
@ -367,9 +365,7 @@ ThrowCompletionOr<UnregulatedTemporalTime> to_temporal_time_record(GlobalObject&
// a. Let property be the Property value of the current row.
// b. Let value be ? Get(temporalTimeLike, property).
auto value = temporal_time_like.get(property);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto value = TRY(temporal_time_like.get(property));
// c. If value is undefined, then
if (value.is_undefined()) {

View file

@ -163,9 +163,7 @@ JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::with)
TRY_OR_DISCARD(reject_temporal_calendar_type(global_object, temporal_time_like));
// 5. Let calendarProperty be ? Get(temporalTimeLike, "calendar").
auto calendar_property = temporal_time_like.get(vm.names.calendar);
if (vm.exception())
return {};
auto calendar_property = TRY_OR_DISCARD(temporal_time_like.get(vm.names.calendar));
// 6. If calendarProperty is not undefined, then
if (!calendar_property.is_undefined()) {
@ -175,9 +173,7 @@ JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::with)
}
// 7. Let timeZoneProperty be ? Get(temporalTimeLike, "timeZone").
auto time_zone_property = temporal_time_like.get(vm.names.timeZone);
if (vm.exception())
return {};
auto time_zone_property = TRY_OR_DISCARD(temporal_time_like.get(vm.names.timeZone));
// 8. If timeZoneProperty is not undefined, then
if (!time_zone_property.is_undefined()) {

View file

@ -333,9 +333,7 @@ ThrowCompletionOr<Object*> to_temporal_time_zone(GlobalObject& global_object, Va
return &temporal_time_zone_like.as_object();
// c. Set temporalTimeZoneLike to ? Get(temporalTimeZoneLike, "timeZone").
temporal_time_zone_like = temporal_time_zone_like.as_object().get(vm.names.timeZone);
if (auto* exception = vm.exception())
return throw_completion(exception->value());
temporal_time_zone_like = TRY(temporal_time_zone_like.as_object().get(vm.names.timeZone));
// d. If Type(temporalTimeZoneLike) is Object and ? HasProperty(temporalTimeZoneLike, "timeZone") is false, return temporalTimeZoneLike.
if (temporal_time_zone_like.is_object()) {

View file

@ -192,9 +192,10 @@ static void initialize_typed_array_from_array_like(GlobalObject& global_object,
typed_array.set_array_length(length);
for (size_t k = 0; k < length; k++) {
auto value = array_like.get(k);
if (vm.exception())
auto value_or_error = array_like.get(k);
if (value_or_error.is_error())
return;
auto value = value_or_error.release_value();
typed_array.set(k, value, Object::ShouldThrowExceptions::Yes);
if (vm.exception())
return;

View file

@ -114,9 +114,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayConstructor::from)
return {};
for (size_t k = 0; k < length; ++k) {
auto k_value = array_like->get(k);
if (vm.exception())
return {};
auto k_value = TRY_OR_DISCARD(array_like->get(k));
Value mapped_value;
if (map_fn)
mapped_value = TRY_OR_DISCARD(vm.call(*map_fn, this_arg, k_value, Value(k)));

View file

@ -118,9 +118,10 @@ static void for_each_item(VM& vm, GlobalObject& global_object, const String& nam
auto this_value = vm.argument(1);
for (size_t i = 0; i < initial_length; ++i) {
auto value = typed_array->get(i);
if (vm.exception())
auto value_or_error = typed_array->get(i);
if (value_or_error.is_error())
return;
auto value = value_or_error.release_value();
auto callback_result_or_error = vm.call(*callback_function, this_value, value, Value((i32)i), typed_array);
if (callback_result_or_error.is_error())
@ -147,9 +148,10 @@ static void for_each_item_from_last(VM& vm, GlobalObject& global_object, const S
auto this_value = vm.argument(1);
for (ssize_t i = (ssize_t)initial_length - 1; i >= 0; --i) {
auto value = typed_array->get(i);
if (vm.exception())
auto value_or_error = typed_array->get(i);
if (value_or_error.is_error())
return;
auto value = value_or_error.release_value();
auto callback_result_or_error = vm.call(*callback_function, this_value, value, Value((i32)i), typed_array);
if (callback_result_or_error.is_error())
@ -225,7 +227,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::at)
}
if (index.has_overflow() || index.value() >= length)
return js_undefined();
return typed_array->get(index.value());
return TRY_OR_DISCARD(typed_array->get(index.value()));
}
// 23.2.3.7 %TypedArray%.prototype.every ( callbackfn [ , thisArg ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.every
@ -404,7 +406,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::includes)
auto search_element = vm.argument(0);
for (; k < length; ++k) {
auto element_k = typed_array->get(k);
auto element_k = MUST(typed_array->get(k));
if (same_value_zero(search_element, element_k))
return Value(true);
@ -449,7 +451,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::index_of)
for (; k < length; ++k) {
auto k_present = typed_array->has_property(k);
if (k_present) {
auto element_k = typed_array->get(k);
auto element_k = MUST(typed_array->get(k));
if (is_strictly_equal(search_element, element_k))
return Value(k);
@ -497,7 +499,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::last_index_of)
for (; k >= 0; --k) {
auto k_present = typed_array->has_property(k);
if (k_present) {
auto element_k = typed_array->get(k);
auto element_k = MUST(typed_array->get(k));
if (is_strictly_equal(search_element, element_k))
return Value(k);
@ -530,12 +532,12 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reduce)
if (vm.argument_count() > 1) {
accumulator = vm.argument(1);
} else {
accumulator = typed_array->get(k);
accumulator = MUST(typed_array->get(k));
++k;
}
for (; k < length; ++k) {
auto k_value = typed_array->get(k);
auto k_value = MUST(typed_array->get(k));
accumulator = TRY_OR_DISCARD(vm.call(*callback_function, js_undefined(), accumulator, k_value, Value(k), typed_array));
}
@ -566,12 +568,12 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reduce_right)
if (vm.argument_count() > 1) {
accumulator = vm.argument(1);
} else {
accumulator = typed_array->get(k);
accumulator = MUST(typed_array->get(k));
--k;
}
for (; k >= 0; --k) {
auto k_value = typed_array->get(k);
auto k_value = MUST(typed_array->get(k));
accumulator = TRY_OR_DISCARD(vm.call(*callback_function, js_undefined(), accumulator, k_value, Value(k), typed_array));
}
@ -611,9 +613,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::join)
for (size_t i = 0; i < length; ++i) {
if (i > 0)
builder.append(separator);
auto value = typed_array->get(i);
if (vm.exception())
return {};
auto value = TRY_OR_DISCARD(typed_array->get(i));
if (value.is_nullish())
continue;
auto string = value.to_string(global_object);
@ -842,9 +842,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::set)
auto limit = checked_limit.value();
auto k = 0;
while (target_byte_index < limit) {
auto value = src->get(k);
if (vm.exception())
return {};
auto value = TRY_OR_DISCARD(src->get(k));
if (typed_array->content_type() == TypedArrayBase::ContentType::BigInt)
value = value.to_bigint(global_object);
else
@ -919,7 +917,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::slice)
if (typed_array->element_name() != new_array->element_name()) {
for (i32 n = 0; k < final; ++k, ++n) {
auto k_value = typed_array->get(k);
auto k_value = MUST(typed_array->get(k));
new_array->set(n, k_value, Object::ShouldThrowExceptions::Yes);
}
} else {
@ -1072,10 +1070,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::sort)
return {};
if (k_present) {
auto k_value = typed_array->get(k);
if (vm.exception())
return {};
auto k_value = TRY_OR_DISCARD(typed_array->get(k));
items.append(k_value);
}
}
@ -1178,11 +1173,11 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reverse)
// b. Let upperP be ! ToString(𝔽(upper)).
// d. Let lowerValue be ! Get(O, lowerP).
auto lower_value = typed_array->get(lower);
auto lower_value = MUST(typed_array->get(lower));
// c. Let lowerP be ! ToString(𝔽(lower)).
// e. Let upperValue be ! Get(O, upperP).
auto upper_value = typed_array->get(upper);
auto upper_value = MUST(typed_array->get(upper));
// f. Perform ! Set(O, lowerP, upperValue, true).
typed_array->set(lower, upper_value, Object::ShouldThrowExceptions::Yes);
@ -1406,7 +1401,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::filter)
for (size_t i = 0; i < initial_length; ++i) {
// a. Let Pk be ! ToString(𝔽(k)).
// b. Let kValue be ! Get(O, Pk).
auto value = typed_array->get(i);
auto value = MUST(typed_array->get(i));
// c. Let selected be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
auto callback_result = TRY_OR_DISCARD(vm.call(*callback_function, this_value, value, Value((i32)i), typed_array)).to_boolean();
@ -1477,7 +1472,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::map)
for (size_t i = 0; i < initial_length; ++i) {
// a. Let Pk be ! ToString(𝔽(k)).
// b. Let kValue be ! Get(O, Pk).
auto value = typed_array->get(i);
auto value = MUST(typed_array->get(i));
// c. Let mappedValue be ? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »).
auto mapped_value = TRY_OR_DISCARD(vm.call(*callback_function, this_value, value, Value((i32)i), typed_array));
@ -1507,9 +1502,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_locale_string)
for (u32 k = 0; k < length; ++k) {
if (k > 0)
builder.append(','); // NOTE: Until we implement ECMA-402 (Intl) this is implementation specific.
auto value = typed_array->get(k);
if (vm.exception())
return {};
auto value = TRY_OR_DISCARD(typed_array->get(k));
if (value.is_nullish())
continue;
auto locale_string_result = TRY_OR_DISCARD(value.invoke(global_object, vm.names.toLocaleString));

View file

@ -282,10 +282,7 @@ ThrowCompletionOr<void> VM::property_binding_initialization(BindingPattern const
if (auto* thrown_exception = exception())
return JS::throw_completion(thrown_exception->value());
auto value_to_assign = object->get(name);
if (auto* thrown_exception = exception())
return JS::throw_completion(thrown_exception->value());
auto value_to_assign = TRY(object->get(name));
if (property.initializer && value_to_assign.is_undefined()) {
value_to_assign = TRY(named_evaluation_if_anonymous_function(global_object, *property.initializer, identifier.string()));
}
@ -312,10 +309,7 @@ ThrowCompletionOr<void> VM::property_binding_initialization(BindingPattern const
if (auto* thrown_exception = exception())
return JS::throw_completion(thrown_exception->value());
auto value_to_assign = object->get(name);
if (auto* thrown_exception = exception())
return JS::throw_completion(thrown_exception->value());
auto value_to_assign = TRY(object->get(name));
if (property.initializer && value_to_assign.is_undefined()) {
if (auto* identifier_ptr = property.alias.get_pointer<NonnullRefPtr<Identifier>>())
value_to_assign = TRY(named_evaluation_if_anonymous_function(global_object, *property.initializer, (*identifier_ptr)->string()));
@ -378,19 +372,13 @@ ThrowCompletionOr<void> VM::iterator_binding_initialization(BindingPattern const
return JS::throw_completion(exception()->value());
}
auto done_property = next_object->get(names.done);
if (auto* thrown_exception = exception())
return JS::throw_completion(thrown_exception->value());
auto done_property = TRY(next_object->get(names.done));
if (done_property.to_boolean()) {
iterator_done = true;
break;
}
auto next_value = next_object->get(names.value);
if (auto* thrown_exception = exception())
return JS::throw_completion(thrown_exception->value());
auto next_value = TRY(next_object->get(names.value));
array->indexed_properties().append(next_value);
}
value = array;
@ -403,19 +391,17 @@ ThrowCompletionOr<void> VM::iterator_binding_initialization(BindingPattern const
return JS::throw_completion(exception()->value());
}
auto done_property = next_object->get(names.done);
if (auto* thrown_exception = exception())
return JS::throw_completion(thrown_exception->value());
auto done_property = TRY(next_object->get(names.done));
if (done_property.to_boolean()) {
iterator_done = true;
value = js_undefined();
} else {
value = next_object->get(names.value);
if (auto* thrown_exception = exception()) {
auto value_or_error = next_object->get(names.value);
if (value_or_error.is_throw_completion()) {
iterator_done = true;
return JS::throw_completion(thrown_exception->value());
return JS::throw_completion(value_or_error.release_error().value());
}
value = value_or_error.release_value();
}
} else {
value = js_undefined();
@ -574,9 +560,7 @@ Value VM::construct(FunctionObject& function, FunctionObject& new_target, Option
&& result.is_object()) {
verify_cast<FunctionEnvironment>(constructor_environment)->replace_this_binding(result);
auto prototype = new_target.get(names.prototype);
if (exception())
return {};
auto prototype = TRY_OR_DISCARD(new_target.get(names.prototype));
if (prototype.is_object())
TRY_OR_DISCARD(result.as_object().internal_set_prototype_of(&prototype.as_object()));
return result;

View file

@ -256,9 +256,7 @@ ThrowCompletionOr<bool> Value::is_regexp(GlobalObject& global_object) const
return false;
auto& vm = global_object.vm();
auto matcher = as_object().get(*vm.well_known_symbol_match());
if (vm.exception())
return false;
auto matcher = TRY(as_object().get(*vm.well_known_symbol_match()));
if (!matcher.is_undefined())
return matcher.to_boolean();
@ -1325,10 +1323,7 @@ Value ordinary_has_instance(GlobalObject& global_object, Value lhs, Value rhs)
return Value(false);
Object* lhs_object = &lhs.as_object();
auto rhs_prototype = rhs_function.get(vm.names.prototype);
if (vm.exception())
return {};
auto rhs_prototype = TRY_OR_DISCARD(rhs_function.get(vm.names.prototype));
if (!rhs_prototype.is_object()) {
vm.throw_exception<TypeError>(global_object, ErrorType::InstanceOfOperatorBadPrototype, rhs.to_string_without_side_effects());
return {};

View file

@ -52,9 +52,7 @@ Value WeakMapConstructor::construct(FunctionObject& new_target)
if (vm.argument(0).is_nullish())
return weak_map;
auto adder = weak_map->get(vm.names.set);
if (vm.exception())
return {};
auto adder = TRY_OR_DISCARD(weak_map->get(vm.names.set));
if (!adder.is_function()) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, "'set' property of WeakMap");
return {};
@ -66,12 +64,14 @@ Value WeakMapConstructor::construct(FunctionObject& new_target)
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, String::formatted("Iterator value {}", iterator_value.to_string_without_side_effects()));
return IterationDecision::Break;
}
auto key = iterator_value.as_object().get(0);
if (vm.exception())
auto key_or_error = iterator_value.as_object().get(0);
if (key_or_error.is_error())
return IterationDecision::Break;
auto value = iterator_value.as_object().get(1);
if (vm.exception())
auto key = key_or_error.release_value();
auto value_or_error = iterator_value.as_object().get(1);
if (value_or_error.is_error())
return IterationDecision::Break;
auto value = value_or_error.release_value();
auto result = vm.call(adder.as_function(), Value(weak_map), key, value);
return result.is_error() ? IterationDecision::Break : IterationDecision::Continue;
});

View file

@ -54,9 +54,7 @@ Value WeakSetConstructor::construct(FunctionObject& new_target)
if (vm.argument(0).is_nullish())
return weak_set;
auto adder = weak_set->get(vm.names.add);
if (vm.exception())
return {};
auto adder = TRY_OR_DISCARD(weak_set->get(vm.names.add));
if (!adder.is_function()) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, "'add' property of WeakSet");
return {};

View file

@ -239,8 +239,7 @@ inline AK::Result<NonnullRefPtr<JS::SourceTextModule>, ParserError> parse_module
inline Optional<JsonValue> get_test_results(JS::Interpreter& interpreter)
{
auto results = interpreter.global_object().get("__TestResults__");
VERIFY(!results.is_empty());
auto results = MUST(interpreter.global_object().get("__TestResults__"));
auto json_string = JS::JSONObject::stringify_impl(interpreter.global_object(), results, JS::js_undefined(), JS::js_undefined());
auto json = JsonValue::from_string(json_string);
@ -388,12 +387,11 @@ inline JSFileResult TestRunner::run_file_test(const String& test_path)
JSFileResult file_result { test_path.substring(m_test_root.length() + 1, test_path.length() - m_test_root.length() - 1) };
// Collect logged messages
auto user_output = interpreter->global_object().get("__UserOutput__");
VERIFY(!user_output.is_empty());
auto user_output = MUST(interpreter->global_object().get("__UserOutput__"));
auto& arr = user_output.as_array();
for (auto& entry : arr.indexed_properties()) {
auto message = arr.get(entry.index());
auto message = MUST(arr.get(entry.index()));
file_result.logged_messages.append(message.to_string_without_side_effects());
}

View file

@ -28,7 +28,7 @@ void NavigatorObject::initialize(JS::GlobalObject& global_object)
define_direct_property("appCodeName", js_string(heap, "Mozilla"), attr);
define_direct_property("appName", js_string(heap, "Netscape"), attr);
define_direct_property("appVersion", js_string(heap, "4.0"), attr);
define_direct_property("language", languages->get(0), attr);
define_direct_property("language", languages->get_without_side_effects(0), attr);
define_direct_property("languages", languages, attr);
define_direct_property("platform", js_string(heap, "SerenityOS"), attr);
define_direct_property("product", js_string(heap, "Gecko"), attr);

View file

@ -609,21 +609,15 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::scroll)
if (vm.exception())
return {};
auto left = options->get("left");
if (vm.exception())
return {};
auto left = TRY_OR_DISCARD(options->get("left"));
if (!left.is_undefined())
x_value = left;
auto top = options->get("top");
if (vm.exception())
return {};
auto top = TRY_OR_DISCARD(options->get("top"));
if (!top.is_undefined())
y_value = top;
auto behavior_string_value = options->get("behavior");
if (vm.exception())
return {};
auto behavior_string_value = TRY_OR_DISCARD(options->get("behavior"));
if (!behavior_string_value.is_undefined())
behavior_string = behavior_string_value.to_string(global_object);
if (vm.exception())
@ -684,16 +678,12 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::scroll_by)
options->set("behavior", JS::js_string(vm, "auto"), ShouldThrowExceptions::No);
}
auto left_value = options->get("left");
if (vm.exception())
return {};
auto left_value = TRY_OR_DISCARD(options->get("left"));
auto left = left_value.to_double(global_object);
if (vm.exception())
return {};
auto top_value = options->get("top");
if (vm.exception())
return {};
auto top_value = TRY_OR_DISCARD(options->get("top"));
auto top = top_value.to_double(global_object);
if (vm.exception())
return {};
@ -705,9 +695,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::scroll_by)
left = left + current_scroll_position.x();
top = top + current_scroll_position.y();
auto behavior_string_value = options->get("behavior");
if (vm.exception())
return {};
auto behavior_string_value = TRY_OR_DISCARD(options->get("behavior"));
auto behavior_string = behavior_string_value.is_undefined() ? "auto" : behavior_string_value.to_string(global_object);
if (vm.exception())
return {};

View file

@ -36,8 +36,8 @@ JS::Value WebAssemblyMemoryConstructor::construct(FunctionObject&)
if (vm.exception())
return {};
auto initial_value = descriptor->get_without_side_effects("initial");
auto maximum_value = descriptor->get_without_side_effects("maximum");
auto initial_value = TRY_OR_DISCARD(descriptor->get("initial"));
auto maximum_value = TRY_OR_DISCARD(descriptor->get("maximum"));
if (initial_value.is_empty()) {
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "Number");

View file

@ -164,16 +164,18 @@ Result<size_t, JS::Value> WebAssemblyObject::instantiate_module(Wasm::Module con
dbgln("Trying to resolve stuff because import object was specified");
for (const Wasm::Linker::Name& import_name : linker.unresolved_imports()) {
dbgln("Trying to resolve {}::{}", import_name.module, import_name.name);
auto value = import_object->get(import_name.module);
if (vm.exception())
auto value_or_error = import_object->get(import_name.module);
if (value_or_error.is_error())
break;
auto value = value_or_error.release_value();
auto object = value.to_object(global_object);
if (vm.exception())
break;
auto import_ = object->get(import_name.name);
if (vm.exception())
auto import_or_error = object->get(import_name.name);
if (import_or_error.is_error())
break;
auto import_ = import_or_error.release_value();
import_name.type.visit(
[&](Wasm::TypeIndex index) {
dbgln("Trying to resolve a function {}::{}, type index {}", import_name.module, import_name.name, index.value());

View file

@ -38,9 +38,7 @@ JS::Value WebAssemblyTableConstructor::construct(FunctionObject&)
if (vm.exception())
return {};
auto element_value = descriptor->get("element");
if (vm.exception())
return {};
auto element_value = TRY_OR_DISCARD(descriptor->get("element"));
if (!element_value.is_string()) {
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::InvalidHint, element_value.to_string_without_side_effects());
return {};
@ -58,12 +56,8 @@ JS::Value WebAssemblyTableConstructor::construct(FunctionObject&)
return {};
}
auto initial_value = descriptor->get("initial");
if (vm.exception())
return {};
auto maximum_value = descriptor->get("maximum");
if (vm.exception())
return {};
auto initial_value = TRY_OR_DISCARD(descriptor->get("initial"));
auto maximum_value = TRY_OR_DISCARD(descriptor->get("maximum"));
auto initial = initial_value.to_u32(global_object);
if (vm.exception())
@ -82,12 +76,9 @@ JS::Value WebAssemblyTableConstructor::construct(FunctionObject&)
return {};
}
auto value_value = descriptor->get("value");
if (vm.exception())
return {};
auto value_value = TRY_OR_DISCARD(descriptor->get("value"));
auto reference_value = [&]() -> Optional<Wasm::Value> {
if (value_value.is_empty() || value_value.is_undefined())
if (value_value.is_undefined())
return Wasm::Value(*reference_type, 0ull);
return to_webassembly_value(value_value, *reference_type, global_object);

View file

@ -38,7 +38,7 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyTablePrototype::grow)
auto initial_size = table->elements().size();
auto value_value = vm.argument(1);
auto reference_value = [&]() -> Optional<Wasm::Value> {
if (value_value.is_empty() || value_value.is_undefined())
if (value_value.is_undefined())
return Wasm::Value(table->type().element_type(), 0ull);
return to_webassembly_value(value_value, table->type().element_type(), global_object);
@ -111,7 +111,7 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyTablePrototype::set)
auto value_value = vm.argument(1);
auto reference_value = [&]() -> Optional<Wasm::Value> {
if (value_value.is_empty() || value_value.is_undefined())
if (value_value.is_undefined())
return Wasm::Value(table->type().element_type(), 0ull);
return to_webassembly_value(value_value, table->type().element_type(), global_object);

View file

@ -210,12 +210,13 @@ static void print_array(JS::Array& array, HashTable<JS::Object*>& seen_objects)
bool first = true;
for (auto it = array.indexed_properties().begin(false); it != array.indexed_properties().end(); ++it) {
print_separator(first);
auto value = array.get(it.index());
auto value_or_error = array.get(it.index());
// The V8 repl doesn't throw an exception here, and instead just
// prints 'undefined'. We may choose to replicate that behavior in
// the future, but for now lets just catch the error
if (vm->exception())
if (value_or_error.is_error())
return;
auto value = value_or_error.release_value();
print_value(value, seen_objects);
}
if (!first)
@ -230,12 +231,13 @@ static void print_object(JS::Object& object, HashTable<JS::Object*>& seen_object
for (auto& entry : object.indexed_properties()) {
print_separator(first);
out("\"\033[33;1m{}\033[0m\": ", entry.index());
auto value = object.get(entry.index());
auto value_or_error = object.get(entry.index());
// The V8 repl doesn't throw an exception here, and instead just
// prints 'undefined'. We may choose to replicate that behavior in
// the future, but for now lets just catch the error
if (vm->exception())
if (value_or_error.is_error())
return;
auto value = value_or_error.release_value();
print_value(value, seen_objects);
}
for (auto& it : object.shape().property_table_ordered()) {
@ -286,7 +288,7 @@ static void print_regexp_object(JS::Object const& object, HashTable<JS::Object*>
{
auto& regexp_object = static_cast<JS::RegExpObject const&>(object);
// Use RegExp.prototype.source rather than RegExpObject::pattern() so we get proper escaping
auto source = regexp_object.get("source").to_primitive_string(object.global_object())->string();
auto source = regexp_object.get_without_side_effects("source").to_primitive_string(object.global_object())->string();
print_type("RegExp");
out(" \033[34;1m/{}/{}\033[0m", source, regexp_object.flags());
}