diff --git a/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.cpp b/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.cpp index 8c4b732df5..4ecca4bd46 100644 --- a/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.cpp @@ -46,13 +46,11 @@ Value AggregateErrorConstructor::construct(FunctionObject& new_target) if (vm.exception()) return {}; - u8 attr = Attribute::Writable | Attribute::Configurable; - if (!vm.argument(1).is_undefined()) { auto message = vm.argument(1).to_string(global_object); if (vm.exception()) return {}; - aggregate_error->define_property(vm.names.message, js_string(vm, message), attr); + aggregate_error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message)); } aggregate_error->install_error_cause(vm.argument(2)); @@ -63,7 +61,7 @@ Value AggregateErrorConstructor::construct(FunctionObject& new_target) if (vm.exception()) return {}; - aggregate_error->define_property(vm.names.errors, Array::create_from(global_object, errors_list), attr); + 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; } diff --git a/Userland/Libraries/LibJS/Runtime/Error.cpp b/Userland/Libraries/LibJS/Runtime/Error.cpp index abec4eba16..8ef82233c8 100644 --- a/Userland/Libraries/LibJS/Runtime/Error.cpp +++ b/Userland/Libraries/LibJS/Runtime/Error.cpp @@ -41,7 +41,7 @@ void Error::install_error_cause(Value options) auto cause = options_object.get(vm.names.cause); if (vm.exception()) return; - define_property(vm.names.cause, cause, Attribute::Writable | Attribute::Configurable); + create_non_enumerable_data_property_or_throw(vm.names.cause, cause); } #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \ diff --git a/Userland/Libraries/LibJS/Runtime/ErrorConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ErrorConstructor.cpp index 9bd61f9db3..3538ae25de 100644 --- a/Userland/Libraries/LibJS/Runtime/ErrorConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/ErrorConstructor.cpp @@ -43,13 +43,11 @@ Value ErrorConstructor::construct(FunctionObject& new_target) if (vm.exception()) return {}; - u8 attr = Attribute::Writable | Attribute::Configurable; - if (!vm.argument(0).is_undefined()) { auto message = vm.argument(0).to_string(global_object); if (vm.exception()) return {}; - error->define_property(vm.names.message, js_string(vm, message), attr); + error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message)); } error->install_error_cause(vm.argument(1)); @@ -59,57 +57,55 @@ Value ErrorConstructor::construct(FunctionObject& new_target) return error; } -#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \ - ConstructorName::ConstructorName(GlobalObject& global_object) \ - : NativeFunction(*static_cast(global_object.error_constructor())) \ - { \ - } \ - \ - void ConstructorName::initialize(GlobalObject& global_object) \ - { \ - auto& vm = this->vm(); \ - NativeFunction::initialize(global_object); \ - \ - /* 20.5.6.2.1 NativeError.prototype, \ - https://tc39.es/ecma262/#sec-nativeerror.prototype */ \ - define_property(vm.names.prototype, global_object.snake_name##_prototype(), 0); \ - \ - define_property(vm.names.length, Value(1), Attribute::Configurable); \ - } \ - \ - ConstructorName::~ConstructorName() { } \ - \ - /* 20.5.6.1.1 NativeError ( message ), https://tc39.es/ecma262/#sec-nativeerror */ \ - Value ConstructorName::call() \ - { \ - return construct(*this); \ - } \ - \ - /* 20.5.6.1.1 NativeError ( message ), https://tc39.es/ecma262/#sec-nativeerror */ \ - Value ConstructorName::construct(FunctionObject& new_target) \ - { \ - auto& vm = this->vm(); \ - auto& global_object = this->global_object(); \ - \ - auto* error = ordinary_create_from_constructor( \ - global_object, new_target, &GlobalObject::snake_name##_prototype); \ - if (vm.exception()) \ - return {}; \ - \ - u8 attr = Attribute::Writable | Attribute::Configurable; \ - \ - if (!vm.argument(0).is_undefined()) { \ - auto message = vm.argument(0).to_string(global_object); \ - if (vm.exception()) \ - return {}; \ - error->define_property(vm.names.message, js_string(vm, message), attr); \ - } \ - \ - error->install_error_cause(vm.argument(1)); \ - if (vm.exception()) \ - return {}; \ - \ - return error; \ +#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \ + ConstructorName::ConstructorName(GlobalObject& global_object) \ + : NativeFunction(*static_cast(global_object.error_constructor())) \ + { \ + } \ + \ + void ConstructorName::initialize(GlobalObject& global_object) \ + { \ + auto& vm = this->vm(); \ + NativeFunction::initialize(global_object); \ + \ + /* 20.5.6.2.1 NativeError.prototype, \ + https://tc39.es/ecma262/#sec-nativeerror.prototype */ \ + define_property(vm.names.prototype, global_object.snake_name##_prototype(), 0); \ + \ + define_property(vm.names.length, Value(1), Attribute::Configurable); \ + } \ + \ + ConstructorName::~ConstructorName() { } \ + \ + /* 20.5.6.1.1 NativeError ( message ), https://tc39.es/ecma262/#sec-nativeerror */ \ + Value ConstructorName::call() \ + { \ + return construct(*this); \ + } \ + \ + /* 20.5.6.1.1 NativeError ( message ), https://tc39.es/ecma262/#sec-nativeerror */ \ + Value ConstructorName::construct(FunctionObject& new_target) \ + { \ + auto& vm = this->vm(); \ + auto& global_object = this->global_object(); \ + \ + auto* error = ordinary_create_from_constructor( \ + global_object, new_target, &GlobalObject::snake_name##_prototype); \ + if (vm.exception()) \ + return {}; \ + \ + if (!vm.argument(0).is_undefined()) { \ + auto message = vm.argument(0).to_string(global_object); \ + if (vm.exception()) \ + return {}; \ + error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message)); \ + } \ + \ + error->install_error_cause(vm.argument(1)); \ + if (vm.exception()) \ + return {}; \ + \ + return error; \ } JS_ENUMERATE_NATIVE_ERRORS diff --git a/Userland/Libraries/LibJS/Runtime/Object.cpp b/Userland/Libraries/LibJS/Runtime/Object.cpp index 6975ddc9d8..bc1d0de283 100644 --- a/Userland/Libraries/LibJS/Runtime/Object.cpp +++ b/Userland/Libraries/LibJS/Runtime/Object.cpp @@ -190,6 +190,19 @@ bool Object::create_data_property_or_throw(PropertyName const& property_name, Va return success; } +// 7.3.6 CreateNonEnumerableDataPropertyOrThrow ( O, P, V ), https://tc39.es/proposal-error-cause/#sec-createnonenumerabledatapropertyorthrow +bool Object::create_non_enumerable_data_property_or_throw(PropertyName const& property_name, Value value) +{ + VERIFY(!value.is_empty()); + VERIFY(property_name.is_valid()); + + // 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). + 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) { diff --git a/Userland/Libraries/LibJS/Runtime/Object.h b/Userland/Libraries/LibJS/Runtime/Object.h index ee9c9fe3e7..4fd6daeece 100644 --- a/Userland/Libraries/LibJS/Runtime/Object.h +++ b/Userland/Libraries/LibJS/Runtime/Object.h @@ -78,6 +78,7 @@ public: bool create_data_property(PropertyName const&, Value); bool create_method_property(PropertyName const&, Value); bool create_data_property_or_throw(PropertyName const&, Value); + bool create_non_enumerable_data_property_or_throw(PropertyName const&, Value); bool define_property_or_throw(PropertyName const&, PropertyDescriptor const&); bool delete_property_or_throw(PropertyName const&); bool has_property(PropertyName const&) const;