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

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
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; return false;
} }
enum class ReturnType {
Completion,
Value,
Void,
};
template<typename ParameterType> 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(); auto scoped_generator = generator.fork();
scoped_generator.set("cpp_name", make_input_acceptable_cpp(cpp_name)); 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()) if (optional_default_value.has_value())
scoped_generator.set("parameter.optional_default_value", *optional_default_value); scoped_generator.set("parameter.optional_default_value", *optional_default_value);
if (return_void) switch (return_type) {
scoped_generator.set("return_statement", "return;"); case ReturnType::Completion:
else 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("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 // FIXME: Add support for optional, variadic, nullable and default values to all types
if (parameter.type->is_string()) { if (parameter.type->is_string()) {
@ -1080,7 +1097,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
} else if (parameter.type->name == "double") { } else if (parameter.type->name == "double") {
if (!optional) { if (!optional) {
scoped_generator.append(R"~~~( 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 { } else {
if (optional_default_value.has_value()) { if (optional_default_value.has_value()) {
@ -1094,7 +1111,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
} }
scoped_generator.append(R"~~~( scoped_generator.append(R"~~~(
if (!@js_name@@js_suffix@.is_undefined()) 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()) { if (optional_default_value.has_value()) {
scoped_generator.append(R"~~~( scoped_generator.append(R"~~~(
@ -1136,15 +1153,15 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
} }
} else if (parameter.type->name == "unsigned long") { } else if (parameter.type->name == "unsigned long") {
scoped_generator.append(R"~~~( 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") { } else if (parameter.type->name == "unsigned short") {
scoped_generator.append(R"~~~( 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") { } else if (parameter.type->name == "long") {
scoped_generator.append(R"~~~( 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") { } else if (parameter.type->name == "EventHandler") {
// x.onfoo = function() { ... } // 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); auto member_value_name = String::formatted("{}_value", member_js_name);
dictionary_generator.set("member_value_name", member_value_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"~~~( dictionary_generator.append(R"~~~(
@cpp_name@.@member_name@ = @member_value_name@; @cpp_name@.@member_name@ = @member_value_name@;
)~~~"); )~~~");
@ -1253,7 +1270,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
} }
template<typename FunctionType> 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(); auto argument_count_check_generator = generator.fork();
argument_count_check_generator.set("function.name", function.name); 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())); 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"~~~( argument_count_check_generator.append(R"~~~(
if (vm.argument_count() < @function.nargs@) { if (vm.argument_count() < @function.nargs@) {
vm.throw_exception<JS::TypeError>(global_object, @.bad_arg_count@, "@function.name@"@.arg_count_suffix@); 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(); 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"); 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; ++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; 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()); function_generator.set(".arguments", arguments_builder.string_view());
if (is_static_function == StaticFunction::No) { 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. // 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. // 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: // 5. If operation was defined without an identifier, then:
if (interface.named_property_setter->name.is_empty()) { 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. // 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. // 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: // 6. If operation was defined without an identifier, then:
if (interface.indexed_property_setter->name.is_empty()) { if (interface.indexed_property_setter->name.is_empty()) {
@ -2540,8 +2569,8 @@ public:
virtual void initialize(JS::GlobalObject&) override; virtual void initialize(JS::GlobalObject&) override;
virtual ~@constructor_class@() override; virtual ~@constructor_class@() override;
virtual JS::Value call() override; virtual JS::ThrowCompletionOr<JS::Value> call() override;
virtual JS::Value construct(JS::FunctionObject& new_target) override; virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "@name@");
return {};
} }
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 // No constructor
generator.set("constructor.length", "0"); generator.set("constructor.length", "0");
generator.append(R"~~~( generator.append(R"~~~(
vm().throw_exception<JS::TypeError>(global_object(), JS::ErrorType::NotAConstructor, "@name@"); return vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::NotAConstructor, "@name@");
return {};
)~~~"); )~~~");
} else if (interface.constructors.size() == 1) { } else if (interface.constructors.size() == 1) {
// Single constructor // Single constructor
@ -2675,10 +2702,10 @@ JS::Value @constructor_class@::construct(FunctionObject&)
)~~~"); )~~~");
if (!constructor.parameters.is_empty()) { if (!constructor.parameters.is_empty()) {
generate_argument_count_check(generator, constructor); generate_argument_count_check(generator, constructor, ReturnType::Completion);
StringBuilder arguments_builder; 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.set(".constructor_arguments", arguments_builder.string_view());
generator.append(R"~~~( generator.append(R"~~~(
@ -2691,7 +2718,7 @@ JS::Value @constructor_class@::construct(FunctionObject&)
} }
generator.append(R"~~~( generator.append(R"~~~(
if (should_return_empty(impl)) if (should_return_empty(impl))
return JS::Value(); return JS::throw_completion(vm.exception()->value());
return wrap(global_object, *impl.release_value()); return wrap(global_object, *impl.release_value());
)~~~"); )~~~");
} else { } else {
@ -3236,7 +3263,7 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(@prototype_class@::@attribute.setter_callback@)
auto value = vm.argument(0); 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.extended_attributes.contains("Reflect")) {
if (attribute.type->name != "boolean") { 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 // 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 // 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& vm = this->vm();
auto& global_object = this->global_object(); 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()) { 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))); 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 })); 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 void initialize(GlobalObject&) override;
virtual ~AggregateErrorConstructor() override = default; virtual ~AggregateErrorConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 25.1.3.1 ArrayBuffer ( length ), https://tc39.es/ecma262/#sec-arraybuffer-length
Value ArrayBufferConstructor::call() ThrowCompletionOr<Value> ArrayBufferConstructor::call()
{ {
auto& vm = this->vm(); auto& vm = this->vm();
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ArrayBuffer); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ArrayBuffer);
return {};
} }
// 25.1.3.1 ArrayBuffer ( length ), https://tc39.es/ecma262/#sec-arraybuffer-length // 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& vm = this->vm();
auto byte_length_or_error = vm.argument(0).to_index(global_object()); 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())) { if (error.value().is_object() && is<RangeError>(error.value().as_object())) {
// Re-throw more specific RangeError // Re-throw more specific RangeError
vm.clear_exception(); 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 // 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 void initialize(GlobalObject&) override;
virtual ~ArrayBufferConstructor() override; virtual ~ArrayBufferConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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 // 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& 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) if (vm.argument_count() == 0)
return Array::create(global_object(), 0, proto); return Array::create(global_object(), 0, proto);
@ -69,18 +69,16 @@ Value ArrayConstructor::construct(FunctionObject& new_target)
int_length = 1; int_length = 1;
} else { } else {
int_length = MUST(length.to_u32(global_object())); int_length = MUST(length.to_u32(global_object()));
if (int_length != length.as_double()) { if (int_length != length.as_double())
vm.throw_exception<RangeError>(global_object(), ErrorType::InvalidLength, "array"); return vm.throw_completion<RangeError>(global_object(), ErrorType::InvalidLength, "array");
return {};
}
} }
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; return array;
} }
auto* array = Array::create(global_object(), vm.argument_count(), proto); auto* array = Array::create(global_object(), vm.argument_count(), proto);
if (vm.exception()) if (auto* exception = vm.exception())
return {}; return throw_completion(exception->value());
for (size_t k = 0; k < vm.argument_count(); ++k) for (size_t k = 0; k < vm.argument_count(); ++k)
MUST(array->create_data_property_or_throw(k, vm.argument(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 void initialize(GlobalObject&) override;
virtual ~ArrayConstructor() override; virtual ~ArrayConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
@ -48,21 +48,20 @@ Value BigIntConstructor::call()
auto value = vm.argument(0); auto value = vm.argument(0);
// 2. Let prim be ? ToPrimitive(value, number). // 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). // 3. If Type(prim) is Number, return ? NumberToBigInt(prim).
if (primitive.is_number()) if (primitive.is_number())
return number_to_bigint(global_object, primitive); return number_to_bigint(global_object, primitive);
// 4. Otherwise, return ? ToBigInt(value). // 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 // 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 vm().throw_completion<TypeError>(global_object(), ErrorType::NotAConstructor, "BigInt");
return {};
} }
// 21.2.2.1 BigInt.asIntN ( bits, bigint ), https://tc39.es/ecma262/#sec-bigint.asintn // 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 void initialize(GlobalObject&) override;
virtual ~BigIntConstructor() override; virtual ~BigIntConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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(); 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 // 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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
auto b = vm.argument(0).to_boolean(); 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 void initialize(GlobalObject&) override;
virtual ~BooleanConstructor() override; virtual ~BooleanConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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(); auto& vm = this->vm();
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.DataView); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.DataView);
return {};
} }
// 25.3.2.1 DataView ( buffer [ , byteOffset [ , byteLength ] ] ), https://tc39.es/ecma262/#sec-dataview-buffer-byteoffset-bytelength // 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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
auto buffer = vm.argument(0); auto buffer = vm.argument(0);
if (!buffer.is_object() || !is<ArrayBuffer>(buffer.as_object())) { 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 vm.throw_completion<TypeError>(global_object, ErrorType::IsNotAn, buffer.to_string_without_side_effects(), vm.names.ArrayBuffer);
return {};
}
auto& array_buffer = static_cast<ArrayBuffer&>(buffer.as_object()); 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()) { if (array_buffer.is_detached())
vm.throw_exception<TypeError>(global_object, ErrorType::DetachedArrayBuffer); return vm.throw_completion<TypeError>(global_object, ErrorType::DetachedArrayBuffer);
return {};
}
auto buffer_byte_length = array_buffer.byte_length(); auto buffer_byte_length = array_buffer.byte_length();
if (offset > buffer_byte_length) { if (offset > buffer_byte_length)
vm.throw_exception<RangeError>(global_object, ErrorType::DataViewOutOfRangeByteOffset, offset, buffer_byte_length); return vm.throw_completion<RangeError>(global_object, ErrorType::DataViewOutOfRangeByteOffset, offset, buffer_byte_length);
return {};
}
size_t view_byte_length; size_t view_byte_length;
if (vm.argument(2).is_undefined()) { if (vm.argument(2).is_undefined()) {
view_byte_length = buffer_byte_length - offset; view_byte_length = buffer_byte_length - offset;
} else { } else {
view_byte_length = TRY_OR_DISCARD(vm.argument(2).to_index(global_object)); view_byte_length = TRY(vm.argument(2).to_index(global_object));
if (offset + view_byte_length > buffer_byte_length) { if (offset + view_byte_length > buffer_byte_length)
vm.throw_exception<RangeError>(global_object, ErrorType::InvalidLength, vm.names.DataView); return vm.throw_completion<RangeError>(global_object, ErrorType::InvalidLength, vm.names.DataView);
return {};
}
} }
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()) { if (array_buffer.is_detached())
vm.throw_exception<TypeError>(global_object, ErrorType::DetachedArrayBuffer); return vm.throw_completion<TypeError>(global_object, ErrorType::DetachedArrayBuffer);
return {};
}
return data_view; return data_view;
} }

View file

@ -18,8 +18,8 @@ public:
virtual void initialize(GlobalObject&) override; virtual void initialize(GlobalObject&) override;
virtual ~DataViewConstructor() override; virtual ~DataViewConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject&) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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 [datetime, milliseconds] = JS::now();
auto* date = Date::create(global_object(), datetime, milliseconds, false); 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 // 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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
if (vm.argument_count() == 0) { if (vm.argument_count() == 0) {
auto [datetime, milliseconds] = JS::now(); 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 datetime = Core::DateTime::create(1970, 1, 1, 0, 0, 0);
auto milliseconds = static_cast<i16>(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) { if (vm.argument_count() == 1) {
@ -209,19 +209,18 @@ Value DateConstructor::construct(FunctionObject& new_target)
if (value.is_string()) if (value.is_string())
value = parse_date_string(value.as_string().string()); value = parse_date_string(value.as_string().string());
else else
value = TRY_OR_DISCARD(value.to_number(global_object)); value = TRY(value.to_number(global_object));
if (!value.is_finite_number()) { if (!value.is_finite_number())
return create_invalid_date(); return TRY(create_invalid_date());
}
// A timestamp since the epoch, in UTC. // A timestamp since the epoch, in UTC.
double value_as_double = value.as_double(); double value_as_double = value.as_double();
if (value_as_double > Date::time_clip) 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 datetime = Core::DateTime::from_timestamp(static_cast<time_t>(value_as_double / 1000));
auto milliseconds = static_cast<i16>(fmod(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. // 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); 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)); auto year_value = TRY(vm.argument(0).to_number(global_object));
if (!year_value.is_finite_number()) { if (!year_value.is_finite_number())
return create_invalid_date(); return TRY(create_invalid_date());
}
auto year = year_value.as_i32(); auto year = year_value.as_i32();
auto month_index_value = TRY_OR_DISCARD(vm.argument(1).to_number(global_object)); auto month_index_value = TRY(vm.argument(1).to_number(global_object));
if (!month_index_value.is_finite_number()) { if (!month_index_value.is_finite_number())
return create_invalid_date(); return TRY(create_invalid_date());
}
auto month_index = month_index_value.as_i32(); auto month_index = month_index_value.as_i32();
auto day_value = TRY_OR_DISCARD(arg_or(2, 1)); auto day_value = TRY(arg_or(2, 1));
if (!day_value.is_finite_number()) { if (!day_value.is_finite_number())
return create_invalid_date(); return TRY(create_invalid_date());
}
auto day = day_value.as_i32(); auto day = day_value.as_i32();
auto hours_value = TRY_OR_DISCARD(arg_or(3, 0)); auto hours_value = TRY(arg_or(3, 0));
if (!hours_value.is_finite_number()) { if (!hours_value.is_finite_number())
return create_invalid_date(); return TRY(create_invalid_date());
}
auto hours = hours_value.as_i32(); auto hours = hours_value.as_i32();
auto minutes_value = TRY_OR_DISCARD(arg_or(4, 0)); auto minutes_value = TRY(arg_or(4, 0));
if (!minutes_value.is_finite_number()) { if (!minutes_value.is_finite_number())
return create_invalid_date(); return TRY(create_invalid_date());
}
auto minutes = minutes_value.as_i32(); auto minutes = minutes_value.as_i32();
auto seconds_value = TRY_OR_DISCARD(arg_or(5, 0)); auto seconds_value = TRY(arg_or(5, 0));
if (!seconds_value.is_finite_number()) { if (!seconds_value.is_finite_number())
return create_invalid_date(); return TRY(create_invalid_date());
}
auto seconds = seconds_value.as_i32(); auto seconds = seconds_value.as_i32();
auto milliseconds_value = TRY_OR_DISCARD(arg_or(6, 0)); auto milliseconds_value = TRY(arg_or(6, 0));
if (!milliseconds_value.is_finite_number()) { if (!milliseconds_value.is_finite_number())
return create_invalid_date(); return TRY(create_invalid_date());
}
auto milliseconds = milliseconds_value.as_i32(); auto milliseconds = milliseconds_value.as_i32();
seconds += milliseconds / 1000; 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 datetime = Core::DateTime::create(year, month, day, hours, minutes, seconds);
auto time = datetime.timestamp() * 1000.0 + milliseconds; auto time = datetime.timestamp() * 1000.0 + milliseconds;
if (time > Date::time_clip) if (time > Date::time_clip)
return create_invalid_date(); return TRY(create_invalid_date());
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));
} }
// 21.4.3.1 Date.now ( ), https://tc39.es/ecma262/#sec-date.now // 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 void initialize(GlobalObject&) override;
virtual ~DateConstructor() override; virtual ~DateConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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 // 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& vm = this->vm();
auto& global_object = this->global_object(); 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()) { 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))); 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; return error;
} }
@ -72,26 +72,26 @@ Value ErrorConstructor::construct(FunctionObject& new_target)
ConstructorName::~ConstructorName() { } \ ConstructorName::~ConstructorName() { } \
\ \
/* 20.5.6.1.1 NativeError ( message ), https://tc39.es/ecma262/#sec-nativeerror */ \ /* 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 */ \ /* 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& vm = this->vm(); \
auto& global_object = this->global_object(); \ 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)); \ global_object, new_target, &GlobalObject::snake_name##_prototype)); \
\ \
if (!vm.argument(0).is_undefined()) { \ 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))); \ 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; \ return error; \
} }

View file

@ -19,8 +19,8 @@ public:
virtual void initialize(GlobalObject&) override; virtual void initialize(GlobalObject&) override;
virtual ~ErrorConstructor() override = default; virtual ~ErrorConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } virtual bool has_constructor() const override { return true; }
@ -34,8 +34,8 @@ private:
explicit ConstructorName(GlobalObject&); \ explicit ConstructorName(GlobalObject&); \
virtual void initialize(GlobalObject&) override; \ virtual void initialize(GlobalObject&) override; \
virtual ~ConstructorName() override; \ virtual ~ConstructorName() override; \
virtual Value call() override; \ virtual ThrowCompletionOr<Value> call() override; \
virtual Value construct(FunctionObject& new_target) override; \ virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; \
\ \
private: \ private: \
virtual bool has_constructor() const override { return true; } \ 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 // 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(); auto& vm = this->vm();
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.FinalizationRegistry); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.FinalizationRegistry);
return {};
} }
// 26.2.1.1 FinalizationRegistry ( cleanupCallback ), https://tc39.es/ecma262/#sec-finalization-registry-cleanup-callback // 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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
auto cleanup_callback = vm.argument(0); auto cleanup_callback = vm.argument(0);
if (!cleanup_callback.is_function()) { if (!cleanup_callback.is_function())
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, cleanup_callback.to_string_without_side_effects()); return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, cleanup_callback.to_string_without_side_effects());
return {};
} return TRY(ordinary_create_from_constructor<FinalizationRegistry>(global_object, new_target, &GlobalObject::finalization_registry_prototype, cleanup_callback.as_function()));
return TRY_OR_DISCARD(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 void initialize(GlobalObject&) override;
virtual ~FinalizationRegistryConstructor() override; virtual ~FinalizationRegistryConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject&) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override;
private: private:
virtual bool has_constructor() const override { return true; } virtual bool has_constructor() const override { return true; }

View file

@ -8,6 +8,7 @@
#include <LibJS/Interpreter.h> #include <LibJS/Interpreter.h>
#include <LibJS/Lexer.h> #include <LibJS/Lexer.h>
#include <LibJS/Parser.h> #include <LibJS/Parser.h>
#include <LibJS/Runtime/ECMAScriptFunctionObject.h>
#include <LibJS/Runtime/Error.h> #include <LibJS/Runtime/Error.h>
#include <LibJS/Runtime/FunctionConstructor.h> #include <LibJS/Runtime/FunctionConstructor.h>
#include <LibJS/Runtime/FunctionObject.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 // 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 // 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); auto function = create_dynamic_function_node(global_object(), new_target, FunctionKind::Regular);
if (!function) if (auto* exception = vm.exception())
return {}; return throw_completion(exception->value());
OwnPtr<Interpreter> local_interpreter; OwnPtr<Interpreter> local_interpreter;
Interpreter* interpreter = vm().interpreter_if_exists(); Interpreter* interpreter = vm.interpreter_if_exists();
if (!interpreter) { if (!interpreter) {
local_interpreter = Interpreter::create_with_existing_realm(*realm()); local_interpreter = Interpreter::create_with_existing_realm(*realm());
@ -87,7 +89,11 @@ Value FunctionConstructor::construct(FunctionObject& new_target)
} }
VM::InterpreterExecutionScope scope(*interpreter); 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 void initialize(GlobalObject&) override;
virtual ~FunctionConstructor() override; virtual ~FunctionConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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 // 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); auto function = FunctionConstructor::create_dynamic_function_node(global_object(), new_target, FunctionKind::Generator);
if (!function) if (auto* exception = vm().exception())
return {}; return throw_completion(exception->value());
auto* bytecode_interpreter = Bytecode::Interpreter::current(); auto* bytecode_interpreter = Bytecode::Interpreter::current();
VERIFY(bytecode_interpreter); VERIFY(bytecode_interpreter);

View file

@ -19,8 +19,8 @@ public:
virtual void initialize(GlobalObject&) override; virtual void initialize(GlobalObject&) override;
virtual ~GeneratorFunctionConstructor() override; virtual ~GeneratorFunctionConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
bool has_constructor() const override { return true; } 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 // 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. // 1. If NewTarget is undefined, throw a TypeError exception.
vm().throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.DisplayNames"); return vm().throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.DisplayNames");
return {};
} }
// 12.2.1 Intl.DisplayNames ( locales, options ), https://tc39.es/ecma402/#sec-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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
@ -54,19 +53,17 @@ Value DisplayNamesConstructor::construct(FunctionObject& new_target)
auto options_value = vm.argument(1); auto options_value = vm.argument(1);
// 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNames.prototype%", « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). // 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). // 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. // 4. If options is undefined, throw a TypeError exception.
if (options_value.is_undefined()) { if (options_value.is_undefined())
vm.throw_exception<TypeError>(global_object, ErrorType::IsUndefined, "options"sv); return vm.throw_completion<TypeError>(global_object, ErrorType::IsUndefined, "options"sv);
return {};
}
// 5. Set options to ? GetOptionsObject(options). // 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. // 6. Let opt be a new Record.
LocaleOptions opt {}; LocaleOptions opt {};
@ -74,7 +71,7 @@ Value DisplayNamesConstructor::construct(FunctionObject& new_target)
// 7. Let localeData be %DisplayNames%.[[LocaleData]]. // 7. Let localeData be %DisplayNames%.[[LocaleData]].
// 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). // 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. // 9. Set opt.[[localeMatcher]] to matcher.
opt.locale_matcher = matcher; opt.locale_matcher = matcher;
@ -83,25 +80,23 @@ Value DisplayNamesConstructor::construct(FunctionObject& new_target)
auto result = resolve_locale(requested_locales, opt, {}); auto result = resolve_locale(requested_locales, opt, {});
// 11. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). // 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. // 12. Set displayNames.[[Style]] to style.
display_names->set_style(style.as_string().string()); display_names->set_style(style.as_string().string());
// 13. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). // 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. // 14. If type is undefined, throw a TypeError exception.
if (type.is_undefined()) { if (type.is_undefined())
vm.throw_exception<TypeError>(global_object, ErrorType::IsUndefined, "options.type"sv); return vm.throw_completion<TypeError>(global_object, ErrorType::IsUndefined, "options.type"sv);
return {};
}
// 15. Set displayNames.[[Type]] to type. // 15. Set displayNames.[[Type]] to type.
display_names->set_type(type.as_string().string()); display_names->set_type(type.as_string().string());
// 16. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). // 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. // 17. Set displayNames.[[Fallback]] to fallback.
display_names->set_fallback(fallback.as_string().string()); display_names->set_fallback(fallback.as_string().string());

View file

@ -18,8 +18,8 @@ public:
virtual void initialize(GlobalObject&) override; virtual void initialize(GlobalObject&) override;
virtual ~DisplayNamesConstructor() override = default; virtual ~DisplayNamesConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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. // 1. If NewTarget is undefined, throw a TypeError exception.
vm().throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.ListFormat"); return vm().throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.ListFormat");
return {};
} }
// 13.2.1 Intl.ListFormat ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sec-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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
@ -53,19 +52,19 @@ Value ListFormatConstructor::construct(FunctionObject& new_target)
auto options_value = vm.argument(1); auto options_value = vm.argument(1);
// 2. Let listFormat be ? OrdinaryCreateFromConstructor(NewTarget, "%ListFormat.prototype%", « [[InitializedListFormat]], [[Locale]], [[Type]], [[Style]], [[Templates]] »). // 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). // 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). // 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. // 5. Let opt be a new Record.
LocaleOptions opt {}; LocaleOptions opt {};
// 6. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). // 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. // 7. Set opt.[[localeMatcher]] to matcher.
opt.locale_matcher = matcher; opt.locale_matcher = matcher;
@ -79,13 +78,13 @@ Value ListFormatConstructor::construct(FunctionObject& new_target)
list_format->set_locale(move(result.locale)); list_format->set_locale(move(result.locale));
// 11. Let type be ? GetOption(options, "type", "string", « "conjunction", "disjunction", "unit" », "conjunction"). // 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. // 12. Set listFormat.[[Type]] to type.
list_format->set_type(type.as_string().string()); list_format->set_type(type.as_string().string());
// 13. Let style be ? GetOption(options, "style", "string", « "long", "short", "narrow" », "long"). // 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. // 14. Set listFormat.[[Style]] to style.
list_format->set_style(style.as_string().string()); list_format->set_style(style.as_string().string());

View file

@ -18,8 +18,8 @@ public:
virtual void initialize(GlobalObject&) override; virtual void initialize(GlobalObject&) override;
virtual ~ListFormatConstructor() override = default; virtual ~ListFormatConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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. // 1. If NewTarget is undefined, throw a TypeError exception.
vm().throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.Locale"); return vm().throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.Locale");
return {};
} }
// 14.1.3 Intl.Locale ( tag [ , options ] ), https://tc39.es/ecma402/#sec-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& vm = this->vm();
auto& global_object = this->global_object(); 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. // a. Append [[Numeric]] as the last element of internalSlotsList.
// 6. Let locale be ? OrdinaryCreateFromConstructor(NewTarget, "%Locale.prototype%", 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; String tag;
// 7. If Type(tag) is not String or Object, throw a TypeError exception. // 7. If Type(tag) is not String or Object, throw a TypeError exception.
if (!tag_value.is_string() && !tag_value.is_object()) { if (!tag_value.is_string() && !tag_value.is_object())
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObjectOrString, "tag"sv); return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObjectOrString, "tag"sv);
return {};
}
// 8. If Type(tag) is Object and tag has an [[InitializedLocale]] internal slot, then // 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())) { if (tag_value.is_object() && is<Locale>(tag_value.as_object())) {
@ -292,17 +289,17 @@ Value LocaleConstructor::construct(FunctionObject& new_target)
// 9. Else, // 9. Else,
else { else {
// a. Let tag be ? ToString(tag). // 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). // 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). // 11. Set tag to ? ApplyOptionsToTag(tag, options).
if (auto applied_tag = apply_options_to_tag(global_object, tag, *options); applied_tag.has_value()) auto applied_tag = apply_options_to_tag(global_object, tag, *options);
tag = applied_tag.release_value(); if (auto* exception = vm.exception())
else return throw_completion(exception->value());
return {}; tag = applied_tag.release_value();
// 12. Let opt be a new Record. // 12. Let opt be a new Record.
LocaleAndKeys opt {}; 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. // a. If calendar does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
// 15. Set opt.[[ca]] to calendar. // 15. Set opt.[[ca]] to calendar.
opt.ca = get_string_option(global_object, *options, vm.names.calendar, Unicode::is_type_identifier); opt.ca = get_string_option(global_object, *options, vm.names.calendar, Unicode::is_type_identifier);
if (vm.exception()) if (auto* exception = vm.exception())
return {}; return throw_completion(exception->value());
// 16. Let collation be ? GetOption(options, "collation", "string", undefined, undefined). // 16. Let collation be ? GetOption(options, "collation", "string", undefined, undefined).
// 17. If collation is not undefined, then // 17. If collation is not undefined, then
// a. If collation does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. // a. If collation does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
// 18. Set opt.[[co]] to collation. // 18. Set opt.[[co]] to collation.
opt.co = get_string_option(global_object, *options, vm.names.collation, Unicode::is_type_identifier); opt.co = get_string_option(global_object, *options, vm.names.collation, Unicode::is_type_identifier);
if (vm.exception()) if (auto* exception = vm.exception())
return {}; return throw_completion(exception->value());
// 19. Let hc be ? GetOption(options, "hourCycle", "string", « "h11", "h12", "h23", "h24" », undefined). // 19. Let hc be ? GetOption(options, "hourCycle", "string", « "h11", "h12", "h23", "h24" », undefined).
// 20. Set opt.[[hc]] to hc. // 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 }); opt.hc = get_string_option(global_object, *options, vm.names.hourCycle, nullptr, { "h11"sv, "h12"sv, "h23"sv, "h24"sv });
if (vm.exception()) if (auto* exception = vm.exception())
return {}; return throw_completion(exception->value());
// 21. Let kf be ? GetOption(options, "caseFirst", "string", « "upper", "lower", "false" », undefined). // 21. Let kf be ? GetOption(options, "caseFirst", "string", « "upper", "lower", "false" », undefined).
// 22. Set opt.[[kf]] to kf. // 22. Set opt.[[kf]] to kf.
opt.kf = get_string_option(global_object, *options, vm.names.caseFirst, nullptr, { "upper"sv, "lower"sv, "false"sv }); opt.kf = get_string_option(global_object, *options, vm.names.caseFirst, nullptr, { "upper"sv, "lower"sv, "false"sv });
if (vm.exception()) if (auto* exception = vm.exception())
return {}; return throw_completion(exception->value());
// 23. Let kn be ? GetOption(options, "numeric", "boolean", undefined, undefined). // 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). // 24. If kn is not undefined, set kn to ! ToString(kn).
// 25. Set opt.[[kn]] to kn. // 25. Set opt.[[kn]] to kn.
if (!kn.is_undefined()) 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). // 26. Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined).
// 27. If numberingSystem is not undefined, then // 27. If numberingSystem is not undefined, then
// a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. // a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
// 28. Set opt.[[nu]] to numberingSystem. // 28. Set opt.[[nu]] to numberingSystem.
opt.nu = get_string_option(global_object, *options, vm.names.numberingSystem, Unicode::is_type_identifier); opt.nu = get_string_option(global_object, *options, vm.names.numberingSystem, Unicode::is_type_identifier);
if (vm.exception()) if (auto* exception = vm.exception())
return {}; return throw_completion(exception->value());
// 29. Let r be ! ApplyUnicodeExtensionToTag(tag, opt, relevantExtensionKeys). // 29. Let r be ! ApplyUnicodeExtensionToTag(tag, opt, relevantExtensionKeys).
auto result = apply_unicode_extension_to_tag(tag, move(opt), relevant_extension_keys); 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 void initialize(GlobalObject&) override;
virtual ~LocaleConstructor() override = default; virtual ~LocaleConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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. // 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 // 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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
@ -51,10 +51,10 @@ Value NumberFormatConstructor::construct(FunctionObject& new_target)
auto options = vm.argument(1); 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]] »). // 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). // 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 // 4. If the implementation supports the normative optional constructor mode of 4.3 Note 1, then
// a. Let this be the this value. // a. Let this be the this value.

View file

@ -18,8 +18,8 @@ public:
virtual void initialize(GlobalObject&) override; virtual void initialize(GlobalObject&) override;
virtual ~NumberFormatConstructor() override = default; virtual ~NumberFormatConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 24.1.1.1 Map ( [ iterable ] ), https://tc39.es/ecma262/#sec-map-iterable
Value MapConstructor::call() ThrowCompletionOr<Value> MapConstructor::call()
{ {
auto& vm = this->vm(); auto& vm = this->vm();
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Map); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Map);
return {};
} }
// 24.1.1.1 Map ( [ iterable ] ), https://tc39.es/ecma262/#sec-map-iterable // 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& vm = this->vm();
auto& global_object = this->global_object(); 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()) if (vm.argument(0).is_nullish())
return map; return map;
auto adder = TRY_OR_DISCARD(map->get(vm.names.set)); auto adder = TRY(map->get(vm.names.set));
if (!adder.is_function()) { if (!adder.is_function())
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, "'set' property of Map"); return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, "'set' property of Map");
return {};
}
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()) 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())); 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 void initialize(GlobalObject&) override;
virtual ~MapConstructor() override; virtual ~MapConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject&) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override;
private: private:
virtual bool has_constructor() const override { return true; } 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(); vm.pop_execution_context();
// 12. Return result. // 12. Return result.
if (auto* exception = vm.exception())
return throw_completion(exception->value());
return result; return result;
} }
@ -179,17 +177,15 @@ ThrowCompletionOr<Object*> NativeFunction::internal_construct(MarkedValueList ar
vm.pop_execution_context(); vm.pop_execution_context();
// 12. Return result. // 12. Return result.
if (auto* exception = vm.exception()) return result;
return throw_completion(exception->value());
return &result.as_object();
} }
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. // Needs to be overridden if [[Construct]] is needed.
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();

View file

@ -7,6 +7,7 @@
#pragma once #pragma once
#include <AK/Function.h> #include <AK/Function.h>
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/FunctionObject.h> #include <LibJS/Runtime/FunctionObject.h>
namespace JS { 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". // 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. // Needs to be overridden by all NativeFunctions without an m_native_function.
virtual Value call(); virtual ThrowCompletionOr<Value> call();
virtual Value construct(FunctionObject& new_target); virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target);
virtual const FlyString& name() const override { return m_name; }; virtual const FlyString& name() const override { return m_name; };
virtual bool is_strict_mode() const override; 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 // 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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
auto number = get_value_from_constructor_argument(global_object); auto number = get_value_from_constructor_argument(global_object);
if (vm.exception()) if (auto* exception = vm.exception())
return {}; return throw_completion(exception->value());
return number; return number;
} }
// 21.1.1.1 Number ( value ), https://tc39.es/ecma262/#sec-number-constructor-number-value // 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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
auto number = get_value_from_constructor_argument(global_object); auto number = get_value_from_constructor_argument(global_object);
if (vm.exception()) if (auto* exception = vm.exception())
return {}; return throw_completion(exception->value());
return TRY_OR_DISCARD(ordinary_create_from_constructor<NumberObject>(global_object, new_target, &GlobalObject::number_prototype, number.as_double())); 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 // 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 void initialize(GlobalObject&) override;
virtual ~NumberConstructor() override; virtual ~NumberConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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 // 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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
if (&new_target != this) 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); auto value = vm.argument(0);
if (value.is_nullish()) if (value.is_nullish())
return Object::create(global_object, global_object.object_prototype()); 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 { enum class GetOwnPropertyKeysType {

View file

@ -19,8 +19,8 @@ public:
virtual void initialize(GlobalObject&) override; virtual void initialize(GlobalObject&) override;
virtual ~ObjectConstructor() override; virtual ~ObjectConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 27.2.3.1 Promise ( executor ), https://tc39.es/ecma262/#sec-promise-executor
Value PromiseConstructor::call() ThrowCompletionOr<Value> PromiseConstructor::call()
{ {
auto& vm = this->vm(); auto& vm = this->vm();
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Promise); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Promise);
return {};
} }
// 27.2.3.1 Promise ( executor ), https://tc39.es/ecma262/#sec-promise-executor // 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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
auto executor = vm.argument(0); auto executor = vm.argument(0);
if (!executor.is_function()) { if (!executor.is_function())
vm.throw_exception<TypeError>(global_object, ErrorType::PromiseExecutorNotAFunction); return vm.throw_completion<TypeError>(global_object, ErrorType::PromiseExecutorNotAFunction);
return {};
}
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(); auto [resolve_function, reject_function] = promise->create_resolving_functions();
@ -278,7 +275,7 @@ Value PromiseConstructor::construct(FunctionObject& new_target)
if (auto* exception = vm.exception()) { if (auto* exception = vm.exception()) {
vm.clear_exception(); vm.clear_exception();
vm.stop_unwind(); vm.stop_unwind();
(void)vm.call(reject_function, js_undefined(), exception->value()); TRY(vm.call(reject_function, js_undefined(), exception->value()));
} }
return promise; return promise;
} }

View file

@ -18,8 +18,8 @@ public:
virtual void initialize(GlobalObject&) override; virtual void initialize(GlobalObject&) override;
virtual ~PromiseConstructor() override = default; virtual ~PromiseConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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& vm = this->vm();
auto& promise_capability = m_reaction.capability(); auto& promise_capability = m_reaction.capability();
@ -64,11 +64,11 @@ Value PromiseReactionJob::call()
vm.stop_unwind(); vm.stop_unwind();
auto* reject_function = promise_capability.value().reject; auto* reject_function = promise_capability.value().reject;
dbgln_if(PROMISE_DEBUG, "[PromiseReactionJob @ {}]: Calling PromiseCapability's reject function @ {}", this, reject_function); 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 { } else {
auto* resolve_function = promise_capability.value().resolve; auto* resolve_function = promise_capability.value().resolve;
dbgln_if(PROMISE_DEBUG, "[PromiseReactionJob @ {}]: Calling PromiseCapability's resolve function @ {}", this, resolve_function); 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 // 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& vm = this->vm();
auto [resolve_function, reject_function] = m_promise_to_resolve.create_resolving_functions(); 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); explicit PromiseReactionJob(PromiseReaction&, Value argument, Object& prototype);
virtual ~PromiseReactionJob() override = default; virtual ~PromiseReactionJob() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
private: private:
virtual void visit_edges(Visitor&) override; virtual void visit_edges(Visitor&) override;
@ -40,7 +40,7 @@ public:
explicit PromiseResolveThenableJob(Promise&, Value thenable, JobCallback then, Object& prototype); explicit PromiseResolveThenableJob(Promise&, Value thenable, JobCallback then, Object& prototype);
virtual ~PromiseResolveThenableJob() override = default; virtual ~PromiseResolveThenableJob() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
private: private:
virtual void visit_edges(Visitor&) override; 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); define_direct_property(vm().names.length, Value(1), Attribute::Configurable);
} }
Value PromiseResolvingElementFunction::call() ThrowCompletionOr<Value> PromiseResolvingElementFunction::call()
{ {
if (m_already_called) if (m_already_called)
return js_undefined(); return js_undefined();

View file

@ -46,7 +46,7 @@ public:
virtual void initialize(GlobalObject&) override; virtual void initialize(GlobalObject&) override;
virtual ~PromiseResolvingElementFunction() override = default; virtual ~PromiseResolvingElementFunction() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
protected: protected:
explicit PromiseResolvingElementFunction(size_t, PromiseValueList&, PromiseCapability, RemainingElements&, Object& prototype); 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); 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) void PromiseResolvingFunction::visit_edges(Cell::Visitor& visitor)

View file

@ -33,7 +33,7 @@ public:
virtual void initialize(GlobalObject&) override; virtual void initialize(GlobalObject&) override;
virtual ~PromiseResolvingFunction() override = default; virtual ~PromiseResolvingFunction() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
private: private:
virtual void visit_edges(Visitor&) override; 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 // 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(); auto& vm = this->vm();
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Proxy); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Proxy);
return {};
} }
// 28.2.1.1 Proxy ( target, handler ), https://tc39.es/ecma262/#sec-proxy-target-handler // 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(); 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 // 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 void initialize(GlobalObject&) override;
virtual ~ProxyConstructor() override; virtual ~ProxyConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
@ -42,19 +42,19 @@ Value RegExpConstructor::call()
auto pattern = vm.argument(0); auto pattern = vm.argument(0);
auto flags = vm.argument(1); 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()) { 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)) if (same_value(this, pattern_constructor))
return pattern; return pattern;
} }
return construct(*this); return TRY(construct(*this));
} }
// 22.2.3.1 RegExp ( pattern, flags ), https://tc39.es/ecma262/#sec-regexp-pattern-flags // 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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
@ -62,7 +62,7 @@ Value RegExpConstructor::construct(FunctionObject&)
auto pattern = vm.argument(0); auto pattern = vm.argument(0);
auto flags = vm.argument(1); 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 pattern_value;
Value flags_value; Value flags_value;
@ -76,10 +76,10 @@ Value RegExpConstructor::construct(FunctionObject&)
else else
flags_value = flags; flags_value = flags;
} else if (pattern_is_regexp) { } 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()) { 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 { } else {
flags_value = flags; flags_value = flags;
} }
@ -88,7 +88,10 @@ Value RegExpConstructor::construct(FunctionObject&)
flags_value = flags; 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 // 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 void initialize(GlobalObject&) override;
virtual ~RegExpConstructor() override; virtual ~RegExpConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 24.2.1.1 Set ( [ iterable ] ), https://tc39.es/ecma262/#sec-set-iterable
Value SetConstructor::call() ThrowCompletionOr<Value> SetConstructor::call()
{ {
auto& vm = this->vm(); auto& vm = this->vm();
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Set); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Set);
return {};
} }
// 24.2.1.1 Set ( [ iterable ] ), https://tc39.es/ecma262/#sec-set-iterable // 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& vm = this->vm();
auto& global_object = this->global_object(); 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()) if (vm.argument(0).is_nullish())
return set; return set;
auto adder = TRY_OR_DISCARD(set->get(vm.names.add)); auto adder = TRY(set->get(vm.names.add));
if (!adder.is_function()) { if (!adder.is_function())
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, "'add' property of Set"); return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, "'add' property of Set");
return {};
}
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)); TRY(vm.call(adder.as_function(), Value(set), iterator_value));
return {}; return {};
})); }));

View file

@ -18,8 +18,8 @@ public:
virtual void initialize(GlobalObject&) override; virtual void initialize(GlobalObject&) override;
virtual ~SetConstructor() override; virtual ~SetConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject&) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 3.2.1 ShadowRealm ( ), https://tc39.es/proposal-shadowrealm/#sec-shadowrealm
Value ShadowRealmConstructor::call() ThrowCompletionOr<Value> ShadowRealmConstructor::call()
{ {
auto& vm = this->vm(); auto& vm = this->vm();
// 1. If NewTarget is undefined, throw a TypeError exception. // 1. If NewTarget is undefined, throw a TypeError exception.
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ShadowRealm); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ShadowRealm);
return {};
} }
// 3.2.1 ShadowRealm ( ), https://tc39.es/proposal-shadowrealm/#sec-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& vm = this->vm();
auto& global_object = this->global_object(); 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]] »). // 2. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%ShadowRealm.prototype%", « [[ShadowRealm]], [[ExecutionContext]] »).
// 4. Set O.[[ShadowRealm]] to realmRec. // 4. Set O.[[ShadowRealm]] to realmRec.
// 9. Set O.[[ExecutionContext]] to context. // 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). // 10. Perform ? SetRealmGlobalObject(realmRec, undefined, undefined).
auto* new_global_object = vm.heap().allocate_without_global_object<GlobalObject>(); auto* new_global_object = vm.heap().allocate_without_global_object<GlobalObject>();

View file

@ -18,8 +18,8 @@ public:
virtual void initialize(GlobalObject&) override; virtual void initialize(GlobalObject&) override;
virtual ~ShadowRealmConstructor() override = default; virtual ~ShadowRealmConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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()) if (!vm().argument_count())
return js_string(heap(), ""); return js_string(heap(), "");
if (vm().argument(0).is_symbol()) if (vm().argument(0).is_symbol())
return js_string(heap(), vm().argument(0).as_symbol().to_string()); 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 // 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(); auto& vm = global_object().vm();
@ -61,8 +61,8 @@ Value StringConstructor::construct(FunctionObject& new_target)
if (!vm.argument_count()) if (!vm.argument_count())
primitive_string = js_string(vm, ""); primitive_string = js_string(vm, "");
else else
primitive_string = TRY_OR_DISCARD(vm.argument(0).to_primitive_string(global_object())); primitive_string = TRY(vm.argument(0).to_primitive_string(global_object()));
auto* prototype = TRY_OR_DISCARD(get_prototype_from_constructor(global_object(), new_target, &GlobalObject::string_prototype)); auto* prototype = TRY(get_prototype_from_constructor(global_object(), new_target, &GlobalObject::string_prototype));
return StringObject::create(global_object(), *primitive_string, *prototype); return StringObject::create(global_object(), *primitive_string, *prototype);
} }

View file

@ -18,8 +18,8 @@ public:
virtual void initialize(GlobalObject&) override; virtual void initialize(GlobalObject&) override;
virtual ~StringConstructor() override; virtual ~StringConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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()) if (vm().argument(0).is_undefined())
return js_symbol(heap(), {}, false); 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 // 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 vm().throw_completion<TypeError>(global_object(), ErrorType::NotAConstructor, "Symbol");
return {};
} }
// 20.4.2.2 Symbol.for ( key ), https://tc39.es/ecma262/#sec-symbol.for // 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 void initialize(GlobalObject&) override;
virtual ~SymbolConstructor() override; virtual ~SymbolConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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(); auto& vm = this->vm();
// 1. If NewTarget is undefined, then // 1. If NewTarget is undefined, then
// a. Throw a TypeError exception. // a. Throw a TypeError exception.
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Calendar"); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Calendar");
return {};
} }
// 12.2.1 Temporal.Calendar ( id ), https://tc39.es/proposal-temporal/#sec-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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
// 2. Set id to ? ToString(id). // 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 // 3. If ! IsBuiltinCalendar(id) is false, then
if (!is_builtin_calendar(identifier)) { if (!is_builtin_calendar(identifier)) {
// a. Throw a RangeError exception. // a. Throw a RangeError exception.
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidCalendarIdentifier, identifier); return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidCalendarIdentifier, identifier);
return {};
} }
// 4. Return ? CreateTemporalCalendar(id, NewTarget). // 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 // 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 void initialize(GlobalObject&) override;
virtual ~CalendarConstructor() override = default; virtual ~CalendarConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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(); auto& vm = this->vm();
// 1. If NewTarget is undefined, then // 1. If NewTarget is undefined, then
// a. Throw a TypeError exception. // a. Throw a TypeError exception.
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Duration"); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Duration");
return {};
} }
// 7.1.1 Temporal.Duration ( [ years [ , months [ , weeks [ , days [ , hours [ , minutes [ , seconds [ , milliseconds [ , microseconds [ , nanoseconds ] ] ] ] ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
// 2. Let y be ? ToIntegerThrowOnInfinity(years). // 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). // 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). // 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). // 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). // 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). // 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). // 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). // 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). // 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). // 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). // 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 // 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 void initialize(GlobalObject&) override;
virtual ~DurationConstructor() override = default; virtual ~DurationConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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(); auto& vm = this->vm();
// 1. If NewTarget is undefined, then // 1. If NewTarget is undefined, then
// a. Throw a TypeError exception. // a. Throw a TypeError exception.
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Instant"); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Instant");
return {};
} }
// 8.1.1 Temporal.Instant ( epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
// 2. Let epochNanoseconds be ? ToBigInt(epochNanoseconds). // 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. // 3. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds)) { if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds))
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidEpochNanoseconds); return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidEpochNanoseconds);
return {};
}
// 4. Return ? CreateTemporalInstant(epochNanoseconds, NewTarget). // 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 // 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 void initialize(GlobalObject&) override;
virtual ~InstantConstructor() override = default; virtual ~InstantConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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(); auto& vm = this->vm();
// 1. If NewTarget is undefined, throw a TypeError exception. // 1. If NewTarget is undefined, throw a TypeError exception.
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainDate"); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainDate");
return {};
} }
// 3.1.1 Temporal.PlainDate ( isoYear, isoMonth, isoDay [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
// 2. Let y be ? ToIntegerThrowOnInfinity(isoYear). // 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). // 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). // 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). // 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. // 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 // 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. // 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)) { 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 vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidPlainDate);
return {};
}
// 6. Return ? CreateTemporalDate(y, m, d, calendar, NewTarget). // 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 // 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 void initialize(GlobalObject&) override;
virtual ~PlainDateConstructor() override = default; virtual ~PlainDateConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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(); auto& vm = this->vm();
// 1. If NewTarget is undefined, throw a TypeError exception. // 1. If NewTarget is undefined, throw a TypeError exception.
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainDateTime"); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainDateTime");
return {};
} }
// 5.1.1 Temporal.PlainDateTime ( isoYear, isoMonth, isoDay [ , hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond [ , calendarLike ] ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
// 2. Let isoYear be ? ToIntegerThrowOnInfinity(isoYear). // 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). // 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). // 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). // 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). // 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). // 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). // 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). // 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). // 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). // 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. // 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 // 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, // 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. // 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)) { 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 vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidPlainDateTime);
return {};
}
// 12. Return ? CreateTemporalDateTime(isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, nanosecond, calendar, NewTarget). // 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 // 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 void initialize(GlobalObject&) override;
virtual ~PlainDateTimeConstructor() override = default; virtual ~PlainDateTimeConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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(); auto& vm = this->vm();
// 1. If NewTarget is undefined, throw a TypeError exception. // 1. If NewTarget is undefined, throw a TypeError exception.
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainMonthDay"); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainMonthDay");
return {};
} }
// 10.1.1 Temporal.PlainMonthDay ( isoMonth, isoDay [ , calendarLike [ , referenceISOYear ] ] ), https://tc39.es/proposal-temporal/#sec-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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
@ -62,27 +61,25 @@ Value PlainMonthDayConstructor::construct(FunctionObject& new_target)
} }
// 3. Let m be ? ToIntegerThrowOnInfinity(isoMonth). // 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). // 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). // 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). // 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. // 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 // 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. // 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)) { 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 vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidPlainYearMonth);
return {};
}
// 7. Return ? CreateTemporalMonthDay(m, d, calendar, ref, NewTarget). // 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 // 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 void initialize(GlobalObject&) override;
virtual ~PlainMonthDayConstructor() override = default; virtual ~PlainMonthDayConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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(); auto& vm = this->vm();
// 1. If NewTarget is undefined, throw a TypeError exception. // 1. If NewTarget is undefined, throw a TypeError exception.
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainTime"); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainTime");
return {};
} }
// 4.1.1 Temporal.PlainTime ( [ hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
// 2. Let hour be ? ToIntegerThrowOnInfinity(hour). // 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). // 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). // 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). // 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). // 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). // 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. // 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 // 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 // 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. // 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)) { 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 vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
return {};
}
// 8. Return ? CreateTemporalTime(hour, minute, second, millisecond, microsecond, nanosecond, NewTarget). // 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 // 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 void initialize(GlobalObject&) override;
virtual ~PlainTimeConstructor() override = default; virtual ~PlainTimeConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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(); auto& vm = this->vm();
// 1. If NewTarget is undefined, throw a TypeError exception. // 1. If NewTarget is undefined, throw a TypeError exception.
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainYearMonth"); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainYearMonth");
return {};
} }
// 9.1.1 Temporal.PlainYearMonth ( isoYear, isoMonth [ , calendarLike [ , referenceISODay ] ] ), https://tc39.es/proposal-temporal/#sec-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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
@ -64,27 +63,25 @@ Value PlainYearMonthConstructor::construct(FunctionObject& new_target)
} }
// 3. Let y be ? ToIntegerThrowOnInfinity(isoYear). // 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). // 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). // 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). // 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. // 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 // 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. // 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)) { 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 vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidPlainYearMonth);
return {};
}
// 7. Return ? CreateTemporalYearMonth(y, m, calendar, ref, NewTarget). // 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 // 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 void initialize(GlobalObject&) override;
virtual ~PlainYearMonthConstructor() override = default; virtual ~PlainYearMonthConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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(); auto& vm = this->vm();
// 1. If NewTarget is undefined, then // 1. If NewTarget is undefined, then
// a. Throw a TypeError exception. // a. Throw a TypeError exception.
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.TimeZone"); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.TimeZone");
return {};
} }
// 11.2.1 Temporal.TimeZone ( identifier ), https://tc39.es/proposal-temporal/#sec-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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
// 2. Set identifier to ? ToString(identifier). // 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; String canonical;
// 3. If identifier satisfies the syntax of a TimeZoneNumericUTCOffset (see 13.33), then // 3. If identifier satisfies the syntax of a TimeZoneNumericUTCOffset (see 13.33), then
if (is_valid_time_zone_numeric_utc_offset_syntax(identifier)) { if (is_valid_time_zone_numeric_utc_offset_syntax(identifier)) {
// a. Let offsetNanoseconds be ? ParseTimeZoneOffsetString(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). // b. Let canonical be ! FormatTimeZoneOffsetString(offsetNanoseconds).
canonical = format_time_zone_offset_string(offset_nanoseconds); 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 // a. If ! IsValidTimeZoneName(identifier) is false, then
if (!is_valid_time_zone_name(identifier)) { if (!is_valid_time_zone_name(identifier)) {
// i. Throw a RangeError exception. // i. Throw a RangeError exception.
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidTimeZoneName); return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidTimeZoneName);
return {};
} }
// b. Let canonical be ! CanonicalizeTimeZoneName(identifier). // b. Let canonical be ! CanonicalizeTimeZoneName(identifier).
@ -75,7 +73,7 @@ Value TimeZoneConstructor::construct(FunctionObject& new_target)
} }
// 5. Return ? CreateTemporalTimeZone(canonical, NewTarget). // 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 // 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 void initialize(GlobalObject&) override;
virtual ~TimeZoneConstructor() override = default; virtual ~TimeZoneConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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(); auto& vm = this->vm();
// 1. If NewTarget is undefined, then // 1. If NewTarget is undefined, then
// a. Throw a TypeError exception. // a. Throw a TypeError exception.
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.ZonedDateTime"); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.ZonedDateTime");
return {};
} }
// 6.1.1 Temporal.ZonedDateTime ( epochNanoseconds, timeZoneLike [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
// 2. Set epochNanoseconds to ? ToBigInt(epochNanoseconds). // 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. // 3. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds)) { if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds))
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidEpochNanoseconds); return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidEpochNanoseconds);
return {};
}
// 4. Let timeZone be ? ToTemporalTimeZone(timeZoneLike). // 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). // 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). // 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 void initialize(GlobalObject&) override;
virtual ~ZonedDateTimeConstructor() override = default; virtual ~ZonedDateTimeConstructor() override = default;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 */ \ /* 23.2.5.1 TypedArray ( ...args ), https://tc39.es/ecma262/#sec-typedarray */ \
Value ConstructorName::call() \ ThrowCompletionOr<Value> ConstructorName::call() \
{ \ { \
auto& vm = this->vm(); \ auto& vm = this->vm(); \
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ClassName); \ return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ClassName); \
return {}; \
} \ } \
\ \
/* 23.2.5.1 TypedArray ( ...args ), https://tc39.es/ecma262/#sec-typedarray */ \ /* 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(); \ auto& vm = this->vm(); \
if (vm.argument_count() == 0) \ if (vm.argument_count() == 0) \
@ -451,27 +450,25 @@ void TypedArrayBase::visit_edges(Visitor& visitor)
auto first_argument = vm.argument(0); \ auto first_argument = vm.argument(0); \
if (first_argument.is_object()) { \ if (first_argument.is_object()) { \
auto* typed_array = ClassName::create(global_object(), 0, new_target); \ auto* typed_array = ClassName::create(global_object(), 0, new_target); \
if (vm.exception()) \ if (auto* exception = vm.exception()) \
return {}; \ return throw_completion(exception->value()); \
if (first_argument.as_object().is_typed_array()) { \ if (first_argument.as_object().is_typed_array()) { \
auto& arg_typed_array = static_cast<TypedArrayBase&>(first_argument.as_object()); \ 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())) { \ } else if (is<ArrayBuffer>(first_argument.as_object())) { \
auto& array_buffer = static_cast<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 */ \ /* 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. */ \ /* 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))); \ vm.argument(1), vm.argument(2))); \
} else { \ } 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) { \ if (iterator) { \
auto values = TRY_OR_DISCARD(iterable_to_list(global_object(), first_argument, iterator)); \ auto values = TRY(iterable_to_list(global_object(), first_argument, iterator)); \
TRY_OR_DISCARD(initialize_typed_array_from_list(global_object(), *typed_array, values)); \ TRY(initialize_typed_array_from_list(global_object(), *typed_array, values)); \
} else { \ } 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; \ return typed_array; \
} \ } \
@ -482,20 +479,16 @@ void TypedArrayBase::visit_edges(Visitor& visitor)
if (error.value().is_object() && is<RangeError>(error.value().as_object())) { \ if (error.value().is_object() && is<RangeError>(error.value().as_object())) { \
/* Re-throw more specific RangeError */ \ /* Re-throw more specific RangeError */ \
vm.clear_exception(); \ 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(); \ auto array_length = array_length_or_error.release_value(); \
if (array_length > NumericLimits<i32>::max() / sizeof(Type)) { \ if (array_length > NumericLimits<i32>::max() / sizeof(Type)) \
vm.throw_exception<RangeError>(global_object(), ErrorType::InvalidLength, "typed array"); \ return vm.throw_completion<RangeError>(global_object(), ErrorType::InvalidLength, "typed array"); \
return {}; \
} \
/* FIXME: What is the best/correct behavior here? */ \ /* FIXME: What is the best/correct behavior here? */ \
if (Checked<u32>::multiplication_would_overflow(array_length, sizeof(Type))) { \ if (Checked<u32>::multiplication_would_overflow(array_length, sizeof(Type))) \
vm.throw_exception<RangeError>(global_object(), ErrorType::InvalidLength, "typed array"); \ return vm.throw_completion<RangeError>(global_object(), ErrorType::InvalidLength, "typed array"); \
return {}; \
} \
return ClassName::create(global_object(), array_length, new_target); \ 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 void initialize(GlobalObject&) override; \
virtual ~ConstructorName() override; \ virtual ~ConstructorName() override; \
\ \
virtual Value call() override; \ virtual ThrowCompletionOr<Value> call() override; \
virtual Value construct(FunctionObject& new_target) override; \ virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; \
\ \
private: \ private: \
virtual bool has_constructor() const override { return true; } \ 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% // 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% // 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 vm().throw_completion<TypeError>(global_object(), ErrorType::ClassIsAbstract, "TypedArray");
return {};
} }
// 23.2.2.1 %TypedArray%.from ( source [ , mapfn [ , thisArg ] ] ), https://tc39.es/ecma262/#sec-%typedarray%.from // 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 void initialize(GlobalObject&) override;
virtual ~TypedArrayConstructor() override; virtual ~TypedArrayConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject& new_target) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 24.3.1.1 WeakMap ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakmap-iterable
Value WeakMapConstructor::call() ThrowCompletionOr<Value> WeakMapConstructor::call()
{ {
auto& vm = this->vm(); auto& vm = this->vm();
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakMap); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakMap);
return {};
} }
// 24.3.1.1 WeakMap ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakmap-iterable // 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& vm = this->vm();
auto& global_object = this->global_object(); 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()) if (vm.argument(0).is_nullish())
return weak_map; return weak_map;
auto adder = TRY_OR_DISCARD(weak_map->get(vm.names.set)); auto adder = TRY(weak_map->get(vm.names.set));
if (!adder.is_function()) { if (!adder.is_function())
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, "'set' property of WeakMap"); return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, "'set' property of WeakMap");
return {};
}
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()) 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())); 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 void initialize(GlobalObject&) override;
virtual ~WeakMapConstructor() override; virtual ~WeakMapConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject&) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 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(); auto& vm = this->vm();
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakRef); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakRef);
return {};
} }
// 26.1.1.1 WeakRef ( target ), https://tc39.es/ecma262/#sec-weak-ref-target // 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& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
auto target = vm.argument(0); auto target = vm.argument(0);
if (!target.is_object()) { if (!target.is_object())
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, target.to_string_without_side_effects()); return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObject, target.to_string_without_side_effects());
return {}; return TRY(ordinary_create_from_constructor<WeakRef>(global_object, new_target, &GlobalObject::weak_ref_prototype, &target.as_object()));
}
return TRY_OR_DISCARD(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 void initialize(GlobalObject&) override;
virtual ~WeakRefConstructor() override; virtual ~WeakRefConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject&) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 // 24.4.1.1 WeakSet ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakset-iterable
Value WeakSetConstructor::call() ThrowCompletionOr<Value> WeakSetConstructor::call()
{ {
auto& vm = this->vm(); auto& vm = this->vm();
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakSet); return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakSet);
return {};
} }
// 24.4.1.1 WeakSet ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakset-iterable // 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& vm = this->vm();
auto& global_object = this->global_object(); 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()) if (vm.argument(0).is_nullish())
return weak_set; return weak_set;
auto adder = TRY_OR_DISCARD(weak_set->get(vm.names.add)); auto adder = TRY(weak_set->get(vm.names.add));
if (!adder.is_function()) { if (!adder.is_function())
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, "'add' property of WeakSet"); return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, "'add' property of WeakSet");
return {};
}
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)); TRY(vm.call(adder.as_function(), Value(weak_set), iterator_value));
return {}; return {};
})); }));

View file

@ -18,8 +18,8 @@ public:
virtual void initialize(GlobalObject&) override; virtual void initialize(GlobalObject&) override;
virtual ~WeakSetConstructor() override; virtual ~WeakSetConstructor() override;
virtual Value call() override; virtual ThrowCompletionOr<Value> call() override;
virtual Value construct(FunctionObject&) override; virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "Image");
return {};
} }
// https://html.spec.whatwg.org/multipage/embedded-content.html#dom-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& window = static_cast<WindowObject&>(global_object());
auto& document = window.impl().associated_document(); auto& document = window.impl().associated_document();
auto image_element = DOM::create_element(document, HTML::TagNames::img, Namespace::HTML); auto image_element = DOM::create_element(document, HTML::TagNames::img, Namespace::HTML);
if (vm().argument_count() > 0) { 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)); image_element->set_attribute(HTML::AttributeNames::width, String::formatted("{}", width));
} }
if (vm().argument_count() > 1) { 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)); image_element->set_attribute(HTML::AttributeNames::height, String::formatted("{}", height));
} }

View file

@ -16,8 +16,8 @@ public:
virtual void initialize(JS::GlobalObject&) override; virtual void initialize(JS::GlobalObject&) override;
virtual ~ImageConstructor() override; virtual ~ImageConstructor() override;
virtual JS::Value call() override; virtual JS::ThrowCompletionOr<JS::Value> call() override;
virtual JS::Value construct(JS::FunctionObject& new_target) override; virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Instance");
return {};
} }
JS::Value WebAssemblyInstanceConstructor::construct(FunctionObject&) JS::ThrowCompletionOr<JS::Object*> WebAssemblyInstanceConstructor::construct(FunctionObject&)
{ {
auto& vm = this->vm(); auto& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
auto* module_argument = TRY_OR_DISCARD(vm.argument(0).to_object(global_object)); auto* module_argument = TRY(vm.argument(0).to_object(global_object));
if (!is<WebAssemblyModuleObject>(module_argument)) { if (!is<WebAssemblyModuleObject>(module_argument))
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "WebAssembly.Module"); return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "WebAssembly.Module");
return {};
}
auto& module_object = static_cast<WebAssemblyModuleObject&>(*module_argument); auto& module_object = static_cast<WebAssemblyModuleObject&>(*module_argument);
auto result = WebAssemblyObject::instantiate_module(module_object.module(), vm, global_object); auto result = WebAssemblyObject::instantiate_module(module_object.module(), vm, global_object);
if (result.is_error()) { if (result.is_error()) {
vm.throw_exception(global_object, result.release_error()); vm.throw_exception(global_object, result.error());
return {}; return JS::throw_completion(result.error());
} }
return heap().allocate<WebAssemblyInstanceObject>(global_object, global_object, result.value()); return heap().allocate<WebAssemblyInstanceObject>(global_object, global_object, result.value());
} }

View file

@ -18,8 +18,8 @@ public:
virtual void initialize(JS::GlobalObject&) override; virtual void initialize(JS::GlobalObject&) override;
virtual ~WebAssemblyInstanceConstructor() override; virtual ~WebAssemblyInstanceConstructor() override;
virtual JS::Value call() override; virtual JS::ThrowCompletionOr<JS::Value> call() override;
virtual JS::Value construct(JS::FunctionObject& new_target) override; virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Memory");
return {};
} }
JS::Value WebAssemblyMemoryConstructor::construct(FunctionObject&) JS::ThrowCompletionOr<JS::Object*> WebAssemblyMemoryConstructor::construct(FunctionObject&)
{ {
auto& vm = this->vm(); auto& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
auto descriptor = TRY_OR_DISCARD(vm.argument(0).to_object(global_object)); auto descriptor = TRY(vm.argument(0).to_object(global_object));
auto initial_value = TRY_OR_DISCARD(descriptor->get("initial")); auto initial_value = TRY(descriptor->get("initial"));
auto maximum_value = TRY_OR_DISCARD(descriptor->get("maximum")); auto maximum_value = TRY(descriptor->get("maximum"));
if (initial_value.is_empty()) { if (initial_value.is_empty())
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "Number"); return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "Number");
return {};
}
auto initial = TRY_OR_DISCARD(initial_value.to_u32(global_object)); auto initial = TRY(initial_value.to_u32(global_object));
Optional<u32> maximum; Optional<u32> maximum;
if (!maximum_value.is_empty()) 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 } }); auto address = WebAssemblyObject::s_abstract_machine.store().allocate(Wasm::MemoryType { Wasm::Limits { initial, maximum } });
if (!address.has_value()) { if (!address.has_value())
vm.throw_exception<JS::TypeError>(global_object, "Wasm Memory allocation failed"); return vm.throw_completion<JS::TypeError>(global_object, "Wasm Memory allocation failed");
return {};
}
return vm.heap().allocate<WebAssemblyMemoryObject>(global_object, global_object, *address); return vm.heap().allocate<WebAssemblyMemoryObject>(global_object, global_object, *address);
} }

View file

@ -18,8 +18,8 @@ public:
virtual void initialize(JS::GlobalObject&) override; virtual void initialize(JS::GlobalObject&) override;
virtual ~WebAssemblyMemoryConstructor() override; virtual ~WebAssemblyMemoryConstructor() override;
virtual JS::Value call() override; virtual JS::ThrowCompletionOr<JS::Value> call() override;
virtual JS::Value construct(JS::FunctionObject& new_target) override; virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Module");
return {};
} }
JS::Value WebAssemblyModuleConstructor::construct(FunctionObject&) JS::ThrowCompletionOr<JS::Object*> WebAssemblyModuleConstructor::construct(FunctionObject&)
{ {
auto& vm = this->vm(); auto& vm = this->vm();
auto& global_object = this->global_object(); 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); auto result = parse_module(global_object, buffer_object);
if (result.is_error()) { if (result.is_error()) {
vm.throw_exception(global_object, result.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()); 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 void initialize(JS::GlobalObject&) override;
virtual ~WebAssemblyModuleConstructor() override; virtual ~WebAssemblyModuleConstructor() override;
virtual JS::Value call() override; virtual JS::ThrowCompletionOr<JS::Value> call() override;
virtual JS::Value construct(JS::FunctionObject& new_target) override; virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } 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 vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Table");
return {};
} }
JS::Value WebAssemblyTableConstructor::construct(FunctionObject&) JS::ThrowCompletionOr<JS::Object*> WebAssemblyTableConstructor::construct(FunctionObject&)
{ {
auto& vm = this->vm(); auto& vm = this->vm();
auto& global_object = this->global_object(); auto& global_object = this->global_object();
auto descriptor = TRY_OR_DISCARD(vm.argument(0).to_object(global_object)); auto descriptor = TRY(vm.argument(0).to_object(global_object));
auto element_value = TRY_OR_DISCARD(descriptor->get("element")); auto element_value = TRY(descriptor->get("element"));
if (!element_value.is_string()) { if (!element_value.is_string())
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::InvalidHint, element_value.to_string_without_side_effects()); return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::InvalidHint, element_value.to_string_without_side_effects());
return {};
}
auto& element = element_value.as_string().string(); auto& element = element_value.as_string().string();
Optional<Wasm::ValueType> reference_type; Optional<Wasm::ValueType> reference_type;
@ -48,27 +45,23 @@ JS::Value WebAssemblyTableConstructor::construct(FunctionObject&)
else if (element == "externref"sv) else if (element == "externref"sv)
reference_type = Wasm::ValueType(Wasm::ValueType::ExternReference); reference_type = Wasm::ValueType(Wasm::ValueType::ExternReference);
if (!reference_type.has_value()) { if (!reference_type.has_value())
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::InvalidHint, element); return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::InvalidHint, element);
return {};
}
auto initial_value = TRY_OR_DISCARD(descriptor->get("initial")); auto initial_value = TRY(descriptor->get("initial"));
auto maximum_value = TRY_OR_DISCARD(descriptor->get("maximum")); 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; Optional<u32> maximum;
if (!maximum_value.is_undefined()) 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) { if (maximum.has_value() && maximum.value() < initial)
vm.throw_exception<JS::RangeError>(global_object, "maximum should be larger than or equal to initial"); return vm.throw_completion<JS::RangeError>(global_object, "maximum should be larger than or equal to initial");
return {};
}
auto value_value = TRY_OR_DISCARD(descriptor->get("value")); auto value_value = TRY(descriptor->get("value"));
auto reference_value = [&]() -> Optional<Wasm::Value> { auto reference_value = [&]() -> Optional<Wasm::Value> {
if (value_value.is_undefined()) if (value_value.is_undefined())
return Wasm::Value(*reference_type, 0ull); 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); return to_webassembly_value(value_value, *reference_type, global_object);
}(); }();
if (!reference_value.has_value()) if (auto* exception = vm.exception())
return {}; return JS::throw_completion(exception->value());
auto& reference = reference_value->value().get<Wasm::Reference>(); auto& reference = reference_value->value().get<Wasm::Reference>();
auto address = WebAssemblyObject::s_abstract_machine.store().allocate(Wasm::TableType { *reference_type, Wasm::Limits { initial, maximum } }); auto address = WebAssemblyObject::s_abstract_machine.store().allocate(Wasm::TableType { *reference_type, Wasm::Limits { initial, maximum } });
if (!address.has_value()) { if (!address.has_value())
vm.throw_exception<JS::TypeError>(global_object, "Wasm Table allocation failed"); return vm.throw_completion<JS::TypeError>(global_object, "Wasm Table allocation failed");
return {};
}
auto& table = *WebAssemblyObject::s_abstract_machine.store().get(*address); auto& table = *WebAssemblyObject::s_abstract_machine.store().get(*address);
for (auto& element : table.elements()) for (auto& element : table.elements())

View file

@ -18,8 +18,8 @@ public:
virtual void initialize(JS::GlobalObject&) override; virtual void initialize(JS::GlobalObject&) override;
virtual ~WebAssemblyTableConstructor() override; virtual ~WebAssemblyTableConstructor() override;
virtual JS::Value call() override; virtual JS::ThrowCompletionOr<JS::Value> call() override;
virtual JS::Value construct(JS::FunctionObject& new_target) override; virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override;
private: private:
virtual bool has_constructor() const override { return true; } virtual bool has_constructor() const override { return true; }