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.
This commit is contained in:
Linus Groh 2021-10-20 21:16:30 +01:00
parent 0881f8160f
commit 5832de62fe
Notes: sideshowbarker 2024-07-18 02:06:32 +09:00
99 changed files with 597 additions and 669 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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