Browse Source

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.
Linus Groh 3 years ago
parent
commit
b7e5f08e56
61 changed files with 326 additions and 686 deletions
  1. 4 3
      Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp
  2. 6 6
      Userland/Applications/Spreadsheet/Spreadsheet.cpp
  3. 1 1
      Userland/Applications/Spreadsheet/SpreadsheetModel.cpp
  4. 4 10
      Userland/Libraries/LibJS/AST.cpp
  5. 13 5
      Userland/Libraries/LibJS/Bytecode/Op.cpp
  6. 2 2
      Userland/Libraries/LibJS/MarkupGenerator.cpp
  7. 6 18
      Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp
  8. 2 2
      Userland/Libraries/LibJS/Runtime/ArgumentsObject.cpp
  9. 1 3
      Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp
  10. 2 3
      Userland/Libraries/LibJS/Runtime/ArrayIteratorPrototype.cpp
  11. 42 118
      Userland/Libraries/LibJS/Runtime/ArrayPrototype.cpp
  12. 1 1
      Userland/Libraries/LibJS/Runtime/DatePrototype.cpp
  13. 1 3
      Userland/Libraries/LibJS/Runtime/Error.cpp
  14. 2 6
      Userland/Libraries/LibJS/Runtime/ErrorPrototype.cpp
  15. 2 6
      Userland/Libraries/LibJS/Runtime/FunctionObject.cpp
  16. 7 6
      Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp
  17. 6 15
      Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp
  18. 4 12
      Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.cpp
  19. 15 20
      Userland/Libraries/LibJS/Runtime/IteratorOperations.cpp
  20. 4 12
      Userland/Libraries/LibJS/Runtime/JSONObject.cpp
  21. 7 7
      Userland/Libraries/LibJS/Runtime/MapConstructor.cpp
  22. 1 1
      Userland/Libraries/LibJS/Runtime/MapPrototype.cpp
  23. 2 2
      Userland/Libraries/LibJS/Runtime/NumberConstructor.cpp
  24. 8 14
      Userland/Libraries/LibJS/Runtime/Object.cpp
  25. 1 1
      Userland/Libraries/LibJS/Runtime/Object.h
  26. 7 7
      Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp
  27. 3 7
      Userland/Libraries/LibJS/Runtime/ObjectEnvironment.cpp
  28. 1 3
      Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp
  29. 5 7
      Userland/Libraries/LibJS/Runtime/Promise.cpp
  30. 6 18
      Userland/Libraries/LibJS/Runtime/PropertyDescriptor.cpp
  31. 1 1
      Userland/Libraries/LibJS/Runtime/Reference.cpp
  32. 3 10
      Userland/Libraries/LibJS/Runtime/RegExpConstructor.cpp
  33. 36 104
      Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp
  34. 2 7
      Userland/Libraries/LibJS/Runtime/RegExpStringIteratorPrototype.cpp
  35. 1 3
      Userland/Libraries/LibJS/Runtime/SetConstructor.cpp
  36. 2 2
      Userland/Libraries/LibJS/Runtime/SetPrototype.cpp
  37. 2 9
      Userland/Libraries/LibJS/Runtime/StringConstructor.cpp
  38. 2 6
      Userland/Libraries/LibJS/Runtime/StringPrototype.cpp
  39. 2 6
      Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp
  40. 15 45
      Userland/Libraries/LibJS/Runtime/Temporal/Calendar.cpp
  41. 2 6
      Userland/Libraries/LibJS/Runtime/Temporal/Duration.cpp
  42. 4 12
      Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.cpp
  43. 4 12
      Userland/Libraries/LibJS/Runtime/Temporal/PlainMonthDay.cpp
  44. 2 6
      Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp
  45. 2 6
      Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.cpp
  46. 1 3
      Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp
  47. 3 2
      Userland/Libraries/LibJS/Runtime/TypedArray.cpp
  48. 1 3
      Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp
  49. 23 30
      Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp
  50. 10 26
      Userland/Libraries/LibJS/Runtime/VM.cpp
  51. 2 7
      Userland/Libraries/LibJS/Runtime/Value.cpp
  52. 7 7
      Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp
  53. 1 3
      Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp
  54. 3 5
      Userland/Libraries/LibTest/JavaScriptTestRunner.h
  55. 1 1
      Userland/Libraries/LibWeb/Bindings/NavigatorObject.cpp
  56. 6 18
      Userland/Libraries/LibWeb/Bindings/WindowObject.cpp
  57. 2 2
      Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryConstructor.cpp
  58. 6 4
      Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp
  59. 5 14
      Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.cpp
  60. 2 2
      Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTablePrototype.cpp
  61. 7 5
      Userland/Utilities/js.cpp

+ 4 - 3
Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp

@@ -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);
 )~~~");
     }
 

+ 6 - 6
Userland/Applications/Spreadsheet/Spreadsheet.cpp

@@ -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;
 

+ 1 - 1
Userland/Applications/Spreadsheet/SpreadsheetModel.cpp

@@ -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();
                     }

+ 4 - 10
Userland/Libraries/LibJS/AST.cpp

@@ -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 {};
                     }

+ 13 - 5
Userland/Libraries/LibJS/Bytecode/Op.cpp

@@ -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();
     }
 }
 

+ 2 - 2
Userland/Libraries/LibJS/MarkupGenerator.cpp

@@ -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())

+ 6 - 18
Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp

@@ -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);

+ 2 - 2
Userland/Libraries/LibJS/Runtime/ArgumentsObject.cpp

@@ -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));
         }
     }
 

+ 1 - 3
Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp

@@ -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)));

+ 2 - 3
Userland/Libraries/LibJS/Runtime/ArrayIteratorPrototype.cpp

@@ -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);
 

+ 42 - 118
Userland/Libraries/LibJS/Runtime/ArrayPrototype.cpp

@@ -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()));
 }
 
 }

+ 1 - 1
Userland/Libraries/LibJS/Runtime/DatePrototype.cpp

@@ -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()

+ 1 - 3
Userland/Libraries/LibJS/Runtime/Error.cpp

@@ -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);

+ 2 - 6
Userland/Libraries/LibJS/Runtime/ErrorPrototype.cpp

@@ -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())

+ 2 - 6
Userland/Libraries/LibJS/Runtime/FunctionObject.cpp

@@ -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();
 

+ 7 - 6
Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp

@@ -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;
     };
 

+ 6 - 15
Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp

@@ -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));

+ 4 - 12
Userland/Libraries/LibJS/Runtime/Intl/NumberFormat.cpp

@@ -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);

+ 15 - 20
Userland/Libraries/LibJS/Runtime/IteratorOperations.cpp

@@ -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);

+ 4 - 12
Userland/Libraries/LibJS/Runtime/JSONObject.cpp

@@ -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));
 

+ 7 - 7
Userland/Libraries/LibJS/Runtime/MapConstructor.cpp

@@ -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;
     });

+ 1 - 1
Userland/Libraries/LibJS/Runtime/MapPrototype.cpp

@@ -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);
 }
 

+ 2 - 2
Userland/Libraries/LibJS/Runtime/NumberConstructor.cpp

@@ -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);

+ 8 - 14
Userland/Libraries/LibJS/Runtime/Object.cpp

@@ -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()) {

+ 1 - 1
Userland/Libraries/LibJS/Runtime/Object.h

@@ -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);

+ 7 - 7
Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp

@@ -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);

+ 3 - 7
Userland/Libraries/LibJS/Runtime/ObjectEnvironment.cpp

@@ -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

+ 1 - 3
Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp

@@ -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;

+ 5 - 7
Userland/Libraries/LibJS/Runtime/Promise.cpp

@@ -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);

+ 6 - 18
Userland/Libraries/LibJS/Runtime/PropertyDescriptor.cpp

@@ -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 {};

+ 1 - 1
Userland/Libraries/LibJS/Runtime/Reference.cpp

@@ -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);

+ 3 - 10
Userland/Libraries/LibJS/Runtime/RegExpConstructor.cpp

@@ -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;
         }

+ 36 - 104
Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp

@@ -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;

+ 2 - 7
Userland/Libraries/LibJS/Runtime/RegExpStringIteratorPrototype.cpp

@@ -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 {};
 

+ 1 - 3
Userland/Libraries/LibJS/Runtime/SetConstructor.cpp

@@ -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 {};

+ 2 - 2
Userland/Libraries/LibJS/Runtime/SetPrototype.cpp

@@ -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);

+ 2 - 9
Userland/Libraries/LibJS/Runtime/StringConstructor.cpp

@@ -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 {};
 

+ 2 - 6
Userland/Libraries/LibJS/Runtime/StringPrototype.cpp

@@ -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())

+ 2 - 6
Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp

@@ -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()) {

+ 15 - 45
Userland/Libraries/LibJS/Runtime/Temporal/Calendar.cpp

@@ -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()) {

+ 2 - 6
Userland/Libraries/LibJS/Runtime/Temporal/Duration.cpp

@@ -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()) {

+ 4 - 12
Userland/Libraries/LibJS/Runtime/Temporal/InstantPrototype.cpp

@@ -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()) {

+ 4 - 12
Userland/Libraries/LibJS/Runtime/Temporal/PlainMonthDay.cpp

@@ -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()) {

+ 2 - 6
Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp

@@ -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()) {

+ 2 - 6
Userland/Libraries/LibJS/Runtime/Temporal/PlainTimePrototype.cpp

@@ -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()) {

+ 1 - 3
Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp

@@ -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()) {

+ 3 - 2
Userland/Libraries/LibJS/Runtime/TypedArray.cpp

@@ -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;

+ 1 - 3
Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp

@@ -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)));

+ 23 - 30
Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp

@@ -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));

+ 10 - 26
Userland/Libraries/LibJS/Runtime/VM.cpp

@@ -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;

+ 2 - 7
Userland/Libraries/LibJS/Runtime/Value.cpp

@@ -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 {};

+ 7 - 7
Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp

@@ -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;
     });

+ 1 - 3
Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp

@@ -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 {};

+ 3 - 5
Userland/Libraries/LibTest/JavaScriptTestRunner.h

@@ -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());
     }
 

+ 1 - 1
Userland/Libraries/LibWeb/Bindings/NavigatorObject.cpp

@@ -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);

+ 6 - 18
Userland/Libraries/LibWeb/Bindings/WindowObject.cpp

@@ -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 {};

+ 2 - 2
Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryConstructor.cpp

@@ -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");

+ 6 - 4
Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp

@@ -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());

+ 5 - 14
Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.cpp

@@ -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);

+ 2 - 2
Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTablePrototype.cpp

@@ -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);

+ 7 - 5
Userland/Utilities/js.cpp

@@ -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());
 }