diff options
author | Linus Groh <mail@linusgroh.de> | 2021-10-20 21:16:30 +0100 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-10-21 09:02:23 +0100 |
commit | 5832de62fe5e2de4f9a65485246df6550aece33f (patch) | |
tree | 485f847a4dedebdcb2b11902bbe0256fa98518ed | |
parent | 0881f8160fd81d8e25b7cc2eff2d64f2aed7ed53 (diff) | |
download | serenity-5832de62fe5e2de4f9a65485246df6550aece33f.zip |
LibJS: Convert NativeFunction::{call,construct}() to ThrowCompletionOr
Both at the same time because many of them call construct() in call()
and I'm not keen on adding a bunch of temporary plumbing to turn
exceptions into throw completions.
Also changes the return value of construct() to Object* instead of Value
as it always needs to return an object; allowing an arbitrary Value is a
massive foot gun.
99 files changed, 597 insertions, 669 deletions
diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp index e5b6a46e6f..c76f2714e4 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp @@ -940,8 +940,14 @@ static bool is_wrappable_type(IDL::Type const& type) return false; } +enum class ReturnType { + Completion, + Value, + Void, +}; + template<typename ParameterType> -static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter, String const& js_name, String const& js_suffix, String const& cpp_name, HashMap<String, IDL::Dictionary> const& dictionaries, bool return_void = false, bool legacy_null_to_empty_string = false, bool optional = false, Optional<String> optional_default_value = {}, bool variadic = false) +static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter, String const& js_name, String const& js_suffix, String const& cpp_name, HashMap<String, IDL::Dictionary> const& dictionaries, ReturnType return_type, bool legacy_null_to_empty_string = false, bool optional = false, Optional<String> optional_default_value = {}, bool variadic = false) { auto scoped_generator = generator.fork(); scoped_generator.set("cpp_name", make_input_acceptable_cpp(cpp_name)); @@ -957,10 +963,21 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter if (optional_default_value.has_value()) scoped_generator.set("parameter.optional_default_value", *optional_default_value); - if (return_void) - scoped_generator.set("return_statement", "return;"); - else + switch (return_type) { + case ReturnType::Completion: + scoped_generator.set("return_statement", "return JS::throw_completion(vm.exception()->value());"); + scoped_generator.set("try_macro", "TRY"); + break; + case ReturnType::Value: scoped_generator.set("return_statement", "return {};"); + scoped_generator.set("try_macro", "TRY_OR_DISCARD"); + break; + case ReturnType::Void: + scoped_generator.set("return_statement", "return;"); + break; + default: + VERIFY_NOT_REACHED(); + } // FIXME: Add support for optional, variadic, nullable and default values to all types if (parameter.type->is_string()) { @@ -1080,7 +1097,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter } else if (parameter.type->name == "double") { if (!optional) { scoped_generator.append(R"~~~( - double @cpp_name@ = TRY_OR_DISCARD(@js_name@@js_suffix@.to_double(global_object)); + double @cpp_name@ = @try_macro@(@js_name@@js_suffix@.to_double(global_object)); )~~~"); } else { if (optional_default_value.has_value()) { @@ -1094,7 +1111,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter } scoped_generator.append(R"~~~( if (!@js_name@@js_suffix@.is_undefined()) - @cpp_name@ = TRY_OR_DISCARD(@js_name@@js_suffix@.to_double(global_object)); + @cpp_name@ = @try_macro@(@js_name@@js_suffix@.to_double(global_object)); )~~~"); if (optional_default_value.has_value()) { scoped_generator.append(R"~~~( @@ -1136,15 +1153,15 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter } } else if (parameter.type->name == "unsigned long") { scoped_generator.append(R"~~~( - auto @cpp_name@ = TRY_OR_DISCARD(@js_name@@js_suffix@.to_u32(global_object)); + auto @cpp_name@ = @try_macro@(@js_name@@js_suffix@.to_u32(global_object)); )~~~"); } else if (parameter.type->name == "unsigned short") { scoped_generator.append(R"~~~( - auto @cpp_name@ = TRY_OR_DISCARD(@js_name@@js_suffix@.to_u16(global_object)); + auto @cpp_name@ = @try_macro@(@js_name@@js_suffix@.to_u16(global_object)); )~~~"); } else if (parameter.type->name == "long") { scoped_generator.append(R"~~~( - auto @cpp_name@ = TRY_OR_DISCARD(@js_name@@js_suffix@.to_i32(global_object)); + auto @cpp_name@ = @try_macro@(@js_name@@js_suffix@.to_i32(global_object)); )~~~"); } else if (parameter.type->name == "EventHandler") { // x.onfoo = function() { ... } @@ -1236,7 +1253,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter auto member_value_name = String::formatted("{}_value", member_js_name); dictionary_generator.set("member_value_name", member_value_name); - generate_to_cpp(dictionary_generator, member, member_js_name, "", member_value_name, dictionaries, return_void, member.extended_attributes.contains("LegacyNullToEmptyString"), !member.required, member.default_value); + generate_to_cpp(dictionary_generator, member, member_js_name, "", member_value_name, dictionaries, return_type, member.extended_attributes.contains("LegacyNullToEmptyString"), !member.required, member.default_value); dictionary_generator.append(R"~~~( @cpp_name@.@member_name@ = @member_value_name@; )~~~"); @@ -1253,7 +1270,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter } template<typename FunctionType> -static void generate_argument_count_check(SourceGenerator& generator, FunctionType& function) +static void generate_argument_count_check(SourceGenerator& generator, FunctionType& function, ReturnType return_type) { auto argument_count_check_generator = generator.fork(); argument_count_check_generator.set("function.name", function.name); @@ -1269,15 +1286,27 @@ static void generate_argument_count_check(SourceGenerator& generator, FunctionTy argument_count_check_generator.set(".arg_count_suffix", String::formatted(", \"{}\"", function.length())); } + switch (return_type) { + case ReturnType::Completion: + argument_count_check_generator.set("return_statement", "return JS::throw_completion(vm.exception()->value());"); + break; + case ReturnType::Value: + argument_count_check_generator.set("return_statement", "return {};"); + break; + default: + // 'Void' not used here. + VERIFY_NOT_REACHED(); + } + argument_count_check_generator.append(R"~~~( if (vm.argument_count() < @function.nargs@) { vm.throw_exception<JS::TypeError>(global_object, @.bad_arg_count@, "@function.name@"@.arg_count_suffix@); - return {}; + @return_statement@ } )~~~"); } -static void generate_arguments(SourceGenerator& generator, Vector<IDL::Parameter> const& parameters, StringBuilder& arguments_builder, HashMap<String, IDL::Dictionary> const& dictionaries, bool return_void = false) +static void generate_arguments(SourceGenerator& generator, Vector<IDL::Parameter> const& parameters, StringBuilder& arguments_builder, HashMap<String, IDL::Dictionary> const& dictionaries, ReturnType return_type) { auto arguments_generator = generator.fork(); @@ -1294,7 +1323,7 @@ static void generate_arguments(SourceGenerator& generator, Vector<IDL::Parameter } bool legacy_null_to_empty_string = parameter.extended_attributes.contains("LegacyNullToEmptyString"); - generate_to_cpp(generator, parameter, "arg", String::number(argument_index), parameter.name.to_snakecase(), dictionaries, return_void, legacy_null_to_empty_string, parameter.optional, parameter.optional_default_value, parameter.variadic); + generate_to_cpp(generator, parameter, "arg", String::number(argument_index), parameter.name.to_snakecase(), dictionaries, return_type, legacy_null_to_empty_string, parameter.optional, parameter.optional_default_value, parameter.variadic); ++argument_index; } @@ -1447,10 +1476,10 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@) )~~~"); } - generate_argument_count_check(generator, function); + generate_argument_count_check(generator, function, ReturnType::Value); StringBuilder arguments_builder; - generate_arguments(generator, function.parameters, arguments_builder, dictionaries); + generate_arguments(generator, function.parameters, arguments_builder, dictionaries, ReturnType::Value); function_generator.set(".arguments", arguments_builder.string_view()); if (is_static_function == StaticFunction::No) { @@ -2039,7 +2068,7 @@ static void invoke_named_property_setter(JS::GlobalObject& global_object, @fully // 4. Let value be the result of converting V to an IDL value of type T. // NOTE: This takes the last parameter as it's enforced that there's only two parameters. - generate_to_cpp(scoped_generator, interface.named_property_setter->parameters.last(), "value", "", "converted_value", interface.dictionaries, true); + generate_to_cpp(scoped_generator, interface.named_property_setter->parameters.last(), "value", "", "converted_value", interface.dictionaries, ReturnType::Void); // 5. If operation was defined without an identifier, then: if (interface.named_property_setter->name.is_empty()) { @@ -2097,7 +2126,7 @@ static void invoke_indexed_property_setter(JS::GlobalObject& global_object, @ful // 5. Let value be the result of converting V to an IDL value of type T. // NOTE: This takes the last parameter as it's enforced that there's only two parameters. - generate_to_cpp(scoped_generator, interface.named_property_setter->parameters.last(), "value", "", "converted_value", interface.dictionaries, true); + generate_to_cpp(scoped_generator, interface.named_property_setter->parameters.last(), "value", "", "converted_value", interface.dictionaries, ReturnType::Void); // 6. If operation was defined without an identifier, then: if (interface.indexed_property_setter->name.is_empty()) { @@ -2540,8 +2569,8 @@ public: virtual void initialize(JS::GlobalObject&) override; virtual ~@constructor_class@() override; - virtual JS::Value call() override; - virtual JS::Value construct(JS::FunctionObject& new_target) override; + virtual JS::ThrowCompletionOr<JS::Value> call() override; + virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } @@ -2644,13 +2673,12 @@ namespace Web::Bindings { { } -JS::Value @constructor_class@::call() +JS::ThrowCompletionOr<JS::Value> @constructor_class@::call() { - vm().throw_exception<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "@name@"); - return {}; + return vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "@name@"); } -JS::Value @constructor_class@::construct(FunctionObject&) +JS::ThrowCompletionOr<JS::Object*> @constructor_class@::construct(FunctionObject&) { )~~~"); @@ -2658,8 +2686,7 @@ JS::Value @constructor_class@::construct(FunctionObject&) // No constructor generator.set("constructor.length", "0"); generator.append(R"~~~( - vm().throw_exception<JS::TypeError>(global_object(), JS::ErrorType::NotAConstructor, "@name@"); - return {}; + return vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::NotAConstructor, "@name@"); )~~~"); } else if (interface.constructors.size() == 1) { // Single constructor @@ -2675,10 +2702,10 @@ JS::Value @constructor_class@::construct(FunctionObject&) )~~~"); if (!constructor.parameters.is_empty()) { - generate_argument_count_check(generator, constructor); + generate_argument_count_check(generator, constructor, ReturnType::Completion); StringBuilder arguments_builder; - generate_arguments(generator, constructor.parameters, arguments_builder, interface.dictionaries); + generate_arguments(generator, constructor.parameters, arguments_builder, interface.dictionaries, ReturnType::Completion); generator.set(".constructor_arguments", arguments_builder.string_view()); generator.append(R"~~~( @@ -2691,7 +2718,7 @@ JS::Value @constructor_class@::construct(FunctionObject&) } generator.append(R"~~~( if (should_return_empty(impl)) - return JS::Value(); + return JS::throw_completion(vm.exception()->value()); return wrap(global_object, *impl.release_value()); )~~~"); } else { @@ -3236,7 +3263,7 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(@prototype_class@::@attribute.setter_callback@) auto value = vm.argument(0); )~~~"); - generate_to_cpp(generator, attribute, "value", "", "cpp_value", interface.dictionaries, false, attribute.extended_attributes.contains("LegacyNullToEmptyString")); + generate_to_cpp(generator, attribute, "value", "", "cpp_value", interface.dictionaries, ReturnType::Value, attribute.extended_attributes.contains("LegacyNullToEmptyString")); if (attribute.extended_attributes.contains("Reflect")) { if (attribute.type->name != "boolean") { diff --git a/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.cpp b/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.cpp index ae6a1cb7d5..7184cd017f 100644 --- a/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.cpp @@ -31,27 +31,27 @@ void AggregateErrorConstructor::initialize(GlobalObject& global_object) } // 20.5.7.1.1 AggregateError ( errors, message ), https://tc39.es/ecma262/#sec-aggregate-error -Value AggregateErrorConstructor::call() +ThrowCompletionOr<Value> AggregateErrorConstructor::call() { - return construct(*this); + return TRY(construct(*this)); } // 20.5.7.1.1 AggregateError ( errors, message ), https://tc39.es/ecma262/#sec-aggregate-error -Value AggregateErrorConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> AggregateErrorConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); - auto* aggregate_error = TRY_OR_DISCARD(ordinary_create_from_constructor<AggregateError>(global_object, new_target, &GlobalObject::aggregate_error_prototype)); + auto* aggregate_error = TRY(ordinary_create_from_constructor<AggregateError>(global_object, new_target, &GlobalObject::aggregate_error_prototype)); if (!vm.argument(1).is_undefined()) { - auto message = TRY_OR_DISCARD(vm.argument(1).to_string(global_object)); + auto message = TRY(vm.argument(1).to_string(global_object)); MUST(aggregate_error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message))); } - TRY_OR_DISCARD(aggregate_error->install_error_cause(vm.argument(2))); + TRY(aggregate_error->install_error_cause(vm.argument(2))); - auto errors_list = TRY_OR_DISCARD(iterable_to_list(global_object, vm.argument(0))); + auto errors_list = TRY(iterable_to_list(global_object, vm.argument(0))); MUST(aggregate_error->define_property_or_throw(vm.names.errors, { .value = Array::create_from(global_object, errors_list), .writable = true, .enumerable = false, .configurable = true })); diff --git a/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.h b/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.h index 87d9bea3b3..94d272a653 100644 --- a/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~AggregateErrorConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/ArrayBufferConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ArrayBufferConstructor.cpp index 9fdd6719ab..38c7d46238 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayBufferConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/ArrayBufferConstructor.cpp @@ -40,15 +40,14 @@ ArrayBufferConstructor::~ArrayBufferConstructor() } // 25.1.3.1 ArrayBuffer ( length ), https://tc39.es/ecma262/#sec-arraybuffer-length -Value ArrayBufferConstructor::call() +ThrowCompletionOr<Value> ArrayBufferConstructor::call() { auto& vm = this->vm(); - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ArrayBuffer); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ArrayBuffer); } // 25.1.3.1 ArrayBuffer ( length ), https://tc39.es/ecma262/#sec-arraybuffer-length -Value ArrayBufferConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> ArrayBufferConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto byte_length_or_error = vm.argument(0).to_index(global_object()); @@ -57,11 +56,11 @@ Value ArrayBufferConstructor::construct(FunctionObject& new_target) if (error.value().is_object() && is<RangeError>(error.value().as_object())) { // Re-throw more specific RangeError vm.clear_exception(); - vm.throw_exception<RangeError>(global_object(), ErrorType::InvalidLength, "array buffer"); + return vm.throw_completion<RangeError>(global_object(), ErrorType::InvalidLength, "array buffer"); } - return {}; + return error; } - return TRY_OR_DISCARD(allocate_array_buffer(global_object(), new_target, byte_length_or_error.release_value())); + return TRY(allocate_array_buffer(global_object(), new_target, byte_length_or_error.release_value())); } // 25.1.4.1 ArrayBuffer.isView ( arg ), https://tc39.es/ecma262/#sec-arraybuffer.isview diff --git a/Userland/Libraries/LibJS/Runtime/ArrayBufferConstructor.h b/Userland/Libraries/LibJS/Runtime/ArrayBufferConstructor.h index 2e3eb81728..34f7c1b66c 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayBufferConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/ArrayBufferConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~ArrayBufferConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp index 670b4bea60..6c76b3a457 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp @@ -45,17 +45,17 @@ void ArrayConstructor::initialize(GlobalObject& global_object) } // 23.1.1.1 Array ( ...values ), https://tc39.es/ecma262/#sec-array -Value ArrayConstructor::call() +ThrowCompletionOr<Value> ArrayConstructor::call() { - return construct(*this); + return TRY(construct(*this)); } // 23.1.1.1 Array ( ...values ), https://tc39.es/ecma262/#sec-array -Value ArrayConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> ArrayConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); - auto* proto = TRY_OR_DISCARD(get_prototype_from_constructor(global_object(), new_target, &GlobalObject::array_prototype)); + auto* proto = TRY(get_prototype_from_constructor(global_object(), new_target, &GlobalObject::array_prototype)); if (vm.argument_count() == 0) return Array::create(global_object(), 0, proto); @@ -69,18 +69,16 @@ Value ArrayConstructor::construct(FunctionObject& new_target) int_length = 1; } else { int_length = MUST(length.to_u32(global_object())); - if (int_length != length.as_double()) { - vm.throw_exception<RangeError>(global_object(), ErrorType::InvalidLength, "array"); - return {}; - } + if (int_length != length.as_double()) + return vm.throw_completion<RangeError>(global_object(), ErrorType::InvalidLength, "array"); } - TRY_OR_DISCARD(array->set(vm.names.length, Value(int_length), Object::ShouldThrowExceptions::Yes)); + TRY(array->set(vm.names.length, Value(int_length), Object::ShouldThrowExceptions::Yes)); return array; } auto* array = Array::create(global_object(), vm.argument_count(), proto); - if (vm.exception()) - return {}; + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); for (size_t k = 0; k < vm.argument_count(); ++k) MUST(array->create_data_property_or_throw(k, vm.argument(k))); diff --git a/Userland/Libraries/LibJS/Runtime/ArrayConstructor.h b/Userland/Libraries/LibJS/Runtime/ArrayConstructor.h index e28dcea2e5..3e9f6ea0b7 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/ArrayConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~ArrayConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/BigIntConstructor.cpp b/Userland/Libraries/LibJS/Runtime/BigIntConstructor.cpp index 86a677d98e..7bc6b149d9 100644 --- a/Userland/Libraries/LibJS/Runtime/BigIntConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/BigIntConstructor.cpp @@ -40,7 +40,7 @@ BigIntConstructor::~BigIntConstructor() } // 21.2.1.1 BigInt ( value ), https://tc39.es/ecma262/#sec-bigint-constructor-number-value -Value BigIntConstructor::call() +ThrowCompletionOr<Value> BigIntConstructor::call() { auto& vm = this->vm(); auto& global_object = this->global_object(); @@ -48,21 +48,20 @@ Value BigIntConstructor::call() auto value = vm.argument(0); // 2. Let prim be ? ToPrimitive(value, number). - auto primitive = TRY_OR_DISCARD(value.to_primitive(global_object, Value::PreferredType::Number)); + auto primitive = TRY(value.to_primitive(global_object, Value::PreferredType::Number)); // 3. If Type(prim) is Number, return ? NumberToBigInt(prim). if (primitive.is_number()) return number_to_bigint(global_object, primitive); // 4. Otherwise, return ? ToBigInt(value). - return TRY_OR_DISCARD(value.to_bigint(global_object)); + return TRY(value.to_bigint(global_object)); } // 21.2.1.1 BigInt ( value ), https://tc39.es/ecma262/#sec-bigint-constructor-number-value -Value BigIntConstructor::construct(FunctionObject&) +ThrowCompletionOr<Object*> BigIntConstructor::construct(FunctionObject&) { - vm().throw_exception<TypeError>(global_object(), ErrorType::NotAConstructor, "BigInt"); - return {}; + return vm().throw_completion<TypeError>(global_object(), ErrorType::NotAConstructor, "BigInt"); } // 21.2.2.1 BigInt.asIntN ( bits, bigint ), https://tc39.es/ecma262/#sec-bigint.asintn diff --git a/Userland/Libraries/LibJS/Runtime/BigIntConstructor.h b/Userland/Libraries/LibJS/Runtime/BigIntConstructor.h index 6f447642f1..190f5d6c5f 100644 --- a/Userland/Libraries/LibJS/Runtime/BigIntConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/BigIntConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~BigIntConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/BooleanConstructor.cpp b/Userland/Libraries/LibJS/Runtime/BooleanConstructor.cpp index e21c26aefb..49fd17a46e 100644 --- a/Userland/Libraries/LibJS/Runtime/BooleanConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/BooleanConstructor.cpp @@ -32,7 +32,7 @@ BooleanConstructor::~BooleanConstructor() } // 20.3.1.1 Boolean ( value ), https://tc39.es/ecma262/#sec-boolean-constructor-boolean-value -Value BooleanConstructor::call() +ThrowCompletionOr<Value> BooleanConstructor::call() { auto& vm = this->vm(); @@ -41,13 +41,13 @@ Value BooleanConstructor::call() } // 20.3.1.1 Boolean ( value ), https://tc39.es/ecma262/#sec-boolean-constructor-boolean-value -Value BooleanConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> BooleanConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); auto b = vm.argument(0).to_boolean(); - return TRY_OR_DISCARD(ordinary_create_from_constructor<BooleanObject>(global_object, new_target, &GlobalObject::boolean_prototype, b)); + return TRY(ordinary_create_from_constructor<BooleanObject>(global_object, new_target, &GlobalObject::boolean_prototype, b)); } } diff --git a/Userland/Libraries/LibJS/Runtime/BooleanConstructor.h b/Userland/Libraries/LibJS/Runtime/BooleanConstructor.h index a2df4f2c6d..4139ce4cdd 100644 --- a/Userland/Libraries/LibJS/Runtime/BooleanConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/BooleanConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~BooleanConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/DataViewConstructor.cpp b/Userland/Libraries/LibJS/Runtime/DataViewConstructor.cpp index bb1133849a..a70fdd5d8e 100644 --- a/Userland/Libraries/LibJS/Runtime/DataViewConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/DataViewConstructor.cpp @@ -33,56 +33,46 @@ DataViewConstructor::~DataViewConstructor() } // 25.3.2.1 DataView ( buffer [ , byteOffset [ , byteLength ] ] ), https://tc39.es/ecma262/#sec-dataview-buffer-byteoffset-bytelength -Value DataViewConstructor::call() +ThrowCompletionOr<Value> DataViewConstructor::call() { auto& vm = this->vm(); - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.DataView); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.DataView); } // 25.3.2.1 DataView ( buffer [ , byteOffset [ , byteLength ] ] ), https://tc39.es/ecma262/#sec-dataview-buffer-byteoffset-bytelength -Value DataViewConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> DataViewConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); auto buffer = vm.argument(0); - if (!buffer.is_object() || !is<ArrayBuffer>(buffer.as_object())) { - vm.throw_exception<TypeError>(global_object, ErrorType::IsNotAn, buffer.to_string_without_side_effects(), vm.names.ArrayBuffer); - return {}; - } + if (!buffer.is_object() || !is<ArrayBuffer>(buffer.as_object())) + return vm.throw_completion<TypeError>(global_object, ErrorType::IsNotAn, buffer.to_string_without_side_effects(), vm.names.ArrayBuffer); + auto& array_buffer = static_cast<ArrayBuffer&>(buffer.as_object()); - auto offset = TRY_OR_DISCARD(vm.argument(1).to_index(global_object)); + auto offset = TRY(vm.argument(1).to_index(global_object)); - if (array_buffer.is_detached()) { - vm.throw_exception<TypeError>(global_object, ErrorType::DetachedArrayBuffer); - return {}; - } + if (array_buffer.is_detached()) + return vm.throw_completion<TypeError>(global_object, ErrorType::DetachedArrayBuffer); auto buffer_byte_length = array_buffer.byte_length(); - if (offset > buffer_byte_length) { - vm.throw_exception<RangeError>(global_object, ErrorType::DataViewOutOfRangeByteOffset, offset, buffer_byte_length); - return {}; - } + if (offset > buffer_byte_length) + return vm.throw_completion<RangeError>(global_object, ErrorType::DataViewOutOfRangeByteOffset, offset, buffer_byte_length); size_t view_byte_length; if (vm.argument(2).is_undefined()) { view_byte_length = buffer_byte_length - offset; } else { - view_byte_length = TRY_OR_DISCARD(vm.argument(2).to_index(global_object)); - if (offset + view_byte_length > buffer_byte_length) { - vm.throw_exception<RangeError>(global_object, ErrorType::InvalidLength, vm.names.DataView); - return {}; - } + view_byte_length = TRY(vm.argument(2).to_index(global_object)); + if (offset + view_byte_length > buffer_byte_length) + return vm.throw_completion<RangeError>(global_object, ErrorType::InvalidLength, vm.names.DataView); } - auto* data_view = TRY_OR_DISCARD(ordinary_create_from_constructor<DataView>(global_object, new_target, &GlobalObject::data_view_prototype, &array_buffer, view_byte_length, offset)); + auto* data_view = TRY(ordinary_create_from_constructor<DataView>(global_object, new_target, &GlobalObject::data_view_prototype, &array_buffer, view_byte_length, offset)); - if (array_buffer.is_detached()) { - vm.throw_exception<TypeError>(global_object, ErrorType::DetachedArrayBuffer); - return {}; - } + if (array_buffer.is_detached()) + return vm.throw_completion<TypeError>(global_object, ErrorType::DetachedArrayBuffer); return data_view; } diff --git a/Userland/Libraries/LibJS/Runtime/DataViewConstructor.h b/Userland/Libraries/LibJS/Runtime/DataViewConstructor.h index b68c350f84..5b81b88281 100644 --- a/Userland/Libraries/LibJS/Runtime/DataViewConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/DataViewConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~DataViewConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject&) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/DateConstructor.cpp b/Userland/Libraries/LibJS/Runtime/DateConstructor.cpp index 57d5726f72..2cadfde8e3 100644 --- a/Userland/Libraries/LibJS/Runtime/DateConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/DateConstructor.cpp @@ -180,7 +180,7 @@ static DatetimeAndMilliseconds now() } // 21.4.2.1 Date ( ...values ), https://tc39.es/ecma262/#sec-date -Value DateConstructor::call() +ThrowCompletionOr<Value> DateConstructor::call() { auto [datetime, milliseconds] = JS::now(); auto* date = Date::create(global_object(), datetime, milliseconds, false); @@ -188,20 +188,20 @@ Value DateConstructor::call() } // 21.4.2.1 Date ( ...values ), https://tc39.es/ecma262/#sec-date -Value DateConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> DateConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); if (vm.argument_count() == 0) { auto [datetime, milliseconds] = JS::now(); - return TRY_OR_DISCARD(ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, false)); + return TRY(ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, false)); } - auto create_invalid_date = [&global_object, &new_target]() -> Date* { + auto create_invalid_date = [&global_object, &new_target]() -> ThrowCompletionOr<Date*> { auto datetime = Core::DateTime::create(1970, 1, 1, 0, 0, 0); auto milliseconds = static_cast<i16>(0); - return TRY_OR_DISCARD(ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, true)); + return ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, true); }; if (vm.argument_count() == 1) { @@ -209,19 +209,18 @@ Value DateConstructor::construct(FunctionObject& new_target) if (value.is_string()) value = parse_date_string(value.as_string().string()); else - value = TRY_OR_DISCARD(value.to_number(global_object)); + value = TRY(value.to_number(global_object)); - if (!value.is_finite_number()) { - return create_invalid_date(); - } + if (!value.is_finite_number()) + return TRY(create_invalid_date()); // A timestamp since the epoch, in UTC. double value_as_double = value.as_double(); if (value_as_double > Date::time_clip) - return create_invalid_date(); + return TRY(create_invalid_date()); auto datetime = Core::DateTime::from_timestamp(static_cast<time_t>(value_as_double / 1000)); auto milliseconds = static_cast<i16>(fmod(value_as_double, 1000)); - return TRY_OR_DISCARD(ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, false)); + return TRY(ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, false)); } // A date/time in components, in local time. @@ -229,46 +228,39 @@ Value DateConstructor::construct(FunctionObject& new_target) return vm.argument_count() > i ? vm.argument(i).to_number(global_object) : Value(fallback); }; - auto year_value = TRY_OR_DISCARD(vm.argument(0).to_number(global_object)); - if (!year_value.is_finite_number()) { - return create_invalid_date(); - } + auto year_value = TRY(vm.argument(0).to_number(global_object)); + if (!year_value.is_finite_number()) + return TRY(create_invalid_date()); auto year = year_value.as_i32(); - auto month_index_value = TRY_OR_DISCARD(vm.argument(1).to_number(global_object)); - if (!month_index_value.is_finite_number()) { - return create_invalid_date(); - } + auto month_index_value = TRY(vm.argument(1).to_number(global_object)); + if (!month_index_value.is_finite_number()) + return TRY(create_invalid_date()); auto month_index = month_index_value.as_i32(); - auto day_value = TRY_OR_DISCARD(arg_or(2, 1)); - if (!day_value.is_finite_number()) { - return create_invalid_date(); - } + auto day_value = TRY(arg_or(2, 1)); + if (!day_value.is_finite_number()) + return TRY(create_invalid_date()); auto day = day_value.as_i32(); - auto hours_value = TRY_OR_DISCARD(arg_or(3, 0)); - if (!hours_value.is_finite_number()) { - return create_invalid_date(); - } + auto hours_value = TRY(arg_or(3, 0)); + if (!hours_value.is_finite_number()) + return TRY(create_invalid_date()); auto hours = hours_value.as_i32(); - auto minutes_value = TRY_OR_DISCARD(arg_or(4, 0)); - if (!minutes_value.is_finite_number()) { - return create_invalid_date(); - } + auto minutes_value = TRY(arg_or(4, 0)); + if (!minutes_value.is_finite_number()) + return TRY(create_invalid_date()); auto minutes = minutes_value.as_i32(); - auto seconds_value = TRY_OR_DISCARD(arg_or(5, 0)); - if (!seconds_value.is_finite_number()) { - return create_invalid_date(); - } + auto seconds_value = TRY(arg_or(5, 0)); + if (!seconds_value.is_finite_number()) + return TRY(create_invalid_date()); auto seconds = seconds_value.as_i32(); - auto milliseconds_value = TRY_OR_DISCARD(arg_or(6, 0)); - if (!milliseconds_value.is_finite_number()) { - return create_invalid_date(); - } + auto milliseconds_value = TRY(arg_or(6, 0)); + if (!milliseconds_value.is_finite_number()) + return TRY(create_invalid_date()); auto milliseconds = milliseconds_value.as_i32(); seconds += milliseconds / 1000; @@ -284,8 +276,8 @@ Value DateConstructor::construct(FunctionObject& new_target) auto datetime = Core::DateTime::create(year, month, day, hours, minutes, seconds); auto time = datetime.timestamp() * 1000.0 + milliseconds; if (time > Date::time_clip) - return create_invalid_date(); - return TRY_OR_DISCARD(ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, false)); + return TRY(create_invalid_date()); + return TRY(ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, false)); } // 21.4.3.1 Date.now ( ), https://tc39.es/ecma262/#sec-date.now diff --git a/Userland/Libraries/LibJS/Runtime/DateConstructor.h b/Userland/Libraries/LibJS/Runtime/DateConstructor.h index d36a9f466f..10bb6dd914 100644 --- a/Userland/Libraries/LibJS/Runtime/DateConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/DateConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~DateConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/ErrorConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ErrorConstructor.cpp index 1f0ed8a418..c992b48a47 100644 --- a/Userland/Libraries/LibJS/Runtime/ErrorConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/ErrorConstructor.cpp @@ -28,25 +28,25 @@ void ErrorConstructor::initialize(GlobalObject& global_object) } // 20.5.1.1 Error ( message ), https://tc39.es/ecma262/#sec-error-message -Value ErrorConstructor::call() +ThrowCompletionOr<Value> ErrorConstructor::call() { - return construct(*this); + return TRY(construct(*this)); } // 20.5.1.1 Error ( message ), https://tc39.es/ecma262/#sec-error-message -Value ErrorConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> ErrorConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); - auto* error = TRY_OR_DISCARD(ordinary_create_from_constructor<Error>(global_object, new_target, &GlobalObject::error_prototype)); + auto* error = TRY(ordinary_create_from_constructor<Error>(global_object, new_target, &GlobalObject::error_prototype)); if (!vm.argument(0).is_undefined()) { - auto message = TRY_OR_DISCARD(vm.argument(0).to_string(global_object)); + auto message = TRY(vm.argument(0).to_string(global_object)); MUST(error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message))); } - TRY_OR_DISCARD(error->install_error_cause(vm.argument(1))); + TRY(error->install_error_cause(vm.argument(1))); return error; } @@ -72,26 +72,26 @@ Value ErrorConstructor::construct(FunctionObject& new_target) ConstructorName::~ConstructorName() { } \ \ /* 20.5.6.1.1 NativeError ( message ), https://tc39.es/ecma262/#sec-nativeerror */ \ - Value ConstructorName::call() \ + ThrowCompletionOr<Value> ConstructorName::call() \ { \ - return construct(*this); \ + return TRY(construct(*this)); \ } \ \ /* 20.5.6.1.1 NativeError ( message ), https://tc39.es/ecma262/#sec-nativeerror */ \ - Value ConstructorName::construct(FunctionObject& new_target) \ + ThrowCompletionOr<Object*> ConstructorName::construct(FunctionObject& new_target) \ { \ auto& vm = this->vm(); \ auto& global_object = this->global_object(); \ \ - auto* error = TRY_OR_DISCARD(ordinary_create_from_constructor<ClassName>( \ + auto* error = TRY(ordinary_create_from_constructor<ClassName>( \ global_object, new_target, &GlobalObject::snake_name##_prototype)); \ \ if (!vm.argument(0).is_undefined()) { \ - auto message = TRY_OR_DISCARD(vm.argument(0).to_string(global_object)); \ + auto message = TRY(vm.argument(0).to_string(global_object)); \ MUST(error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message))); \ } \ \ - TRY_OR_DISCARD(error->install_error_cause(vm.argument(1))); \ + TRY(error->install_error_cause(vm.argument(1))); \ \ return error; \ } diff --git a/Userland/Libraries/LibJS/Runtime/ErrorConstructor.h b/Userland/Libraries/LibJS/Runtime/ErrorConstructor.h index 8c37dbb1e2..4226c6107f 100644 --- a/Userland/Libraries/LibJS/Runtime/ErrorConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/ErrorConstructor.h @@ -19,8 +19,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~ErrorConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } @@ -34,8 +34,8 @@ private: explicit ConstructorName(GlobalObject&); \ virtual void initialize(GlobalObject&) override; \ virtual ~ConstructorName() override; \ - virtual Value call() override; \ - virtual Value construct(FunctionObject& new_target) override; \ + virtual ThrowCompletionOr<Value> call() override; \ + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; \ \ private: \ virtual bool has_constructor() const override { return true; } \ diff --git a/Userland/Libraries/LibJS/Runtime/FinalizationRegistryConstructor.cpp b/Userland/Libraries/LibJS/Runtime/FinalizationRegistryConstructor.cpp index 3fb0c21ad1..8e01326888 100644 --- a/Userland/Libraries/LibJS/Runtime/FinalizationRegistryConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/FinalizationRegistryConstructor.cpp @@ -33,25 +33,23 @@ FinalizationRegistryConstructor::~FinalizationRegistryConstructor() } // 26.2.1.1 FinalizationRegistry ( cleanupCallback ), https://tc39.es/ecma262/#sec-finalization-registry-cleanup-callback -Value FinalizationRegistryConstructor::call() +ThrowCompletionOr<Value> FinalizationRegistryConstructor::call() { auto& vm = this->vm(); - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.FinalizationRegistry); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.FinalizationRegistry); } // 26.2.1.1 FinalizationRegistry ( cleanupCallback ), https://tc39.es/ecma262/#sec-finalization-registry-cleanup-callback -Value FinalizationRegistryConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> FinalizationRegistryConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); auto cleanup_callback = vm.argument(0); - if (!cleanup_callback.is_function()) { - vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, cleanup_callback.to_string_without_side_effects()); - return {}; - } - return TRY_OR_DISCARD(ordinary_create_from_constructor<FinalizationRegistry>(global_object, new_target, &GlobalObject::finalization_registry_prototype, cleanup_callback.as_function())); + if (!cleanup_callback.is_function()) + return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, cleanup_callback.to_string_without_side_effects()); + + return TRY(ordinary_create_from_constructor<FinalizationRegistry>(global_object, new_target, &GlobalObject::finalization_registry_prototype, cleanup_callback.as_function())); } } diff --git a/Userland/Libraries/LibJS/Runtime/FinalizationRegistryConstructor.h b/Userland/Libraries/LibJS/Runtime/FinalizationRegistryConstructor.h index 461113d506..1476cd9ac8 100644 --- a/Userland/Libraries/LibJS/Runtime/FinalizationRegistryConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/FinalizationRegistryConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~FinalizationRegistryConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject&) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/FunctionConstructor.cpp b/Userland/Libraries/LibJS/Runtime/FunctionConstructor.cpp index 9a343d3529..92cf4c1425 100644 --- a/Userland/Libraries/LibJS/Runtime/FunctionConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/FunctionConstructor.cpp @@ -8,6 +8,7 @@ #include <LibJS/Interpreter.h> #include <LibJS/Lexer.h> #include <LibJS/Parser.h> +#include <LibJS/Runtime/ECMAScriptFunctionObject.h> #include <LibJS/Runtime/Error.h> #include <LibJS/Runtime/FunctionConstructor.h> #include <LibJS/Runtime/FunctionObject.h> @@ -66,20 +67,21 @@ RefPtr<FunctionExpression> FunctionConstructor::create_dynamic_function_node(Glo } // 20.2.1.1 Function ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-function-p1-p2-pn-body -Value FunctionConstructor::call() +ThrowCompletionOr<Value> FunctionConstructor::call() { - return construct(*this); + return TRY(construct(*this)); } // 20.2.1.1 Function ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-function-p1-p2-pn-body -Value FunctionConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> FunctionConstructor::construct(FunctionObject& new_target) { + auto& vm = this->vm(); auto function = create_dynamic_function_node(global_object(), new_target, FunctionKind::Regular); - if (!function) - return {}; + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); OwnPtr<Interpreter> local_interpreter; - Interpreter* interpreter = vm().interpreter_if_exists(); + Interpreter* interpreter = vm.interpreter_if_exists(); if (!interpreter) { local_interpreter = Interpreter::create_with_existing_realm(*realm()); @@ -87,7 +89,11 @@ Value FunctionConstructor::construct(FunctionObject& new_target) } VM::InterpreterExecutionScope scope(*interpreter); - return function->execute(*interpreter, global_object()); + auto result = function->execute(*interpreter, global_object()); + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); + VERIFY(result.is_object() && is<ECMAScriptFunctionObject>(result.as_object())); + return &result.as_object(); } } diff --git a/Userland/Libraries/LibJS/Runtime/FunctionConstructor.h b/Userland/Libraries/LibJS/Runtime/FunctionConstructor.h index 7444f8525b..426782de44 100644 --- a/Userland/Libraries/LibJS/Runtime/FunctionConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/FunctionConstructor.h @@ -21,8 +21,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~FunctionConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/GeneratorFunctionConstructor.cpp b/Userland/Libraries/LibJS/Runtime/GeneratorFunctionConstructor.cpp index c164ba7678..ef310a384d 100644 --- a/Userland/Libraries/LibJS/Runtime/GeneratorFunctionConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/GeneratorFunctionConstructor.cpp @@ -37,17 +37,17 @@ GeneratorFunctionConstructor::~GeneratorFunctionConstructor() } // 27.3.1.1 GeneratorFunction ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-generatorfunction -Value GeneratorFunctionConstructor::call() +ThrowCompletionOr<Value> GeneratorFunctionConstructor::call() { - return construct(*this); + return TRY(construct(*this)); } // 27.3.1.1 GeneratorFunction ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-generatorfunction -Value GeneratorFunctionConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> GeneratorFunctionConstructor::construct(FunctionObject& new_target) { auto function = FunctionConstructor::create_dynamic_function_node(global_object(), new_target, FunctionKind::Generator); - if (!function) - return {}; + if (auto* exception = vm().exception()) + return throw_completion(exception->value()); auto* bytecode_interpreter = Bytecode::Interpreter::current(); VERIFY(bytecode_interpreter); diff --git a/Userland/Libraries/LibJS/Runtime/GeneratorFunctionConstructor.h b/Userland/Libraries/LibJS/Runtime/GeneratorFunctionConstructor.h index 2ccd439531..66f4b5ba95 100644 --- a/Userland/Libraries/LibJS/Runtime/GeneratorFunctionConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/GeneratorFunctionConstructor.h @@ -19,8 +19,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~GeneratorFunctionConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DisplayNamesConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Intl/DisplayNamesConstructor.cpp index c2a7b28140..a36a2af2af 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/DisplayNamesConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/DisplayNamesConstructor.cpp @@ -37,15 +37,14 @@ void DisplayNamesConstructor::initialize(GlobalObject& global_object) } // 12.2.1 Intl.DisplayNames ( locales, options ), https://tc39.es/ecma402/#sec-Intl.DisplayNames -Value DisplayNamesConstructor::call() +ThrowCompletionOr<Value> DisplayNamesConstructor::call() { // 1. If NewTarget is undefined, throw a TypeError exception. - vm().throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.DisplayNames"); - return {}; + return vm().throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.DisplayNames"); } // 12.2.1 Intl.DisplayNames ( locales, options ), https://tc39.es/ecma402/#sec-Intl.DisplayNames -Value DisplayNamesConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> DisplayNamesConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); @@ -54,19 +53,17 @@ Value DisplayNamesConstructor::construct(FunctionObject& new_target) auto options_value = vm.argument(1); // 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNames.prototype%", « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). - auto* display_names = TRY_OR_DISCARD(ordinary_create_from_constructor<DisplayNames>(global_object, new_target, &GlobalObject::intl_display_names_prototype)); + auto* display_names = TRY(ordinary_create_from_constructor<DisplayNames>(global_object, new_target, &GlobalObject::intl_display_names_prototype)); // 3. Let requestedLocales be ? CanonicalizeLocaleList(locales). - auto requested_locales = TRY_OR_DISCARD(canonicalize_locale_list(global_object, locale_value)); + auto requested_locales = TRY(canonicalize_locale_list(global_object, locale_value)); // 4. If options is undefined, throw a TypeError exception. - if (options_value.is_undefined()) { - vm.throw_exception<TypeError>(global_object, ErrorType::IsUndefined, "options"sv); - return {}; - } + if (options_value.is_undefined()) + return vm.throw_completion<TypeError>(global_object, ErrorType::IsUndefined, "options"sv); // 5. Set options to ? GetOptionsObject(options). - auto* options = TRY_OR_DISCARD(Temporal::get_options_object(global_object, options_value)); + auto* options = TRY(Temporal::get_options_object(global_object, options_value)); // 6. Let opt be a new Record. LocaleOptions opt {}; @@ -74,7 +71,7 @@ Value DisplayNamesConstructor::construct(FunctionObject& new_target) // 7. Let localeData be %DisplayNames%.[[LocaleData]]. // 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). - auto matcher = TRY_OR_DISCARD(get_option(global_object, *options, vm.names.localeMatcher, Value::Type::String, { "lookup"sv, "best fit"sv }, "best fit"sv)); + auto matcher = TRY(get_option(global_object, *options, vm.names.localeMatcher, Value::Type::String, { "lookup"sv, "best fit"sv }, "best fit"sv)); // 9. Set opt.[[localeMatcher]] to matcher. opt.locale_matcher = matcher; @@ -83,25 +80,23 @@ Value DisplayNamesConstructor::construct(FunctionObject& new_target) auto result = resolve_locale(requested_locales, opt, {}); // 11. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). - auto style = TRY_OR_DISCARD(get_option(global_object, *options, vm.names.style, Value::Type::String, { "narrow"sv, "short"sv, "long"sv }, "long"sv)); + auto style = TRY(get_option(global_object, *options, vm.names.style, Value::Type::String, { "narrow"sv, "short"sv, "long"sv }, "long"sv)); // 12. Set displayNames.[[Style]] to style. display_names->set_style(style.as_string().string()); // 13. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). - auto type = TRY_OR_DISCARD(get_option(global_object, *options, vm.names.type, Value::Type::String, { "language"sv, "region"sv, "script"sv, "currency"sv }, Empty {})); + auto type = TRY(get_option(global_object, *options, vm.names.type, Value::Type::String, { "language"sv, "region"sv, "script"sv, "currency"sv }, Empty {})); // 14. If type is undefined, throw a TypeError exception. - if (type.is_undefined()) { - vm.throw_exception<TypeError>(global_object, ErrorType::IsUndefined, "options.type"sv); - return {}; - } + if (type.is_undefined()) + return vm.throw_completion<TypeError>(global_object, ErrorType::IsUndefined, "options.type"sv); // 15. Set displayNames.[[Type]] to type. display_names->set_type(type.as_string().string()); // 16. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). - auto fallback = TRY_OR_DISCARD(get_option(global_object, *options, vm.names.fallback, Value::Type::String, { "code"sv, "none"sv }, "code"sv)); + auto fallback = TRY(get_option(global_object, *options, vm.names.fallback, Value::Type::String, { "code"sv, "none"sv }, "code"sv)); // 17. Set displayNames.[[Fallback]] to fallback. display_names->set_fallback(fallback.as_string().string()); diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DisplayNamesConstructor.h b/Userland/Libraries/LibJS/Runtime/Intl/DisplayNamesConstructor.h index 38b4d32943..5fe7229d8f 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/DisplayNamesConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/DisplayNamesConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~DisplayNamesConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/Intl/ListFormatConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Intl/ListFormatConstructor.cpp index 35d6f5cc5e..6aea4da788 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/ListFormatConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/ListFormatConstructor.cpp @@ -36,15 +36,14 @@ void ListFormatConstructor::initialize(GlobalObject& global_object) } // 13.2.1 Intl.ListFormat ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sec-Intl.ListFormat -Value ListFormatConstructor::call() +ThrowCompletionOr<Value> ListFormatConstructor::call() { // 1. If NewTarget is undefined, throw a TypeError exception. - vm().throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.ListFormat"); - return {}; + return vm().throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.ListFormat"); } // 13.2.1 Intl.ListFormat ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sec-Intl.ListFormat -Value ListFormatConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> ListFormatConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); @@ -53,19 +52,19 @@ Value ListFormatConstructor::construct(FunctionObject& new_target) auto options_value = vm.argument(1); // 2. Let listFormat be ? OrdinaryCreateFromConstructor(NewTarget, "%ListFormat.prototype%", « [[InitializedListFormat]], [[Locale]], [[Type]], [[Style]], [[Templates]] »). - auto* list_format = TRY_OR_DISCARD(ordinary_create_from_constructor<ListFormat>(global_object, new_target, &GlobalObject::intl_list_format_prototype)); + auto* list_format = TRY(ordinary_create_from_constructor<ListFormat>(global_object, new_target, &GlobalObject::intl_list_format_prototype)); // 3. Let requestedLocales be ? CanonicalizeLocaleList(locales). - auto requested_locales = TRY_OR_DISCARD(canonicalize_locale_list(global_object, locale_value)); + auto requested_locales = TRY(canonicalize_locale_list(global_object, locale_value)); // 4. Set options to ? GetOptionsObject(options). - auto* options = TRY_OR_DISCARD(Temporal::get_options_object(global_object, options_value)); + auto* options = TRY(Temporal::get_options_object(global_object, options_value)); // 5. Let opt be a new Record. LocaleOptions opt {}; // 6. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). - auto matcher = TRY_OR_DISCARD(get_option(global_object, *options, vm.names.localeMatcher, Value::Type::String, { "lookup"sv, "best fit"sv }, "best fit"sv)); + auto matcher = TRY(get_option(global_object, *options, vm.names.localeMatcher, Value::Type::String, { "lookup"sv, "best fit"sv }, "best fit"sv)); // 7. Set opt.[[localeMatcher]] to matcher. opt.locale_matcher = matcher; @@ -79,13 +78,13 @@ Value ListFormatConstructor::construct(FunctionObject& new_target) list_format->set_locale(move(result.locale)); // 11. Let type be ? GetOption(options, "type", "string", « "conjunction", "disjunction", "unit" », "conjunction"). - auto type = TRY_OR_DISCARD(get_option(global_object, *options, vm.names.type, Value::Type::String, { "conjunction"sv, "disjunction"sv, "unit"sv }, "conjunction"sv)); + auto type = TRY(get_option(global_object, *options, vm.names.type, Value::Type::String, { "conjunction"sv, "disjunction"sv, "unit"sv }, "conjunction"sv)); // 12. Set listFormat.[[Type]] to type. list_format->set_type(type.as_string().string()); // 13. Let style be ? GetOption(options, "style", "string", « "long", "short", "narrow" », "long"). - auto style = TRY_OR_DISCARD(get_option(global_object, *options, vm.names.style, Value::Type::String, { "long"sv, "short"sv, "narrow"sv }, "long"sv)); + auto style = TRY(get_option(global_object, *options, vm.names.style, Value::Type::String, { "long"sv, "short"sv, "narrow"sv }, "long"sv)); // 14. Set listFormat.[[Style]] to style. list_format->set_style(style.as_string().string()); diff --git a/Userland/Libraries/LibJS/Runtime/Intl/ListFormatConstructor.h b/Userland/Libraries/LibJS/Runtime/Intl/ListFormatConstructor.h index c9e0752c71..4a70ae9398 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/ListFormatConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/ListFormatConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~ListFormatConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/Intl/LocaleConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Intl/LocaleConstructor.cpp index b93a0ff94c..d0e9e57c57 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/LocaleConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/LocaleConstructor.cpp @@ -247,15 +247,14 @@ void LocaleConstructor::initialize(GlobalObject& global_object) } // 14.1.3 Intl.Locale ( tag [ , options ] ), https://tc39.es/ecma402/#sec-Intl.Locale -Value LocaleConstructor::call() +ThrowCompletionOr<Value> LocaleConstructor::call() { // 1. If NewTarget is undefined, throw a TypeError exception. - vm().throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.Locale"); - return {}; + return vm().throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.Locale"); } // 14.1.3 Intl.Locale ( tag [ , options ] ), https://tc39.es/ecma402/#sec-Intl.Locale -Value LocaleConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> LocaleConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); @@ -273,15 +272,13 @@ Value LocaleConstructor::construct(FunctionObject& new_target) // a. Append [[Numeric]] as the last element of internalSlotsList. // 6. Let locale be ? OrdinaryCreateFromConstructor(NewTarget, "%Locale.prototype%", internalSlotsList). - auto* locale = TRY_OR_DISCARD(ordinary_create_from_constructor<Locale>(global_object, new_target, &GlobalObject::intl_locale_prototype)); + auto* locale = TRY(ordinary_create_from_constructor<Locale>(global_object, new_target, &GlobalObject::intl_locale_prototype)); String tag; // 7. If Type(tag) is not String or Object, throw a TypeError exception. - if (!tag_value.is_string() && !tag_value.is_object()) { - vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObjectOrString, "tag"sv); - return {}; - } + if (!tag_value.is_string() && !tag_value.is_object()) + return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObjectOrString, "tag"sv); // 8. If Type(tag) is Object and tag has an [[InitializedLocale]] internal slot, then if (tag_value.is_object() && is<Locale>(tag_value.as_object())) { @@ -292,17 +289,17 @@ Value LocaleConstructor::construct(FunctionObject& new_target) // 9. Else, else { // a. Let tag be ? ToString(tag). - tag = TRY_OR_DISCARD(tag_value.to_string(global_object)); + tag = TRY(tag_value.to_string(global_object)); } // 10. Set options to ? CoerceOptionsToObject(options). - auto* options = TRY_OR_DISCARD(coerce_options_to_object(global_object, options_value)); + auto* options = TRY(coerce_options_to_object(global_object, options_value)); // 11. Set tag to ? ApplyOptionsToTag(tag, options). - if (auto applied_tag = apply_options_to_tag(global_object, tag, *options); applied_tag.has_value()) - tag = applied_tag.release_value(); - else - return {}; + auto applied_tag = apply_options_to_tag(global_object, tag, *options); + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); + tag = applied_tag.release_value(); // 12. Let opt be a new Record. LocaleAndKeys opt {}; @@ -312,44 +309,44 @@ Value LocaleConstructor::construct(FunctionObject& new_target) // a. If calendar does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. // 15. Set opt.[[ca]] to calendar. opt.ca = get_string_option(global_object, *options, vm.names.calendar, Unicode::is_type_identifier); - if (vm.exception()) - return {}; + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); // 16. Let collation be ? GetOption(options, "collation", "string", undefined, undefined). // 17. If collation is not undefined, then // a. If collation does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. // 18. Set opt.[[co]] to collation. opt.co = get_string_option(global_object, *options, vm.names.collation, Unicode::is_type_identifier); - if (vm.exception()) - return {}; + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); // 19. Let hc be ? GetOption(options, "hourCycle", "string", « "h11", "h12", "h23", "h24" », undefined). // 20. Set opt.[[hc]] to hc. opt.hc = get_string_option(global_object, *options, vm.names.hourCycle, nullptr, { "h11"sv, "h12"sv, "h23"sv, "h24"sv }); - if (vm.exception()) - return {}; + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); // 21. Let kf be ? GetOption(options, "caseFirst", "string", « "upper", "lower", "false" », undefined). // 22. Set opt.[[kf]] to kf. opt.kf = get_string_option(global_object, *options, vm.names.caseFirst, nullptr, { "upper"sv, "lower"sv, "false"sv }); - if (vm.exception()) - return {}; + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); // 23. Let kn be ? GetOption(options, "numeric", "boolean", undefined, undefined). - auto kn = TRY_OR_DISCARD(get_option(global_object, *options, vm.names.numeric, Value::Type::Boolean, {}, Empty {})); + auto kn = TRY(get_option(global_object, *options, vm.names.numeric, Value::Type::Boolean, {}, Empty {})); // 24. If kn is not undefined, set kn to ! ToString(kn). // 25. Set opt.[[kn]] to kn. if (!kn.is_undefined()) - opt.kn = TRY_OR_DISCARD(kn.to_string(global_object)); + opt.kn = TRY(kn.to_string(global_object)); // 26. Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined). // 27. If numberingSystem is not undefined, then // a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. // 28. Set opt.[[nu]] to numberingSystem. opt.nu = get_string_option(global_object, *options, vm.names.numberingSystem, Unicode::is_type_identifier); - if (vm.exception()) - return {}; + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); // 29. Let r be ! ApplyUnicodeExtensionToTag(tag, opt, relevantExtensionKeys). auto result = apply_unicode_extension_to_tag(tag, move(opt), relevant_extension_keys); diff --git a/Userland/Libraries/LibJS/Runtime/Intl/LocaleConstructor.h b/Userland/Libraries/LibJS/Runtime/Intl/LocaleConstructor.h index f7e5d68c9e..0051c079d3 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/LocaleConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/LocaleConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~LocaleConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/Intl/NumberFormatConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Intl/NumberFormatConstructor.cpp index 76e9f6bab7..99856f338e 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/NumberFormatConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/NumberFormatConstructor.cpp @@ -35,14 +35,14 @@ void NumberFormatConstructor::initialize(GlobalObject& global_object) } // 15.2.1 Intl.NumberFormat ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sec-intl.numberformat -Value NumberFormatConstructor::call() +ThrowCompletionOr<Value> NumberFormatConstructor::call() { // 1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget. - return construct(*this); + return TRY(construct(*this)); } // 15.2.1 Intl.NumberFormat ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sec-intl.numberformat -Value NumberFormatConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> NumberFormatConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); @@ -51,10 +51,10 @@ Value NumberFormatConstructor::construct(FunctionObject& new_target) auto options = vm.argument(1); // 2. Let numberFormat be ? OrdinaryCreateFromConstructor(newTarget, "%NumberFormat.prototype%", « [[InitializedNumberFormat]], [[Locale]], [[DataLocale]], [[NumberingSystem]], [[Style]], [[Unit]], [[UnitDisplay]], [[Currency]], [[CurrencyDisplay]], [[CurrencySign]], [[MinimumIntegerDigits]], [[MinimumFractionDigits]], [[MaximumFractionDigits]], [[MinimumSignificantDigits]], [[MaximumSignificantDigits]], [[RoundingType]], [[Notation]], [[CompactDisplay]], [[UseGrouping]], [[SignDisplay]], [[BoundFormat]] »). - auto* number_format = TRY_OR_DISCARD(ordinary_create_from_constructor<NumberFormat>(global_object, new_target, &GlobalObject::intl_number_format_prototype)); + auto* number_format = TRY(ordinary_create_from_constructor<NumberFormat>(global_object, new_target, &GlobalObject::intl_number_format_prototype)); // 3. Perform ? InitializeNumberFormat(numberFormat, locales, options). - TRY_OR_DISCARD(initialize_number_format(global_object, *number_format, locales, options)); + TRY(initialize_number_format(global_object, *number_format, locales, options)); // 4. If the implementation supports the normative optional constructor mode of 4.3 Note 1, then // a. Let this be the this value. diff --git a/Userland/Libraries/LibJS/Runtime/Intl/NumberFormatConstructor.h b/Userland/Libraries/LibJS/Runtime/Intl/NumberFormatConstructor.h index 853499a688..8e4a7e7e6e 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/NumberFormatConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/Intl/NumberFormatConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~NumberFormatConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/MapConstructor.cpp b/Userland/Libraries/LibJS/Runtime/MapConstructor.cpp index 3744e7ff53..ffe1ac6986 100644 --- a/Userland/Libraries/LibJS/Runtime/MapConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/MapConstructor.cpp @@ -36,31 +36,28 @@ MapConstructor::~MapConstructor() } // 24.1.1.1 Map ( [ iterable ] ), https://tc39.es/ecma262/#sec-map-iterable -Value MapConstructor::call() +ThrowCompletionOr<Value> MapConstructor::call() { auto& vm = this->vm(); - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Map); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Map); } // 24.1.1.1 Map ( [ iterable ] ), https://tc39.es/ecma262/#sec-map-iterable -Value MapConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> MapConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); - auto* map = TRY_OR_DISCARD(ordinary_create_from_constructor<Map>(global_object, new_target, &GlobalObject::map_prototype)); + auto* map = TRY(ordinary_create_from_constructor<Map>(global_object, new_target, &GlobalObject::map_prototype)); if (vm.argument(0).is_nullish()) return map; - 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 {}; - } + auto adder = TRY(map->get(vm.names.set)); + if (!adder.is_function()) + return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, "'set' property of Map"); - TRY_OR_DISCARD(get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) -> Optional<Completion> { + TRY(get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) -> Optional<Completion> { if (!iterator_value.is_object()) return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObject, String::formatted("Iterator value {}", iterator_value.to_string_without_side_effects())); diff --git a/Userland/Libraries/LibJS/Runtime/MapConstructor.h b/Userland/Libraries/LibJS/Runtime/MapConstructor.h index c1eebc2f65..9e9b6104ae 100644 --- a/Userland/Libraries/LibJS/Runtime/MapConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/MapConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~MapConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject&) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/NativeFunction.cpp b/Userland/Libraries/LibJS/Runtime/NativeFunction.cpp index ada146e147..8034f98eea 100644 --- a/Userland/Libraries/LibJS/Runtime/NativeFunction.cpp +++ b/Userland/Libraries/LibJS/Runtime/NativeFunction.cpp @@ -113,8 +113,6 @@ ThrowCompletionOr<Value> NativeFunction::internal_call(Value this_argument, Mark vm.pop_execution_context(); // 12. Return result. - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); return result; } @@ -179,17 +177,15 @@ ThrowCompletionOr<Object*> NativeFunction::internal_construct(MarkedValueList ar vm.pop_execution_context(); // 12. Return result. - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); - return &result.as_object(); + return result; } -Value NativeFunction::call() +ThrowCompletionOr<Value> NativeFunction::call() { - return TRY_OR_DISCARD(m_native_function(vm(), global_object())); + return m_native_function(vm(), global_object()); } -Value NativeFunction::construct(FunctionObject&) +ThrowCompletionOr<Object*> NativeFunction::construct(FunctionObject&) { // Needs to be overridden if [[Construct]] is needed. VERIFY_NOT_REACHED(); diff --git a/Userland/Libraries/LibJS/Runtime/NativeFunction.h b/Userland/Libraries/LibJS/Runtime/NativeFunction.h index 05b1002d40..d028b629f9 100644 --- a/Userland/Libraries/LibJS/Runtime/NativeFunction.h +++ b/Userland/Libraries/LibJS/Runtime/NativeFunction.h @@ -7,6 +7,7 @@ #pragma once #include <AK/Function.h> +#include <LibJS/Runtime/Completion.h> #include <LibJS/Runtime/FunctionObject.h> namespace JS { @@ -26,8 +27,8 @@ public: // Used for [[Call]] / [[Construct]]'s "...result of evaluating F in a manner that conforms to the specification of F". // Needs to be overridden by all NativeFunctions without an m_native_function. - virtual Value call(); - virtual Value construct(FunctionObject& new_target); + virtual ThrowCompletionOr<Value> call(); + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target); virtual const FlyString& name() const override { return m_name; }; virtual bool is_strict_mode() const override; diff --git a/Userland/Libraries/LibJS/Runtime/NumberConstructor.cpp b/Userland/Libraries/LibJS/Runtime/NumberConstructor.cpp index 32a5768e9f..4b2280c956 100644 --- a/Userland/Libraries/LibJS/Runtime/NumberConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/NumberConstructor.cpp @@ -81,27 +81,27 @@ static Value get_value_from_constructor_argument(GlobalObject& global_object) } // 21.1.1.1 Number ( value ), https://tc39.es/ecma262/#sec-number-constructor-number-value -Value NumberConstructor::call() +ThrowCompletionOr<Value> NumberConstructor::call() { auto& vm = this->vm(); auto& global_object = this->global_object(); auto number = get_value_from_constructor_argument(global_object); - if (vm.exception()) - return {}; + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); return number; } // 21.1.1.1 Number ( value ), https://tc39.es/ecma262/#sec-number-constructor-number-value -Value NumberConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> NumberConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); auto number = get_value_from_constructor_argument(global_object); - if (vm.exception()) - return {}; - return TRY_OR_DISCARD(ordinary_create_from_constructor<NumberObject>(global_object, new_target, &GlobalObject::number_prototype, number.as_double())); + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); + return TRY(ordinary_create_from_constructor<NumberObject>(global_object, new_target, &GlobalObject::number_prototype, number.as_double())); } // 21.1.2.2 Number.isFinite ( number ), https://tc39.es/ecma262/#sec-number.isfinite diff --git a/Userland/Libraries/LibJS/Runtime/NumberConstructor.h b/Userland/Libraries/LibJS/Runtime/NumberConstructor.h index 7e898ca606..d74d8c3f77 100644 --- a/Userland/Libraries/LibJS/Runtime/NumberConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/NumberConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~NumberConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp index 4c8fefdf42..4f48450cec 100644 --- a/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp @@ -62,23 +62,23 @@ ObjectConstructor::~ObjectConstructor() } // 20.1.1.1 Object ( [ value ] ), https://tc39.es/ecma262/#sec-object-value -Value ObjectConstructor::call() +ThrowCompletionOr<Value> ObjectConstructor::call() { - return construct(*this); + return TRY(construct(*this)); } // 20.1.1.1 Object ( [ value ] ), https://tc39.es/ecma262/#sec-object-value -Value ObjectConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> ObjectConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); if (&new_target != this) - return TRY_OR_DISCARD(ordinary_create_from_constructor<Object>(global_object, new_target, &GlobalObject::object_prototype)); + return TRY(ordinary_create_from_constructor<Object>(global_object, new_target, &GlobalObject::object_prototype)); auto value = vm.argument(0); if (value.is_nullish()) return Object::create(global_object, global_object.object_prototype()); - return TRY_OR_DISCARD(value.to_object(global_object)); + return value.to_object(global_object); } enum class GetOwnPropertyKeysType { diff --git a/Userland/Libraries/LibJS/Runtime/ObjectConstructor.h b/Userland/Libraries/LibJS/Runtime/ObjectConstructor.h index 24716a5d62..a35a686648 100644 --- a/Userland/Libraries/LibJS/Runtime/ObjectConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/ObjectConstructor.h @@ -19,8 +19,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~ObjectConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp b/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp index 5272d60231..ea33265c66 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp @@ -251,26 +251,23 @@ void PromiseConstructor::initialize(GlobalObject& global_object) } // 27.2.3.1 Promise ( executor ), https://tc39.es/ecma262/#sec-promise-executor -Value PromiseConstructor::call() +ThrowCompletionOr<Value> PromiseConstructor::call() { auto& vm = this->vm(); - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Promise); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Promise); } // 27.2.3.1 Promise ( executor ), https://tc39.es/ecma262/#sec-promise-executor -Value PromiseConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> PromiseConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); auto executor = vm.argument(0); - if (!executor.is_function()) { - vm.throw_exception<TypeError>(global_object, ErrorType::PromiseExecutorNotAFunction); - return {}; - } + if (!executor.is_function()) + return vm.throw_completion<TypeError>(global_object, ErrorType::PromiseExecutorNotAFunction); - auto* promise = TRY_OR_DISCARD(ordinary_create_from_constructor<Promise>(global_object, new_target, &GlobalObject::promise_prototype)); + auto* promise = TRY(ordinary_create_from_constructor<Promise>(global_object, new_target, &GlobalObject::promise_prototype)); auto [resolve_function, reject_function] = promise->create_resolving_functions(); @@ -278,7 +275,7 @@ Value PromiseConstructor::construct(FunctionObject& new_target) if (auto* exception = vm.exception()) { vm.clear_exception(); vm.stop_unwind(); - (void)vm.call(reject_function, js_undefined(), exception->value()); + TRY(vm.call(reject_function, js_undefined(), exception->value())); } return promise; } diff --git a/Userland/Libraries/LibJS/Runtime/PromiseConstructor.h b/Userland/Libraries/LibJS/Runtime/PromiseConstructor.h index 319b124cd0..5650a33e5e 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/PromiseConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~PromiseConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/PromiseJobs.cpp b/Userland/Libraries/LibJS/Runtime/PromiseJobs.cpp index 319670ea26..ec6504beb0 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseJobs.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromiseJobs.cpp @@ -26,7 +26,7 @@ PromiseReactionJob::PromiseReactionJob(PromiseReaction& reaction, Value argument } // 27.2.2.1 NewPromiseReactionJob ( reaction, argument ), https://tc39.es/ecma262/#sec-newpromisereactionjob -Value PromiseReactionJob::call() +ThrowCompletionOr<Value> PromiseReactionJob::call() { auto& vm = this->vm(); auto& promise_capability = m_reaction.capability(); @@ -64,11 +64,11 @@ Value PromiseReactionJob::call() vm.stop_unwind(); auto* reject_function = promise_capability.value().reject; dbgln_if(PROMISE_DEBUG, "[PromiseReactionJob @ {}]: Calling PromiseCapability's reject function @ {}", this, reject_function); - return TRY_OR_DISCARD(vm.call(*reject_function, js_undefined(), handler_result)); + return vm.call(*reject_function, js_undefined(), handler_result); } else { auto* resolve_function = promise_capability.value().resolve; dbgln_if(PROMISE_DEBUG, "[PromiseReactionJob @ {}]: Calling PromiseCapability's resolve function @ {}", this, resolve_function); - return TRY_OR_DISCARD(vm.call(*resolve_function, js_undefined(), handler_result)); + return vm.call(*resolve_function, js_undefined(), handler_result); } } @@ -94,7 +94,7 @@ PromiseResolveThenableJob::PromiseResolveThenableJob(Promise& promise_to_resolve } // 27.2.2.2 NewPromiseResolveThenableJob ( promiseToResolve, thenable, then ), https://tc39.es/ecma262/#sec-newpromiseresolvethenablejob -Value PromiseResolveThenableJob::call() +ThrowCompletionOr<Value> PromiseResolveThenableJob::call() { auto& vm = this->vm(); auto [resolve_function, reject_function] = m_promise_to_resolve.create_resolving_functions(); diff --git a/Userland/Libraries/LibJS/Runtime/PromiseJobs.h b/Userland/Libraries/LibJS/Runtime/PromiseJobs.h index 82262aeed4..8405e56326 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseJobs.h +++ b/Userland/Libraries/LibJS/Runtime/PromiseJobs.h @@ -22,7 +22,7 @@ public: explicit PromiseReactionJob(PromiseReaction&, Value argument, Object& prototype); virtual ~PromiseReactionJob() override = default; - virtual Value call() override; + virtual ThrowCompletionOr<Value> call() override; private: virtual void visit_edges(Visitor&) override; @@ -40,7 +40,7 @@ public: explicit PromiseResolveThenableJob(Promise&, Value thenable, JobCallback then, Object& prototype); virtual ~PromiseResolveThenableJob() override = default; - virtual Value call() override; + virtual ThrowCompletionOr<Value> call() override; private: virtual void visit_edges(Visitor&) override; diff --git a/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.cpp b/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.cpp index 2f068b35d5..d1d77fc517 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.cpp @@ -28,7 +28,7 @@ void PromiseResolvingElementFunction::initialize(GlobalObject& global_object) define_direct_property(vm().names.length, Value(1), Attribute::Configurable); } -Value PromiseResolvingElementFunction::call() +ThrowCompletionOr<Value> PromiseResolvingElementFunction::call() { if (m_already_called) return js_undefined(); diff --git a/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.h b/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.h index feecc2d76a..0c56aeae0a 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.h +++ b/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.h @@ -46,7 +46,7 @@ public: virtual void initialize(GlobalObject&) override; virtual ~PromiseResolvingElementFunction() override = default; - virtual Value call() override; + virtual ThrowCompletionOr<Value> call() override; protected: explicit PromiseResolvingElementFunction(size_t, PromiseValueList&, PromiseCapability, RemainingElements&, Object& prototype); diff --git a/Userland/Libraries/LibJS/Runtime/PromiseResolvingFunction.cpp b/Userland/Libraries/LibJS/Runtime/PromiseResolvingFunction.cpp index 87264a9c1a..fcafeed728 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseResolvingFunction.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromiseResolvingFunction.cpp @@ -30,9 +30,9 @@ void PromiseResolvingFunction::initialize(GlobalObject& global_object) define_direct_property(vm().names.length, Value(1), Attribute::Configurable); } -Value PromiseResolvingFunction::call() +ThrowCompletionOr<Value> PromiseResolvingFunction::call() { - return TRY_OR_DISCARD(m_native_function(vm(), global_object(), m_promise, m_already_resolved)); + return m_native_function(vm(), global_object(), m_promise, m_already_resolved); } void PromiseResolvingFunction::visit_edges(Cell::Visitor& visitor) diff --git a/Userland/Libraries/LibJS/Runtime/PromiseResolvingFunction.h b/Userland/Libraries/LibJS/Runtime/PromiseResolvingFunction.h index ceb11e7315..b200b0b068 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseResolvingFunction.h +++ b/Userland/Libraries/LibJS/Runtime/PromiseResolvingFunction.h @@ -33,7 +33,7 @@ public: virtual void initialize(GlobalObject&) override; virtual ~PromiseResolvingFunction() override = default; - virtual Value call() override; + virtual ThrowCompletionOr<Value> call() override; private: virtual void visit_edges(Visitor&) override; diff --git a/Userland/Libraries/LibJS/Runtime/ProxyConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ProxyConstructor.cpp index 33596e4f53..1e8e0ebad2 100644 --- a/Userland/Libraries/LibJS/Runtime/ProxyConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/ProxyConstructor.cpp @@ -48,18 +48,20 @@ ProxyConstructor::~ProxyConstructor() } // 28.2.1.1 Proxy ( target, handler ), https://tc39.es/ecma262/#sec-proxy-target-handler -Value ProxyConstructor::call() +ThrowCompletionOr<Value> ProxyConstructor::call() { auto& vm = this->vm(); - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Proxy); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Proxy); } // 28.2.1.1 Proxy ( target, handler ), https://tc39.es/ecma262/#sec-proxy-target-handler -Value ProxyConstructor::construct(FunctionObject&) +ThrowCompletionOr<Object*> ProxyConstructor::construct(FunctionObject&) { auto& vm = this->vm(); - return proxy_create(global_object(), vm.argument(0), vm.argument(1)); + auto* proxy = proxy_create(global_object(), vm.argument(0), vm.argument(1)); + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); + return proxy; } // 28.2.2.1 Proxy.revocable ( target, handler ), https://tc39.es/ecma262/#sec-proxy.revocable diff --git a/Userland/Libraries/LibJS/Runtime/ProxyConstructor.h b/Userland/Libraries/LibJS/Runtime/ProxyConstructor.h index e2d87a7d40..9d0c776477 100644 --- a/Userland/Libraries/LibJS/Runtime/ProxyConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/ProxyConstructor.h @@ -19,8 +19,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~ProxyConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/RegExpConstructor.cpp b/Userland/Libraries/LibJS/Runtime/RegExpConstructor.cpp index 6320e826b9..cf5de31032 100644 --- a/Userland/Libraries/LibJS/Runtime/RegExpConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/RegExpConstructor.cpp @@ -34,7 +34,7 @@ RegExpConstructor::~RegExpConstructor() } // 22.2.3.1 RegExp ( pattern, flags ), https://tc39.es/ecma262/#sec-regexp-pattern-flags -Value RegExpConstructor::call() +ThrowCompletionOr<Value> RegExpConstructor::call() { auto& vm = this->vm(); auto& global_object = this->global_object(); @@ -42,19 +42,19 @@ Value RegExpConstructor::call() auto pattern = vm.argument(0); auto flags = vm.argument(1); - bool pattern_is_regexp = TRY_OR_DISCARD(pattern.is_regexp(global_object)); + bool pattern_is_regexp = TRY(pattern.is_regexp(global_object)); if (pattern_is_regexp && flags.is_undefined()) { - auto pattern_constructor = TRY_OR_DISCARD(pattern.as_object().get(vm.names.constructor)); + auto pattern_constructor = TRY(pattern.as_object().get(vm.names.constructor)); if (same_value(this, pattern_constructor)) return pattern; } - return construct(*this); + return TRY(construct(*this)); } // 22.2.3.1 RegExp ( pattern, flags ), https://tc39.es/ecma262/#sec-regexp-pattern-flags -Value RegExpConstructor::construct(FunctionObject&) +ThrowCompletionOr<Object*> RegExpConstructor::construct(FunctionObject&) { auto& vm = this->vm(); auto& global_object = this->global_object(); @@ -62,7 +62,7 @@ Value RegExpConstructor::construct(FunctionObject&) auto pattern = vm.argument(0); auto flags = vm.argument(1); - bool pattern_is_regexp = TRY_OR_DISCARD(pattern.is_regexp(global_object)); + bool pattern_is_regexp = TRY(pattern.is_regexp(global_object)); Value pattern_value; Value flags_value; @@ -76,10 +76,10 @@ Value RegExpConstructor::construct(FunctionObject&) else flags_value = flags; } else if (pattern_is_regexp) { - pattern_value = TRY_OR_DISCARD(pattern.as_object().get(vm.names.source)); + pattern_value = TRY(pattern.as_object().get(vm.names.source)); if (flags.is_undefined()) { - flags_value = TRY_OR_DISCARD(pattern.as_object().get(vm.names.flags)); + flags_value = TRY(pattern.as_object().get(vm.names.flags)); } else { flags_value = flags; } @@ -88,7 +88,10 @@ Value RegExpConstructor::construct(FunctionObject&) flags_value = flags; } - return regexp_create(global_object, pattern_value, flags_value); + auto* regexp = regexp_create(global_object, pattern_value, flags_value); + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); + return regexp; } // 22.2.4.2 get RegExp [ @@species ], https://tc39.es/ecma262/#sec-get-regexp-@@species diff --git a/Userland/Libraries/LibJS/Runtime/RegExpConstructor.h b/Userland/Libraries/LibJS/Runtime/RegExpConstructor.h index b3ea4a61ff..9cb23dac9b 100644 --- a/Userland/Libraries/LibJS/Runtime/RegExpConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/RegExpConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~RegExpConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/SetConstructor.cpp b/Userland/Libraries/LibJS/Runtime/SetConstructor.cpp index 0bd301d452..64c64306ef 100644 --- a/Userland/Libraries/LibJS/Runtime/SetConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/SetConstructor.cpp @@ -36,31 +36,28 @@ SetConstructor::~SetConstructor() } // 24.2.1.1 Set ( [ iterable ] ), https://tc39.es/ecma262/#sec-set-iterable -Value SetConstructor::call() +ThrowCompletionOr<Value> SetConstructor::call() { auto& vm = this->vm(); - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Set); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Set); } // 24.2.1.1 Set ( [ iterable ] ), https://tc39.es/ecma262/#sec-set-iterable -Value SetConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> SetConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); - auto* set = TRY_OR_DISCARD(ordinary_create_from_constructor<Set>(global_object, new_target, &GlobalObject::set_prototype)); + auto* set = TRY(ordinary_create_from_constructor<Set>(global_object, new_target, &GlobalObject::set_prototype)); if (vm.argument(0).is_nullish()) return set; - 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 {}; - } + auto adder = TRY(set->get(vm.names.add)); + if (!adder.is_function()) + return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, "'add' property of Set"); - TRY_OR_DISCARD(get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) -> Optional<Completion> { + TRY(get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) -> Optional<Completion> { TRY(vm.call(adder.as_function(), Value(set), iterator_value)); return {}; })); diff --git a/Userland/Libraries/LibJS/Runtime/SetConstructor.h b/Userland/Libraries/LibJS/Runtime/SetConstructor.h index 2221775ae3..1f49d69fa8 100644 --- a/Userland/Libraries/LibJS/Runtime/SetConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/SetConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~SetConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject&) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/ShadowRealmConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ShadowRealmConstructor.cpp index 8b83c85331..cd8da12739 100644 --- a/Userland/Libraries/LibJS/Runtime/ShadowRealmConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/ShadowRealmConstructor.cpp @@ -28,17 +28,16 @@ void ShadowRealmConstructor::initialize(GlobalObject& global_object) } // 3.2.1 ShadowRealm ( ), https://tc39.es/proposal-shadowrealm/#sec-shadowrealm -Value ShadowRealmConstructor::call() +ThrowCompletionOr<Value> ShadowRealmConstructor::call() { auto& vm = this->vm(); // 1. If NewTarget is undefined, throw a TypeError exception. - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ShadowRealm); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ShadowRealm); } // 3.2.1 ShadowRealm ( ), https://tc39.es/proposal-shadowrealm/#sec-shadowrealm -Value ShadowRealmConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> ShadowRealmConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); @@ -61,7 +60,7 @@ Value ShadowRealmConstructor::construct(FunctionObject& new_target) // 2. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%ShadowRealm.prototype%", « [[ShadowRealm]], [[ExecutionContext]] »). // 4. Set O.[[ShadowRealm]] to realmRec. // 9. Set O.[[ExecutionContext]] to context. - auto* object = TRY_OR_DISCARD(ordinary_create_from_constructor<ShadowRealm>(global_object, new_target, &GlobalObject::shadow_realm_prototype, *realm, move(context))); + auto* object = TRY(ordinary_create_from_constructor<ShadowRealm>(global_object, new_target, &GlobalObject::shadow_realm_prototype, *realm, move(context))); // 10. Perform ? SetRealmGlobalObject(realmRec, undefined, undefined). auto* new_global_object = vm.heap().allocate_without_global_object<GlobalObject>(); diff --git a/Userland/Libraries/LibJS/Runtime/ShadowRealmConstructor.h b/Userland/Libraries/LibJS/Runtime/ShadowRealmConstructor.h index d84581ea9c..bdbd160bfe 100644 --- a/Userland/Libraries/LibJS/Runtime/ShadowRealmConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/ShadowRealmConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~ShadowRealmConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/StringConstructor.cpp b/Userland/Libraries/LibJS/Runtime/StringConstructor.cpp index 9c4b5ad5ca..b6576656e6 100644 --- a/Userland/Libraries/LibJS/Runtime/StringConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/StringConstructor.cpp @@ -43,17 +43,17 @@ StringConstructor::~StringConstructor() } // 22.1.1.1 String ( value ), https://tc39.es/ecma262/#sec-string-constructor-string-value -Value StringConstructor::call() +ThrowCompletionOr<Value> StringConstructor::call() { if (!vm().argument_count()) return js_string(heap(), ""); if (vm().argument(0).is_symbol()) return js_string(heap(), vm().argument(0).as_symbol().to_string()); - return TRY_OR_DISCARD(vm().argument(0).to_primitive_string(global_object())); + return TRY(vm().argument(0).to_primitive_string(global_object())); } // 22.1.1.1 String ( value ), https://tc39.es/ecma262/#sec-string-constructor-string-value -Value StringConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> StringConstructor::construct(FunctionObject& new_target) { auto& vm = global_object().vm(); @@ -61,8 +61,8 @@ Value StringConstructor::construct(FunctionObject& new_target) if (!vm.argument_count()) primitive_string = js_string(vm, ""); else - primitive_string = TRY_OR_DISCARD(vm.argument(0).to_primitive_string(global_object())); - auto* prototype = TRY_OR_DISCARD(get_prototype_from_constructor(global_object(), new_target, &GlobalObject::string_prototype)); + primitive_string = TRY(vm.argument(0).to_primitive_string(global_object())); + auto* prototype = TRY(get_prototype_from_constructor(global_object(), new_target, &GlobalObject::string_prototype)); return StringObject::create(global_object(), *primitive_string, *prototype); } diff --git a/Userland/Libraries/LibJS/Runtime/StringConstructor.h b/Userland/Libraries/LibJS/Runtime/StringConstructor.h index 47085ec340..053ba074d4 100644 --- a/Userland/Libraries/LibJS/Runtime/StringConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/StringConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~StringConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/SymbolConstructor.cpp b/Userland/Libraries/LibJS/Runtime/SymbolConstructor.cpp index b5f4afef12..4fefdea077 100644 --- a/Userland/Libraries/LibJS/Runtime/SymbolConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/SymbolConstructor.cpp @@ -40,18 +40,17 @@ SymbolConstructor::~SymbolConstructor() } // 20.4.1.1 Symbol ( [ description ] ), https://tc39.es/ecma262/#sec-symbol-description -Value SymbolConstructor::call() +ThrowCompletionOr<Value> SymbolConstructor::call() { if (vm().argument(0).is_undefined()) return js_symbol(heap(), {}, false); - return js_symbol(heap(), TRY_OR_DISCARD(vm().argument(0).to_string(global_object())), false); + return js_symbol(heap(), TRY(vm().argument(0).to_string(global_object())), false); } // 20.4.1.1 Symbol ( [ description ] ), https://tc39.es/ecma262/#sec-symbol-description -Value SymbolConstructor::construct(FunctionObject&) +ThrowCompletionOr<Object*> SymbolConstructor::construct(FunctionObject&) { - vm().throw_exception<TypeError>(global_object(), ErrorType::NotAConstructor, "Symbol"); - return {}; + return vm().throw_completion<TypeError>(global_object(), ErrorType::NotAConstructor, "Symbol"); } // 20.4.2.2 Symbol.for ( key ), https://tc39.es/ecma262/#sec-symbol.for diff --git a/Userland/Libraries/LibJS/Runtime/SymbolConstructor.h b/Userland/Libraries/LibJS/Runtime/SymbolConstructor.h index aa06900c45..e4cfaf568c 100644 --- a/Userland/Libraries/LibJS/Runtime/SymbolConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/SymbolConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~SymbolConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/CalendarConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/CalendarConstructor.cpp index d494236c1e..5a9bc03892 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/CalendarConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/CalendarConstructor.cpp @@ -32,34 +32,32 @@ void CalendarConstructor::initialize(GlobalObject& global_object) } // 12.2.1 Temporal.Calendar ( id ), https://tc39.es/proposal-temporal/#sec-temporal.calendar -Value CalendarConstructor::call() +ThrowCompletionOr<Value> CalendarConstructor::call() { auto& vm = this->vm(); // 1. If NewTarget is undefined, then // a. Throw a TypeError exception. - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Calendar"); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Calendar"); } // 12.2.1 Temporal.Calendar ( id ), https://tc39.es/proposal-temporal/#sec-temporal.calendar -Value CalendarConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> CalendarConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); // 2. Set id to ? ToString(id). - auto identifier = TRY_OR_DISCARD(vm.argument(0).to_string(global_object)); + auto identifier = TRY(vm.argument(0).to_string(global_object)); // 3. If ! IsBuiltinCalendar(id) is false, then if (!is_builtin_calendar(identifier)) { // a. Throw a RangeError exception. - vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidCalendarIdentifier, identifier); - return {}; + return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidCalendarIdentifier, identifier); } // 4. Return ? CreateTemporalCalendar(id, NewTarget). - return TRY_OR_DISCARD(create_temporal_calendar(global_object, identifier, &new_target)); + return TRY(create_temporal_calendar(global_object, identifier, &new_target)); } // 12.3.2 Temporal.Calendar.from ( item ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.from diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/CalendarConstructor.h b/Userland/Libraries/LibJS/Runtime/Temporal/CalendarConstructor.h index 10ae604691..f4bdd3ce9c 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/CalendarConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/CalendarConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~CalendarConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/DurationConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/DurationConstructor.cpp index d5b52f3203..8c898e6c9b 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/DurationConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/DurationConstructor.cpp @@ -34,54 +34,53 @@ void DurationConstructor::initialize(GlobalObject& global_object) } // 7.1.1 Temporal.Duration ( [ years [ , months [ , weeks [ , days [ , hours [ , minutes [ , seconds [ , milliseconds [ , microseconds [ , nanoseconds ] ] ] ] ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.duration -Value DurationConstructor::call() +ThrowCompletionOr<Value> DurationConstructor::call() { auto& vm = this->vm(); // 1. If NewTarget is undefined, then // a. Throw a TypeError exception. - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Duration"); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Duration"); } // 7.1.1 Temporal.Duration ( [ years [ , months [ , weeks [ , days [ , hours [ , minutes [ , seconds [ , milliseconds [ , microseconds [ , nanoseconds ] ] ] ] ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.duration -Value DurationConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> DurationConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); // 2. Let y be ? ToIntegerThrowOnInfinity(years). - auto y = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(0), ErrorType::TemporalInvalidDuration)); + auto y = TRY(to_integer_throw_on_infinity(global_object, vm.argument(0), ErrorType::TemporalInvalidDuration)); // 3. Let mo be ? ToIntegerThrowOnInfinity(months). - auto mo = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(1), ErrorType::TemporalInvalidDuration)); + auto mo = TRY(to_integer_throw_on_infinity(global_object, vm.argument(1), ErrorType::TemporalInvalidDuration)); // 4. Let w be ? ToIntegerThrowOnInfinity(weeks). - auto w = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(2), ErrorType::TemporalInvalidDuration)); + auto w = TRY(to_integer_throw_on_infinity(global_object, vm.argument(2), ErrorType::TemporalInvalidDuration)); // 5. Let d be ? ToIntegerThrowOnInfinity(days). - auto d = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(3), ErrorType::TemporalInvalidDuration)); + auto d = TRY(to_integer_throw_on_infinity(global_object, vm.argument(3), ErrorType::TemporalInvalidDuration)); // 6. Let h be ? ToIntegerThrowOnInfinity(hours). - auto h = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(4), ErrorType::TemporalInvalidDuration)); + auto h = TRY(to_integer_throw_on_infinity(global_object, vm.argument(4), ErrorType::TemporalInvalidDuration)); // 7. Let m be ? ToIntegerThrowOnInfinity(minutes). - auto m = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(5), ErrorType::TemporalInvalidDuration)); + auto m = TRY(to_integer_throw_on_infinity(global_object, vm.argument(5), ErrorType::TemporalInvalidDuration)); // 8. Let s be ? ToIntegerThrowOnInfinity(seconds). - auto s = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(6), ErrorType::TemporalInvalidDuration)); + auto s = TRY(to_integer_throw_on_infinity(global_object, vm.argument(6), ErrorType::TemporalInvalidDuration)); // 9. Let ms be ? ToIntegerThrowOnInfinity(milliseconds). - auto ms = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(7), ErrorType::TemporalInvalidDuration)); + auto ms = TRY(to_integer_throw_on_infinity(global_object, vm.argument(7), ErrorType::TemporalInvalidDuration)); // 10. Let mis be ? ToIntegerThrowOnInfinity(microseconds). - auto mis = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(8), ErrorType::TemporalInvalidDuration)); + auto mis = TRY(to_integer_throw_on_infinity(global_object, vm.argument(8), ErrorType::TemporalInvalidDuration)); // 11. Let ns be ? ToIntegerThrowOnInfinity(nanoseconds). - auto ns = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(9), ErrorType::TemporalInvalidDuration)); + auto ns = TRY(to_integer_throw_on_infinity(global_object, vm.argument(9), ErrorType::TemporalInvalidDuration)); // 12. Return ? CreateTemporalDuration(y, mo, w, d, h, m, s, ms, mis, ns, NewTarget). - return TRY_OR_DISCARD(create_temporal_duration(global_object, y, mo, w, d, h, m, s, ms, mis, ns, &new_target)); + return TRY(create_temporal_duration(global_object, y, mo, w, d, h, m, s, ms, mis, ns, &new_target)); } // 7.2.2 Temporal.Duration.from ( item ), https://tc39.es/proposal-temporal/#sec-temporal.duration.from diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/DurationConstructor.h b/Userland/Libraries/LibJS/Runtime/Temporal/DurationConstructor.h index f431f4c658..47a2f1ddf2 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/DurationConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/DurationConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~DurationConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.cpp index 2e40a4bf35..c765422f9a 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.cpp @@ -39,33 +39,30 @@ void InstantConstructor::initialize(GlobalObject& global_object) } // 8.1.1 Temporal.Instant ( epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal.instant -Value InstantConstructor::call() +ThrowCompletionOr<Value> InstantConstructor::call() { auto& vm = this->vm(); // 1. If NewTarget is undefined, then // a. Throw a TypeError exception. - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Instant"); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Instant"); } // 8.1.1 Temporal.Instant ( epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal.instant -Value InstantConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> InstantConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); // 2. Let epochNanoseconds be ? ToBigInt(epochNanoseconds). - auto* epoch_nanoseconds = TRY_OR_DISCARD(vm.argument(0).to_bigint(global_object)); + auto* epoch_nanoseconds = TRY(vm.argument(0).to_bigint(global_object)); // 3. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception. - if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds)) { - vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidEpochNanoseconds); - return {}; - } + if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds)) + return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidEpochNanoseconds); // 4. Return ? CreateTemporalInstant(epochNanoseconds, NewTarget). - return TRY_OR_DISCARD(create_temporal_instant(global_object, *epoch_nanoseconds, &new_target)); + return TRY(create_temporal_instant(global_object, *epoch_nanoseconds, &new_target)); } // 8.2.2 Temporal.Instant.from ( item ), https://tc39.es/proposal-temporal/#sec-temporal.instant.from diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.h b/Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.h index cdce6d7d97..3f8581f2f6 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/InstantConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~InstantConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateConstructor.cpp index 4ffd49a4c0..c7aeed99bc 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateConstructor.cpp @@ -37,43 +37,40 @@ void PlainDateConstructor::initialize(GlobalObject& global_object) } // 3.1.1 Temporal.PlainDate ( isoYear, isoMonth, isoDay [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate -Value PlainDateConstructor::call() +ThrowCompletionOr<Value> PlainDateConstructor::call() { auto& vm = this->vm(); // 1. If NewTarget is undefined, throw a TypeError exception. - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainDate"); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainDate"); } // 3.1.1 Temporal.PlainDate ( isoYear, isoMonth, isoDay [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate -Value PlainDateConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> PlainDateConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); // 2. Let y be ? ToIntegerThrowOnInfinity(isoYear). - auto y = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(0), ErrorType::TemporalInvalidPlainDate)); + auto y = TRY(to_integer_throw_on_infinity(global_object, vm.argument(0), ErrorType::TemporalInvalidPlainDate)); // 3. Let m be ? ToIntegerThrowOnInfinity(isoMonth). - auto m = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(1), ErrorType::TemporalInvalidPlainDate)); + auto m = TRY(to_integer_throw_on_infinity(global_object, vm.argument(1), ErrorType::TemporalInvalidPlainDate)); // 4. Let d be ? ToIntegerThrowOnInfinity(isoDay). - auto d = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(2), ErrorType::TemporalInvalidPlainDate)); + auto d = TRY(to_integer_throw_on_infinity(global_object, vm.argument(2), ErrorType::TemporalInvalidPlainDate)); // 5. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). - auto* calendar = TRY_OR_DISCARD(to_temporal_calendar_with_iso_default(global_object, vm.argument(3))); + auto* calendar = TRY(to_temporal_calendar_with_iso_default(global_object, vm.argument(3))); // IMPLEMENTATION DEFINED: This is an optimization that allows us to treat these doubles as normal integers from this point onwards. // This does not change the exposed behavior as the call to CreateTemporalDate will immediately check that these values are valid // ISO values (for years: -273975 - 273975, for months: 1 - 12, for days: 1 - 31) all of which are subsets of this check. - if (!AK::is_within_range<i32>(y) || !AK::is_within_range<u8>(m) || !AK::is_within_range<u8>(d)) { - vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainDate); - return {}; - } + if (!AK::is_within_range<i32>(y) || !AK::is_within_range<u8>(m) || !AK::is_within_range<u8>(d)) + return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidPlainDate); // 6. Return ? CreateTemporalDate(y, m, d, calendar, NewTarget). - return TRY_OR_DISCARD(create_temporal_date(global_object, y, m, d, *calendar, &new_target)); + return TRY(create_temporal_date(global_object, y, m, d, *calendar, &new_target)); } // 3.2.2 Temporal.PlainDate.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.from diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateConstructor.h b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateConstructor.h index 4df961ddf2..7c790a6a7c 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~PlainDateConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTimeConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTimeConstructor.cpp index ebd70a63f4..decb35c759 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTimeConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTimeConstructor.cpp @@ -37,62 +37,59 @@ void PlainDateTimeConstructor::initialize(GlobalObject& global_object) } // 5.1.1 Temporal.PlainDateTime ( isoYear, isoMonth, isoDay [ , hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond [ , calendarLike ] ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime -Value PlainDateTimeConstructor::call() +ThrowCompletionOr<Value> PlainDateTimeConstructor::call() { auto& vm = this->vm(); // 1. If NewTarget is undefined, throw a TypeError exception. - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainDateTime"); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainDateTime"); } // 5.1.1 Temporal.PlainDateTime ( isoYear, isoMonth, isoDay [ , hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond [ , calendarLike ] ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime -Value PlainDateTimeConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> PlainDateTimeConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); // 2. Let isoYear be ? ToIntegerThrowOnInfinity(isoYear). - auto iso_year = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(0), ErrorType::TemporalInvalidPlainDateTime)); + auto iso_year = TRY(to_integer_throw_on_infinity(global_object, vm.argument(0), ErrorType::TemporalInvalidPlainDateTime)); // 3. Let isoMonth be ? ToIntegerThrowOnInfinity(isoMonth). - auto iso_month = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(1), ErrorType::TemporalInvalidPlainDateTime)); + auto iso_month = TRY(to_integer_throw_on_infinity(global_object, vm.argument(1), ErrorType::TemporalInvalidPlainDateTime)); // 4. Let isoDay be ? ToIntegerThrowOnInfinity(isoDay). - auto iso_day = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(2), ErrorType::TemporalInvalidPlainDateTime)); + auto iso_day = TRY(to_integer_throw_on_infinity(global_object, vm.argument(2), ErrorType::TemporalInvalidPlainDateTime)); // 5. Let hour be ? ToIntegerThrowOnInfinity(hour). - auto hour = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(3), ErrorType::TemporalInvalidPlainDateTime)); + auto hour = TRY(to_integer_throw_on_infinity(global_object, vm.argument(3), ErrorType::TemporalInvalidPlainDateTime)); // 6. Let minute be ? ToIntegerThrowOnInfinity(minute). - auto minute = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(4), ErrorType::TemporalInvalidPlainDateTime)); + auto minute = TRY(to_integer_throw_on_infinity(global_object, vm.argument(4), ErrorType::TemporalInvalidPlainDateTime)); // 7. Let second be ? ToIntegerThrowOnInfinity(second). - auto second = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(5), ErrorType::TemporalInvalidPlainDateTime)); + auto second = TRY(to_integer_throw_on_infinity(global_object, vm.argument(5), ErrorType::TemporalInvalidPlainDateTime)); // 8. Let millisecond be ? ToIntegerThrowOnInfinity(millisecond). - auto millisecond = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(6), ErrorType::TemporalInvalidPlainDateTime)); + auto millisecond = TRY(to_integer_throw_on_infinity(global_object, vm.argument(6), ErrorType::TemporalInvalidPlainDateTime)); // 9. Let microsecond be ? ToIntegerThrowOnInfinity(microsecond). - auto microsecond = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(7), ErrorType::TemporalInvalidPlainDateTime)); + auto microsecond = TRY(to_integer_throw_on_infinity(global_object, vm.argument(7), ErrorType::TemporalInvalidPlainDateTime)); // 10. Let nanosecond be ? ToIntegerThrowOnInfinity(nanosecond). - auto nanosecond = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(8), ErrorType::TemporalInvalidPlainDateTime)); + auto nanosecond = TRY(to_integer_throw_on_infinity(global_object, vm.argument(8), ErrorType::TemporalInvalidPlainDateTime)); // 11. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). - auto* calendar = TRY_OR_DISCARD(to_temporal_calendar_with_iso_default(global_object, vm.argument(9))); + auto* calendar = TRY(to_temporal_calendar_with_iso_default(global_object, vm.argument(9))); // IMPLEMENTATION DEFINED: This is an optimization that allows us to treat these doubles as normal integers from this point onwards. // This does not change the exposed behavior as the call to CreateTemporalDateTime will immediately check that these values are valid // ISO values (for years: -273975 - 273975, for months: 1 - 12, for days: 1 - 31, for hours: 0 - 23, for minutes and seconds: 0 - 59, // milliseconds, microseconds, and nanoseconds: 0 - 999) all of which are subsets of this check. - if (!AK::is_within_range<i32>(iso_year) || !AK::is_within_range<u8>(iso_month) || !AK::is_within_range<u8>(iso_day) || !AK::is_within_range<u8>(hour) || !AK::is_within_range<u8>(minute) || !AK::is_within_range<u8>(second) || !AK::is_within_range<u16>(millisecond) || !AK::is_within_range<u16>(microsecond) || !AK::is_within_range<u16>(nanosecond)) { - vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainDateTime); - return {}; - } + if (!AK::is_within_range<i32>(iso_year) || !AK::is_within_range<u8>(iso_month) || !AK::is_within_range<u8>(iso_day) || !AK::is_within_range<u8>(hour) || !AK::is_within_range<u8>(minute) || !AK::is_within_range<u8>(second) || !AK::is_within_range<u16>(millisecond) || !AK::is_within_range<u16>(microsecond) || !AK::is_within_range<u16>(nanosecond)) + return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidPlainDateTime); // 12. Return ? CreateTemporalDateTime(isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, nanosecond, calendar, NewTarget). - return TRY_OR_DISCARD(create_temporal_date_time(global_object, iso_year, iso_month, iso_day, hour, minute, second, millisecond, microsecond, nanosecond, *calendar, &new_target)); + return TRY(create_temporal_date_time(global_object, iso_year, iso_month, iso_day, hour, minute, second, millisecond, microsecond, nanosecond, *calendar, &new_target)); } // 5.2.2 Temporal.PlainDateTime.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.from diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTimeConstructor.h b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTimeConstructor.h index 0d9941a842..c561fb5723 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTimeConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTimeConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~PlainDateTimeConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainMonthDayConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/PlainMonthDayConstructor.cpp index fa6fdfb355..08392178f9 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainMonthDayConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainMonthDayConstructor.cpp @@ -35,17 +35,16 @@ void PlainMonthDayConstructor::initialize(GlobalObject& global_object) } // 10.1.1 Temporal.PlainMonthDay ( isoMonth, isoDay [ , calendarLike [ , referenceISOYear ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday -Value PlainMonthDayConstructor::call() +ThrowCompletionOr<Value> PlainMonthDayConstructor::call() { auto& vm = this->vm(); // 1. If NewTarget is undefined, throw a TypeError exception. - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainMonthDay"); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainMonthDay"); } // 10.1.1 Temporal.PlainMonthDay ( isoMonth, isoDay [ , calendarLike [ , referenceISOYear ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday -Value PlainMonthDayConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> PlainMonthDayConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); @@ -62,27 +61,25 @@ Value PlainMonthDayConstructor::construct(FunctionObject& new_target) } // 3. Let m be ? ToIntegerThrowOnInfinity(isoMonth). - auto m = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, iso_month, ErrorType::TemporalInvalidPlainMonthDay)); + auto m = TRY(to_integer_throw_on_infinity(global_object, iso_month, ErrorType::TemporalInvalidPlainMonthDay)); // 4. Let d be ? ToIntegerThrowOnInfinity(isoDay). - auto d = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, iso_day, ErrorType::TemporalInvalidPlainMonthDay)); + auto d = TRY(to_integer_throw_on_infinity(global_object, iso_day, ErrorType::TemporalInvalidPlainMonthDay)); // 5. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). - auto* calendar = TRY_OR_DISCARD(to_temporal_calendar_with_iso_default(global_object, calendar_like)); + auto* calendar = TRY(to_temporal_calendar_with_iso_default(global_object, calendar_like)); // 6. Let ref be ? ToIntegerThrowOnInfinity(referenceISOYear). - auto ref = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, reference_iso_year, ErrorType::TemporalInvalidPlainMonthDay)); + auto ref = TRY(to_integer_throw_on_infinity(global_object, reference_iso_year, ErrorType::TemporalInvalidPlainMonthDay)); // IMPLEMENTATION DEFINED: This is an optimization that allows us to treat these doubles as normal integers from this point onwards. // This does not change the exposed behavior as the call to CreateTemporalMonthDay will immediately check that these values are valid // ISO values (for years: -273975 - 273975, for months: 1 - 12, for days: 1 - 31) all of which are subsets of this check. - if (!AK::is_within_range<i32>(ref) || !AK::is_within_range<u8>(m) || !AK::is_within_range<u8>(d)) { - vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainYearMonth); - return {}; - } + if (!AK::is_within_range<i32>(ref) || !AK::is_within_range<u8>(m) || !AK::is_within_range<u8>(d)) + return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidPlainYearMonth); // 7. Return ? CreateTemporalMonthDay(m, d, calendar, ref, NewTarget). - return TRY_OR_DISCARD(create_temporal_month_day(global_object, m, d, *calendar, ref, &new_target)); + return TRY(create_temporal_month_day(global_object, m, d, *calendar, ref, &new_target)); } // 10.2.2 Temporal.PlainMonthDay.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday.from diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainMonthDayConstructor.h b/Userland/Libraries/LibJS/Runtime/Temporal/PlainMonthDayConstructor.h index e1b9690eb9..418d45188a 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainMonthDayConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainMonthDayConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~PlainMonthDayConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.cpp index 473eeb8dcc..2323b8473b 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.cpp @@ -35,50 +35,47 @@ void PlainTimeConstructor::initialize(GlobalObject& global_object) } // 4.1.1 Temporal.PlainTime ( [ hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime -Value PlainTimeConstructor::call() +ThrowCompletionOr<Value> PlainTimeConstructor::call() { auto& vm = this->vm(); // 1. If NewTarget is undefined, throw a TypeError exception. - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainTime"); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainTime"); } // 4.1.1 Temporal.PlainTime ( [ hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime -Value PlainTimeConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> PlainTimeConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); // 2. Let hour be ? ToIntegerThrowOnInfinity(hour). - auto hour = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(0), ErrorType::TemporalInvalidPlainTime)); + auto hour = TRY(to_integer_throw_on_infinity(global_object, vm.argument(0), ErrorType::TemporalInvalidPlainTime)); // 3. Let minute be ? ToIntegerThrowOnInfinity(hour). - auto minute = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(1), ErrorType::TemporalInvalidPlainTime)); + auto minute = TRY(to_integer_throw_on_infinity(global_object, vm.argument(1), ErrorType::TemporalInvalidPlainTime)); // 4. Let second be ? ToIntegerThrowOnInfinity(hour). - auto second = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(2), ErrorType::TemporalInvalidPlainTime)); + auto second = TRY(to_integer_throw_on_infinity(global_object, vm.argument(2), ErrorType::TemporalInvalidPlainTime)); // 5. Let millisecond be ? ToIntegerThrowOnInfinity(hour). - auto millisecond = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(3), ErrorType::TemporalInvalidPlainTime)); + auto millisecond = TRY(to_integer_throw_on_infinity(global_object, vm.argument(3), ErrorType::TemporalInvalidPlainTime)); // 6. Let microsecond be ? ToIntegerThrowOnInfinity(hour). - auto microsecond = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(4), ErrorType::TemporalInvalidPlainTime)); + auto microsecond = TRY(to_integer_throw_on_infinity(global_object, vm.argument(4), ErrorType::TemporalInvalidPlainTime)); // 7. Let nanosecond be ? ToIntegerThrowOnInfinity(hour). - auto nanosecond = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(5), ErrorType::TemporalInvalidPlainTime)); + auto nanosecond = TRY(to_integer_throw_on_infinity(global_object, vm.argument(5), ErrorType::TemporalInvalidPlainTime)); // IMPLEMENTATION DEFINED: This is an optimization that allows us to treat these doubles as normal integers from this point onwards. // This does not change the exposed behavior as the call to CreateTemporalTime will immediately check that these values are valid // ISO values (for hours: 0 - 23, for minutes and seconds: 0 - 59, milliseconds, microseconds, and nanoseconds: 0 - 999) all of which // are subsets of this check. - if (!AK::is_within_range<u8>(hour) || !AK::is_within_range<u8>(minute) || !AK::is_within_range<u8>(second) || !AK::is_within_range<u16>(millisecond) || !AK::is_within_range<u16>(microsecond) || !AK::is_within_range<u16>(nanosecond)) { - vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime); - return {}; - } + if (!AK::is_within_range<u8>(hour) || !AK::is_within_range<u8>(minute) || !AK::is_within_range<u8>(second) || !AK::is_within_range<u16>(millisecond) || !AK::is_within_range<u16>(microsecond) || !AK::is_within_range<u16>(nanosecond)) + return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime); // 8. Return ? CreateTemporalTime(hour, minute, second, millisecond, microsecond, nanosecond, NewTarget). - return TRY_OR_DISCARD(create_temporal_time(global_object, hour, minute, second, millisecond, microsecond, nanosecond, &new_target)); + return TRY(create_temporal_time(global_object, hour, minute, second, millisecond, microsecond, nanosecond, &new_target)); } // 4.2.2 Temporal.PlainTime.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.from diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.h b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.h index 31f6465d9d..ea92684a50 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainTimeConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~PlainTimeConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainYearMonthConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/PlainYearMonthConstructor.cpp index 4effdeb95a..0cbc2b007a 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainYearMonthConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainYearMonthConstructor.cpp @@ -37,17 +37,16 @@ void PlainYearMonthConstructor::initialize(GlobalObject& global_object) } // 9.1.1 Temporal.PlainYearMonth ( isoYear, isoMonth [ , calendarLike [ , referenceISODay ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth -Value PlainYearMonthConstructor::call() +ThrowCompletionOr<Value> PlainYearMonthConstructor::call() { auto& vm = this->vm(); // 1. If NewTarget is undefined, throw a TypeError exception. - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainYearMonth"); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainYearMonth"); } // 9.1.1 Temporal.PlainYearMonth ( isoYear, isoMonth [ , calendarLike [ , referenceISODay ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth -Value PlainYearMonthConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> PlainYearMonthConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); @@ -64,27 +63,25 @@ Value PlainYearMonthConstructor::construct(FunctionObject& new_target) } // 3. Let y be ? ToIntegerThrowOnInfinity(isoYear). - auto y = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, iso_year, ErrorType::TemporalInvalidPlainYearMonth)); + auto y = TRY(to_integer_throw_on_infinity(global_object, iso_year, ErrorType::TemporalInvalidPlainYearMonth)); // 4. Let m be ? ToIntegerThrowOnInfinity(isoMonth). - auto m = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, iso_month, ErrorType::TemporalInvalidPlainYearMonth)); + auto m = TRY(to_integer_throw_on_infinity(global_object, iso_month, ErrorType::TemporalInvalidPlainYearMonth)); // 5. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). - auto* calendar = TRY_OR_DISCARD(to_temporal_calendar_with_iso_default(global_object, calendar_like)); + auto* calendar = TRY(to_temporal_calendar_with_iso_default(global_object, calendar_like)); // 6. Let ref be ? ToIntegerThrowOnInfinity(referenceISODay). - auto ref = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, reference_iso_day, ErrorType::TemporalInvalidPlainYearMonth)); + auto ref = TRY(to_integer_throw_on_infinity(global_object, reference_iso_day, ErrorType::TemporalInvalidPlainYearMonth)); // IMPLEMENTATION DEFINED: This is an optimization that allows us to treat these doubles as normal integers from this point onwards. // This does not change the exposed behavior as the call to CreateTemporalYearMonth will immediately check that these values are valid // ISO values (for years: -273975 - 273975, for months: 1 - 12, for days: 1 - 31) all of which are subsets of this check. - if (!AK::is_within_range<i32>(y) || !AK::is_within_range<u8>(m) || !AK::is_within_range<u8>(ref)) { - vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainYearMonth); - return {}; - } + if (!AK::is_within_range<i32>(y) || !AK::is_within_range<u8>(m) || !AK::is_within_range<u8>(ref)) + return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidPlainYearMonth); // 7. Return ? CreateTemporalYearMonth(y, m, calendar, ref, NewTarget). - return TRY_OR_DISCARD(create_temporal_year_month(global_object, y, m, *calendar, ref, &new_target)); + return TRY(create_temporal_year_month(global_object, y, m, *calendar, ref, &new_target)); } // 9.2.2 Temporal.PlainYearMonth.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.from diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainYearMonthConstructor.h b/Userland/Libraries/LibJS/Runtime/Temporal/PlainYearMonthConstructor.h index 58b64e807d..64a7a9d665 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainYearMonthConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainYearMonthConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~PlainYearMonthConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.cpp index 705a5d3a47..2d99e5b22b 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.cpp @@ -32,31 +32,30 @@ void TimeZoneConstructor::initialize(GlobalObject& global_object) } // 11.2.1 Temporal.TimeZone ( identifier ), https://tc39.es/proposal-temporal/#sec-temporal.timezone -Value TimeZoneConstructor::call() +ThrowCompletionOr<Value> TimeZoneConstructor::call() { auto& vm = this->vm(); // 1. If NewTarget is undefined, then // a. Throw a TypeError exception. - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.TimeZone"); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.TimeZone"); } // 11.2.1 Temporal.TimeZone ( identifier ), https://tc39.es/proposal-temporal/#sec-temporal.timezone -Value TimeZoneConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> TimeZoneConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); // 2. Set identifier to ? ToString(identifier). - auto identifier = TRY_OR_DISCARD(vm.argument(0).to_string(global_object)); + auto identifier = TRY(vm.argument(0).to_string(global_object)); String canonical; // 3. If identifier satisfies the syntax of a TimeZoneNumericUTCOffset (see 13.33), then if (is_valid_time_zone_numeric_utc_offset_syntax(identifier)) { // a. Let offsetNanoseconds be ? ParseTimeZoneOffsetString(identifier). - auto offset_nanoseconds = TRY_OR_DISCARD(parse_time_zone_offset_string(global_object, identifier)); + auto offset_nanoseconds = TRY(parse_time_zone_offset_string(global_object, identifier)); // b. Let canonical be ! FormatTimeZoneOffsetString(offsetNanoseconds). canonical = format_time_zone_offset_string(offset_nanoseconds); @@ -66,8 +65,7 @@ Value TimeZoneConstructor::construct(FunctionObject& new_target) // a. If ! IsValidTimeZoneName(identifier) is false, then if (!is_valid_time_zone_name(identifier)) { // i. Throw a RangeError exception. - vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidTimeZoneName); - return {}; + return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidTimeZoneName); } // b. Let canonical be ! CanonicalizeTimeZoneName(identifier). @@ -75,7 +73,7 @@ Value TimeZoneConstructor::construct(FunctionObject& new_target) } // 5. Return ? CreateTemporalTimeZone(canonical, NewTarget). - return TRY_OR_DISCARD(create_temporal_time_zone(global_object, canonical, &new_target)); + return TRY(create_temporal_time_zone(global_object, canonical, &new_target)); } // 11.3.2 Temporal.TimeZone.from ( item ), https://tc39.es/proposal-temporal/#sec-temporal.timezone.from diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.h b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.h index fb655b515b..0b071fb722 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~TimeZoneConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/ZonedDateTimeConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/ZonedDateTimeConstructor.cpp index e8888412d1..4cee1b0ceb 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/ZonedDateTimeConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/ZonedDateTimeConstructor.cpp @@ -32,39 +32,36 @@ void ZonedDateTimeConstructor::initialize(GlobalObject& global_object) } // 6.1.1 Temporal.ZonedDateTime ( epochNanoseconds, timeZoneLike [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime -Value ZonedDateTimeConstructor::call() +ThrowCompletionOr<Value> ZonedDateTimeConstructor::call() { auto& vm = this->vm(); // 1. If NewTarget is undefined, then // a. Throw a TypeError exception. - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.ZonedDateTime"); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.ZonedDateTime"); } // 6.1.1 Temporal.ZonedDateTime ( epochNanoseconds, timeZoneLike [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime -Value ZonedDateTimeConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> ZonedDateTimeConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); // 2. Set epochNanoseconds to ? ToBigInt(epochNanoseconds). - auto* epoch_nanoseconds = TRY_OR_DISCARD(vm.argument(0).to_bigint(global_object)); + auto* epoch_nanoseconds = TRY(vm.argument(0).to_bigint(global_object)); // 3. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception. - if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds)) { - vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidEpochNanoseconds); - return {}; - } + if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds)) + return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidEpochNanoseconds); // 4. Let timeZone be ? ToTemporalTimeZone(timeZoneLike). - auto* time_zone = TRY_OR_DISCARD(to_temporal_time_zone(global_object, vm.argument(1))); + auto* time_zone = TRY(to_temporal_time_zone(global_object, vm.argument(1))); // 5. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike). - auto* calendar = TRY_OR_DISCARD(to_temporal_calendar_with_iso_default(global_object, vm.argument(2))); + auto* calendar = TRY(to_temporal_calendar_with_iso_default(global_object, vm.argument(2))); // 6. Return ? CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar, NewTarget). - return TRY_OR_DISCARD(create_temporal_zoned_date_time(global_object, *epoch_nanoseconds, *time_zone, *calendar, &new_target)); + return TRY(create_temporal_zoned_date_time(global_object, *epoch_nanoseconds, *time_zone, *calendar, &new_target)); } } diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/ZonedDateTimeConstructor.h b/Userland/Libraries/LibJS/Runtime/Temporal/ZonedDateTimeConstructor.h index bad9761826..1db77736b2 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/ZonedDateTimeConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/ZonedDateTimeConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~ZonedDateTimeConstructor() override = default; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/TypedArray.cpp b/Userland/Libraries/LibJS/Runtime/TypedArray.cpp index d3cc6ea433..9173bac418 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArray.cpp +++ b/Userland/Libraries/LibJS/Runtime/TypedArray.cpp @@ -434,15 +434,14 @@ void TypedArrayBase::visit_edges(Visitor& visitor) } \ \ /* 23.2.5.1 TypedArray ( ...args ), https://tc39.es/ecma262/#sec-typedarray */ \ - Value ConstructorName::call() \ + ThrowCompletionOr<Value> ConstructorName::call() \ { \ auto& vm = this->vm(); \ - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ClassName); \ - return {}; \ + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ClassName); \ } \ \ /* 23.2.5.1 TypedArray ( ...args ), https://tc39.es/ecma262/#sec-typedarray */ \ - Value ConstructorName::construct(FunctionObject& new_target) \ + ThrowCompletionOr<Object*> ConstructorName::construct(FunctionObject& new_target) \ { \ auto& vm = this->vm(); \ if (vm.argument_count() == 0) \ @@ -451,27 +450,25 @@ void TypedArrayBase::visit_edges(Visitor& visitor) auto first_argument = vm.argument(0); \ if (first_argument.is_object()) { \ auto* typed_array = ClassName::create(global_object(), 0, new_target); \ - if (vm.exception()) \ - return {}; \ + if (auto* exception = vm.exception()) \ + return throw_completion(exception->value()); \ if (first_argument.as_object().is_typed_array()) { \ auto& arg_typed_array = static_cast<TypedArrayBase&>(first_argument.as_object()); \ - TRY_OR_DISCARD(initialize_typed_array_from_typed_array(global_object(), *typed_array, arg_typed_array)); \ + TRY(initialize_typed_array_from_typed_array(global_object(), *typed_array, arg_typed_array)); \ } else if (is<ArrayBuffer>(first_argument.as_object())) { \ auto& array_buffer = static_cast<ArrayBuffer&>(first_argument.as_object()); \ /* NOTE: I added the padding below to not reindent 150+ lines for a single line change. If you edit this, and the */ \ /* width happens to change anyway, feel free to remove it. */ \ - TRY_OR_DISCARD(initialize_typed_array_from_array_buffer(global_object(), *typed_array, array_buffer, /* */ \ + TRY(initialize_typed_array_from_array_buffer(global_object(), *typed_array, array_buffer, /* */ \ vm.argument(1), vm.argument(2))); \ } else { \ - auto iterator = TRY_OR_DISCARD(first_argument.get_method(global_object(), *vm.well_known_symbol_iterator())); \ + auto iterator = TRY(first_argument.get_method(global_object(), *vm.well_known_symbol_iterator())); \ if (iterator) { \ - auto values = TRY_OR_DISCARD(iterable_to_list(global_object(), first_argument, iterator)); \ - TRY_OR_DISCARD(initialize_typed_array_from_list(global_object(), *typed_array, values)); \ + auto values = TRY(iterable_to_list(global_object(), first_argument, iterator)); \ + TRY(initialize_typed_array_from_list(global_object(), *typed_array, values)); \ } else { \ - TRY_OR_DISCARD(initialize_typed_array_from_array_like(global_object(), *typed_array, first_argument.as_object())); \ + TRY(initialize_typed_array_from_array_like(global_object(), *typed_array, first_argument.as_object())); \ } \ - if (vm.exception()) \ - return {}; \ } \ return typed_array; \ } \ @@ -482,20 +479,16 @@ void TypedArrayBase::visit_edges(Visitor& visitor) if (error.value().is_object() && is<RangeError>(error.value().as_object())) { \ /* Re-throw more specific RangeError */ \ vm.clear_exception(); \ - vm.throw_exception<RangeError>(global_object(), ErrorType::InvalidLength, "typed array"); \ + return vm.throw_completion<RangeError>(global_object(), ErrorType::InvalidLength, "typed array"); \ } \ - return {}; \ + return error; \ } \ auto array_length = array_length_or_error.release_value(); \ - if (array_length > NumericLimits<i32>::max() / sizeof(Type)) { \ - vm.throw_exception<RangeError>(global_object(), ErrorType::InvalidLength, "typed array"); \ - return {}; \ - } \ + if (array_length > NumericLimits<i32>::max() / sizeof(Type)) \ + return vm.throw_completion<RangeError>(global_object(), ErrorType::InvalidLength, "typed array"); \ /* FIXME: What is the best/correct behavior here? */ \ - if (Checked<u32>::multiplication_would_overflow(array_length, sizeof(Type))) { \ - vm.throw_exception<RangeError>(global_object(), ErrorType::InvalidLength, "typed array"); \ - return {}; \ - } \ + if (Checked<u32>::multiplication_would_overflow(array_length, sizeof(Type))) \ + return vm.throw_completion<RangeError>(global_object(), ErrorType::InvalidLength, "typed array"); \ return ClassName::create(global_object(), array_length, new_target); \ } diff --git a/Userland/Libraries/LibJS/Runtime/TypedArray.h b/Userland/Libraries/LibJS/Runtime/TypedArray.h index d77e6abfc2..c758ea6208 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArray.h +++ b/Userland/Libraries/LibJS/Runtime/TypedArray.h @@ -510,8 +510,8 @@ ThrowCompletionOr<TypedArrayBase*> typed_array_create(GlobalObject& global_objec virtual void initialize(GlobalObject&) override; \ virtual ~ConstructorName() override; \ \ - virtual Value call() override; \ - virtual Value construct(FunctionObject& new_target) override; \ + virtual ThrowCompletionOr<Value> call() override; \ + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; \ \ private: \ virtual bool has_constructor() const override { return true; } \ diff --git a/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp b/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp index 614f3976cd..c6ff2e4e19 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp @@ -43,16 +43,15 @@ TypedArrayConstructor::~TypedArrayConstructor() } // 23.2.1.1 %TypedArray% ( ), https://tc39.es/ecma262/#sec-%typedarray% -Value TypedArrayConstructor::call() +ThrowCompletionOr<Value> TypedArrayConstructor::call() { - return construct(*this); + return TRY(construct(*this)); } // 23.2.1.1 %TypedArray% ( ), https://tc39.es/ecma262/#sec-%typedarray% -Value TypedArrayConstructor::construct(FunctionObject&) +ThrowCompletionOr<Object*> TypedArrayConstructor::construct(FunctionObject&) { - vm().throw_exception<TypeError>(global_object(), ErrorType::ClassIsAbstract, "TypedArray"); - return {}; + return vm().throw_completion<TypeError>(global_object(), ErrorType::ClassIsAbstract, "TypedArray"); } // 23.2.2.1 %TypedArray%.from ( source [ , mapfn [ , thisArg ] ] ), https://tc39.es/ecma262/#sec-%typedarray%.from diff --git a/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.h b/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.h index 16e838011c..2cc6582b9b 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.h @@ -19,8 +19,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~TypedArrayConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject& new_target) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp b/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp index 2eed46b414..c823920c15 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp @@ -34,31 +34,28 @@ WeakMapConstructor::~WeakMapConstructor() } // 24.3.1.1 WeakMap ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakmap-iterable -Value WeakMapConstructor::call() +ThrowCompletionOr<Value> WeakMapConstructor::call() { auto& vm = this->vm(); - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakMap); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakMap); } // 24.3.1.1 WeakMap ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakmap-iterable -Value WeakMapConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> WeakMapConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); - auto* weak_map = TRY_OR_DISCARD(ordinary_create_from_constructor<WeakMap>(global_object, new_target, &GlobalObject::weak_map_prototype)); + auto* weak_map = TRY(ordinary_create_from_constructor<WeakMap>(global_object, new_target, &GlobalObject::weak_map_prototype)); if (vm.argument(0).is_nullish()) return weak_map; - 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 {}; - } + auto adder = TRY(weak_map->get(vm.names.set)); + if (!adder.is_function()) + return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, "'set' property of WeakMap"); - TRY_OR_DISCARD(get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) -> Optional<Completion> { + TRY(get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) -> Optional<Completion> { if (!iterator_value.is_object()) return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObject, String::formatted("Iterator value {}", iterator_value.to_string_without_side_effects())); diff --git a/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.h b/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.h index df71a2b69f..bb7a733e0a 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~WeakMapConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject&) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/WeakRefConstructor.cpp b/Userland/Libraries/LibJS/Runtime/WeakRefConstructor.cpp index dd9c719b8b..7b38c121d6 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakRefConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/WeakRefConstructor.cpp @@ -33,25 +33,22 @@ WeakRefConstructor::~WeakRefConstructor() } // 26.1.1.1 WeakRef ( target ), https://tc39.es/ecma262/#sec-weak-ref-target -Value WeakRefConstructor::call() +ThrowCompletionOr<Value> WeakRefConstructor::call() { auto& vm = this->vm(); - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakRef); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakRef); } // 26.1.1.1 WeakRef ( target ), https://tc39.es/ecma262/#sec-weak-ref-target -Value WeakRefConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> WeakRefConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); auto target = vm.argument(0); - if (!target.is_object()) { - vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, target.to_string_without_side_effects()); - return {}; - } - return TRY_OR_DISCARD(ordinary_create_from_constructor<WeakRef>(global_object, new_target, &GlobalObject::weak_ref_prototype, &target.as_object())); + if (!target.is_object()) + return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObject, target.to_string_without_side_effects()); + return TRY(ordinary_create_from_constructor<WeakRef>(global_object, new_target, &GlobalObject::weak_ref_prototype, &target.as_object())); } } diff --git a/Userland/Libraries/LibJS/Runtime/WeakRefConstructor.h b/Userland/Libraries/LibJS/Runtime/WeakRefConstructor.h index 346537d5d9..34cd74d110 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakRefConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/WeakRefConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~WeakRefConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject&) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp b/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp index 926ac3ec78..bf2fec5147 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp @@ -34,31 +34,28 @@ WeakSetConstructor::~WeakSetConstructor() } // 24.4.1.1 WeakSet ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakset-iterable -Value WeakSetConstructor::call() +ThrowCompletionOr<Value> WeakSetConstructor::call() { auto& vm = this->vm(); - vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakSet); - return {}; + return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakSet); } // 24.4.1.1 WeakSet ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakset-iterable -Value WeakSetConstructor::construct(FunctionObject& new_target) +ThrowCompletionOr<Object*> WeakSetConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); auto& global_object = this->global_object(); - auto* weak_set = TRY_OR_DISCARD(ordinary_create_from_constructor<WeakSet>(global_object, new_target, &GlobalObject::weak_set_prototype)); + auto* weak_set = TRY(ordinary_create_from_constructor<WeakSet>(global_object, new_target, &GlobalObject::weak_set_prototype)); if (vm.argument(0).is_nullish()) return weak_set; - 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 {}; - } + auto adder = TRY(weak_set->get(vm.names.add)); + if (!adder.is_function()) + return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, "'add' property of WeakSet"); - TRY_OR_DISCARD(get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) -> Optional<Completion> { + TRY(get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) -> Optional<Completion> { TRY(vm.call(adder.as_function(), Value(weak_set), iterator_value)); return {}; })); diff --git a/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.h b/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.h index 93e54888e8..fffb93be2a 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.h +++ b/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(GlobalObject&) override; virtual ~WeakSetConstructor() override; - virtual Value call() override; - virtual Value construct(FunctionObject&) override; + virtual ThrowCompletionOr<Value> call() override; + virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibWeb/Bindings/ImageConstructor.cpp b/Userland/Libraries/LibWeb/Bindings/ImageConstructor.cpp index 3260bba7cc..9acff1182c 100644 --- a/Userland/Libraries/LibWeb/Bindings/ImageConstructor.cpp +++ b/Userland/Libraries/LibWeb/Bindings/ImageConstructor.cpp @@ -33,26 +33,25 @@ ImageConstructor::~ImageConstructor() { } -JS::Value ImageConstructor::call() +JS::ThrowCompletionOr<JS::Value> ImageConstructor::call() { - vm().throw_exception<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "Image"); - return {}; + return vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "Image"); } // https://html.spec.whatwg.org/multipage/embedded-content.html#dom-image -JS::Value ImageConstructor::construct(FunctionObject&) +JS::ThrowCompletionOr<JS::Object*> ImageConstructor::construct(FunctionObject&) { auto& window = static_cast<WindowObject&>(global_object()); auto& document = window.impl().associated_document(); auto image_element = DOM::create_element(document, HTML::TagNames::img, Namespace::HTML); if (vm().argument_count() > 0) { - u32 width = TRY_OR_DISCARD(vm().argument(0).to_u32(global_object())); + u32 width = TRY(vm().argument(0).to_u32(global_object())); image_element->set_attribute(HTML::AttributeNames::width, String::formatted("{}", width)); } if (vm().argument_count() > 1) { - u32 height = TRY_OR_DISCARD(vm().argument(1).to_u32(global_object())); + u32 height = TRY(vm().argument(1).to_u32(global_object())); image_element->set_attribute(HTML::AttributeNames::height, String::formatted("{}", height)); } diff --git a/Userland/Libraries/LibWeb/Bindings/ImageConstructor.h b/Userland/Libraries/LibWeb/Bindings/ImageConstructor.h index 54959d0cab..b516216cfd 100644 --- a/Userland/Libraries/LibWeb/Bindings/ImageConstructor.h +++ b/Userland/Libraries/LibWeb/Bindings/ImageConstructor.h @@ -16,8 +16,8 @@ public: virtual void initialize(JS::GlobalObject&) override; virtual ~ImageConstructor() override; - virtual JS::Value call() override; - virtual JS::Value construct(JS::FunctionObject& new_target) override; + virtual JS::ThrowCompletionOr<JS::Value> call() override; + virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceConstructor.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceConstructor.cpp index aa33ca5916..d6d034ea82 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceConstructor.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceConstructor.cpp @@ -23,27 +23,23 @@ WebAssemblyInstanceConstructor::~WebAssemblyInstanceConstructor() { } -JS::Value WebAssemblyInstanceConstructor::call() +JS::ThrowCompletionOr<JS::Value> WebAssemblyInstanceConstructor::call() { - vm().throw_exception<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Instance"); - return {}; + return vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Instance"); } -JS::Value WebAssemblyInstanceConstructor::construct(FunctionObject&) +JS::ThrowCompletionOr<JS::Object*> WebAssemblyInstanceConstructor::construct(FunctionObject&) { auto& vm = this->vm(); auto& global_object = this->global_object(); - auto* module_argument = TRY_OR_DISCARD(vm.argument(0).to_object(global_object)); - if (!is<WebAssemblyModuleObject>(module_argument)) { - vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "WebAssembly.Module"); - return {}; - } - + auto* module_argument = TRY(vm.argument(0).to_object(global_object)); + if (!is<WebAssemblyModuleObject>(module_argument)) + return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "WebAssembly.Module"); auto& module_object = static_cast<WebAssemblyModuleObject&>(*module_argument); auto result = WebAssemblyObject::instantiate_module(module_object.module(), vm, global_object); if (result.is_error()) { - vm.throw_exception(global_object, result.release_error()); - return {}; + vm.throw_exception(global_object, result.error()); + return JS::throw_completion(result.error()); } return heap().allocate<WebAssemblyInstanceObject>(global_object, global_object, result.value()); } diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceConstructor.h b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceConstructor.h index 309ab550a6..90bdcb92a7 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceConstructor.h +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(JS::GlobalObject&) override; virtual ~WebAssemblyInstanceConstructor() override; - virtual JS::Value call() override; - virtual JS::Value construct(JS::FunctionObject& new_target) override; + virtual JS::ThrowCompletionOr<JS::Value> call() override; + virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryConstructor.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryConstructor.cpp index 25bf3cbc5a..bc5fbc20ab 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryConstructor.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryConstructor.cpp @@ -21,38 +21,33 @@ WebAssemblyMemoryConstructor::~WebAssemblyMemoryConstructor() { } -JS::Value WebAssemblyMemoryConstructor::call() +JS::ThrowCompletionOr<JS::Value> WebAssemblyMemoryConstructor::call() { - vm().throw_exception<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Memory"); - return {}; + return vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Memory"); } -JS::Value WebAssemblyMemoryConstructor::construct(FunctionObject&) +JS::ThrowCompletionOr<JS::Object*> WebAssemblyMemoryConstructor::construct(FunctionObject&) { auto& vm = this->vm(); auto& global_object = this->global_object(); - auto descriptor = TRY_OR_DISCARD(vm.argument(0).to_object(global_object)); - auto initial_value = TRY_OR_DISCARD(descriptor->get("initial")); - auto maximum_value = TRY_OR_DISCARD(descriptor->get("maximum")); + auto descriptor = TRY(vm.argument(0).to_object(global_object)); + auto initial_value = TRY(descriptor->get("initial")); + auto maximum_value = TRY(descriptor->get("maximum")); - if (initial_value.is_empty()) { - vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "Number"); - return {}; - } + if (initial_value.is_empty()) + return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "Number"); - auto initial = TRY_OR_DISCARD(initial_value.to_u32(global_object)); + auto initial = TRY(initial_value.to_u32(global_object)); Optional<u32> maximum; if (!maximum_value.is_empty()) - maximum = TRY_OR_DISCARD(maximum_value.to_u32(global_object)); + maximum = TRY(maximum_value.to_u32(global_object)); auto address = WebAssemblyObject::s_abstract_machine.store().allocate(Wasm::MemoryType { Wasm::Limits { initial, maximum } }); - if (!address.has_value()) { - vm.throw_exception<JS::TypeError>(global_object, "Wasm Memory allocation failed"); - return {}; - } + if (!address.has_value()) + return vm.throw_completion<JS::TypeError>(global_object, "Wasm Memory allocation failed"); return vm.heap().allocate<WebAssemblyMemoryObject>(global_object, global_object, *address); } diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryConstructor.h b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryConstructor.h index c14f127871..9391ec7b03 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryConstructor.h +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyMemoryConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(JS::GlobalObject&) override; virtual ~WebAssemblyMemoryConstructor() override; - virtual JS::Value call() override; - virtual JS::Value construct(JS::FunctionObject& new_target) override; + virtual JS::ThrowCompletionOr<JS::Value> call() override; + virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.cpp index 2d8e188f54..da86d1d29d 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.cpp @@ -23,22 +23,21 @@ WebAssemblyModuleConstructor::~WebAssemblyModuleConstructor() { } -JS::Value WebAssemblyModuleConstructor::call() +JS::ThrowCompletionOr<JS::Value> WebAssemblyModuleConstructor::call() { - vm().throw_exception<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Module"); - return {}; + return vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Module"); } -JS::Value WebAssemblyModuleConstructor::construct(FunctionObject&) +JS::ThrowCompletionOr<JS::Object*> WebAssemblyModuleConstructor::construct(FunctionObject&) { auto& vm = this->vm(); auto& global_object = this->global_object(); - auto* buffer_object = TRY_OR_DISCARD(vm.argument(0).to_object(global_object)); + auto* buffer_object = TRY(vm.argument(0).to_object(global_object)); auto result = parse_module(global_object, buffer_object); if (result.is_error()) { vm.throw_exception(global_object, result.error()); - return {}; + return JS::throw_completion(result.error()); } return heap().allocate<WebAssemblyModuleObject>(global_object, global_object, result.release_value()); diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.h b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.h index 9df31c2a2a..a77815343d 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.h +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(JS::GlobalObject&) override; virtual ~WebAssemblyModuleConstructor() override; - virtual JS::Value call() override; - virtual JS::Value construct(JS::FunctionObject& new_target) override; + virtual JS::ThrowCompletionOr<JS::Value> call() override; + virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.cpp index 6399af78f9..83647680c2 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.cpp @@ -23,23 +23,20 @@ WebAssemblyTableConstructor::~WebAssemblyTableConstructor() { } -JS::Value WebAssemblyTableConstructor::call() +JS::ThrowCompletionOr<JS::Value> WebAssemblyTableConstructor::call() { - vm().throw_exception<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Table"); - return {}; + return vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Table"); } -JS::Value WebAssemblyTableConstructor::construct(FunctionObject&) +JS::ThrowCompletionOr<JS::Object*> WebAssemblyTableConstructor::construct(FunctionObject&) { auto& vm = this->vm(); auto& global_object = this->global_object(); - auto descriptor = TRY_OR_DISCARD(vm.argument(0).to_object(global_object)); - 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 {}; - } + auto descriptor = TRY(vm.argument(0).to_object(global_object)); + auto element_value = TRY(descriptor->get("element")); + if (!element_value.is_string()) + return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::InvalidHint, element_value.to_string_without_side_effects()); auto& element = element_value.as_string().string(); Optional<Wasm::ValueType> reference_type; @@ -48,27 +45,23 @@ JS::Value WebAssemblyTableConstructor::construct(FunctionObject&) else if (element == "externref"sv) reference_type = Wasm::ValueType(Wasm::ValueType::ExternReference); - if (!reference_type.has_value()) { - vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::InvalidHint, element); - return {}; - } + if (!reference_type.has_value()) + return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::InvalidHint, element); - auto initial_value = TRY_OR_DISCARD(descriptor->get("initial")); - auto maximum_value = TRY_OR_DISCARD(descriptor->get("maximum")); + auto initial_value = TRY(descriptor->get("initial")); + auto maximum_value = TRY(descriptor->get("maximum")); - auto initial = TRY_OR_DISCARD(initial_value.to_u32(global_object)); + auto initial = TRY(initial_value.to_u32(global_object)); Optional<u32> maximum; if (!maximum_value.is_undefined()) - maximum = TRY_OR_DISCARD(maximum_value.to_u32(global_object)); + maximum = TRY(maximum_value.to_u32(global_object)); - if (maximum.has_value() && maximum.value() < initial) { - vm.throw_exception<JS::RangeError>(global_object, "maximum should be larger than or equal to initial"); - return {}; - } + if (maximum.has_value() && maximum.value() < initial) + return vm.throw_completion<JS::RangeError>(global_object, "maximum should be larger than or equal to initial"); - auto value_value = TRY_OR_DISCARD(descriptor->get("value")); + auto value_value = TRY(descriptor->get("value")); auto reference_value = [&]() -> Optional<Wasm::Value> { if (value_value.is_undefined()) return Wasm::Value(*reference_type, 0ull); @@ -76,16 +69,14 @@ JS::Value WebAssemblyTableConstructor::construct(FunctionObject&) return to_webassembly_value(value_value, *reference_type, global_object); }(); - if (!reference_value.has_value()) - return {}; + if (auto* exception = vm.exception()) + return JS::throw_completion(exception->value()); auto& reference = reference_value->value().get<Wasm::Reference>(); auto address = WebAssemblyObject::s_abstract_machine.store().allocate(Wasm::TableType { *reference_type, Wasm::Limits { initial, maximum } }); - if (!address.has_value()) { - vm.throw_exception<JS::TypeError>(global_object, "Wasm Table allocation failed"); - return {}; - } + if (!address.has_value()) + return vm.throw_completion<JS::TypeError>(global_object, "Wasm Table allocation failed"); auto& table = *WebAssemblyObject::s_abstract_machine.store().get(*address); for (auto& element : table.elements()) diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.h b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.h index 56536a4d58..c6aad1424a 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.h +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.h @@ -18,8 +18,8 @@ public: virtual void initialize(JS::GlobalObject&) override; virtual ~WebAssemblyTableConstructor() override; - virtual JS::Value call() override; - virtual JS::Value construct(JS::FunctionObject& new_target) override; + virtual JS::ThrowCompletionOr<JS::Value> call() override; + virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override; private: virtual bool has_constructor() const override { return true; } |