1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 04:48:14 +00:00

LibJS: Convert define_property_or_throw() to ThrowCompletionOr

This commit is contained in:
Linus Groh 2021-10-03 01:35:36 +01:00
parent ebf57df431
commit fe86b04b42
12 changed files with 31 additions and 58 deletions

View file

@ -1260,21 +1260,19 @@ ThrowCompletionOr<Value> ClassExpression::class_definition_evaluation(Interprete
switch (method.kind()) { switch (method.kind()) {
case ClassMethod::Kind::Method: 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; break;
case ClassMethod::Kind::Getter: case ClassMethod::Kind::Getter:
update_function_name(method_value, String::formatted("get {}", get_function_name(global_object, key))); 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; break;
case ClassMethod::Kind::Setter: case ClassMethod::Kind::Setter:
update_function_name(method_value, String::formatted("set {}", get_function_name(global_object, key))); 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; break;
default: default:
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
if (auto* exception = interpreter.exception())
return throw_completion(exception->value());
} }
for (auto& field : m_fields) { for (auto& field : m_fields) {

View file

@ -684,8 +684,7 @@ Object* create_unmapped_arguments_object(GlobalObject& global_object, Span<Value
object->set_has_parameter_map(); object->set_has_parameter_map();
// 4. Perform DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }). // 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 }); MUST(object->define_property_or_throw(vm.names.length, { .value = Value(length), .writable = true, .enumerable = false, .configurable = true }));
VERIFY(!vm.exception());
// 5. Let index be 0. // 5. Let index be 0.
// 6. Repeat, while index < len, // 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 }). // 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(); 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 }); MUST(object->define_property_or_throw(*vm.well_known_symbol_iterator(), { .value = array_prototype_values, .writable = true, .enumerable = false, .configurable = true }));
VERIFY(!vm.exception());
// 8. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Get]]: %ThrowTypeError%, [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false }). // 8. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Get]]: %ThrowTypeError%, [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false }).
auto* throw_type_error = global_object.throw_type_error_function(); 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 }); MUST(object->define_property_or_throw(vm.names.callee, { .get = throw_type_error, .set = throw_type_error, .enumerable = false, .configurable = false }));
VERIFY(!vm.exception());
// 9. Return obj. // 9. Return obj.
return object; 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 }). // 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 }); MUST(object->define_property_or_throw(vm.names.length, { .value = Value(length), .writable = true, .enumerable = false, .configurable = true }));
VERIFY(!vm.exception());
// 17. Let mappedNames be a new empty List. // 17. Let mappedNames be a new empty List.
HashTable<FlyString> mapped_names; 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 }). // 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(); 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 }); MUST(object->define_property_or_throw(*vm.well_known_symbol_iterator(), { .value = array_prototype_values, .writable = true, .enumerable = false, .configurable = true }));
VERIFY(!vm.exception());
// 21. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Value]]: func, [[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 }); MUST(object->define_property_or_throw(vm.names.callee, { .value = &function, .writable = true, .enumerable = false, .configurable = true }));
VERIFY(!vm.exception());
// 22. Return obj. // 22. Return obj.
return object; return object;

View file

@ -57,7 +57,7 @@ Value AggregateErrorConstructor::construct(FunctionObject& new_target)
if (vm.exception()) if (vm.exception())
return {}; 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; return aggregate_error;
} }

View file

@ -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()); auto* prototype = vm.heap().allocate<Object>(global_object, *global_object.new_ordinary_function_prototype_object_shape());
switch (m_kind) { switch (m_kind) {
case FunctionKind::Regular: 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; break;
case FunctionKind::Generator: case FunctionKind::Generator:
// prototype is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png) // 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_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 }); MUST(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.name, { .value = js_string(vm, m_name.is_null() ? "" : m_name), .writable = false, .enumerable = false, .configurable = true }));
} }
ECMAScriptFunctionObject::~ECMAScriptFunctionObject() ECMAScriptFunctionObject::~ECMAScriptFunctionObject()
@ -428,7 +428,7 @@ void ECMAScriptFunctionObject::set_name(const FlyString& name)
VERIFY(!name.is_null()); VERIFY(!name.is_null());
auto& vm = this->vm(); auto& vm = this->vm();
m_name = name; 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); VERIFY(success);
} }

View file

@ -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 // 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) 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& global_object = m_object_record->binding_object();
auto existing_prop_or_error = global_object.internal_get_own_property(name); auto existing_prop_or_error = global_object.internal_get_own_property(name);
if (existing_prop_or_error.is_error()) 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 }; desc = { .value = value, .writable = true, .enumerable = true, .configurable = can_be_deleted };
else else
desc = { .value = value }; desc = { .value = value };
global_object.define_property_or_throw(name, desc); auto result_or_error = global_object.define_property_or_throw(name, desc);
if (vm.exception()) if (result_or_error.is_error())
return; 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()) if (result_or_error.is_error())
return; return;
if (!m_var_names.contains_slow(name)) if (!m_var_names.contains_slow(name))

View file

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

View file

@ -81,7 +81,7 @@ public:
ThrowCompletionOr<bool> create_method_property(PropertyName const&, Value); ThrowCompletionOr<bool> create_method_property(PropertyName const&, Value);
ThrowCompletionOr<bool> create_data_property_or_throw(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); 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 delete_property_or_throw(PropertyName const&);
bool has_property(PropertyName const&) const; bool has_property(PropertyName const&) const;
bool has_own_property(PropertyName const&) const; bool has_own_property(PropertyName const&) const;

View file

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

View file

@ -49,7 +49,7 @@ void ObjectEnvironment::create_mutable_binding(GlobalObject&, FlyString const& n
{ {
// 1. Let bindingObject be envRec.[[BindingObject]]. // 1. Let bindingObject be envRec.[[BindingObject]].
// 2. Return ? DefinePropertyOrThrow(bindingObject, N, PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: D }). // 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 // 9.1.1.2.3 CreateImmutableBinding ( N, S ), https://tc39.es/ecma262/#sec-object-environment-records-createimmutablebinding-n-s

View file

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

View file

@ -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 errors_array = Array::create_from(global_object, errors.values());
auto* error = AggregateError::create(global_object); 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); vm.throw_exception(global_object, error);
return {}; return {};

View file

@ -152,7 +152,7 @@ Value PromiseAnyRejectElementFunction::resolve_element()
auto errors_array = Array::create_from(global_object, m_values.values()); auto errors_array = Array::create_from(global_object, m_values.values());
auto* error = AggregateError::create(global_object); 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)); return TRY_OR_DISCARD(vm.call(*m_capability.reject, js_undefined(), error));
} }