浏览代码

LibJS: Convert define_property_or_throw() to ThrowCompletionOr

Linus Groh 3 年之前
父节点
当前提交
fe86b04b42

+ 3 - 5
Userland/Libraries/LibJS/AST.cpp

@@ -1260,21 +1260,19 @@ ThrowCompletionOr<Value> ClassExpression::class_definition_evaluation(Interprete
 
         switch (method.kind()) {
         case ClassMethod::Kind::Method:
-            target.define_property_or_throw(property_key, { .value = method_value, .writable = true, .enumerable = false, .configurable = true });
+            TRY(target.define_property_or_throw(property_key, { .value = method_value, .writable = true, .enumerable = false, .configurable = true }));
             break;
         case ClassMethod::Kind::Getter:
             update_function_name(method_value, String::formatted("get {}", get_function_name(global_object, key)));
-            target.define_property_or_throw(property_key, { .get = &method_function, .enumerable = true, .configurable = true });
+            TRY(target.define_property_or_throw(property_key, { .get = &method_function, .enumerable = true, .configurable = true }));
             break;
         case ClassMethod::Kind::Setter:
             update_function_name(method_value, String::formatted("set {}", get_function_name(global_object, key)));
-            target.define_property_or_throw(property_key, { .set = &method_function, .enumerable = true, .configurable = true });
+            TRY(target.define_property_or_throw(property_key, { .set = &method_function, .enumerable = true, .configurable = true }));
             break;
         default:
             VERIFY_NOT_REACHED();
         }
-        if (auto* exception = interpreter.exception())
-            return throw_completion(exception->value());
     }
 
     for (auto& field : m_fields) {

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

@@ -684,8 +684,7 @@ Object* create_unmapped_arguments_object(GlobalObject& global_object, Span<Value
     object->set_has_parameter_map();
 
     // 4. Perform DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
-    object->define_property_or_throw(vm.names.length, { .value = Value(length), .writable = true, .enumerable = false, .configurable = true });
-    VERIFY(!vm.exception());
+    MUST(object->define_property_or_throw(vm.names.length, { .value = Value(length), .writable = true, .enumerable = false, .configurable = true }));
 
     // 5. Let index be 0.
     // 6. Repeat, while index < len,
@@ -701,13 +700,11 @@ Object* create_unmapped_arguments_object(GlobalObject& global_object, Span<Value
 
     // 7. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
     auto* array_prototype_values = global_object.array_prototype_values_function();
-    object->define_property_or_throw(*vm.well_known_symbol_iterator(), { .value = array_prototype_values, .writable = true, .enumerable = false, .configurable = true });
-    VERIFY(!vm.exception());
+    MUST(object->define_property_or_throw(*vm.well_known_symbol_iterator(), { .value = array_prototype_values, .writable = true, .enumerable = false, .configurable = true }));
 
     // 8. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Get]]: %ThrowTypeError%, [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false }).
     auto* throw_type_error = global_object.throw_type_error_function();
-    object->define_property_or_throw(vm.names.callee, { .get = throw_type_error, .set = throw_type_error, .enumerable = false, .configurable = false });
-    VERIFY(!vm.exception());
+    MUST(object->define_property_or_throw(vm.names.callee, { .get = throw_type_error, .set = throw_type_error, .enumerable = false, .configurable = false }));
 
     // 9. Return obj.
     return object;
@@ -747,8 +744,7 @@ Object* create_mapped_arguments_object(GlobalObject& global_object, FunctionObje
     }
 
     // 16. Perform ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
-    object->define_property_or_throw(vm.names.length, { .value = Value(length), .writable = true, .enumerable = false, .configurable = true });
-    VERIFY(!vm.exception());
+    MUST(object->define_property_or_throw(vm.names.length, { .value = Value(length), .writable = true, .enumerable = false, .configurable = true }));
 
     // 17. Let mappedNames be a new empty List.
     HashTable<FlyString> mapped_names;
@@ -787,12 +783,10 @@ Object* create_mapped_arguments_object(GlobalObject& global_object, FunctionObje
 
     // 20. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
     auto* array_prototype_values = global_object.array_prototype_values_function();
-    object->define_property_or_throw(*vm.well_known_symbol_iterator(), { .value = array_prototype_values, .writable = true, .enumerable = false, .configurable = true });
-    VERIFY(!vm.exception());
+    MUST(object->define_property_or_throw(*vm.well_known_symbol_iterator(), { .value = array_prototype_values, .writable = true, .enumerable = false, .configurable = true }));
 
     // 21. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Value]]: func, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
-    object->define_property_or_throw(vm.names.callee, { .value = &function, .writable = true, .enumerable = false, .configurable = true });
-    VERIFY(!vm.exception());
+    MUST(object->define_property_or_throw(vm.names.callee, { .value = &function, .writable = true, .enumerable = false, .configurable = true }));
 
     // 22. Return obj.
     return object;

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

@@ -57,7 +57,7 @@ Value AggregateErrorConstructor::construct(FunctionObject& new_target)
     if (vm.exception())
         return {};
 
-    aggregate_error->define_property_or_throw(vm.names.errors, { .value = Array::create_from(global_object, errors_list), .writable = true, .enumerable = false, .configurable = true });
+    MUST(aggregate_error->define_property_or_throw(vm.names.errors, { .value = Array::create_from(global_object, errors_list), .writable = true, .enumerable = false, .configurable = true }));
 
     return aggregate_error;
 }

+ 4 - 4
Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp

@@ -78,7 +78,7 @@ void ECMAScriptFunctionObject::initialize(GlobalObject& global_object)
         auto* prototype = vm.heap().allocate<Object>(global_object, *global_object.new_ordinary_function_prototype_object_shape());
         switch (m_kind) {
         case FunctionKind::Regular:
-            prototype->define_property_or_throw(vm.names.constructor, { .value = this, .writable = true, .enumerable = false, .configurable = true });
+            MUST(prototype->define_property_or_throw(vm.names.constructor, { .value = this, .writable = true, .enumerable = false, .configurable = true }));
             break;
         case FunctionKind::Generator:
             // prototype is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
@@ -87,8 +87,8 @@ void ECMAScriptFunctionObject::initialize(GlobalObject& global_object)
         }
         define_direct_property(vm.names.prototype, prototype, Attribute::Writable);
     }
-    define_property_or_throw(vm.names.length, { .value = Value(m_function_length), .writable = false, .enumerable = false, .configurable = true });
-    define_property_or_throw(vm.names.name, { .value = js_string(vm, m_name.is_null() ? "" : m_name), .writable = false, .enumerable = false, .configurable = true });
+    MUST(define_property_or_throw(vm.names.length, { .value = Value(m_function_length), .writable = false, .enumerable = false, .configurable = true }));
+    MUST(define_property_or_throw(vm.names.name, { .value = js_string(vm, m_name.is_null() ? "" : m_name), .writable = false, .enumerable = false, .configurable = true }));
 }
 
 ECMAScriptFunctionObject::~ECMAScriptFunctionObject()
@@ -428,7 +428,7 @@ void ECMAScriptFunctionObject::set_name(const FlyString& name)
     VERIFY(!name.is_null());
     auto& vm = this->vm();
     m_name = name;
-    auto success = define_property_or_throw(vm.names.name, { .value = js_string(vm, m_name), .writable = false, .enumerable = false, .configurable = true });
+    auto success = MUST(define_property_or_throw(vm.names.name, { .value = js_string(vm, m_name), .writable = false, .enumerable = false, .configurable = true }));
     VERIFY(success);
 }
 

+ 3 - 4
Userland/Libraries/LibJS/Runtime/GlobalEnvironment.cpp

@@ -187,7 +187,6 @@ void GlobalEnvironment::create_global_var_binding(FlyString const& name, bool ca
 // 9.1.1.4.18 CreateGlobalFunctionBinding ( N, V, D ), https://tc39.es/ecma262/#sec-createglobalfunctionbinding
 void GlobalEnvironment::create_global_function_binding(FlyString const& name, Value value, bool can_be_deleted)
 {
-    auto& vm = this->vm();
     auto& global_object = m_object_record->binding_object();
     auto existing_prop_or_error = global_object.internal_get_own_property(name);
     if (existing_prop_or_error.is_error())
@@ -198,10 +197,10 @@ void GlobalEnvironment::create_global_function_binding(FlyString const& name, Va
         desc = { .value = value, .writable = true, .enumerable = true, .configurable = can_be_deleted };
     else
         desc = { .value = value };
-    global_object.define_property_or_throw(name, desc);
-    if (vm.exception())
+    auto result_or_error = global_object.define_property_or_throw(name, desc);
+    if (result_or_error.is_error())
         return;
-    auto result_or_error = global_object.set(name, value, Object::ShouldThrowExceptions::Yes);
+    result_or_error = global_object.set(name, value, Object::ShouldThrowExceptions::Yes);
     if (result_or_error.is_error())
         return;
     if (!m_var_names.contains_slow(name))

+ 7 - 19
Userland/Libraries/LibJS/Runtime/Object.cpp

@@ -187,20 +187,16 @@ ThrowCompletionOr<bool> Object::create_non_enumerable_data_property_or_throw(Pro
 {
     VERIFY(!value.is_empty());
     VERIFY(property_name.is_valid());
-    auto& vm = this->vm();
 
     // 1. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
     auto new_description = PropertyDescriptor { .value = value, .writable = true, .enumerable = false, .configurable = true };
 
     // 2. Return ? DefinePropertyOrThrow(O, P, newDesc).
-    auto result = define_property_or_throw(property_name, new_description);
-    if (auto* exception = vm.exception())
-        return throw_completion(exception->value());
-    return result;
+    return define_property_or_throw(property_name, new_description);
 }
 
 // 7.3.8 DefinePropertyOrThrow ( O, P, desc ), https://tc39.es/ecma262/#sec-definepropertyorthrow
-bool Object::define_property_or_throw(PropertyName const& property_name, PropertyDescriptor const& property_descriptor)
+ThrowCompletionOr<bool> Object::define_property_or_throw(PropertyName const& property_name, PropertyDescriptor const& property_descriptor)
 {
     auto& vm = this->vm();
 
@@ -210,13 +206,12 @@ bool Object::define_property_or_throw(PropertyName const& property_name, Propert
     VERIFY(property_name.is_valid());
 
     // 3. Let success be ? O.[[DefineOwnProperty]](P, desc).
-    auto success = TRY_OR_DISCARD(internal_define_own_property(property_name, property_descriptor));
+    auto success = TRY(internal_define_own_property(property_name, property_descriptor));
 
     // 4. If success is false, throw a TypeError exception.
     if (!success) {
         // FIXME: Improve/contextualize error message
-        vm.throw_exception<TypeError>(global_object(), ErrorType::ObjectDefineOwnPropertyReturnedFalse);
-        return {};
+        return vm.throw_completion<TypeError>(global_object(), ErrorType::ObjectDefineOwnPropertyReturnedFalse);
     }
 
     // 5. Return success.
@@ -281,7 +276,6 @@ bool Object::has_own_property(PropertyName const& property_name) const
 // 7.3.15 SetIntegrityLevel ( O, level ), https://tc39.es/ecma262/#sec-setintegritylevel
 bool Object::set_integrity_level(IntegrityLevel level)
 {
-    auto& vm = this->vm();
     auto& global_object = this->global_object();
 
     // 1. Assert: Type(O) is Object.
@@ -306,9 +300,7 @@ bool Object::set_integrity_level(IntegrityLevel level)
             auto property_name = PropertyName::from_value(global_object, key);
 
             // i. Perform ? DefinePropertyOrThrow(O, k, PropertyDescriptor { [[Configurable]]: false }).
-            define_property_or_throw(property_name, { .configurable = false });
-            if (vm.exception())
-                return {};
+            TRY_OR_DISCARD(define_property_or_throw(property_name, { .configurable = false }));
         }
     }
     // 7. Else,
@@ -340,9 +332,7 @@ bool Object::set_integrity_level(IntegrityLevel level)
             }
 
             // 3. Perform ? DefinePropertyOrThrow(O, k, desc).
-            define_property_or_throw(property_name, descriptor);
-            if (vm.exception())
-                return {};
+            TRY_OR_DISCARD(define_property_or_throw(property_name, descriptor));
         }
     }
 
@@ -1110,9 +1100,7 @@ Object* Object::define_properties(Value properties)
         // b. Let desc be the second element of pair.
 
         // c. Perform ? DefinePropertyOrThrow(O, P, desc).
-        define_property_or_throw(name, descriptor);
-        if (vm.exception())
-            return {};
+        TRY_OR_DISCARD(define_property_or_throw(name, descriptor));
     }
 
     // 7. Return O.

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

@@ -81,7 +81,7 @@ public:
     ThrowCompletionOr<bool> create_method_property(PropertyName const&, Value);
     ThrowCompletionOr<bool> create_data_property_or_throw(PropertyName const&, Value);
     ThrowCompletionOr<bool> create_non_enumerable_data_property_or_throw(PropertyName const&, Value);
-    bool define_property_or_throw(PropertyName const&, PropertyDescriptor const&);
+    ThrowCompletionOr<bool> define_property_or_throw(PropertyName const&, PropertyDescriptor const&);
     bool delete_property_or_throw(PropertyName const&);
     bool has_property(PropertyName const&) const;
     bool has_own_property(PropertyName const&) const;

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

@@ -341,9 +341,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::define_property)
     auto descriptor = to_property_descriptor(global_object, vm.argument(2));
     if (vm.exception())
         return {};
-    vm.argument(0).as_object().define_property_or_throw(key, descriptor);
-    if (vm.exception())
-        return {};
+    TRY_OR_DISCARD(vm.argument(0).as_object().define_property_or_throw(key, descriptor));
     return vm.argument(0);
 }
 

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

@@ -49,7 +49,7 @@ void ObjectEnvironment::create_mutable_binding(GlobalObject&, FlyString const& n
 {
     // 1. Let bindingObject be envRec.[[BindingObject]].
     // 2. Return ? DefinePropertyOrThrow(bindingObject, N, PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: D }).
-    m_binding_object.define_property_or_throw(name, { .value = js_undefined(), .writable = true, .enumerable = true, .configurable = can_be_deleted });
+    MUST(m_binding_object.define_property_or_throw(name, { .value = js_undefined(), .writable = true, .enumerable = true, .configurable = can_be_deleted }));
 }
 
 // 9.1.1.2.3 CreateImmutableBinding ( N, S ), https://tc39.es/ecma262/#sec-object-environment-records-createimmutablebinding-n-s

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

@@ -211,9 +211,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::define_getter)
     if (vm.exception())
         return {};
 
-    object->define_property_or_throw(key, descriptor);
-    if (vm.exception())
-        return {};
+    TRY_OR_DISCARD(object->define_property_or_throw(key, descriptor));
 
     return js_undefined();
 }
@@ -237,9 +235,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::define_setter)
     if (vm.exception())
         return {};
 
-    object->define_property_or_throw(key, descriptor);
-    if (vm.exception())
-        return {};
+    TRY_OR_DISCARD(object->define_property_or_throw(key, descriptor));
 
     return js_undefined();
 }

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

@@ -187,7 +187,7 @@ static Value perform_promise_any(GlobalObject& global_object, Object& iterator_r
             auto errors_array = Array::create_from(global_object, errors.values());
 
             auto* error = AggregateError::create(global_object);
-            error->define_property_or_throw(vm.names.errors, { .value = errors_array, .writable = true, .enumerable = false, .configurable = true });
+            MUST(error->define_property_or_throw(vm.names.errors, { .value = errors_array, .writable = true, .enumerable = false, .configurable = true }));
 
             vm.throw_exception(global_object, error);
             return {};

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

@@ -152,7 +152,7 @@ Value PromiseAnyRejectElementFunction::resolve_element()
         auto errors_array = Array::create_from(global_object, m_values.values());
 
         auto* error = AggregateError::create(global_object);
-        error->define_property_or_throw(vm.names.errors, { .value = errors_array, .writable = true, .enumerable = false, .configurable = true });
+        MUST(error->define_property_or_throw(vm.names.errors, { .value = errors_array, .writable = true, .enumerable = false, .configurable = true }));
 
         return TRY_OR_DISCARD(vm.call(*m_capability.reject, js_undefined(), error));
     }