mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-04 05:20:30 +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:
parent
0881f8160f
commit
5832de62fe
Notes:
sideshowbarker
2024-07-18 02:06:32 +09:00
Author: https://github.com/linusg Commit: https://github.com/SerenityOS/serenity/commit/5832de62fe5 Pull-request: https://github.com/SerenityOS/serenity/pull/10548 Reviewed-by: https://github.com/IdanHo ✅
99 changed files with 597 additions and 669 deletions
|
@ -940,8 +940,14 @@ static bool is_wrappable_type(IDL::Type const& type)
|
|||
return false;
|
||||
}
|
||||
|
||||
enum class ReturnType {
|
||||
Completion,
|
||||
Value,
|
||||
Void,
|
||||
};
|
||||
|
||||
template<typename ParameterType>
|
||||
static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter, String const& js_name, String const& js_suffix, String const& cpp_name, HashMap<String, IDL::Dictionary> const& dictionaries, bool return_void = false, bool legacy_null_to_empty_string = false, bool optional = false, Optional<String> optional_default_value = {}, bool variadic = false)
|
||||
static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter, String const& js_name, String const& js_suffix, String const& cpp_name, HashMap<String, IDL::Dictionary> const& dictionaries, ReturnType return_type, bool legacy_null_to_empty_string = false, bool optional = false, Optional<String> optional_default_value = {}, bool variadic = false)
|
||||
{
|
||||
auto scoped_generator = generator.fork();
|
||||
scoped_generator.set("cpp_name", make_input_acceptable_cpp(cpp_name));
|
||||
|
@ -957,10 +963,21 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
if (optional_default_value.has_value())
|
||||
scoped_generator.set("parameter.optional_default_value", *optional_default_value);
|
||||
|
||||
if (return_void)
|
||||
scoped_generator.set("return_statement", "return;");
|
||||
else
|
||||
switch (return_type) {
|
||||
case ReturnType::Completion:
|
||||
scoped_generator.set("return_statement", "return JS::throw_completion(vm.exception()->value());");
|
||||
scoped_generator.set("try_macro", "TRY");
|
||||
break;
|
||||
case ReturnType::Value:
|
||||
scoped_generator.set("return_statement", "return {};");
|
||||
scoped_generator.set("try_macro", "TRY_OR_DISCARD");
|
||||
break;
|
||||
case ReturnType::Void:
|
||||
scoped_generator.set("return_statement", "return;");
|
||||
break;
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
// FIXME: Add support for optional, variadic, nullable and default values to all types
|
||||
if (parameter.type->is_string()) {
|
||||
|
@ -1080,7 +1097,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
} else if (parameter.type->name == "double") {
|
||||
if (!optional) {
|
||||
scoped_generator.append(R"~~~(
|
||||
double @cpp_name@ = TRY_OR_DISCARD(@js_name@@js_suffix@.to_double(global_object));
|
||||
double @cpp_name@ = @try_macro@(@js_name@@js_suffix@.to_double(global_object));
|
||||
)~~~");
|
||||
} else {
|
||||
if (optional_default_value.has_value()) {
|
||||
|
@ -1094,7 +1111,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
}
|
||||
scoped_generator.append(R"~~~(
|
||||
if (!@js_name@@js_suffix@.is_undefined())
|
||||
@cpp_name@ = TRY_OR_DISCARD(@js_name@@js_suffix@.to_double(global_object));
|
||||
@cpp_name@ = @try_macro@(@js_name@@js_suffix@.to_double(global_object));
|
||||
)~~~");
|
||||
if (optional_default_value.has_value()) {
|
||||
scoped_generator.append(R"~~~(
|
||||
|
@ -1136,15 +1153,15 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
}
|
||||
} else if (parameter.type->name == "unsigned long") {
|
||||
scoped_generator.append(R"~~~(
|
||||
auto @cpp_name@ = TRY_OR_DISCARD(@js_name@@js_suffix@.to_u32(global_object));
|
||||
auto @cpp_name@ = @try_macro@(@js_name@@js_suffix@.to_u32(global_object));
|
||||
)~~~");
|
||||
} else if (parameter.type->name == "unsigned short") {
|
||||
scoped_generator.append(R"~~~(
|
||||
auto @cpp_name@ = TRY_OR_DISCARD(@js_name@@js_suffix@.to_u16(global_object));
|
||||
auto @cpp_name@ = @try_macro@(@js_name@@js_suffix@.to_u16(global_object));
|
||||
)~~~");
|
||||
} else if (parameter.type->name == "long") {
|
||||
scoped_generator.append(R"~~~(
|
||||
auto @cpp_name@ = TRY_OR_DISCARD(@js_name@@js_suffix@.to_i32(global_object));
|
||||
auto @cpp_name@ = @try_macro@(@js_name@@js_suffix@.to_i32(global_object));
|
||||
)~~~");
|
||||
} else if (parameter.type->name == "EventHandler") {
|
||||
// x.onfoo = function() { ... }
|
||||
|
@ -1236,7 +1253,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
|
||||
auto member_value_name = String::formatted("{}_value", member_js_name);
|
||||
dictionary_generator.set("member_value_name", member_value_name);
|
||||
generate_to_cpp(dictionary_generator, member, member_js_name, "", member_value_name, dictionaries, return_void, member.extended_attributes.contains("LegacyNullToEmptyString"), !member.required, member.default_value);
|
||||
generate_to_cpp(dictionary_generator, member, member_js_name, "", member_value_name, dictionaries, return_type, member.extended_attributes.contains("LegacyNullToEmptyString"), !member.required, member.default_value);
|
||||
dictionary_generator.append(R"~~~(
|
||||
@cpp_name@.@member_name@ = @member_value_name@;
|
||||
)~~~");
|
||||
|
@ -1253,7 +1270,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
}
|
||||
|
||||
template<typename FunctionType>
|
||||
static void generate_argument_count_check(SourceGenerator& generator, FunctionType& function)
|
||||
static void generate_argument_count_check(SourceGenerator& generator, FunctionType& function, ReturnType return_type)
|
||||
{
|
||||
auto argument_count_check_generator = generator.fork();
|
||||
argument_count_check_generator.set("function.name", function.name);
|
||||
|
@ -1269,15 +1286,27 @@ static void generate_argument_count_check(SourceGenerator& generator, FunctionTy
|
|||
argument_count_check_generator.set(".arg_count_suffix", String::formatted(", \"{}\"", function.length()));
|
||||
}
|
||||
|
||||
switch (return_type) {
|
||||
case ReturnType::Completion:
|
||||
argument_count_check_generator.set("return_statement", "return JS::throw_completion(vm.exception()->value());");
|
||||
break;
|
||||
case ReturnType::Value:
|
||||
argument_count_check_generator.set("return_statement", "return {};");
|
||||
break;
|
||||
default:
|
||||
// 'Void' not used here.
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
argument_count_check_generator.append(R"~~~(
|
||||
if (vm.argument_count() < @function.nargs@) {
|
||||
vm.throw_exception<JS::TypeError>(global_object, @.bad_arg_count@, "@function.name@"@.arg_count_suffix@);
|
||||
return {};
|
||||
@return_statement@
|
||||
}
|
||||
)~~~");
|
||||
}
|
||||
|
||||
static void generate_arguments(SourceGenerator& generator, Vector<IDL::Parameter> const& parameters, StringBuilder& arguments_builder, HashMap<String, IDL::Dictionary> const& dictionaries, bool return_void = false)
|
||||
static void generate_arguments(SourceGenerator& generator, Vector<IDL::Parameter> const& parameters, StringBuilder& arguments_builder, HashMap<String, IDL::Dictionary> const& dictionaries, ReturnType return_type)
|
||||
{
|
||||
auto arguments_generator = generator.fork();
|
||||
|
||||
|
@ -1294,7 +1323,7 @@ static void generate_arguments(SourceGenerator& generator, Vector<IDL::Parameter
|
|||
}
|
||||
|
||||
bool legacy_null_to_empty_string = parameter.extended_attributes.contains("LegacyNullToEmptyString");
|
||||
generate_to_cpp(generator, parameter, "arg", String::number(argument_index), parameter.name.to_snakecase(), dictionaries, return_void, legacy_null_to_empty_string, parameter.optional, parameter.optional_default_value, parameter.variadic);
|
||||
generate_to_cpp(generator, parameter, "arg", String::number(argument_index), parameter.name.to_snakecase(), dictionaries, return_type, legacy_null_to_empty_string, parameter.optional, parameter.optional_default_value, parameter.variadic);
|
||||
++argument_index;
|
||||
}
|
||||
|
||||
|
@ -1447,10 +1476,10 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@)
|
|||
)~~~");
|
||||
}
|
||||
|
||||
generate_argument_count_check(generator, function);
|
||||
generate_argument_count_check(generator, function, ReturnType::Value);
|
||||
|
||||
StringBuilder arguments_builder;
|
||||
generate_arguments(generator, function.parameters, arguments_builder, dictionaries);
|
||||
generate_arguments(generator, function.parameters, arguments_builder, dictionaries, ReturnType::Value);
|
||||
function_generator.set(".arguments", arguments_builder.string_view());
|
||||
|
||||
if (is_static_function == StaticFunction::No) {
|
||||
|
@ -2039,7 +2068,7 @@ static void invoke_named_property_setter(JS::GlobalObject& global_object, @fully
|
|||
|
||||
// 4. Let value be the result of converting V to an IDL value of type T.
|
||||
// NOTE: This takes the last parameter as it's enforced that there's only two parameters.
|
||||
generate_to_cpp(scoped_generator, interface.named_property_setter->parameters.last(), "value", "", "converted_value", interface.dictionaries, true);
|
||||
generate_to_cpp(scoped_generator, interface.named_property_setter->parameters.last(), "value", "", "converted_value", interface.dictionaries, ReturnType::Void);
|
||||
|
||||
// 5. If operation was defined without an identifier, then:
|
||||
if (interface.named_property_setter->name.is_empty()) {
|
||||
|
@ -2097,7 +2126,7 @@ static void invoke_indexed_property_setter(JS::GlobalObject& global_object, @ful
|
|||
|
||||
// 5. Let value be the result of converting V to an IDL value of type T.
|
||||
// NOTE: This takes the last parameter as it's enforced that there's only two parameters.
|
||||
generate_to_cpp(scoped_generator, interface.named_property_setter->parameters.last(), "value", "", "converted_value", interface.dictionaries, true);
|
||||
generate_to_cpp(scoped_generator, interface.named_property_setter->parameters.last(), "value", "", "converted_value", interface.dictionaries, ReturnType::Void);
|
||||
|
||||
// 6. If operation was defined without an identifier, then:
|
||||
if (interface.indexed_property_setter->name.is_empty()) {
|
||||
|
@ -2540,8 +2569,8 @@ public:
|
|||
virtual void initialize(JS::GlobalObject&) override;
|
||||
virtual ~@constructor_class@() override;
|
||||
|
||||
virtual JS::Value call() override;
|
||||
virtual JS::Value construct(JS::FunctionObject& new_target) override;
|
||||
virtual JS::ThrowCompletionOr<JS::Value> call() override;
|
||||
virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
@ -2644,13 +2673,12 @@ namespace Web::Bindings {
|
|||
{
|
||||
}
|
||||
|
||||
JS::Value @constructor_class@::call()
|
||||
JS::ThrowCompletionOr<JS::Value> @constructor_class@::call()
|
||||
{
|
||||
vm().throw_exception<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "@name@");
|
||||
return {};
|
||||
return vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "@name@");
|
||||
}
|
||||
|
||||
JS::Value @constructor_class@::construct(FunctionObject&)
|
||||
JS::ThrowCompletionOr<JS::Object*> @constructor_class@::construct(FunctionObject&)
|
||||
{
|
||||
)~~~");
|
||||
|
||||
|
@ -2658,8 +2686,7 @@ JS::Value @constructor_class@::construct(FunctionObject&)
|
|||
// No constructor
|
||||
generator.set("constructor.length", "0");
|
||||
generator.append(R"~~~(
|
||||
vm().throw_exception<JS::TypeError>(global_object(), JS::ErrorType::NotAConstructor, "@name@");
|
||||
return {};
|
||||
return vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::NotAConstructor, "@name@");
|
||||
)~~~");
|
||||
} else if (interface.constructors.size() == 1) {
|
||||
// Single constructor
|
||||
|
@ -2675,10 +2702,10 @@ JS::Value @constructor_class@::construct(FunctionObject&)
|
|||
)~~~");
|
||||
|
||||
if (!constructor.parameters.is_empty()) {
|
||||
generate_argument_count_check(generator, constructor);
|
||||
generate_argument_count_check(generator, constructor, ReturnType::Completion);
|
||||
|
||||
StringBuilder arguments_builder;
|
||||
generate_arguments(generator, constructor.parameters, arguments_builder, interface.dictionaries);
|
||||
generate_arguments(generator, constructor.parameters, arguments_builder, interface.dictionaries, ReturnType::Completion);
|
||||
generator.set(".constructor_arguments", arguments_builder.string_view());
|
||||
|
||||
generator.append(R"~~~(
|
||||
|
@ -2691,7 +2718,7 @@ JS::Value @constructor_class@::construct(FunctionObject&)
|
|||
}
|
||||
generator.append(R"~~~(
|
||||
if (should_return_empty(impl))
|
||||
return JS::Value();
|
||||
return JS::throw_completion(vm.exception()->value());
|
||||
return wrap(global_object, *impl.release_value());
|
||||
)~~~");
|
||||
} else {
|
||||
|
@ -3236,7 +3263,7 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(@prototype_class@::@attribute.setter_callback@)
|
|||
auto value = vm.argument(0);
|
||||
)~~~");
|
||||
|
||||
generate_to_cpp(generator, attribute, "value", "", "cpp_value", interface.dictionaries, false, attribute.extended_attributes.contains("LegacyNullToEmptyString"));
|
||||
generate_to_cpp(generator, attribute, "value", "", "cpp_value", interface.dictionaries, ReturnType::Value, attribute.extended_attributes.contains("LegacyNullToEmptyString"));
|
||||
|
||||
if (attribute.extended_attributes.contains("Reflect")) {
|
||||
if (attribute.type->name != "boolean") {
|
||||
|
|
|
@ -31,27 +31,27 @@ void AggregateErrorConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 20.5.7.1.1 AggregateError ( errors, message ), https://tc39.es/ecma262/#sec-aggregate-error
|
||||
Value AggregateErrorConstructor::call()
|
||||
ThrowCompletionOr<Value> AggregateErrorConstructor::call()
|
||||
{
|
||||
return construct(*this);
|
||||
return TRY(construct(*this));
|
||||
}
|
||||
|
||||
// 20.5.7.1.1 AggregateError ( errors, message ), https://tc39.es/ecma262/#sec-aggregate-error
|
||||
Value AggregateErrorConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> AggregateErrorConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto* aggregate_error = TRY_OR_DISCARD(ordinary_create_from_constructor<AggregateError>(global_object, new_target, &GlobalObject::aggregate_error_prototype));
|
||||
auto* aggregate_error = TRY(ordinary_create_from_constructor<AggregateError>(global_object, new_target, &GlobalObject::aggregate_error_prototype));
|
||||
|
||||
if (!vm.argument(1).is_undefined()) {
|
||||
auto message = TRY_OR_DISCARD(vm.argument(1).to_string(global_object));
|
||||
auto message = TRY(vm.argument(1).to_string(global_object));
|
||||
MUST(aggregate_error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message)));
|
||||
}
|
||||
|
||||
TRY_OR_DISCARD(aggregate_error->install_error_cause(vm.argument(2)));
|
||||
TRY(aggregate_error->install_error_cause(vm.argument(2)));
|
||||
|
||||
auto errors_list = TRY_OR_DISCARD(iterable_to_list(global_object, vm.argument(0)));
|
||||
auto errors_list = TRY(iterable_to_list(global_object, vm.argument(0)));
|
||||
|
||||
MUST(aggregate_error->define_property_or_throw(vm.names.errors, { .value = Array::create_from(global_object, errors_list), .writable = true, .enumerable = false, .configurable = true }));
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~AggregateErrorConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -40,15 +40,14 @@ ArrayBufferConstructor::~ArrayBufferConstructor()
|
|||
}
|
||||
|
||||
// 25.1.3.1 ArrayBuffer ( length ), https://tc39.es/ecma262/#sec-arraybuffer-length
|
||||
Value ArrayBufferConstructor::call()
|
||||
ThrowCompletionOr<Value> ArrayBufferConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ArrayBuffer);
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ArrayBuffer);
|
||||
}
|
||||
|
||||
// 25.1.3.1 ArrayBuffer ( length ), https://tc39.es/ecma262/#sec-arraybuffer-length
|
||||
Value ArrayBufferConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> ArrayBufferConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto byte_length_or_error = vm.argument(0).to_index(global_object());
|
||||
|
@ -57,11 +56,11 @@ Value ArrayBufferConstructor::construct(FunctionObject& new_target)
|
|||
if (error.value().is_object() && is<RangeError>(error.value().as_object())) {
|
||||
// Re-throw more specific RangeError
|
||||
vm.clear_exception();
|
||||
vm.throw_exception<RangeError>(global_object(), ErrorType::InvalidLength, "array buffer");
|
||||
return vm.throw_completion<RangeError>(global_object(), ErrorType::InvalidLength, "array buffer");
|
||||
}
|
||||
return {};
|
||||
return error;
|
||||
}
|
||||
return TRY_OR_DISCARD(allocate_array_buffer(global_object(), new_target, byte_length_or_error.release_value()));
|
||||
return TRY(allocate_array_buffer(global_object(), new_target, byte_length_or_error.release_value()));
|
||||
}
|
||||
|
||||
// 25.1.4.1 ArrayBuffer.isView ( arg ), https://tc39.es/ecma262/#sec-arraybuffer.isview
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~ArrayBufferConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -45,17 +45,17 @@ void ArrayConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 23.1.1.1 Array ( ...values ), https://tc39.es/ecma262/#sec-array
|
||||
Value ArrayConstructor::call()
|
||||
ThrowCompletionOr<Value> ArrayConstructor::call()
|
||||
{
|
||||
return construct(*this);
|
||||
return TRY(construct(*this));
|
||||
}
|
||||
|
||||
// 23.1.1.1 Array ( ...values ), https://tc39.es/ecma262/#sec-array
|
||||
Value ArrayConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> ArrayConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
auto* proto = TRY_OR_DISCARD(get_prototype_from_constructor(global_object(), new_target, &GlobalObject::array_prototype));
|
||||
auto* proto = TRY(get_prototype_from_constructor(global_object(), new_target, &GlobalObject::array_prototype));
|
||||
|
||||
if (vm.argument_count() == 0)
|
||||
return Array::create(global_object(), 0, proto);
|
||||
|
@ -69,18 +69,16 @@ Value ArrayConstructor::construct(FunctionObject& new_target)
|
|||
int_length = 1;
|
||||
} else {
|
||||
int_length = MUST(length.to_u32(global_object()));
|
||||
if (int_length != length.as_double()) {
|
||||
vm.throw_exception<RangeError>(global_object(), ErrorType::InvalidLength, "array");
|
||||
return {};
|
||||
}
|
||||
if (int_length != length.as_double())
|
||||
return vm.throw_completion<RangeError>(global_object(), ErrorType::InvalidLength, "array");
|
||||
}
|
||||
TRY_OR_DISCARD(array->set(vm.names.length, Value(int_length), Object::ShouldThrowExceptions::Yes));
|
||||
TRY(array->set(vm.names.length, Value(int_length), Object::ShouldThrowExceptions::Yes));
|
||||
return array;
|
||||
}
|
||||
|
||||
auto* array = Array::create(global_object(), vm.argument_count(), proto);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (auto* exception = vm.exception())
|
||||
return throw_completion(exception->value());
|
||||
|
||||
for (size_t k = 0; k < vm.argument_count(); ++k)
|
||||
MUST(array->create_data_property_or_throw(k, vm.argument(k)));
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~ArrayConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -40,7 +40,7 @@ BigIntConstructor::~BigIntConstructor()
|
|||
}
|
||||
|
||||
// 21.2.1.1 BigInt ( value ), https://tc39.es/ecma262/#sec-bigint-constructor-number-value
|
||||
Value BigIntConstructor::call()
|
||||
ThrowCompletionOr<Value> BigIntConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
@ -48,21 +48,20 @@ Value BigIntConstructor::call()
|
|||
auto value = vm.argument(0);
|
||||
|
||||
// 2. Let prim be ? ToPrimitive(value, number).
|
||||
auto primitive = TRY_OR_DISCARD(value.to_primitive(global_object, Value::PreferredType::Number));
|
||||
auto primitive = TRY(value.to_primitive(global_object, Value::PreferredType::Number));
|
||||
|
||||
// 3. If Type(prim) is Number, return ? NumberToBigInt(prim).
|
||||
if (primitive.is_number())
|
||||
return number_to_bigint(global_object, primitive);
|
||||
|
||||
// 4. Otherwise, return ? ToBigInt(value).
|
||||
return TRY_OR_DISCARD(value.to_bigint(global_object));
|
||||
return TRY(value.to_bigint(global_object));
|
||||
}
|
||||
|
||||
// 21.2.1.1 BigInt ( value ), https://tc39.es/ecma262/#sec-bigint-constructor-number-value
|
||||
Value BigIntConstructor::construct(FunctionObject&)
|
||||
ThrowCompletionOr<Object*> BigIntConstructor::construct(FunctionObject&)
|
||||
{
|
||||
vm().throw_exception<TypeError>(global_object(), ErrorType::NotAConstructor, "BigInt");
|
||||
return {};
|
||||
return vm().throw_completion<TypeError>(global_object(), ErrorType::NotAConstructor, "BigInt");
|
||||
}
|
||||
|
||||
// 21.2.2.1 BigInt.asIntN ( bits, bigint ), https://tc39.es/ecma262/#sec-bigint.asintn
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~BigIntConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -32,7 +32,7 @@ BooleanConstructor::~BooleanConstructor()
|
|||
}
|
||||
|
||||
// 20.3.1.1 Boolean ( value ), https://tc39.es/ecma262/#sec-boolean-constructor-boolean-value
|
||||
Value BooleanConstructor::call()
|
||||
ThrowCompletionOr<Value> BooleanConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
|
@ -41,13 +41,13 @@ Value BooleanConstructor::call()
|
|||
}
|
||||
|
||||
// 20.3.1.1 Boolean ( value ), https://tc39.es/ecma262/#sec-boolean-constructor-boolean-value
|
||||
Value BooleanConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> BooleanConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto b = vm.argument(0).to_boolean();
|
||||
return TRY_OR_DISCARD(ordinary_create_from_constructor<BooleanObject>(global_object, new_target, &GlobalObject::boolean_prototype, b));
|
||||
return TRY(ordinary_create_from_constructor<BooleanObject>(global_object, new_target, &GlobalObject::boolean_prototype, b));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~BooleanConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -33,56 +33,46 @@ DataViewConstructor::~DataViewConstructor()
|
|||
}
|
||||
|
||||
// 25.3.2.1 DataView ( buffer [ , byteOffset [ , byteLength ] ] ), https://tc39.es/ecma262/#sec-dataview-buffer-byteoffset-bytelength
|
||||
Value DataViewConstructor::call()
|
||||
ThrowCompletionOr<Value> DataViewConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.DataView);
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.DataView);
|
||||
}
|
||||
|
||||
// 25.3.2.1 DataView ( buffer [ , byteOffset [ , byteLength ] ] ), https://tc39.es/ecma262/#sec-dataview-buffer-byteoffset-bytelength
|
||||
Value DataViewConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> DataViewConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto buffer = vm.argument(0);
|
||||
if (!buffer.is_object() || !is<ArrayBuffer>(buffer.as_object())) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::IsNotAn, buffer.to_string_without_side_effects(), vm.names.ArrayBuffer);
|
||||
return {};
|
||||
}
|
||||
if (!buffer.is_object() || !is<ArrayBuffer>(buffer.as_object()))
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::IsNotAn, buffer.to_string_without_side_effects(), vm.names.ArrayBuffer);
|
||||
|
||||
auto& array_buffer = static_cast<ArrayBuffer&>(buffer.as_object());
|
||||
|
||||
auto offset = TRY_OR_DISCARD(vm.argument(1).to_index(global_object));
|
||||
auto offset = TRY(vm.argument(1).to_index(global_object));
|
||||
|
||||
if (array_buffer.is_detached()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::DetachedArrayBuffer);
|
||||
return {};
|
||||
}
|
||||
if (array_buffer.is_detached())
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::DetachedArrayBuffer);
|
||||
|
||||
auto buffer_byte_length = array_buffer.byte_length();
|
||||
if (offset > buffer_byte_length) {
|
||||
vm.throw_exception<RangeError>(global_object, ErrorType::DataViewOutOfRangeByteOffset, offset, buffer_byte_length);
|
||||
return {};
|
||||
}
|
||||
if (offset > buffer_byte_length)
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::DataViewOutOfRangeByteOffset, offset, buffer_byte_length);
|
||||
|
||||
size_t view_byte_length;
|
||||
if (vm.argument(2).is_undefined()) {
|
||||
view_byte_length = buffer_byte_length - offset;
|
||||
} else {
|
||||
view_byte_length = TRY_OR_DISCARD(vm.argument(2).to_index(global_object));
|
||||
if (offset + view_byte_length > buffer_byte_length) {
|
||||
vm.throw_exception<RangeError>(global_object, ErrorType::InvalidLength, vm.names.DataView);
|
||||
return {};
|
||||
}
|
||||
view_byte_length = TRY(vm.argument(2).to_index(global_object));
|
||||
if (offset + view_byte_length > buffer_byte_length)
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::InvalidLength, vm.names.DataView);
|
||||
}
|
||||
|
||||
auto* data_view = TRY_OR_DISCARD(ordinary_create_from_constructor<DataView>(global_object, new_target, &GlobalObject::data_view_prototype, &array_buffer, view_byte_length, offset));
|
||||
auto* data_view = TRY(ordinary_create_from_constructor<DataView>(global_object, new_target, &GlobalObject::data_view_prototype, &array_buffer, view_byte_length, offset));
|
||||
|
||||
if (array_buffer.is_detached()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::DetachedArrayBuffer);
|
||||
return {};
|
||||
}
|
||||
if (array_buffer.is_detached())
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::DetachedArrayBuffer);
|
||||
|
||||
return data_view;
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~DataViewConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject&) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -180,7 +180,7 @@ static DatetimeAndMilliseconds now()
|
|||
}
|
||||
|
||||
// 21.4.2.1 Date ( ...values ), https://tc39.es/ecma262/#sec-date
|
||||
Value DateConstructor::call()
|
||||
ThrowCompletionOr<Value> DateConstructor::call()
|
||||
{
|
||||
auto [datetime, milliseconds] = JS::now();
|
||||
auto* date = Date::create(global_object(), datetime, milliseconds, false);
|
||||
|
@ -188,20 +188,20 @@ Value DateConstructor::call()
|
|||
}
|
||||
|
||||
// 21.4.2.1 Date ( ...values ), https://tc39.es/ecma262/#sec-date
|
||||
Value DateConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> DateConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
if (vm.argument_count() == 0) {
|
||||
auto [datetime, milliseconds] = JS::now();
|
||||
return TRY_OR_DISCARD(ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, false));
|
||||
return TRY(ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, false));
|
||||
}
|
||||
|
||||
auto create_invalid_date = [&global_object, &new_target]() -> Date* {
|
||||
auto create_invalid_date = [&global_object, &new_target]() -> ThrowCompletionOr<Date*> {
|
||||
auto datetime = Core::DateTime::create(1970, 1, 1, 0, 0, 0);
|
||||
auto milliseconds = static_cast<i16>(0);
|
||||
return TRY_OR_DISCARD(ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, true));
|
||||
return ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, true);
|
||||
};
|
||||
|
||||
if (vm.argument_count() == 1) {
|
||||
|
@ -209,19 +209,18 @@ Value DateConstructor::construct(FunctionObject& new_target)
|
|||
if (value.is_string())
|
||||
value = parse_date_string(value.as_string().string());
|
||||
else
|
||||
value = TRY_OR_DISCARD(value.to_number(global_object));
|
||||
value = TRY(value.to_number(global_object));
|
||||
|
||||
if (!value.is_finite_number()) {
|
||||
return create_invalid_date();
|
||||
}
|
||||
if (!value.is_finite_number())
|
||||
return TRY(create_invalid_date());
|
||||
|
||||
// A timestamp since the epoch, in UTC.
|
||||
double value_as_double = value.as_double();
|
||||
if (value_as_double > Date::time_clip)
|
||||
return create_invalid_date();
|
||||
return TRY(create_invalid_date());
|
||||
auto datetime = Core::DateTime::from_timestamp(static_cast<time_t>(value_as_double / 1000));
|
||||
auto milliseconds = static_cast<i16>(fmod(value_as_double, 1000));
|
||||
return TRY_OR_DISCARD(ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, false));
|
||||
return TRY(ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, false));
|
||||
}
|
||||
|
||||
// A date/time in components, in local time.
|
||||
|
@ -229,46 +228,39 @@ Value DateConstructor::construct(FunctionObject& new_target)
|
|||
return vm.argument_count() > i ? vm.argument(i).to_number(global_object) : Value(fallback);
|
||||
};
|
||||
|
||||
auto year_value = TRY_OR_DISCARD(vm.argument(0).to_number(global_object));
|
||||
if (!year_value.is_finite_number()) {
|
||||
return create_invalid_date();
|
||||
}
|
||||
auto year_value = TRY(vm.argument(0).to_number(global_object));
|
||||
if (!year_value.is_finite_number())
|
||||
return TRY(create_invalid_date());
|
||||
auto year = year_value.as_i32();
|
||||
|
||||
auto month_index_value = TRY_OR_DISCARD(vm.argument(1).to_number(global_object));
|
||||
if (!month_index_value.is_finite_number()) {
|
||||
return create_invalid_date();
|
||||
}
|
||||
auto month_index_value = TRY(vm.argument(1).to_number(global_object));
|
||||
if (!month_index_value.is_finite_number())
|
||||
return TRY(create_invalid_date());
|
||||
auto month_index = month_index_value.as_i32();
|
||||
|
||||
auto day_value = TRY_OR_DISCARD(arg_or(2, 1));
|
||||
if (!day_value.is_finite_number()) {
|
||||
return create_invalid_date();
|
||||
}
|
||||
auto day_value = TRY(arg_or(2, 1));
|
||||
if (!day_value.is_finite_number())
|
||||
return TRY(create_invalid_date());
|
||||
auto day = day_value.as_i32();
|
||||
|
||||
auto hours_value = TRY_OR_DISCARD(arg_or(3, 0));
|
||||
if (!hours_value.is_finite_number()) {
|
||||
return create_invalid_date();
|
||||
}
|
||||
auto hours_value = TRY(arg_or(3, 0));
|
||||
if (!hours_value.is_finite_number())
|
||||
return TRY(create_invalid_date());
|
||||
auto hours = hours_value.as_i32();
|
||||
|
||||
auto minutes_value = TRY_OR_DISCARD(arg_or(4, 0));
|
||||
if (!minutes_value.is_finite_number()) {
|
||||
return create_invalid_date();
|
||||
}
|
||||
auto minutes_value = TRY(arg_or(4, 0));
|
||||
if (!minutes_value.is_finite_number())
|
||||
return TRY(create_invalid_date());
|
||||
auto minutes = minutes_value.as_i32();
|
||||
|
||||
auto seconds_value = TRY_OR_DISCARD(arg_or(5, 0));
|
||||
if (!seconds_value.is_finite_number()) {
|
||||
return create_invalid_date();
|
||||
}
|
||||
auto seconds_value = TRY(arg_or(5, 0));
|
||||
if (!seconds_value.is_finite_number())
|
||||
return TRY(create_invalid_date());
|
||||
auto seconds = seconds_value.as_i32();
|
||||
|
||||
auto milliseconds_value = TRY_OR_DISCARD(arg_or(6, 0));
|
||||
if (!milliseconds_value.is_finite_number()) {
|
||||
return create_invalid_date();
|
||||
}
|
||||
auto milliseconds_value = TRY(arg_or(6, 0));
|
||||
if (!milliseconds_value.is_finite_number())
|
||||
return TRY(create_invalid_date());
|
||||
auto milliseconds = milliseconds_value.as_i32();
|
||||
|
||||
seconds += milliseconds / 1000;
|
||||
|
@ -284,8 +276,8 @@ Value DateConstructor::construct(FunctionObject& new_target)
|
|||
auto datetime = Core::DateTime::create(year, month, day, hours, minutes, seconds);
|
||||
auto time = datetime.timestamp() * 1000.0 + milliseconds;
|
||||
if (time > Date::time_clip)
|
||||
return create_invalid_date();
|
||||
return TRY_OR_DISCARD(ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, false));
|
||||
return TRY(create_invalid_date());
|
||||
return TRY(ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, false));
|
||||
}
|
||||
|
||||
// 21.4.3.1 Date.now ( ), https://tc39.es/ecma262/#sec-date.now
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~DateConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -28,25 +28,25 @@ void ErrorConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 20.5.1.1 Error ( message ), https://tc39.es/ecma262/#sec-error-message
|
||||
Value ErrorConstructor::call()
|
||||
ThrowCompletionOr<Value> ErrorConstructor::call()
|
||||
{
|
||||
return construct(*this);
|
||||
return TRY(construct(*this));
|
||||
}
|
||||
|
||||
// 20.5.1.1 Error ( message ), https://tc39.es/ecma262/#sec-error-message
|
||||
Value ErrorConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> ErrorConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto* error = TRY_OR_DISCARD(ordinary_create_from_constructor<Error>(global_object, new_target, &GlobalObject::error_prototype));
|
||||
auto* error = TRY(ordinary_create_from_constructor<Error>(global_object, new_target, &GlobalObject::error_prototype));
|
||||
|
||||
if (!vm.argument(0).is_undefined()) {
|
||||
auto message = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
|
||||
auto message = TRY(vm.argument(0).to_string(global_object));
|
||||
MUST(error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message)));
|
||||
}
|
||||
|
||||
TRY_OR_DISCARD(error->install_error_cause(vm.argument(1)));
|
||||
TRY(error->install_error_cause(vm.argument(1)));
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -72,26 +72,26 @@ Value ErrorConstructor::construct(FunctionObject& new_target)
|
|||
ConstructorName::~ConstructorName() { } \
|
||||
\
|
||||
/* 20.5.6.1.1 NativeError ( message ), https://tc39.es/ecma262/#sec-nativeerror */ \
|
||||
Value ConstructorName::call() \
|
||||
ThrowCompletionOr<Value> ConstructorName::call() \
|
||||
{ \
|
||||
return construct(*this); \
|
||||
return TRY(construct(*this)); \
|
||||
} \
|
||||
\
|
||||
/* 20.5.6.1.1 NativeError ( message ), https://tc39.es/ecma262/#sec-nativeerror */ \
|
||||
Value ConstructorName::construct(FunctionObject& new_target) \
|
||||
ThrowCompletionOr<Object*> ConstructorName::construct(FunctionObject& new_target) \
|
||||
{ \
|
||||
auto& vm = this->vm(); \
|
||||
auto& global_object = this->global_object(); \
|
||||
\
|
||||
auto* error = TRY_OR_DISCARD(ordinary_create_from_constructor<ClassName>( \
|
||||
auto* error = TRY(ordinary_create_from_constructor<ClassName>( \
|
||||
global_object, new_target, &GlobalObject::snake_name##_prototype)); \
|
||||
\
|
||||
if (!vm.argument(0).is_undefined()) { \
|
||||
auto message = TRY_OR_DISCARD(vm.argument(0).to_string(global_object)); \
|
||||
auto message = TRY(vm.argument(0).to_string(global_object)); \
|
||||
MUST(error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message))); \
|
||||
} \
|
||||
\
|
||||
TRY_OR_DISCARD(error->install_error_cause(vm.argument(1))); \
|
||||
TRY(error->install_error_cause(vm.argument(1))); \
|
||||
\
|
||||
return error; \
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~ErrorConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
@ -34,8 +34,8 @@ private:
|
|||
explicit ConstructorName(GlobalObject&); \
|
||||
virtual void initialize(GlobalObject&) override; \
|
||||
virtual ~ConstructorName() override; \
|
||||
virtual Value call() override; \
|
||||
virtual Value construct(FunctionObject& new_target) override; \
|
||||
virtual ThrowCompletionOr<Value> call() override; \
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; \
|
||||
\
|
||||
private: \
|
||||
virtual bool has_constructor() const override { return true; } \
|
||||
|
|
|
@ -33,25 +33,23 @@ FinalizationRegistryConstructor::~FinalizationRegistryConstructor()
|
|||
}
|
||||
|
||||
// 26.2.1.1 FinalizationRegistry ( cleanupCallback ), https://tc39.es/ecma262/#sec-finalization-registry-cleanup-callback
|
||||
Value FinalizationRegistryConstructor::call()
|
||||
ThrowCompletionOr<Value> FinalizationRegistryConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.FinalizationRegistry);
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.FinalizationRegistry);
|
||||
}
|
||||
|
||||
// 26.2.1.1 FinalizationRegistry ( cleanupCallback ), https://tc39.es/ecma262/#sec-finalization-registry-cleanup-callback
|
||||
Value FinalizationRegistryConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> FinalizationRegistryConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto cleanup_callback = vm.argument(0);
|
||||
if (!cleanup_callback.is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, cleanup_callback.to_string_without_side_effects());
|
||||
return {};
|
||||
}
|
||||
return TRY_OR_DISCARD(ordinary_create_from_constructor<FinalizationRegistry>(global_object, new_target, &GlobalObject::finalization_registry_prototype, cleanup_callback.as_function()));
|
||||
if (!cleanup_callback.is_function())
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, cleanup_callback.to_string_without_side_effects());
|
||||
|
||||
return TRY(ordinary_create_from_constructor<FinalizationRegistry>(global_object, new_target, &GlobalObject::finalization_registry_prototype, cleanup_callback.as_function()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~FinalizationRegistryConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject&) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <LibJS/Interpreter.h>
|
||||
#include <LibJS/Lexer.h>
|
||||
#include <LibJS/Parser.h>
|
||||
#include <LibJS/Runtime/ECMAScriptFunctionObject.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/FunctionConstructor.h>
|
||||
#include <LibJS/Runtime/FunctionObject.h>
|
||||
|
@ -66,20 +67,21 @@ RefPtr<FunctionExpression> FunctionConstructor::create_dynamic_function_node(Glo
|
|||
}
|
||||
|
||||
// 20.2.1.1 Function ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-function-p1-p2-pn-body
|
||||
Value FunctionConstructor::call()
|
||||
ThrowCompletionOr<Value> FunctionConstructor::call()
|
||||
{
|
||||
return construct(*this);
|
||||
return TRY(construct(*this));
|
||||
}
|
||||
|
||||
// 20.2.1.1 Function ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-function-p1-p2-pn-body
|
||||
Value FunctionConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> FunctionConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto function = create_dynamic_function_node(global_object(), new_target, FunctionKind::Regular);
|
||||
if (!function)
|
||||
return {};
|
||||
if (auto* exception = vm.exception())
|
||||
return throw_completion(exception->value());
|
||||
|
||||
OwnPtr<Interpreter> local_interpreter;
|
||||
Interpreter* interpreter = vm().interpreter_if_exists();
|
||||
Interpreter* interpreter = vm.interpreter_if_exists();
|
||||
|
||||
if (!interpreter) {
|
||||
local_interpreter = Interpreter::create_with_existing_realm(*realm());
|
||||
|
@ -87,7 +89,11 @@ Value FunctionConstructor::construct(FunctionObject& new_target)
|
|||
}
|
||||
|
||||
VM::InterpreterExecutionScope scope(*interpreter);
|
||||
return function->execute(*interpreter, global_object());
|
||||
auto result = function->execute(*interpreter, global_object());
|
||||
if (auto* exception = vm.exception())
|
||||
return throw_completion(exception->value());
|
||||
VERIFY(result.is_object() && is<ECMAScriptFunctionObject>(result.as_object()));
|
||||
return &result.as_object();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~FunctionConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -37,17 +37,17 @@ GeneratorFunctionConstructor::~GeneratorFunctionConstructor()
|
|||
}
|
||||
|
||||
// 27.3.1.1 GeneratorFunction ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-generatorfunction
|
||||
Value GeneratorFunctionConstructor::call()
|
||||
ThrowCompletionOr<Value> GeneratorFunctionConstructor::call()
|
||||
{
|
||||
return construct(*this);
|
||||
return TRY(construct(*this));
|
||||
}
|
||||
|
||||
// 27.3.1.1 GeneratorFunction ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-generatorfunction
|
||||
Value GeneratorFunctionConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> GeneratorFunctionConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto function = FunctionConstructor::create_dynamic_function_node(global_object(), new_target, FunctionKind::Generator);
|
||||
if (!function)
|
||||
return {};
|
||||
if (auto* exception = vm().exception())
|
||||
return throw_completion(exception->value());
|
||||
|
||||
auto* bytecode_interpreter = Bytecode::Interpreter::current();
|
||||
VERIFY(bytecode_interpreter);
|
||||
|
|
|
@ -19,8 +19,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~GeneratorFunctionConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -37,15 +37,14 @@ void DisplayNamesConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 12.2.1 Intl.DisplayNames ( locales, options ), https://tc39.es/ecma402/#sec-Intl.DisplayNames
|
||||
Value DisplayNamesConstructor::call()
|
||||
ThrowCompletionOr<Value> DisplayNamesConstructor::call()
|
||||
{
|
||||
// 1. If NewTarget is undefined, throw a TypeError exception.
|
||||
vm().throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.DisplayNames");
|
||||
return {};
|
||||
return vm().throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.DisplayNames");
|
||||
}
|
||||
|
||||
// 12.2.1 Intl.DisplayNames ( locales, options ), https://tc39.es/ecma402/#sec-Intl.DisplayNames
|
||||
Value DisplayNamesConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> DisplayNamesConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
@ -54,19 +53,17 @@ Value DisplayNamesConstructor::construct(FunctionObject& new_target)
|
|||
auto options_value = vm.argument(1);
|
||||
|
||||
// 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNames.prototype%", « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »).
|
||||
auto* display_names = TRY_OR_DISCARD(ordinary_create_from_constructor<DisplayNames>(global_object, new_target, &GlobalObject::intl_display_names_prototype));
|
||||
auto* display_names = TRY(ordinary_create_from_constructor<DisplayNames>(global_object, new_target, &GlobalObject::intl_display_names_prototype));
|
||||
|
||||
// 3. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
auto requested_locales = TRY_OR_DISCARD(canonicalize_locale_list(global_object, locale_value));
|
||||
auto requested_locales = TRY(canonicalize_locale_list(global_object, locale_value));
|
||||
|
||||
// 4. If options is undefined, throw a TypeError exception.
|
||||
if (options_value.is_undefined()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::IsUndefined, "options"sv);
|
||||
return {};
|
||||
}
|
||||
if (options_value.is_undefined())
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::IsUndefined, "options"sv);
|
||||
|
||||
// 5. Set options to ? GetOptionsObject(options).
|
||||
auto* options = TRY_OR_DISCARD(Temporal::get_options_object(global_object, options_value));
|
||||
auto* options = TRY(Temporal::get_options_object(global_object, options_value));
|
||||
|
||||
// 6. Let opt be a new Record.
|
||||
LocaleOptions opt {};
|
||||
|
@ -74,7 +71,7 @@ Value DisplayNamesConstructor::construct(FunctionObject& new_target)
|
|||
// 7. Let localeData be %DisplayNames%.[[LocaleData]].
|
||||
|
||||
// 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit").
|
||||
auto matcher = TRY_OR_DISCARD(get_option(global_object, *options, vm.names.localeMatcher, Value::Type::String, { "lookup"sv, "best fit"sv }, "best fit"sv));
|
||||
auto matcher = TRY(get_option(global_object, *options, vm.names.localeMatcher, Value::Type::String, { "lookup"sv, "best fit"sv }, "best fit"sv));
|
||||
|
||||
// 9. Set opt.[[localeMatcher]] to matcher.
|
||||
opt.locale_matcher = matcher;
|
||||
|
@ -83,25 +80,23 @@ Value DisplayNamesConstructor::construct(FunctionObject& new_target)
|
|||
auto result = resolve_locale(requested_locales, opt, {});
|
||||
|
||||
// 11. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long").
|
||||
auto style = TRY_OR_DISCARD(get_option(global_object, *options, vm.names.style, Value::Type::String, { "narrow"sv, "short"sv, "long"sv }, "long"sv));
|
||||
auto style = TRY(get_option(global_object, *options, vm.names.style, Value::Type::String, { "narrow"sv, "short"sv, "long"sv }, "long"sv));
|
||||
|
||||
// 12. Set displayNames.[[Style]] to style.
|
||||
display_names->set_style(style.as_string().string());
|
||||
|
||||
// 13. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined).
|
||||
auto type = TRY_OR_DISCARD(get_option(global_object, *options, vm.names.type, Value::Type::String, { "language"sv, "region"sv, "script"sv, "currency"sv }, Empty {}));
|
||||
auto type = TRY(get_option(global_object, *options, vm.names.type, Value::Type::String, { "language"sv, "region"sv, "script"sv, "currency"sv }, Empty {}));
|
||||
|
||||
// 14. If type is undefined, throw a TypeError exception.
|
||||
if (type.is_undefined()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::IsUndefined, "options.type"sv);
|
||||
return {};
|
||||
}
|
||||
if (type.is_undefined())
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::IsUndefined, "options.type"sv);
|
||||
|
||||
// 15. Set displayNames.[[Type]] to type.
|
||||
display_names->set_type(type.as_string().string());
|
||||
|
||||
// 16. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code").
|
||||
auto fallback = TRY_OR_DISCARD(get_option(global_object, *options, vm.names.fallback, Value::Type::String, { "code"sv, "none"sv }, "code"sv));
|
||||
auto fallback = TRY(get_option(global_object, *options, vm.names.fallback, Value::Type::String, { "code"sv, "none"sv }, "code"sv));
|
||||
|
||||
// 17. Set displayNames.[[Fallback]] to fallback.
|
||||
display_names->set_fallback(fallback.as_string().string());
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~DisplayNamesConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -36,15 +36,14 @@ void ListFormatConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 13.2.1 Intl.ListFormat ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sec-Intl.ListFormat
|
||||
Value ListFormatConstructor::call()
|
||||
ThrowCompletionOr<Value> ListFormatConstructor::call()
|
||||
{
|
||||
// 1. If NewTarget is undefined, throw a TypeError exception.
|
||||
vm().throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.ListFormat");
|
||||
return {};
|
||||
return vm().throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.ListFormat");
|
||||
}
|
||||
|
||||
// 13.2.1 Intl.ListFormat ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sec-Intl.ListFormat
|
||||
Value ListFormatConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> ListFormatConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
@ -53,19 +52,19 @@ Value ListFormatConstructor::construct(FunctionObject& new_target)
|
|||
auto options_value = vm.argument(1);
|
||||
|
||||
// 2. Let listFormat be ? OrdinaryCreateFromConstructor(NewTarget, "%ListFormat.prototype%", « [[InitializedListFormat]], [[Locale]], [[Type]], [[Style]], [[Templates]] »).
|
||||
auto* list_format = TRY_OR_DISCARD(ordinary_create_from_constructor<ListFormat>(global_object, new_target, &GlobalObject::intl_list_format_prototype));
|
||||
auto* list_format = TRY(ordinary_create_from_constructor<ListFormat>(global_object, new_target, &GlobalObject::intl_list_format_prototype));
|
||||
|
||||
// 3. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
auto requested_locales = TRY_OR_DISCARD(canonicalize_locale_list(global_object, locale_value));
|
||||
auto requested_locales = TRY(canonicalize_locale_list(global_object, locale_value));
|
||||
|
||||
// 4. Set options to ? GetOptionsObject(options).
|
||||
auto* options = TRY_OR_DISCARD(Temporal::get_options_object(global_object, options_value));
|
||||
auto* options = TRY(Temporal::get_options_object(global_object, options_value));
|
||||
|
||||
// 5. Let opt be a new Record.
|
||||
LocaleOptions opt {};
|
||||
|
||||
// 6. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit").
|
||||
auto matcher = TRY_OR_DISCARD(get_option(global_object, *options, vm.names.localeMatcher, Value::Type::String, { "lookup"sv, "best fit"sv }, "best fit"sv));
|
||||
auto matcher = TRY(get_option(global_object, *options, vm.names.localeMatcher, Value::Type::String, { "lookup"sv, "best fit"sv }, "best fit"sv));
|
||||
|
||||
// 7. Set opt.[[localeMatcher]] to matcher.
|
||||
opt.locale_matcher = matcher;
|
||||
|
@ -79,13 +78,13 @@ Value ListFormatConstructor::construct(FunctionObject& new_target)
|
|||
list_format->set_locale(move(result.locale));
|
||||
|
||||
// 11. Let type be ? GetOption(options, "type", "string", « "conjunction", "disjunction", "unit" », "conjunction").
|
||||
auto type = TRY_OR_DISCARD(get_option(global_object, *options, vm.names.type, Value::Type::String, { "conjunction"sv, "disjunction"sv, "unit"sv }, "conjunction"sv));
|
||||
auto type = TRY(get_option(global_object, *options, vm.names.type, Value::Type::String, { "conjunction"sv, "disjunction"sv, "unit"sv }, "conjunction"sv));
|
||||
|
||||
// 12. Set listFormat.[[Type]] to type.
|
||||
list_format->set_type(type.as_string().string());
|
||||
|
||||
// 13. Let style be ? GetOption(options, "style", "string", « "long", "short", "narrow" », "long").
|
||||
auto style = TRY_OR_DISCARD(get_option(global_object, *options, vm.names.style, Value::Type::String, { "long"sv, "short"sv, "narrow"sv }, "long"sv));
|
||||
auto style = TRY(get_option(global_object, *options, vm.names.style, Value::Type::String, { "long"sv, "short"sv, "narrow"sv }, "long"sv));
|
||||
|
||||
// 14. Set listFormat.[[Style]] to style.
|
||||
list_format->set_style(style.as_string().string());
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~ListFormatConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -247,15 +247,14 @@ void LocaleConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 14.1.3 Intl.Locale ( tag [ , options ] ), https://tc39.es/ecma402/#sec-Intl.Locale
|
||||
Value LocaleConstructor::call()
|
||||
ThrowCompletionOr<Value> LocaleConstructor::call()
|
||||
{
|
||||
// 1. If NewTarget is undefined, throw a TypeError exception.
|
||||
vm().throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.Locale");
|
||||
return {};
|
||||
return vm().throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Intl.Locale");
|
||||
}
|
||||
|
||||
// 14.1.3 Intl.Locale ( tag [ , options ] ), https://tc39.es/ecma402/#sec-Intl.Locale
|
||||
Value LocaleConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> LocaleConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
@ -273,15 +272,13 @@ Value LocaleConstructor::construct(FunctionObject& new_target)
|
|||
// a. Append [[Numeric]] as the last element of internalSlotsList.
|
||||
|
||||
// 6. Let locale be ? OrdinaryCreateFromConstructor(NewTarget, "%Locale.prototype%", internalSlotsList).
|
||||
auto* locale = TRY_OR_DISCARD(ordinary_create_from_constructor<Locale>(global_object, new_target, &GlobalObject::intl_locale_prototype));
|
||||
auto* locale = TRY(ordinary_create_from_constructor<Locale>(global_object, new_target, &GlobalObject::intl_locale_prototype));
|
||||
|
||||
String tag;
|
||||
|
||||
// 7. If Type(tag) is not String or Object, throw a TypeError exception.
|
||||
if (!tag_value.is_string() && !tag_value.is_object()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObjectOrString, "tag"sv);
|
||||
return {};
|
||||
}
|
||||
if (!tag_value.is_string() && !tag_value.is_object())
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObjectOrString, "tag"sv);
|
||||
|
||||
// 8. If Type(tag) is Object and tag has an [[InitializedLocale]] internal slot, then
|
||||
if (tag_value.is_object() && is<Locale>(tag_value.as_object())) {
|
||||
|
@ -292,17 +289,17 @@ Value LocaleConstructor::construct(FunctionObject& new_target)
|
|||
// 9. Else,
|
||||
else {
|
||||
// a. Let tag be ? ToString(tag).
|
||||
tag = TRY_OR_DISCARD(tag_value.to_string(global_object));
|
||||
tag = TRY(tag_value.to_string(global_object));
|
||||
}
|
||||
|
||||
// 10. Set options to ? CoerceOptionsToObject(options).
|
||||
auto* options = TRY_OR_DISCARD(coerce_options_to_object(global_object, options_value));
|
||||
auto* options = TRY(coerce_options_to_object(global_object, options_value));
|
||||
|
||||
// 11. Set tag to ? ApplyOptionsToTag(tag, options).
|
||||
if (auto applied_tag = apply_options_to_tag(global_object, tag, *options); applied_tag.has_value())
|
||||
tag = applied_tag.release_value();
|
||||
else
|
||||
return {};
|
||||
auto applied_tag = apply_options_to_tag(global_object, tag, *options);
|
||||
if (auto* exception = vm.exception())
|
||||
return throw_completion(exception->value());
|
||||
tag = applied_tag.release_value();
|
||||
|
||||
// 12. Let opt be a new Record.
|
||||
LocaleAndKeys opt {};
|
||||
|
@ -312,44 +309,44 @@ Value LocaleConstructor::construct(FunctionObject& new_target)
|
|||
// a. If calendar does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
|
||||
// 15. Set opt.[[ca]] to calendar.
|
||||
opt.ca = get_string_option(global_object, *options, vm.names.calendar, Unicode::is_type_identifier);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (auto* exception = vm.exception())
|
||||
return throw_completion(exception->value());
|
||||
|
||||
// 16. Let collation be ? GetOption(options, "collation", "string", undefined, undefined).
|
||||
// 17. If collation is not undefined, then
|
||||
// a. If collation does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
|
||||
// 18. Set opt.[[co]] to collation.
|
||||
opt.co = get_string_option(global_object, *options, vm.names.collation, Unicode::is_type_identifier);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (auto* exception = vm.exception())
|
||||
return throw_completion(exception->value());
|
||||
|
||||
// 19. Let hc be ? GetOption(options, "hourCycle", "string", « "h11", "h12", "h23", "h24" », undefined).
|
||||
// 20. Set opt.[[hc]] to hc.
|
||||
opt.hc = get_string_option(global_object, *options, vm.names.hourCycle, nullptr, { "h11"sv, "h12"sv, "h23"sv, "h24"sv });
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (auto* exception = vm.exception())
|
||||
return throw_completion(exception->value());
|
||||
|
||||
// 21. Let kf be ? GetOption(options, "caseFirst", "string", « "upper", "lower", "false" », undefined).
|
||||
// 22. Set opt.[[kf]] to kf.
|
||||
opt.kf = get_string_option(global_object, *options, vm.names.caseFirst, nullptr, { "upper"sv, "lower"sv, "false"sv });
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (auto* exception = vm.exception())
|
||||
return throw_completion(exception->value());
|
||||
|
||||
// 23. Let kn be ? GetOption(options, "numeric", "boolean", undefined, undefined).
|
||||
auto kn = TRY_OR_DISCARD(get_option(global_object, *options, vm.names.numeric, Value::Type::Boolean, {}, Empty {}));
|
||||
auto kn = TRY(get_option(global_object, *options, vm.names.numeric, Value::Type::Boolean, {}, Empty {}));
|
||||
|
||||
// 24. If kn is not undefined, set kn to ! ToString(kn).
|
||||
// 25. Set opt.[[kn]] to kn.
|
||||
if (!kn.is_undefined())
|
||||
opt.kn = TRY_OR_DISCARD(kn.to_string(global_object));
|
||||
opt.kn = TRY(kn.to_string(global_object));
|
||||
|
||||
// 26. Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined).
|
||||
// 27. If numberingSystem is not undefined, then
|
||||
// a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
|
||||
// 28. Set opt.[[nu]] to numberingSystem.
|
||||
opt.nu = get_string_option(global_object, *options, vm.names.numberingSystem, Unicode::is_type_identifier);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (auto* exception = vm.exception())
|
||||
return throw_completion(exception->value());
|
||||
|
||||
// 29. Let r be ! ApplyUnicodeExtensionToTag(tag, opt, relevantExtensionKeys).
|
||||
auto result = apply_unicode_extension_to_tag(tag, move(opt), relevant_extension_keys);
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~LocaleConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -35,14 +35,14 @@ void NumberFormatConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 15.2.1 Intl.NumberFormat ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sec-intl.numberformat
|
||||
Value NumberFormatConstructor::call()
|
||||
ThrowCompletionOr<Value> NumberFormatConstructor::call()
|
||||
{
|
||||
// 1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
|
||||
return construct(*this);
|
||||
return TRY(construct(*this));
|
||||
}
|
||||
|
||||
// 15.2.1 Intl.NumberFormat ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sec-intl.numberformat
|
||||
Value NumberFormatConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> NumberFormatConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
@ -51,10 +51,10 @@ Value NumberFormatConstructor::construct(FunctionObject& new_target)
|
|||
auto options = vm.argument(1);
|
||||
|
||||
// 2. Let numberFormat be ? OrdinaryCreateFromConstructor(newTarget, "%NumberFormat.prototype%", « [[InitializedNumberFormat]], [[Locale]], [[DataLocale]], [[NumberingSystem]], [[Style]], [[Unit]], [[UnitDisplay]], [[Currency]], [[CurrencyDisplay]], [[CurrencySign]], [[MinimumIntegerDigits]], [[MinimumFractionDigits]], [[MaximumFractionDigits]], [[MinimumSignificantDigits]], [[MaximumSignificantDigits]], [[RoundingType]], [[Notation]], [[CompactDisplay]], [[UseGrouping]], [[SignDisplay]], [[BoundFormat]] »).
|
||||
auto* number_format = TRY_OR_DISCARD(ordinary_create_from_constructor<NumberFormat>(global_object, new_target, &GlobalObject::intl_number_format_prototype));
|
||||
auto* number_format = TRY(ordinary_create_from_constructor<NumberFormat>(global_object, new_target, &GlobalObject::intl_number_format_prototype));
|
||||
|
||||
// 3. Perform ? InitializeNumberFormat(numberFormat, locales, options).
|
||||
TRY_OR_DISCARD(initialize_number_format(global_object, *number_format, locales, options));
|
||||
TRY(initialize_number_format(global_object, *number_format, locales, options));
|
||||
|
||||
// 4. If the implementation supports the normative optional constructor mode of 4.3 Note 1, then
|
||||
// a. Let this be the this value.
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~NumberFormatConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -36,31 +36,28 @@ MapConstructor::~MapConstructor()
|
|||
}
|
||||
|
||||
// 24.1.1.1 Map ( [ iterable ] ), https://tc39.es/ecma262/#sec-map-iterable
|
||||
Value MapConstructor::call()
|
||||
ThrowCompletionOr<Value> MapConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Map);
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Map);
|
||||
}
|
||||
|
||||
// 24.1.1.1 Map ( [ iterable ] ), https://tc39.es/ecma262/#sec-map-iterable
|
||||
Value MapConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> MapConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto* map = TRY_OR_DISCARD(ordinary_create_from_constructor<Map>(global_object, new_target, &GlobalObject::map_prototype));
|
||||
auto* map = TRY(ordinary_create_from_constructor<Map>(global_object, new_target, &GlobalObject::map_prototype));
|
||||
|
||||
if (vm.argument(0).is_nullish())
|
||||
return map;
|
||||
|
||||
auto adder = TRY_OR_DISCARD(map->get(vm.names.set));
|
||||
if (!adder.is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, "'set' property of Map");
|
||||
return {};
|
||||
}
|
||||
auto adder = TRY(map->get(vm.names.set));
|
||||
if (!adder.is_function())
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, "'set' property of Map");
|
||||
|
||||
TRY_OR_DISCARD(get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) -> Optional<Completion> {
|
||||
TRY(get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) -> Optional<Completion> {
|
||||
if (!iterator_value.is_object())
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObject, String::formatted("Iterator value {}", iterator_value.to_string_without_side_effects()));
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~MapConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject&) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -113,8 +113,6 @@ ThrowCompletionOr<Value> NativeFunction::internal_call(Value this_argument, Mark
|
|||
vm.pop_execution_context();
|
||||
|
||||
// 12. Return result.
|
||||
if (auto* exception = vm.exception())
|
||||
return throw_completion(exception->value());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -179,17 +177,15 @@ ThrowCompletionOr<Object*> NativeFunction::internal_construct(MarkedValueList ar
|
|||
vm.pop_execution_context();
|
||||
|
||||
// 12. Return result.
|
||||
if (auto* exception = vm.exception())
|
||||
return throw_completion(exception->value());
|
||||
return &result.as_object();
|
||||
return result;
|
||||
}
|
||||
|
||||
Value NativeFunction::call()
|
||||
ThrowCompletionOr<Value> NativeFunction::call()
|
||||
{
|
||||
return TRY_OR_DISCARD(m_native_function(vm(), global_object()));
|
||||
return m_native_function(vm(), global_object());
|
||||
}
|
||||
|
||||
Value NativeFunction::construct(FunctionObject&)
|
||||
ThrowCompletionOr<Object*> NativeFunction::construct(FunctionObject&)
|
||||
{
|
||||
// Needs to be overridden if [[Construct]] is needed.
|
||||
VERIFY_NOT_REACHED();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Function.h>
|
||||
#include <LibJS/Runtime/Completion.h>
|
||||
#include <LibJS/Runtime/FunctionObject.h>
|
||||
|
||||
namespace JS {
|
||||
|
@ -26,8 +27,8 @@ public:
|
|||
|
||||
// Used for [[Call]] / [[Construct]]'s "...result of evaluating F in a manner that conforms to the specification of F".
|
||||
// Needs to be overridden by all NativeFunctions without an m_native_function.
|
||||
virtual Value call();
|
||||
virtual Value construct(FunctionObject& new_target);
|
||||
virtual ThrowCompletionOr<Value> call();
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target);
|
||||
|
||||
virtual const FlyString& name() const override { return m_name; };
|
||||
virtual bool is_strict_mode() const override;
|
||||
|
|
|
@ -81,27 +81,27 @@ static Value get_value_from_constructor_argument(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 21.1.1.1 Number ( value ), https://tc39.es/ecma262/#sec-number-constructor-number-value
|
||||
Value NumberConstructor::call()
|
||||
ThrowCompletionOr<Value> NumberConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto number = get_value_from_constructor_argument(global_object);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (auto* exception = vm.exception())
|
||||
return throw_completion(exception->value());
|
||||
return number;
|
||||
}
|
||||
|
||||
// 21.1.1.1 Number ( value ), https://tc39.es/ecma262/#sec-number-constructor-number-value
|
||||
Value NumberConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> NumberConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto number = get_value_from_constructor_argument(global_object);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
return TRY_OR_DISCARD(ordinary_create_from_constructor<NumberObject>(global_object, new_target, &GlobalObject::number_prototype, number.as_double()));
|
||||
if (auto* exception = vm.exception())
|
||||
return throw_completion(exception->value());
|
||||
return TRY(ordinary_create_from_constructor<NumberObject>(global_object, new_target, &GlobalObject::number_prototype, number.as_double()));
|
||||
}
|
||||
|
||||
// 21.1.2.2 Number.isFinite ( number ), https://tc39.es/ecma262/#sec-number.isfinite
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~NumberConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -62,23 +62,23 @@ ObjectConstructor::~ObjectConstructor()
|
|||
}
|
||||
|
||||
// 20.1.1.1 Object ( [ value ] ), https://tc39.es/ecma262/#sec-object-value
|
||||
Value ObjectConstructor::call()
|
||||
ThrowCompletionOr<Value> ObjectConstructor::call()
|
||||
{
|
||||
return construct(*this);
|
||||
return TRY(construct(*this));
|
||||
}
|
||||
|
||||
// 20.1.1.1 Object ( [ value ] ), https://tc39.es/ecma262/#sec-object-value
|
||||
Value ObjectConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> ObjectConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
if (&new_target != this)
|
||||
return TRY_OR_DISCARD(ordinary_create_from_constructor<Object>(global_object, new_target, &GlobalObject::object_prototype));
|
||||
return TRY(ordinary_create_from_constructor<Object>(global_object, new_target, &GlobalObject::object_prototype));
|
||||
auto value = vm.argument(0);
|
||||
if (value.is_nullish())
|
||||
return Object::create(global_object, global_object.object_prototype());
|
||||
return TRY_OR_DISCARD(value.to_object(global_object));
|
||||
return value.to_object(global_object);
|
||||
}
|
||||
|
||||
enum class GetOwnPropertyKeysType {
|
||||
|
|
|
@ -19,8 +19,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~ObjectConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -251,26 +251,23 @@ void PromiseConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 27.2.3.1 Promise ( executor ), https://tc39.es/ecma262/#sec-promise-executor
|
||||
Value PromiseConstructor::call()
|
||||
ThrowCompletionOr<Value> PromiseConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Promise);
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Promise);
|
||||
}
|
||||
|
||||
// 27.2.3.1 Promise ( executor ), https://tc39.es/ecma262/#sec-promise-executor
|
||||
Value PromiseConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> PromiseConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto executor = vm.argument(0);
|
||||
if (!executor.is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::PromiseExecutorNotAFunction);
|
||||
return {};
|
||||
}
|
||||
if (!executor.is_function())
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::PromiseExecutorNotAFunction);
|
||||
|
||||
auto* promise = TRY_OR_DISCARD(ordinary_create_from_constructor<Promise>(global_object, new_target, &GlobalObject::promise_prototype));
|
||||
auto* promise = TRY(ordinary_create_from_constructor<Promise>(global_object, new_target, &GlobalObject::promise_prototype));
|
||||
|
||||
auto [resolve_function, reject_function] = promise->create_resolving_functions();
|
||||
|
||||
|
@ -278,7 +275,7 @@ Value PromiseConstructor::construct(FunctionObject& new_target)
|
|||
if (auto* exception = vm.exception()) {
|
||||
vm.clear_exception();
|
||||
vm.stop_unwind();
|
||||
(void)vm.call(reject_function, js_undefined(), exception->value());
|
||||
TRY(vm.call(reject_function, js_undefined(), exception->value()));
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~PromiseConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -26,7 +26,7 @@ PromiseReactionJob::PromiseReactionJob(PromiseReaction& reaction, Value argument
|
|||
}
|
||||
|
||||
// 27.2.2.1 NewPromiseReactionJob ( reaction, argument ), https://tc39.es/ecma262/#sec-newpromisereactionjob
|
||||
Value PromiseReactionJob::call()
|
||||
ThrowCompletionOr<Value> PromiseReactionJob::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& promise_capability = m_reaction.capability();
|
||||
|
@ -64,11 +64,11 @@ Value PromiseReactionJob::call()
|
|||
vm.stop_unwind();
|
||||
auto* reject_function = promise_capability.value().reject;
|
||||
dbgln_if(PROMISE_DEBUG, "[PromiseReactionJob @ {}]: Calling PromiseCapability's reject function @ {}", this, reject_function);
|
||||
return TRY_OR_DISCARD(vm.call(*reject_function, js_undefined(), handler_result));
|
||||
return vm.call(*reject_function, js_undefined(), handler_result);
|
||||
} else {
|
||||
auto* resolve_function = promise_capability.value().resolve;
|
||||
dbgln_if(PROMISE_DEBUG, "[PromiseReactionJob @ {}]: Calling PromiseCapability's resolve function @ {}", this, resolve_function);
|
||||
return TRY_OR_DISCARD(vm.call(*resolve_function, js_undefined(), handler_result));
|
||||
return vm.call(*resolve_function, js_undefined(), handler_result);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ PromiseResolveThenableJob::PromiseResolveThenableJob(Promise& promise_to_resolve
|
|||
}
|
||||
|
||||
// 27.2.2.2 NewPromiseResolveThenableJob ( promiseToResolve, thenable, then ), https://tc39.es/ecma262/#sec-newpromiseresolvethenablejob
|
||||
Value PromiseResolveThenableJob::call()
|
||||
ThrowCompletionOr<Value> PromiseResolveThenableJob::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto [resolve_function, reject_function] = m_promise_to_resolve.create_resolving_functions();
|
||||
|
|
|
@ -22,7 +22,7 @@ public:
|
|||
explicit PromiseReactionJob(PromiseReaction&, Value argument, Object& prototype);
|
||||
virtual ~PromiseReactionJob() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
|
||||
private:
|
||||
virtual void visit_edges(Visitor&) override;
|
||||
|
@ -40,7 +40,7 @@ public:
|
|||
explicit PromiseResolveThenableJob(Promise&, Value thenable, JobCallback then, Object& prototype);
|
||||
virtual ~PromiseResolveThenableJob() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
|
||||
private:
|
||||
virtual void visit_edges(Visitor&) override;
|
||||
|
|
|
@ -28,7 +28,7 @@ void PromiseResolvingElementFunction::initialize(GlobalObject& global_object)
|
|||
define_direct_property(vm().names.length, Value(1), Attribute::Configurable);
|
||||
}
|
||||
|
||||
Value PromiseResolvingElementFunction::call()
|
||||
ThrowCompletionOr<Value> PromiseResolvingElementFunction::call()
|
||||
{
|
||||
if (m_already_called)
|
||||
return js_undefined();
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~PromiseResolvingElementFunction() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
|
||||
protected:
|
||||
explicit PromiseResolvingElementFunction(size_t, PromiseValueList&, PromiseCapability, RemainingElements&, Object& prototype);
|
||||
|
|
|
@ -30,9 +30,9 @@ void PromiseResolvingFunction::initialize(GlobalObject& global_object)
|
|||
define_direct_property(vm().names.length, Value(1), Attribute::Configurable);
|
||||
}
|
||||
|
||||
Value PromiseResolvingFunction::call()
|
||||
ThrowCompletionOr<Value> PromiseResolvingFunction::call()
|
||||
{
|
||||
return TRY_OR_DISCARD(m_native_function(vm(), global_object(), m_promise, m_already_resolved));
|
||||
return m_native_function(vm(), global_object(), m_promise, m_already_resolved);
|
||||
}
|
||||
|
||||
void PromiseResolvingFunction::visit_edges(Cell::Visitor& visitor)
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~PromiseResolvingFunction() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
|
||||
private:
|
||||
virtual void visit_edges(Visitor&) override;
|
||||
|
|
|
@ -48,18 +48,20 @@ ProxyConstructor::~ProxyConstructor()
|
|||
}
|
||||
|
||||
// 28.2.1.1 Proxy ( target, handler ), https://tc39.es/ecma262/#sec-proxy-target-handler
|
||||
Value ProxyConstructor::call()
|
||||
ThrowCompletionOr<Value> ProxyConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Proxy);
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Proxy);
|
||||
}
|
||||
|
||||
// 28.2.1.1 Proxy ( target, handler ), https://tc39.es/ecma262/#sec-proxy-target-handler
|
||||
Value ProxyConstructor::construct(FunctionObject&)
|
||||
ThrowCompletionOr<Object*> ProxyConstructor::construct(FunctionObject&)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
return proxy_create(global_object(), vm.argument(0), vm.argument(1));
|
||||
auto* proxy = proxy_create(global_object(), vm.argument(0), vm.argument(1));
|
||||
if (auto* exception = vm.exception())
|
||||
return throw_completion(exception->value());
|
||||
return proxy;
|
||||
}
|
||||
|
||||
// 28.2.2.1 Proxy.revocable ( target, handler ), https://tc39.es/ecma262/#sec-proxy.revocable
|
||||
|
|
|
@ -19,8 +19,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~ProxyConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -34,7 +34,7 @@ RegExpConstructor::~RegExpConstructor()
|
|||
}
|
||||
|
||||
// 22.2.3.1 RegExp ( pattern, flags ), https://tc39.es/ecma262/#sec-regexp-pattern-flags
|
||||
Value RegExpConstructor::call()
|
||||
ThrowCompletionOr<Value> RegExpConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
@ -42,19 +42,19 @@ Value RegExpConstructor::call()
|
|||
auto pattern = vm.argument(0);
|
||||
auto flags = vm.argument(1);
|
||||
|
||||
bool pattern_is_regexp = TRY_OR_DISCARD(pattern.is_regexp(global_object));
|
||||
bool pattern_is_regexp = TRY(pattern.is_regexp(global_object));
|
||||
|
||||
if (pattern_is_regexp && flags.is_undefined()) {
|
||||
auto pattern_constructor = TRY_OR_DISCARD(pattern.as_object().get(vm.names.constructor));
|
||||
auto pattern_constructor = TRY(pattern.as_object().get(vm.names.constructor));
|
||||
if (same_value(this, pattern_constructor))
|
||||
return pattern;
|
||||
}
|
||||
|
||||
return construct(*this);
|
||||
return TRY(construct(*this));
|
||||
}
|
||||
|
||||
// 22.2.3.1 RegExp ( pattern, flags ), https://tc39.es/ecma262/#sec-regexp-pattern-flags
|
||||
Value RegExpConstructor::construct(FunctionObject&)
|
||||
ThrowCompletionOr<Object*> RegExpConstructor::construct(FunctionObject&)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
@ -62,7 +62,7 @@ Value RegExpConstructor::construct(FunctionObject&)
|
|||
auto pattern = vm.argument(0);
|
||||
auto flags = vm.argument(1);
|
||||
|
||||
bool pattern_is_regexp = TRY_OR_DISCARD(pattern.is_regexp(global_object));
|
||||
bool pattern_is_regexp = TRY(pattern.is_regexp(global_object));
|
||||
|
||||
Value pattern_value;
|
||||
Value flags_value;
|
||||
|
@ -76,10 +76,10 @@ Value RegExpConstructor::construct(FunctionObject&)
|
|||
else
|
||||
flags_value = flags;
|
||||
} else if (pattern_is_regexp) {
|
||||
pattern_value = TRY_OR_DISCARD(pattern.as_object().get(vm.names.source));
|
||||
pattern_value = TRY(pattern.as_object().get(vm.names.source));
|
||||
|
||||
if (flags.is_undefined()) {
|
||||
flags_value = TRY_OR_DISCARD(pattern.as_object().get(vm.names.flags));
|
||||
flags_value = TRY(pattern.as_object().get(vm.names.flags));
|
||||
} else {
|
||||
flags_value = flags;
|
||||
}
|
||||
|
@ -88,7 +88,10 @@ Value RegExpConstructor::construct(FunctionObject&)
|
|||
flags_value = flags;
|
||||
}
|
||||
|
||||
return regexp_create(global_object, pattern_value, flags_value);
|
||||
auto* regexp = regexp_create(global_object, pattern_value, flags_value);
|
||||
if (auto* exception = vm.exception())
|
||||
return throw_completion(exception->value());
|
||||
return regexp;
|
||||
}
|
||||
|
||||
// 22.2.4.2 get RegExp [ @@species ], https://tc39.es/ecma262/#sec-get-regexp-@@species
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~RegExpConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -36,31 +36,28 @@ SetConstructor::~SetConstructor()
|
|||
}
|
||||
|
||||
// 24.2.1.1 Set ( [ iterable ] ), https://tc39.es/ecma262/#sec-set-iterable
|
||||
Value SetConstructor::call()
|
||||
ThrowCompletionOr<Value> SetConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Set);
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Set);
|
||||
}
|
||||
|
||||
// 24.2.1.1 Set ( [ iterable ] ), https://tc39.es/ecma262/#sec-set-iterable
|
||||
Value SetConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> SetConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto* set = TRY_OR_DISCARD(ordinary_create_from_constructor<Set>(global_object, new_target, &GlobalObject::set_prototype));
|
||||
auto* set = TRY(ordinary_create_from_constructor<Set>(global_object, new_target, &GlobalObject::set_prototype));
|
||||
|
||||
if (vm.argument(0).is_nullish())
|
||||
return set;
|
||||
|
||||
auto adder = TRY_OR_DISCARD(set->get(vm.names.add));
|
||||
if (!adder.is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, "'add' property of Set");
|
||||
return {};
|
||||
}
|
||||
auto adder = TRY(set->get(vm.names.add));
|
||||
if (!adder.is_function())
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, "'add' property of Set");
|
||||
|
||||
TRY_OR_DISCARD(get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) -> Optional<Completion> {
|
||||
TRY(get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) -> Optional<Completion> {
|
||||
TRY(vm.call(adder.as_function(), Value(set), iterator_value));
|
||||
return {};
|
||||
}));
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~SetConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject&) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -28,17 +28,16 @@ void ShadowRealmConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 3.2.1 ShadowRealm ( ), https://tc39.es/proposal-shadowrealm/#sec-shadowrealm
|
||||
Value ShadowRealmConstructor::call()
|
||||
ThrowCompletionOr<Value> ShadowRealmConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If NewTarget is undefined, throw a TypeError exception.
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ShadowRealm);
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ShadowRealm);
|
||||
}
|
||||
|
||||
// 3.2.1 ShadowRealm ( ), https://tc39.es/proposal-shadowrealm/#sec-shadowrealm
|
||||
Value ShadowRealmConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> ShadowRealmConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
@ -61,7 +60,7 @@ Value ShadowRealmConstructor::construct(FunctionObject& new_target)
|
|||
// 2. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%ShadowRealm.prototype%", « [[ShadowRealm]], [[ExecutionContext]] »).
|
||||
// 4. Set O.[[ShadowRealm]] to realmRec.
|
||||
// 9. Set O.[[ExecutionContext]] to context.
|
||||
auto* object = TRY_OR_DISCARD(ordinary_create_from_constructor<ShadowRealm>(global_object, new_target, &GlobalObject::shadow_realm_prototype, *realm, move(context)));
|
||||
auto* object = TRY(ordinary_create_from_constructor<ShadowRealm>(global_object, new_target, &GlobalObject::shadow_realm_prototype, *realm, move(context)));
|
||||
|
||||
// 10. Perform ? SetRealmGlobalObject(realmRec, undefined, undefined).
|
||||
auto* new_global_object = vm.heap().allocate_without_global_object<GlobalObject>();
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~ShadowRealmConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -43,17 +43,17 @@ StringConstructor::~StringConstructor()
|
|||
}
|
||||
|
||||
// 22.1.1.1 String ( value ), https://tc39.es/ecma262/#sec-string-constructor-string-value
|
||||
Value StringConstructor::call()
|
||||
ThrowCompletionOr<Value> StringConstructor::call()
|
||||
{
|
||||
if (!vm().argument_count())
|
||||
return js_string(heap(), "");
|
||||
if (vm().argument(0).is_symbol())
|
||||
return js_string(heap(), vm().argument(0).as_symbol().to_string());
|
||||
return TRY_OR_DISCARD(vm().argument(0).to_primitive_string(global_object()));
|
||||
return TRY(vm().argument(0).to_primitive_string(global_object()));
|
||||
}
|
||||
|
||||
// 22.1.1.1 String ( value ), https://tc39.es/ecma262/#sec-string-constructor-string-value
|
||||
Value StringConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> StringConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = global_object().vm();
|
||||
|
||||
|
@ -61,8 +61,8 @@ Value StringConstructor::construct(FunctionObject& new_target)
|
|||
if (!vm.argument_count())
|
||||
primitive_string = js_string(vm, "");
|
||||
else
|
||||
primitive_string = TRY_OR_DISCARD(vm.argument(0).to_primitive_string(global_object()));
|
||||
auto* prototype = TRY_OR_DISCARD(get_prototype_from_constructor(global_object(), new_target, &GlobalObject::string_prototype));
|
||||
primitive_string = TRY(vm.argument(0).to_primitive_string(global_object()));
|
||||
auto* prototype = TRY(get_prototype_from_constructor(global_object(), new_target, &GlobalObject::string_prototype));
|
||||
return StringObject::create(global_object(), *primitive_string, *prototype);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~StringConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -40,18 +40,17 @@ SymbolConstructor::~SymbolConstructor()
|
|||
}
|
||||
|
||||
// 20.4.1.1 Symbol ( [ description ] ), https://tc39.es/ecma262/#sec-symbol-description
|
||||
Value SymbolConstructor::call()
|
||||
ThrowCompletionOr<Value> SymbolConstructor::call()
|
||||
{
|
||||
if (vm().argument(0).is_undefined())
|
||||
return js_symbol(heap(), {}, false);
|
||||
return js_symbol(heap(), TRY_OR_DISCARD(vm().argument(0).to_string(global_object())), false);
|
||||
return js_symbol(heap(), TRY(vm().argument(0).to_string(global_object())), false);
|
||||
}
|
||||
|
||||
// 20.4.1.1 Symbol ( [ description ] ), https://tc39.es/ecma262/#sec-symbol-description
|
||||
Value SymbolConstructor::construct(FunctionObject&)
|
||||
ThrowCompletionOr<Object*> SymbolConstructor::construct(FunctionObject&)
|
||||
{
|
||||
vm().throw_exception<TypeError>(global_object(), ErrorType::NotAConstructor, "Symbol");
|
||||
return {};
|
||||
return vm().throw_completion<TypeError>(global_object(), ErrorType::NotAConstructor, "Symbol");
|
||||
}
|
||||
|
||||
// 20.4.2.2 Symbol.for ( key ), https://tc39.es/ecma262/#sec-symbol.for
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~SymbolConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -32,34 +32,32 @@ void CalendarConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 12.2.1 Temporal.Calendar ( id ), https://tc39.es/proposal-temporal/#sec-temporal.calendar
|
||||
Value CalendarConstructor::call()
|
||||
ThrowCompletionOr<Value> CalendarConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If NewTarget is undefined, then
|
||||
// a. Throw a TypeError exception.
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Calendar");
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Calendar");
|
||||
}
|
||||
|
||||
// 12.2.1 Temporal.Calendar ( id ), https://tc39.es/proposal-temporal/#sec-temporal.calendar
|
||||
Value CalendarConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> CalendarConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
// 2. Set id to ? ToString(id).
|
||||
auto identifier = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
|
||||
auto identifier = TRY(vm.argument(0).to_string(global_object));
|
||||
|
||||
// 3. If ! IsBuiltinCalendar(id) is false, then
|
||||
if (!is_builtin_calendar(identifier)) {
|
||||
// a. Throw a RangeError exception.
|
||||
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidCalendarIdentifier, identifier);
|
||||
return {};
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidCalendarIdentifier, identifier);
|
||||
}
|
||||
|
||||
// 4. Return ? CreateTemporalCalendar(id, NewTarget).
|
||||
return TRY_OR_DISCARD(create_temporal_calendar(global_object, identifier, &new_target));
|
||||
return TRY(create_temporal_calendar(global_object, identifier, &new_target));
|
||||
}
|
||||
|
||||
// 12.3.2 Temporal.Calendar.from ( item ), https://tc39.es/proposal-temporal/#sec-temporal.calendar.from
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~CalendarConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -34,54 +34,53 @@ void DurationConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 7.1.1 Temporal.Duration ( [ years [ , months [ , weeks [ , days [ , hours [ , minutes [ , seconds [ , milliseconds [ , microseconds [ , nanoseconds ] ] ] ] ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.duration
|
||||
Value DurationConstructor::call()
|
||||
ThrowCompletionOr<Value> DurationConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If NewTarget is undefined, then
|
||||
// a. Throw a TypeError exception.
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Duration");
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Duration");
|
||||
}
|
||||
|
||||
// 7.1.1 Temporal.Duration ( [ years [ , months [ , weeks [ , days [ , hours [ , minutes [ , seconds [ , milliseconds [ , microseconds [ , nanoseconds ] ] ] ] ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.duration
|
||||
Value DurationConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> DurationConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
// 2. Let y be ? ToIntegerThrowOnInfinity(years).
|
||||
auto y = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(0), ErrorType::TemporalInvalidDuration));
|
||||
auto y = TRY(to_integer_throw_on_infinity(global_object, vm.argument(0), ErrorType::TemporalInvalidDuration));
|
||||
|
||||
// 3. Let mo be ? ToIntegerThrowOnInfinity(months).
|
||||
auto mo = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(1), ErrorType::TemporalInvalidDuration));
|
||||
auto mo = TRY(to_integer_throw_on_infinity(global_object, vm.argument(1), ErrorType::TemporalInvalidDuration));
|
||||
|
||||
// 4. Let w be ? ToIntegerThrowOnInfinity(weeks).
|
||||
auto w = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(2), ErrorType::TemporalInvalidDuration));
|
||||
auto w = TRY(to_integer_throw_on_infinity(global_object, vm.argument(2), ErrorType::TemporalInvalidDuration));
|
||||
|
||||
// 5. Let d be ? ToIntegerThrowOnInfinity(days).
|
||||
auto d = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(3), ErrorType::TemporalInvalidDuration));
|
||||
auto d = TRY(to_integer_throw_on_infinity(global_object, vm.argument(3), ErrorType::TemporalInvalidDuration));
|
||||
|
||||
// 6. Let h be ? ToIntegerThrowOnInfinity(hours).
|
||||
auto h = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(4), ErrorType::TemporalInvalidDuration));
|
||||
auto h = TRY(to_integer_throw_on_infinity(global_object, vm.argument(4), ErrorType::TemporalInvalidDuration));
|
||||
|
||||
// 7. Let m be ? ToIntegerThrowOnInfinity(minutes).
|
||||
auto m = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(5), ErrorType::TemporalInvalidDuration));
|
||||
auto m = TRY(to_integer_throw_on_infinity(global_object, vm.argument(5), ErrorType::TemporalInvalidDuration));
|
||||
|
||||
// 8. Let s be ? ToIntegerThrowOnInfinity(seconds).
|
||||
auto s = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(6), ErrorType::TemporalInvalidDuration));
|
||||
auto s = TRY(to_integer_throw_on_infinity(global_object, vm.argument(6), ErrorType::TemporalInvalidDuration));
|
||||
|
||||
// 9. Let ms be ? ToIntegerThrowOnInfinity(milliseconds).
|
||||
auto ms = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(7), ErrorType::TemporalInvalidDuration));
|
||||
auto ms = TRY(to_integer_throw_on_infinity(global_object, vm.argument(7), ErrorType::TemporalInvalidDuration));
|
||||
|
||||
// 10. Let mis be ? ToIntegerThrowOnInfinity(microseconds).
|
||||
auto mis = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(8), ErrorType::TemporalInvalidDuration));
|
||||
auto mis = TRY(to_integer_throw_on_infinity(global_object, vm.argument(8), ErrorType::TemporalInvalidDuration));
|
||||
|
||||
// 11. Let ns be ? ToIntegerThrowOnInfinity(nanoseconds).
|
||||
auto ns = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(9), ErrorType::TemporalInvalidDuration));
|
||||
auto ns = TRY(to_integer_throw_on_infinity(global_object, vm.argument(9), ErrorType::TemporalInvalidDuration));
|
||||
|
||||
// 12. Return ? CreateTemporalDuration(y, mo, w, d, h, m, s, ms, mis, ns, NewTarget).
|
||||
return TRY_OR_DISCARD(create_temporal_duration(global_object, y, mo, w, d, h, m, s, ms, mis, ns, &new_target));
|
||||
return TRY(create_temporal_duration(global_object, y, mo, w, d, h, m, s, ms, mis, ns, &new_target));
|
||||
}
|
||||
|
||||
// 7.2.2 Temporal.Duration.from ( item ), https://tc39.es/proposal-temporal/#sec-temporal.duration.from
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~DurationConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -39,33 +39,30 @@ void InstantConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 8.1.1 Temporal.Instant ( epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal.instant
|
||||
Value InstantConstructor::call()
|
||||
ThrowCompletionOr<Value> InstantConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If NewTarget is undefined, then
|
||||
// a. Throw a TypeError exception.
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Instant");
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.Instant");
|
||||
}
|
||||
|
||||
// 8.1.1 Temporal.Instant ( epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal.instant
|
||||
Value InstantConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> InstantConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
// 2. Let epochNanoseconds be ? ToBigInt(epochNanoseconds).
|
||||
auto* epoch_nanoseconds = TRY_OR_DISCARD(vm.argument(0).to_bigint(global_object));
|
||||
auto* epoch_nanoseconds = TRY(vm.argument(0).to_bigint(global_object));
|
||||
|
||||
// 3. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
|
||||
if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds)) {
|
||||
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidEpochNanoseconds);
|
||||
return {};
|
||||
}
|
||||
if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds))
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidEpochNanoseconds);
|
||||
|
||||
// 4. Return ? CreateTemporalInstant(epochNanoseconds, NewTarget).
|
||||
return TRY_OR_DISCARD(create_temporal_instant(global_object, *epoch_nanoseconds, &new_target));
|
||||
return TRY(create_temporal_instant(global_object, *epoch_nanoseconds, &new_target));
|
||||
}
|
||||
|
||||
// 8.2.2 Temporal.Instant.from ( item ), https://tc39.es/proposal-temporal/#sec-temporal.instant.from
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~InstantConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -37,43 +37,40 @@ void PlainDateConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 3.1.1 Temporal.PlainDate ( isoYear, isoMonth, isoDay [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate
|
||||
Value PlainDateConstructor::call()
|
||||
ThrowCompletionOr<Value> PlainDateConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If NewTarget is undefined, throw a TypeError exception.
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainDate");
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainDate");
|
||||
}
|
||||
|
||||
// 3.1.1 Temporal.PlainDate ( isoYear, isoMonth, isoDay [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate
|
||||
Value PlainDateConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> PlainDateConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
// 2. Let y be ? ToIntegerThrowOnInfinity(isoYear).
|
||||
auto y = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(0), ErrorType::TemporalInvalidPlainDate));
|
||||
auto y = TRY(to_integer_throw_on_infinity(global_object, vm.argument(0), ErrorType::TemporalInvalidPlainDate));
|
||||
|
||||
// 3. Let m be ? ToIntegerThrowOnInfinity(isoMonth).
|
||||
auto m = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(1), ErrorType::TemporalInvalidPlainDate));
|
||||
auto m = TRY(to_integer_throw_on_infinity(global_object, vm.argument(1), ErrorType::TemporalInvalidPlainDate));
|
||||
|
||||
// 4. Let d be ? ToIntegerThrowOnInfinity(isoDay).
|
||||
auto d = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(2), ErrorType::TemporalInvalidPlainDate));
|
||||
auto d = TRY(to_integer_throw_on_infinity(global_object, vm.argument(2), ErrorType::TemporalInvalidPlainDate));
|
||||
|
||||
// 5. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike).
|
||||
auto* calendar = TRY_OR_DISCARD(to_temporal_calendar_with_iso_default(global_object, vm.argument(3)));
|
||||
auto* calendar = TRY(to_temporal_calendar_with_iso_default(global_object, vm.argument(3)));
|
||||
|
||||
// IMPLEMENTATION DEFINED: This is an optimization that allows us to treat these doubles as normal integers from this point onwards.
|
||||
// This does not change the exposed behavior as the call to CreateTemporalDate will immediately check that these values are valid
|
||||
// ISO values (for years: -273975 - 273975, for months: 1 - 12, for days: 1 - 31) all of which are subsets of this check.
|
||||
if (!AK::is_within_range<i32>(y) || !AK::is_within_range<u8>(m) || !AK::is_within_range<u8>(d)) {
|
||||
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainDate);
|
||||
return {};
|
||||
}
|
||||
if (!AK::is_within_range<i32>(y) || !AK::is_within_range<u8>(m) || !AK::is_within_range<u8>(d))
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidPlainDate);
|
||||
|
||||
// 6. Return ? CreateTemporalDate(y, m, d, calendar, NewTarget).
|
||||
return TRY_OR_DISCARD(create_temporal_date(global_object, y, m, d, *calendar, &new_target));
|
||||
return TRY(create_temporal_date(global_object, y, m, d, *calendar, &new_target));
|
||||
}
|
||||
|
||||
// 3.2.2 Temporal.PlainDate.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.from
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~PlainDateConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -37,62 +37,59 @@ void PlainDateTimeConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 5.1.1 Temporal.PlainDateTime ( isoYear, isoMonth, isoDay [ , hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond [ , calendarLike ] ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime
|
||||
Value PlainDateTimeConstructor::call()
|
||||
ThrowCompletionOr<Value> PlainDateTimeConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If NewTarget is undefined, throw a TypeError exception.
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainDateTime");
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainDateTime");
|
||||
}
|
||||
|
||||
// 5.1.1 Temporal.PlainDateTime ( isoYear, isoMonth, isoDay [ , hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond [ , calendarLike ] ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime
|
||||
Value PlainDateTimeConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> PlainDateTimeConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
// 2. Let isoYear be ? ToIntegerThrowOnInfinity(isoYear).
|
||||
auto iso_year = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(0), ErrorType::TemporalInvalidPlainDateTime));
|
||||
auto iso_year = TRY(to_integer_throw_on_infinity(global_object, vm.argument(0), ErrorType::TemporalInvalidPlainDateTime));
|
||||
|
||||
// 3. Let isoMonth be ? ToIntegerThrowOnInfinity(isoMonth).
|
||||
auto iso_month = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(1), ErrorType::TemporalInvalidPlainDateTime));
|
||||
auto iso_month = TRY(to_integer_throw_on_infinity(global_object, vm.argument(1), ErrorType::TemporalInvalidPlainDateTime));
|
||||
|
||||
// 4. Let isoDay be ? ToIntegerThrowOnInfinity(isoDay).
|
||||
auto iso_day = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(2), ErrorType::TemporalInvalidPlainDateTime));
|
||||
auto iso_day = TRY(to_integer_throw_on_infinity(global_object, vm.argument(2), ErrorType::TemporalInvalidPlainDateTime));
|
||||
|
||||
// 5. Let hour be ? ToIntegerThrowOnInfinity(hour).
|
||||
auto hour = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(3), ErrorType::TemporalInvalidPlainDateTime));
|
||||
auto hour = TRY(to_integer_throw_on_infinity(global_object, vm.argument(3), ErrorType::TemporalInvalidPlainDateTime));
|
||||
|
||||
// 6. Let minute be ? ToIntegerThrowOnInfinity(minute).
|
||||
auto minute = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(4), ErrorType::TemporalInvalidPlainDateTime));
|
||||
auto minute = TRY(to_integer_throw_on_infinity(global_object, vm.argument(4), ErrorType::TemporalInvalidPlainDateTime));
|
||||
|
||||
// 7. Let second be ? ToIntegerThrowOnInfinity(second).
|
||||
auto second = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(5), ErrorType::TemporalInvalidPlainDateTime));
|
||||
auto second = TRY(to_integer_throw_on_infinity(global_object, vm.argument(5), ErrorType::TemporalInvalidPlainDateTime));
|
||||
|
||||
// 8. Let millisecond be ? ToIntegerThrowOnInfinity(millisecond).
|
||||
auto millisecond = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(6), ErrorType::TemporalInvalidPlainDateTime));
|
||||
auto millisecond = TRY(to_integer_throw_on_infinity(global_object, vm.argument(6), ErrorType::TemporalInvalidPlainDateTime));
|
||||
|
||||
// 9. Let microsecond be ? ToIntegerThrowOnInfinity(microsecond).
|
||||
auto microsecond = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(7), ErrorType::TemporalInvalidPlainDateTime));
|
||||
auto microsecond = TRY(to_integer_throw_on_infinity(global_object, vm.argument(7), ErrorType::TemporalInvalidPlainDateTime));
|
||||
|
||||
// 10. Let nanosecond be ? ToIntegerThrowOnInfinity(nanosecond).
|
||||
auto nanosecond = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(8), ErrorType::TemporalInvalidPlainDateTime));
|
||||
auto nanosecond = TRY(to_integer_throw_on_infinity(global_object, vm.argument(8), ErrorType::TemporalInvalidPlainDateTime));
|
||||
|
||||
// 11. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike).
|
||||
auto* calendar = TRY_OR_DISCARD(to_temporal_calendar_with_iso_default(global_object, vm.argument(9)));
|
||||
auto* calendar = TRY(to_temporal_calendar_with_iso_default(global_object, vm.argument(9)));
|
||||
|
||||
// IMPLEMENTATION DEFINED: This is an optimization that allows us to treat these doubles as normal integers from this point onwards.
|
||||
// This does not change the exposed behavior as the call to CreateTemporalDateTime will immediately check that these values are valid
|
||||
// ISO values (for years: -273975 - 273975, for months: 1 - 12, for days: 1 - 31, for hours: 0 - 23, for minutes and seconds: 0 - 59,
|
||||
// milliseconds, microseconds, and nanoseconds: 0 - 999) all of which are subsets of this check.
|
||||
if (!AK::is_within_range<i32>(iso_year) || !AK::is_within_range<u8>(iso_month) || !AK::is_within_range<u8>(iso_day) || !AK::is_within_range<u8>(hour) || !AK::is_within_range<u8>(minute) || !AK::is_within_range<u8>(second) || !AK::is_within_range<u16>(millisecond) || !AK::is_within_range<u16>(microsecond) || !AK::is_within_range<u16>(nanosecond)) {
|
||||
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainDateTime);
|
||||
return {};
|
||||
}
|
||||
if (!AK::is_within_range<i32>(iso_year) || !AK::is_within_range<u8>(iso_month) || !AK::is_within_range<u8>(iso_day) || !AK::is_within_range<u8>(hour) || !AK::is_within_range<u8>(minute) || !AK::is_within_range<u8>(second) || !AK::is_within_range<u16>(millisecond) || !AK::is_within_range<u16>(microsecond) || !AK::is_within_range<u16>(nanosecond))
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidPlainDateTime);
|
||||
|
||||
// 12. Return ? CreateTemporalDateTime(isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, nanosecond, calendar, NewTarget).
|
||||
return TRY_OR_DISCARD(create_temporal_date_time(global_object, iso_year, iso_month, iso_day, hour, minute, second, millisecond, microsecond, nanosecond, *calendar, &new_target));
|
||||
return TRY(create_temporal_date_time(global_object, iso_year, iso_month, iso_day, hour, minute, second, millisecond, microsecond, nanosecond, *calendar, &new_target));
|
||||
}
|
||||
|
||||
// 5.2.2 Temporal.PlainDateTime.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.from
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~PlainDateTimeConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -35,17 +35,16 @@ void PlainMonthDayConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 10.1.1 Temporal.PlainMonthDay ( isoMonth, isoDay [ , calendarLike [ , referenceISOYear ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday
|
||||
Value PlainMonthDayConstructor::call()
|
||||
ThrowCompletionOr<Value> PlainMonthDayConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If NewTarget is undefined, throw a TypeError exception.
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainMonthDay");
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainMonthDay");
|
||||
}
|
||||
|
||||
// 10.1.1 Temporal.PlainMonthDay ( isoMonth, isoDay [ , calendarLike [ , referenceISOYear ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday
|
||||
Value PlainMonthDayConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> PlainMonthDayConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
@ -62,27 +61,25 @@ Value PlainMonthDayConstructor::construct(FunctionObject& new_target)
|
|||
}
|
||||
|
||||
// 3. Let m be ? ToIntegerThrowOnInfinity(isoMonth).
|
||||
auto m = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, iso_month, ErrorType::TemporalInvalidPlainMonthDay));
|
||||
auto m = TRY(to_integer_throw_on_infinity(global_object, iso_month, ErrorType::TemporalInvalidPlainMonthDay));
|
||||
|
||||
// 4. Let d be ? ToIntegerThrowOnInfinity(isoDay).
|
||||
auto d = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, iso_day, ErrorType::TemporalInvalidPlainMonthDay));
|
||||
auto d = TRY(to_integer_throw_on_infinity(global_object, iso_day, ErrorType::TemporalInvalidPlainMonthDay));
|
||||
|
||||
// 5. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike).
|
||||
auto* calendar = TRY_OR_DISCARD(to_temporal_calendar_with_iso_default(global_object, calendar_like));
|
||||
auto* calendar = TRY(to_temporal_calendar_with_iso_default(global_object, calendar_like));
|
||||
|
||||
// 6. Let ref be ? ToIntegerThrowOnInfinity(referenceISOYear).
|
||||
auto ref = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, reference_iso_year, ErrorType::TemporalInvalidPlainMonthDay));
|
||||
auto ref = TRY(to_integer_throw_on_infinity(global_object, reference_iso_year, ErrorType::TemporalInvalidPlainMonthDay));
|
||||
|
||||
// IMPLEMENTATION DEFINED: This is an optimization that allows us to treat these doubles as normal integers from this point onwards.
|
||||
// This does not change the exposed behavior as the call to CreateTemporalMonthDay will immediately check that these values are valid
|
||||
// ISO values (for years: -273975 - 273975, for months: 1 - 12, for days: 1 - 31) all of which are subsets of this check.
|
||||
if (!AK::is_within_range<i32>(ref) || !AK::is_within_range<u8>(m) || !AK::is_within_range<u8>(d)) {
|
||||
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainYearMonth);
|
||||
return {};
|
||||
}
|
||||
if (!AK::is_within_range<i32>(ref) || !AK::is_within_range<u8>(m) || !AK::is_within_range<u8>(d))
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidPlainYearMonth);
|
||||
|
||||
// 7. Return ? CreateTemporalMonthDay(m, d, calendar, ref, NewTarget).
|
||||
return TRY_OR_DISCARD(create_temporal_month_day(global_object, m, d, *calendar, ref, &new_target));
|
||||
return TRY(create_temporal_month_day(global_object, m, d, *calendar, ref, &new_target));
|
||||
}
|
||||
|
||||
// 10.2.2 Temporal.PlainMonthDay.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainmonthday.from
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~PlainMonthDayConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -35,50 +35,47 @@ void PlainTimeConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 4.1.1 Temporal.PlainTime ( [ hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime
|
||||
Value PlainTimeConstructor::call()
|
||||
ThrowCompletionOr<Value> PlainTimeConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If NewTarget is undefined, throw a TypeError exception.
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainTime");
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainTime");
|
||||
}
|
||||
|
||||
// 4.1.1 Temporal.PlainTime ( [ hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime
|
||||
Value PlainTimeConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> PlainTimeConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
// 2. Let hour be ? ToIntegerThrowOnInfinity(hour).
|
||||
auto hour = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(0), ErrorType::TemporalInvalidPlainTime));
|
||||
auto hour = TRY(to_integer_throw_on_infinity(global_object, vm.argument(0), ErrorType::TemporalInvalidPlainTime));
|
||||
|
||||
// 3. Let minute be ? ToIntegerThrowOnInfinity(hour).
|
||||
auto minute = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(1), ErrorType::TemporalInvalidPlainTime));
|
||||
auto minute = TRY(to_integer_throw_on_infinity(global_object, vm.argument(1), ErrorType::TemporalInvalidPlainTime));
|
||||
|
||||
// 4. Let second be ? ToIntegerThrowOnInfinity(hour).
|
||||
auto second = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(2), ErrorType::TemporalInvalidPlainTime));
|
||||
auto second = TRY(to_integer_throw_on_infinity(global_object, vm.argument(2), ErrorType::TemporalInvalidPlainTime));
|
||||
|
||||
// 5. Let millisecond be ? ToIntegerThrowOnInfinity(hour).
|
||||
auto millisecond = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(3), ErrorType::TemporalInvalidPlainTime));
|
||||
auto millisecond = TRY(to_integer_throw_on_infinity(global_object, vm.argument(3), ErrorType::TemporalInvalidPlainTime));
|
||||
|
||||
// 6. Let microsecond be ? ToIntegerThrowOnInfinity(hour).
|
||||
auto microsecond = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(4), ErrorType::TemporalInvalidPlainTime));
|
||||
auto microsecond = TRY(to_integer_throw_on_infinity(global_object, vm.argument(4), ErrorType::TemporalInvalidPlainTime));
|
||||
|
||||
// 7. Let nanosecond be ? ToIntegerThrowOnInfinity(hour).
|
||||
auto nanosecond = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, vm.argument(5), ErrorType::TemporalInvalidPlainTime));
|
||||
auto nanosecond = TRY(to_integer_throw_on_infinity(global_object, vm.argument(5), ErrorType::TemporalInvalidPlainTime));
|
||||
|
||||
// IMPLEMENTATION DEFINED: This is an optimization that allows us to treat these doubles as normal integers from this point onwards.
|
||||
// This does not change the exposed behavior as the call to CreateTemporalTime will immediately check that these values are valid
|
||||
// ISO values (for hours: 0 - 23, for minutes and seconds: 0 - 59, milliseconds, microseconds, and nanoseconds: 0 - 999) all of which
|
||||
// are subsets of this check.
|
||||
if (!AK::is_within_range<u8>(hour) || !AK::is_within_range<u8>(minute) || !AK::is_within_range<u8>(second) || !AK::is_within_range<u16>(millisecond) || !AK::is_within_range<u16>(microsecond) || !AK::is_within_range<u16>(nanosecond)) {
|
||||
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
|
||||
return {};
|
||||
}
|
||||
if (!AK::is_within_range<u8>(hour) || !AK::is_within_range<u8>(minute) || !AK::is_within_range<u8>(second) || !AK::is_within_range<u16>(millisecond) || !AK::is_within_range<u16>(microsecond) || !AK::is_within_range<u16>(nanosecond))
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
|
||||
|
||||
// 8. Return ? CreateTemporalTime(hour, minute, second, millisecond, microsecond, nanosecond, NewTarget).
|
||||
return TRY_OR_DISCARD(create_temporal_time(global_object, hour, minute, second, millisecond, microsecond, nanosecond, &new_target));
|
||||
return TRY(create_temporal_time(global_object, hour, minute, second, millisecond, microsecond, nanosecond, &new_target));
|
||||
}
|
||||
|
||||
// 4.2.2 Temporal.PlainTime.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.from
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~PlainTimeConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -37,17 +37,16 @@ void PlainYearMonthConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 9.1.1 Temporal.PlainYearMonth ( isoYear, isoMonth [ , calendarLike [ , referenceISODay ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth
|
||||
Value PlainYearMonthConstructor::call()
|
||||
ThrowCompletionOr<Value> PlainYearMonthConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If NewTarget is undefined, throw a TypeError exception.
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainYearMonth");
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainYearMonth");
|
||||
}
|
||||
|
||||
// 9.1.1 Temporal.PlainYearMonth ( isoYear, isoMonth [ , calendarLike [ , referenceISODay ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth
|
||||
Value PlainYearMonthConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> PlainYearMonthConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
@ -64,27 +63,25 @@ Value PlainYearMonthConstructor::construct(FunctionObject& new_target)
|
|||
}
|
||||
|
||||
// 3. Let y be ? ToIntegerThrowOnInfinity(isoYear).
|
||||
auto y = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, iso_year, ErrorType::TemporalInvalidPlainYearMonth));
|
||||
auto y = TRY(to_integer_throw_on_infinity(global_object, iso_year, ErrorType::TemporalInvalidPlainYearMonth));
|
||||
|
||||
// 4. Let m be ? ToIntegerThrowOnInfinity(isoMonth).
|
||||
auto m = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, iso_month, ErrorType::TemporalInvalidPlainYearMonth));
|
||||
auto m = TRY(to_integer_throw_on_infinity(global_object, iso_month, ErrorType::TemporalInvalidPlainYearMonth));
|
||||
|
||||
// 5. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike).
|
||||
auto* calendar = TRY_OR_DISCARD(to_temporal_calendar_with_iso_default(global_object, calendar_like));
|
||||
auto* calendar = TRY(to_temporal_calendar_with_iso_default(global_object, calendar_like));
|
||||
|
||||
// 6. Let ref be ? ToIntegerThrowOnInfinity(referenceISODay).
|
||||
auto ref = TRY_OR_DISCARD(to_integer_throw_on_infinity(global_object, reference_iso_day, ErrorType::TemporalInvalidPlainYearMonth));
|
||||
auto ref = TRY(to_integer_throw_on_infinity(global_object, reference_iso_day, ErrorType::TemporalInvalidPlainYearMonth));
|
||||
|
||||
// IMPLEMENTATION DEFINED: This is an optimization that allows us to treat these doubles as normal integers from this point onwards.
|
||||
// This does not change the exposed behavior as the call to CreateTemporalYearMonth will immediately check that these values are valid
|
||||
// ISO values (for years: -273975 - 273975, for months: 1 - 12, for days: 1 - 31) all of which are subsets of this check.
|
||||
if (!AK::is_within_range<i32>(y) || !AK::is_within_range<u8>(m) || !AK::is_within_range<u8>(ref)) {
|
||||
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainYearMonth);
|
||||
return {};
|
||||
}
|
||||
if (!AK::is_within_range<i32>(y) || !AK::is_within_range<u8>(m) || !AK::is_within_range<u8>(ref))
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidPlainYearMonth);
|
||||
|
||||
// 7. Return ? CreateTemporalYearMonth(y, m, calendar, ref, NewTarget).
|
||||
return TRY_OR_DISCARD(create_temporal_year_month(global_object, y, m, *calendar, ref, &new_target));
|
||||
return TRY(create_temporal_year_month(global_object, y, m, *calendar, ref, &new_target));
|
||||
}
|
||||
|
||||
// 9.2.2 Temporal.PlainYearMonth.from ( item [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plainyearmonth.from
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~PlainYearMonthConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -32,31 +32,30 @@ void TimeZoneConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 11.2.1 Temporal.TimeZone ( identifier ), https://tc39.es/proposal-temporal/#sec-temporal.timezone
|
||||
Value TimeZoneConstructor::call()
|
||||
ThrowCompletionOr<Value> TimeZoneConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If NewTarget is undefined, then
|
||||
// a. Throw a TypeError exception.
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.TimeZone");
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.TimeZone");
|
||||
}
|
||||
|
||||
// 11.2.1 Temporal.TimeZone ( identifier ), https://tc39.es/proposal-temporal/#sec-temporal.timezone
|
||||
Value TimeZoneConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> TimeZoneConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
// 2. Set identifier to ? ToString(identifier).
|
||||
auto identifier = TRY_OR_DISCARD(vm.argument(0).to_string(global_object));
|
||||
auto identifier = TRY(vm.argument(0).to_string(global_object));
|
||||
|
||||
String canonical;
|
||||
|
||||
// 3. If identifier satisfies the syntax of a TimeZoneNumericUTCOffset (see 13.33), then
|
||||
if (is_valid_time_zone_numeric_utc_offset_syntax(identifier)) {
|
||||
// a. Let offsetNanoseconds be ? ParseTimeZoneOffsetString(identifier).
|
||||
auto offset_nanoseconds = TRY_OR_DISCARD(parse_time_zone_offset_string(global_object, identifier));
|
||||
auto offset_nanoseconds = TRY(parse_time_zone_offset_string(global_object, identifier));
|
||||
|
||||
// b. Let canonical be ! FormatTimeZoneOffsetString(offsetNanoseconds).
|
||||
canonical = format_time_zone_offset_string(offset_nanoseconds);
|
||||
|
@ -66,8 +65,7 @@ Value TimeZoneConstructor::construct(FunctionObject& new_target)
|
|||
// a. If ! IsValidTimeZoneName(identifier) is false, then
|
||||
if (!is_valid_time_zone_name(identifier)) {
|
||||
// i. Throw a RangeError exception.
|
||||
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidTimeZoneName);
|
||||
return {};
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidTimeZoneName);
|
||||
}
|
||||
|
||||
// b. Let canonical be ! CanonicalizeTimeZoneName(identifier).
|
||||
|
@ -75,7 +73,7 @@ Value TimeZoneConstructor::construct(FunctionObject& new_target)
|
|||
}
|
||||
|
||||
// 5. Return ? CreateTemporalTimeZone(canonical, NewTarget).
|
||||
return TRY_OR_DISCARD(create_temporal_time_zone(global_object, canonical, &new_target));
|
||||
return TRY(create_temporal_time_zone(global_object, canonical, &new_target));
|
||||
}
|
||||
|
||||
// 11.3.2 Temporal.TimeZone.from ( item ), https://tc39.es/proposal-temporal/#sec-temporal.timezone.from
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~TimeZoneConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -32,39 +32,36 @@ void ZonedDateTimeConstructor::initialize(GlobalObject& global_object)
|
|||
}
|
||||
|
||||
// 6.1.1 Temporal.ZonedDateTime ( epochNanoseconds, timeZoneLike [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime
|
||||
Value ZonedDateTimeConstructor::call()
|
||||
ThrowCompletionOr<Value> ZonedDateTimeConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. If NewTarget is undefined, then
|
||||
// a. Throw a TypeError exception.
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.ZonedDateTime");
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.ZonedDateTime");
|
||||
}
|
||||
|
||||
// 6.1.1 Temporal.ZonedDateTime ( epochNanoseconds, timeZoneLike [ , calendarLike ] ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime
|
||||
Value ZonedDateTimeConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> ZonedDateTimeConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
// 2. Set epochNanoseconds to ? ToBigInt(epochNanoseconds).
|
||||
auto* epoch_nanoseconds = TRY_OR_DISCARD(vm.argument(0).to_bigint(global_object));
|
||||
auto* epoch_nanoseconds = TRY(vm.argument(0).to_bigint(global_object));
|
||||
|
||||
// 3. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
|
||||
if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds)) {
|
||||
vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidEpochNanoseconds);
|
||||
return {};
|
||||
}
|
||||
if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds))
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidEpochNanoseconds);
|
||||
|
||||
// 4. Let timeZone be ? ToTemporalTimeZone(timeZoneLike).
|
||||
auto* time_zone = TRY_OR_DISCARD(to_temporal_time_zone(global_object, vm.argument(1)));
|
||||
auto* time_zone = TRY(to_temporal_time_zone(global_object, vm.argument(1)));
|
||||
|
||||
// 5. Let calendar be ? ToTemporalCalendarWithISODefault(calendarLike).
|
||||
auto* calendar = TRY_OR_DISCARD(to_temporal_calendar_with_iso_default(global_object, vm.argument(2)));
|
||||
auto* calendar = TRY(to_temporal_calendar_with_iso_default(global_object, vm.argument(2)));
|
||||
|
||||
// 6. Return ? CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar, NewTarget).
|
||||
return TRY_OR_DISCARD(create_temporal_zoned_date_time(global_object, *epoch_nanoseconds, *time_zone, *calendar, &new_target));
|
||||
return TRY(create_temporal_zoned_date_time(global_object, *epoch_nanoseconds, *time_zone, *calendar, &new_target));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~ZonedDateTimeConstructor() override = default;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -434,15 +434,14 @@ void TypedArrayBase::visit_edges(Visitor& visitor)
|
|||
} \
|
||||
\
|
||||
/* 23.2.5.1 TypedArray ( ...args ), https://tc39.es/ecma262/#sec-typedarray */ \
|
||||
Value ConstructorName::call() \
|
||||
ThrowCompletionOr<Value> ConstructorName::call() \
|
||||
{ \
|
||||
auto& vm = this->vm(); \
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ClassName); \
|
||||
return {}; \
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ClassName); \
|
||||
} \
|
||||
\
|
||||
/* 23.2.5.1 TypedArray ( ...args ), https://tc39.es/ecma262/#sec-typedarray */ \
|
||||
Value ConstructorName::construct(FunctionObject& new_target) \
|
||||
ThrowCompletionOr<Object*> ConstructorName::construct(FunctionObject& new_target) \
|
||||
{ \
|
||||
auto& vm = this->vm(); \
|
||||
if (vm.argument_count() == 0) \
|
||||
|
@ -451,27 +450,25 @@ void TypedArrayBase::visit_edges(Visitor& visitor)
|
|||
auto first_argument = vm.argument(0); \
|
||||
if (first_argument.is_object()) { \
|
||||
auto* typed_array = ClassName::create(global_object(), 0, new_target); \
|
||||
if (vm.exception()) \
|
||||
return {}; \
|
||||
if (auto* exception = vm.exception()) \
|
||||
return throw_completion(exception->value()); \
|
||||
if (first_argument.as_object().is_typed_array()) { \
|
||||
auto& arg_typed_array = static_cast<TypedArrayBase&>(first_argument.as_object()); \
|
||||
TRY_OR_DISCARD(initialize_typed_array_from_typed_array(global_object(), *typed_array, arg_typed_array)); \
|
||||
TRY(initialize_typed_array_from_typed_array(global_object(), *typed_array, arg_typed_array)); \
|
||||
} else if (is<ArrayBuffer>(first_argument.as_object())) { \
|
||||
auto& array_buffer = static_cast<ArrayBuffer&>(first_argument.as_object()); \
|
||||
/* NOTE: I added the padding below to not reindent 150+ lines for a single line change. If you edit this, and the */ \
|
||||
/* width happens to change anyway, feel free to remove it. */ \
|
||||
TRY_OR_DISCARD(initialize_typed_array_from_array_buffer(global_object(), *typed_array, array_buffer, /* */ \
|
||||
TRY(initialize_typed_array_from_array_buffer(global_object(), *typed_array, array_buffer, /* */ \
|
||||
vm.argument(1), vm.argument(2))); \
|
||||
} else { \
|
||||
auto iterator = TRY_OR_DISCARD(first_argument.get_method(global_object(), *vm.well_known_symbol_iterator())); \
|
||||
auto iterator = TRY(first_argument.get_method(global_object(), *vm.well_known_symbol_iterator())); \
|
||||
if (iterator) { \
|
||||
auto values = TRY_OR_DISCARD(iterable_to_list(global_object(), first_argument, iterator)); \
|
||||
TRY_OR_DISCARD(initialize_typed_array_from_list(global_object(), *typed_array, values)); \
|
||||
auto values = TRY(iterable_to_list(global_object(), first_argument, iterator)); \
|
||||
TRY(initialize_typed_array_from_list(global_object(), *typed_array, values)); \
|
||||
} else { \
|
||||
TRY_OR_DISCARD(initialize_typed_array_from_array_like(global_object(), *typed_array, first_argument.as_object())); \
|
||||
TRY(initialize_typed_array_from_array_like(global_object(), *typed_array, first_argument.as_object())); \
|
||||
} \
|
||||
if (vm.exception()) \
|
||||
return {}; \
|
||||
} \
|
||||
return typed_array; \
|
||||
} \
|
||||
|
@ -482,20 +479,16 @@ void TypedArrayBase::visit_edges(Visitor& visitor)
|
|||
if (error.value().is_object() && is<RangeError>(error.value().as_object())) { \
|
||||
/* Re-throw more specific RangeError */ \
|
||||
vm.clear_exception(); \
|
||||
vm.throw_exception<RangeError>(global_object(), ErrorType::InvalidLength, "typed array"); \
|
||||
return vm.throw_completion<RangeError>(global_object(), ErrorType::InvalidLength, "typed array"); \
|
||||
} \
|
||||
return {}; \
|
||||
return error; \
|
||||
} \
|
||||
auto array_length = array_length_or_error.release_value(); \
|
||||
if (array_length > NumericLimits<i32>::max() / sizeof(Type)) { \
|
||||
vm.throw_exception<RangeError>(global_object(), ErrorType::InvalidLength, "typed array"); \
|
||||
return {}; \
|
||||
} \
|
||||
if (array_length > NumericLimits<i32>::max() / sizeof(Type)) \
|
||||
return vm.throw_completion<RangeError>(global_object(), ErrorType::InvalidLength, "typed array"); \
|
||||
/* FIXME: What is the best/correct behavior here? */ \
|
||||
if (Checked<u32>::multiplication_would_overflow(array_length, sizeof(Type))) { \
|
||||
vm.throw_exception<RangeError>(global_object(), ErrorType::InvalidLength, "typed array"); \
|
||||
return {}; \
|
||||
} \
|
||||
if (Checked<u32>::multiplication_would_overflow(array_length, sizeof(Type))) \
|
||||
return vm.throw_completion<RangeError>(global_object(), ErrorType::InvalidLength, "typed array"); \
|
||||
return ClassName::create(global_object(), array_length, new_target); \
|
||||
}
|
||||
|
||||
|
|
|
@ -510,8 +510,8 @@ ThrowCompletionOr<TypedArrayBase*> typed_array_create(GlobalObject& global_objec
|
|||
virtual void initialize(GlobalObject&) override; \
|
||||
virtual ~ConstructorName() override; \
|
||||
\
|
||||
virtual Value call() override; \
|
||||
virtual Value construct(FunctionObject& new_target) override; \
|
||||
virtual ThrowCompletionOr<Value> call() override; \
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override; \
|
||||
\
|
||||
private: \
|
||||
virtual bool has_constructor() const override { return true; } \
|
||||
|
|
|
@ -43,16 +43,15 @@ TypedArrayConstructor::~TypedArrayConstructor()
|
|||
}
|
||||
|
||||
// 23.2.1.1 %TypedArray% ( ), https://tc39.es/ecma262/#sec-%typedarray%
|
||||
Value TypedArrayConstructor::call()
|
||||
ThrowCompletionOr<Value> TypedArrayConstructor::call()
|
||||
{
|
||||
return construct(*this);
|
||||
return TRY(construct(*this));
|
||||
}
|
||||
|
||||
// 23.2.1.1 %TypedArray% ( ), https://tc39.es/ecma262/#sec-%typedarray%
|
||||
Value TypedArrayConstructor::construct(FunctionObject&)
|
||||
ThrowCompletionOr<Object*> TypedArrayConstructor::construct(FunctionObject&)
|
||||
{
|
||||
vm().throw_exception<TypeError>(global_object(), ErrorType::ClassIsAbstract, "TypedArray");
|
||||
return {};
|
||||
return vm().throw_completion<TypeError>(global_object(), ErrorType::ClassIsAbstract, "TypedArray");
|
||||
}
|
||||
|
||||
// 23.2.2.1 %TypedArray%.from ( source [ , mapfn [ , thisArg ] ] ), https://tc39.es/ecma262/#sec-%typedarray%.from
|
||||
|
|
|
@ -19,8 +19,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~TypedArrayConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject& new_target) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -34,31 +34,28 @@ WeakMapConstructor::~WeakMapConstructor()
|
|||
}
|
||||
|
||||
// 24.3.1.1 WeakMap ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakmap-iterable
|
||||
Value WeakMapConstructor::call()
|
||||
ThrowCompletionOr<Value> WeakMapConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakMap);
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakMap);
|
||||
}
|
||||
|
||||
// 24.3.1.1 WeakMap ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakmap-iterable
|
||||
Value WeakMapConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> WeakMapConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto* weak_map = TRY_OR_DISCARD(ordinary_create_from_constructor<WeakMap>(global_object, new_target, &GlobalObject::weak_map_prototype));
|
||||
auto* weak_map = TRY(ordinary_create_from_constructor<WeakMap>(global_object, new_target, &GlobalObject::weak_map_prototype));
|
||||
|
||||
if (vm.argument(0).is_nullish())
|
||||
return weak_map;
|
||||
|
||||
auto adder = TRY_OR_DISCARD(weak_map->get(vm.names.set));
|
||||
if (!adder.is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, "'set' property of WeakMap");
|
||||
return {};
|
||||
}
|
||||
auto adder = TRY(weak_map->get(vm.names.set));
|
||||
if (!adder.is_function())
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, "'set' property of WeakMap");
|
||||
|
||||
TRY_OR_DISCARD(get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) -> Optional<Completion> {
|
||||
TRY(get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) -> Optional<Completion> {
|
||||
if (!iterator_value.is_object())
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObject, String::formatted("Iterator value {}", iterator_value.to_string_without_side_effects()));
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~WeakMapConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject&) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -33,25 +33,22 @@ WeakRefConstructor::~WeakRefConstructor()
|
|||
}
|
||||
|
||||
// 26.1.1.1 WeakRef ( target ), https://tc39.es/ecma262/#sec-weak-ref-target
|
||||
Value WeakRefConstructor::call()
|
||||
ThrowCompletionOr<Value> WeakRefConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakRef);
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakRef);
|
||||
}
|
||||
|
||||
// 26.1.1.1 WeakRef ( target ), https://tc39.es/ecma262/#sec-weak-ref-target
|
||||
Value WeakRefConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> WeakRefConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto target = vm.argument(0);
|
||||
if (!target.is_object()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, target.to_string_without_side_effects());
|
||||
return {};
|
||||
}
|
||||
return TRY_OR_DISCARD(ordinary_create_from_constructor<WeakRef>(global_object, new_target, &GlobalObject::weak_ref_prototype, &target.as_object()));
|
||||
if (!target.is_object())
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObject, target.to_string_without_side_effects());
|
||||
return TRY(ordinary_create_from_constructor<WeakRef>(global_object, new_target, &GlobalObject::weak_ref_prototype, &target.as_object()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~WeakRefConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject&) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -34,31 +34,28 @@ WeakSetConstructor::~WeakSetConstructor()
|
|||
}
|
||||
|
||||
// 24.4.1.1 WeakSet ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakset-iterable
|
||||
Value WeakSetConstructor::call()
|
||||
ThrowCompletionOr<Value> WeakSetConstructor::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakSet);
|
||||
return {};
|
||||
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.WeakSet);
|
||||
}
|
||||
|
||||
// 24.4.1.1 WeakSet ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakset-iterable
|
||||
Value WeakSetConstructor::construct(FunctionObject& new_target)
|
||||
ThrowCompletionOr<Object*> WeakSetConstructor::construct(FunctionObject& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto* weak_set = TRY_OR_DISCARD(ordinary_create_from_constructor<WeakSet>(global_object, new_target, &GlobalObject::weak_set_prototype));
|
||||
auto* weak_set = TRY(ordinary_create_from_constructor<WeakSet>(global_object, new_target, &GlobalObject::weak_set_prototype));
|
||||
|
||||
if (vm.argument(0).is_nullish())
|
||||
return weak_set;
|
||||
|
||||
auto adder = TRY_OR_DISCARD(weak_set->get(vm.names.add));
|
||||
if (!adder.is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, "'add' property of WeakSet");
|
||||
return {};
|
||||
}
|
||||
auto adder = TRY(weak_set->get(vm.names.add));
|
||||
if (!adder.is_function())
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, "'add' property of WeakSet");
|
||||
|
||||
TRY_OR_DISCARD(get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) -> Optional<Completion> {
|
||||
TRY(get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) -> Optional<Completion> {
|
||||
TRY(vm.call(adder.as_function(), Value(weak_set), iterator_value));
|
||||
return {};
|
||||
}));
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~WeakSetConstructor() override;
|
||||
|
||||
virtual Value call() override;
|
||||
virtual Value construct(FunctionObject&) override;
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
virtual ThrowCompletionOr<Object*> construct(FunctionObject&) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -33,26 +33,25 @@ ImageConstructor::~ImageConstructor()
|
|||
{
|
||||
}
|
||||
|
||||
JS::Value ImageConstructor::call()
|
||||
JS::ThrowCompletionOr<JS::Value> ImageConstructor::call()
|
||||
{
|
||||
vm().throw_exception<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "Image");
|
||||
return {};
|
||||
return vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "Image");
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/embedded-content.html#dom-image
|
||||
JS::Value ImageConstructor::construct(FunctionObject&)
|
||||
JS::ThrowCompletionOr<JS::Object*> ImageConstructor::construct(FunctionObject&)
|
||||
{
|
||||
auto& window = static_cast<WindowObject&>(global_object());
|
||||
auto& document = window.impl().associated_document();
|
||||
auto image_element = DOM::create_element(document, HTML::TagNames::img, Namespace::HTML);
|
||||
|
||||
if (vm().argument_count() > 0) {
|
||||
u32 width = TRY_OR_DISCARD(vm().argument(0).to_u32(global_object()));
|
||||
u32 width = TRY(vm().argument(0).to_u32(global_object()));
|
||||
image_element->set_attribute(HTML::AttributeNames::width, String::formatted("{}", width));
|
||||
}
|
||||
|
||||
if (vm().argument_count() > 1) {
|
||||
u32 height = TRY_OR_DISCARD(vm().argument(1).to_u32(global_object()));
|
||||
u32 height = TRY(vm().argument(1).to_u32(global_object()));
|
||||
image_element->set_attribute(HTML::AttributeNames::height, String::formatted("{}", height));
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ public:
|
|||
virtual void initialize(JS::GlobalObject&) override;
|
||||
virtual ~ImageConstructor() override;
|
||||
|
||||
virtual JS::Value call() override;
|
||||
virtual JS::Value construct(JS::FunctionObject& new_target) override;
|
||||
virtual JS::ThrowCompletionOr<JS::Value> call() override;
|
||||
virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -23,27 +23,23 @@ WebAssemblyInstanceConstructor::~WebAssemblyInstanceConstructor()
|
|||
{
|
||||
}
|
||||
|
||||
JS::Value WebAssemblyInstanceConstructor::call()
|
||||
JS::ThrowCompletionOr<JS::Value> WebAssemblyInstanceConstructor::call()
|
||||
{
|
||||
vm().throw_exception<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Instance");
|
||||
return {};
|
||||
return vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Instance");
|
||||
}
|
||||
|
||||
JS::Value WebAssemblyInstanceConstructor::construct(FunctionObject&)
|
||||
JS::ThrowCompletionOr<JS::Object*> WebAssemblyInstanceConstructor::construct(FunctionObject&)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
auto* module_argument = TRY_OR_DISCARD(vm.argument(0).to_object(global_object));
|
||||
if (!is<WebAssemblyModuleObject>(module_argument)) {
|
||||
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "WebAssembly.Module");
|
||||
return {};
|
||||
}
|
||||
|
||||
auto* module_argument = TRY(vm.argument(0).to_object(global_object));
|
||||
if (!is<WebAssemblyModuleObject>(module_argument))
|
||||
return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "WebAssembly.Module");
|
||||
auto& module_object = static_cast<WebAssemblyModuleObject&>(*module_argument);
|
||||
auto result = WebAssemblyObject::instantiate_module(module_object.module(), vm, global_object);
|
||||
if (result.is_error()) {
|
||||
vm.throw_exception(global_object, result.release_error());
|
||||
return {};
|
||||
vm.throw_exception(global_object, result.error());
|
||||
return JS::throw_completion(result.error());
|
||||
}
|
||||
return heap().allocate<WebAssemblyInstanceObject>(global_object, global_object, result.value());
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(JS::GlobalObject&) override;
|
||||
virtual ~WebAssemblyInstanceConstructor() override;
|
||||
|
||||
virtual JS::Value call() override;
|
||||
virtual JS::Value construct(JS::FunctionObject& new_target) override;
|
||||
virtual JS::ThrowCompletionOr<JS::Value> call() override;
|
||||
virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -21,38 +21,33 @@ WebAssemblyMemoryConstructor::~WebAssemblyMemoryConstructor()
|
|||
{
|
||||
}
|
||||
|
||||
JS::Value WebAssemblyMemoryConstructor::call()
|
||||
JS::ThrowCompletionOr<JS::Value> WebAssemblyMemoryConstructor::call()
|
||||
{
|
||||
vm().throw_exception<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Memory");
|
||||
return {};
|
||||
return vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Memory");
|
||||
}
|
||||
|
||||
JS::Value WebAssemblyMemoryConstructor::construct(FunctionObject&)
|
||||
JS::ThrowCompletionOr<JS::Object*> WebAssemblyMemoryConstructor::construct(FunctionObject&)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto descriptor = TRY_OR_DISCARD(vm.argument(0).to_object(global_object));
|
||||
auto initial_value = TRY_OR_DISCARD(descriptor->get("initial"));
|
||||
auto maximum_value = TRY_OR_DISCARD(descriptor->get("maximum"));
|
||||
auto descriptor = TRY(vm.argument(0).to_object(global_object));
|
||||
auto initial_value = TRY(descriptor->get("initial"));
|
||||
auto maximum_value = TRY(descriptor->get("maximum"));
|
||||
|
||||
if (initial_value.is_empty()) {
|
||||
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "Number");
|
||||
return {};
|
||||
}
|
||||
if (initial_value.is_empty())
|
||||
return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "Number");
|
||||
|
||||
auto initial = TRY_OR_DISCARD(initial_value.to_u32(global_object));
|
||||
auto initial = TRY(initial_value.to_u32(global_object));
|
||||
|
||||
Optional<u32> maximum;
|
||||
|
||||
if (!maximum_value.is_empty())
|
||||
maximum = TRY_OR_DISCARD(maximum_value.to_u32(global_object));
|
||||
maximum = TRY(maximum_value.to_u32(global_object));
|
||||
|
||||
auto address = WebAssemblyObject::s_abstract_machine.store().allocate(Wasm::MemoryType { Wasm::Limits { initial, maximum } });
|
||||
if (!address.has_value()) {
|
||||
vm.throw_exception<JS::TypeError>(global_object, "Wasm Memory allocation failed");
|
||||
return {};
|
||||
}
|
||||
if (!address.has_value())
|
||||
return vm.throw_completion<JS::TypeError>(global_object, "Wasm Memory allocation failed");
|
||||
|
||||
return vm.heap().allocate<WebAssemblyMemoryObject>(global_object, global_object, *address);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(JS::GlobalObject&) override;
|
||||
virtual ~WebAssemblyMemoryConstructor() override;
|
||||
|
||||
virtual JS::Value call() override;
|
||||
virtual JS::Value construct(JS::FunctionObject& new_target) override;
|
||||
virtual JS::ThrowCompletionOr<JS::Value> call() override;
|
||||
virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -23,22 +23,21 @@ WebAssemblyModuleConstructor::~WebAssemblyModuleConstructor()
|
|||
{
|
||||
}
|
||||
|
||||
JS::Value WebAssemblyModuleConstructor::call()
|
||||
JS::ThrowCompletionOr<JS::Value> WebAssemblyModuleConstructor::call()
|
||||
{
|
||||
vm().throw_exception<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Module");
|
||||
return {};
|
||||
return vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Module");
|
||||
}
|
||||
|
||||
JS::Value WebAssemblyModuleConstructor::construct(FunctionObject&)
|
||||
JS::ThrowCompletionOr<JS::Object*> WebAssemblyModuleConstructor::construct(FunctionObject&)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto* buffer_object = TRY_OR_DISCARD(vm.argument(0).to_object(global_object));
|
||||
auto* buffer_object = TRY(vm.argument(0).to_object(global_object));
|
||||
auto result = parse_module(global_object, buffer_object);
|
||||
if (result.is_error()) {
|
||||
vm.throw_exception(global_object, result.error());
|
||||
return {};
|
||||
return JS::throw_completion(result.error());
|
||||
}
|
||||
|
||||
return heap().allocate<WebAssemblyModuleObject>(global_object, global_object, result.release_value());
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(JS::GlobalObject&) override;
|
||||
virtual ~WebAssemblyModuleConstructor() override;
|
||||
|
||||
virtual JS::Value call() override;
|
||||
virtual JS::Value construct(JS::FunctionObject& new_target) override;
|
||||
virtual JS::ThrowCompletionOr<JS::Value> call() override;
|
||||
virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
|
@ -23,23 +23,20 @@ WebAssemblyTableConstructor::~WebAssemblyTableConstructor()
|
|||
{
|
||||
}
|
||||
|
||||
JS::Value WebAssemblyTableConstructor::call()
|
||||
JS::ThrowCompletionOr<JS::Value> WebAssemblyTableConstructor::call()
|
||||
{
|
||||
vm().throw_exception<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Table");
|
||||
return {};
|
||||
return vm().throw_completion<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Table");
|
||||
}
|
||||
|
||||
JS::Value WebAssemblyTableConstructor::construct(FunctionObject&)
|
||||
JS::ThrowCompletionOr<JS::Object*> WebAssemblyTableConstructor::construct(FunctionObject&)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto descriptor = TRY_OR_DISCARD(vm.argument(0).to_object(global_object));
|
||||
auto element_value = TRY_OR_DISCARD(descriptor->get("element"));
|
||||
if (!element_value.is_string()) {
|
||||
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::InvalidHint, element_value.to_string_without_side_effects());
|
||||
return {};
|
||||
}
|
||||
auto descriptor = TRY(vm.argument(0).to_object(global_object));
|
||||
auto element_value = TRY(descriptor->get("element"));
|
||||
if (!element_value.is_string())
|
||||
return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::InvalidHint, element_value.to_string_without_side_effects());
|
||||
auto& element = element_value.as_string().string();
|
||||
|
||||
Optional<Wasm::ValueType> reference_type;
|
||||
|
@ -48,27 +45,23 @@ JS::Value WebAssemblyTableConstructor::construct(FunctionObject&)
|
|||
else if (element == "externref"sv)
|
||||
reference_type = Wasm::ValueType(Wasm::ValueType::ExternReference);
|
||||
|
||||
if (!reference_type.has_value()) {
|
||||
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::InvalidHint, element);
|
||||
return {};
|
||||
}
|
||||
if (!reference_type.has_value())
|
||||
return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::InvalidHint, element);
|
||||
|
||||
auto initial_value = TRY_OR_DISCARD(descriptor->get("initial"));
|
||||
auto maximum_value = TRY_OR_DISCARD(descriptor->get("maximum"));
|
||||
auto initial_value = TRY(descriptor->get("initial"));
|
||||
auto maximum_value = TRY(descriptor->get("maximum"));
|
||||
|
||||
auto initial = TRY_OR_DISCARD(initial_value.to_u32(global_object));
|
||||
auto initial = TRY(initial_value.to_u32(global_object));
|
||||
|
||||
Optional<u32> maximum;
|
||||
|
||||
if (!maximum_value.is_undefined())
|
||||
maximum = TRY_OR_DISCARD(maximum_value.to_u32(global_object));
|
||||
maximum = TRY(maximum_value.to_u32(global_object));
|
||||
|
||||
if (maximum.has_value() && maximum.value() < initial) {
|
||||
vm.throw_exception<JS::RangeError>(global_object, "maximum should be larger than or equal to initial");
|
||||
return {};
|
||||
}
|
||||
if (maximum.has_value() && maximum.value() < initial)
|
||||
return vm.throw_completion<JS::RangeError>(global_object, "maximum should be larger than or equal to initial");
|
||||
|
||||
auto value_value = TRY_OR_DISCARD(descriptor->get("value"));
|
||||
auto value_value = TRY(descriptor->get("value"));
|
||||
auto reference_value = [&]() -> Optional<Wasm::Value> {
|
||||
if (value_value.is_undefined())
|
||||
return Wasm::Value(*reference_type, 0ull);
|
||||
|
@ -76,16 +69,14 @@ JS::Value WebAssemblyTableConstructor::construct(FunctionObject&)
|
|||
return to_webassembly_value(value_value, *reference_type, global_object);
|
||||
}();
|
||||
|
||||
if (!reference_value.has_value())
|
||||
return {};
|
||||
if (auto* exception = vm.exception())
|
||||
return JS::throw_completion(exception->value());
|
||||
|
||||
auto& reference = reference_value->value().get<Wasm::Reference>();
|
||||
|
||||
auto address = WebAssemblyObject::s_abstract_machine.store().allocate(Wasm::TableType { *reference_type, Wasm::Limits { initial, maximum } });
|
||||
if (!address.has_value()) {
|
||||
vm.throw_exception<JS::TypeError>(global_object, "Wasm Table allocation failed");
|
||||
return {};
|
||||
}
|
||||
if (!address.has_value())
|
||||
return vm.throw_completion<JS::TypeError>(global_object, "Wasm Table allocation failed");
|
||||
|
||||
auto& table = *WebAssemblyObject::s_abstract_machine.store().get(*address);
|
||||
for (auto& element : table.elements())
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual void initialize(JS::GlobalObject&) override;
|
||||
virtual ~WebAssemblyTableConstructor() override;
|
||||
|
||||
virtual JS::Value call() override;
|
||||
virtual JS::Value construct(JS::FunctionObject& new_target) override;
|
||||
virtual JS::ThrowCompletionOr<JS::Value> call() override;
|
||||
virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override;
|
||||
|
||||
private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
|
|
Loading…
Reference in a new issue