From 253d9a38d15c148ee5ef430711ebbe9403f01e41 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sun, 3 Oct 2021 21:03:57 +0100 Subject: [PATCH] LibJS: Convert typed_array_create() to ThrowCompletionOr Also add spec step comments to it while we're here. --- .../Libraries/LibJS/Runtime/TypedArray.cpp | 37 ++++++++++--------- Userland/Libraries/LibJS/Runtime/TypedArray.h | 2 +- .../LibJS/Runtime/TypedArrayConstructor.cpp | 12 ++---- .../LibJS/Runtime/TypedArrayPrototype.cpp | 4 +- 4 files changed, 25 insertions(+), 30 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/TypedArray.cpp b/Userland/Libraries/LibJS/Runtime/TypedArray.cpp index e1dde33072a..83076eac38a 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArray.cpp +++ b/Userland/Libraries/LibJS/Runtime/TypedArray.cpp @@ -345,29 +345,32 @@ static ThrowCompletionOr initialize_typed_array_from_list(GlobalObject& gl } // 23.2.4.2 TypedArrayCreate ( constructor, argumentList ), https://tc39.es/ecma262/#typedarray-create -TypedArrayBase* typed_array_create(GlobalObject& global_object, FunctionObject& constructor, MarkedValueList arguments) +ThrowCompletionOr typed_array_create(GlobalObject& global_object, FunctionObject& constructor, MarkedValueList arguments) { auto& vm = global_object.vm(); - auto argument_count = arguments.size(); - auto first_argument = argument_count > 0 ? arguments[0] : js_undefined(); - + Optional first_argument; + if (!arguments.is_empty()) + first_argument = arguments[0]; + // 1. Let newTypedArray be ? Construct(constructor, argumentList). auto new_typed_array = vm.construct(constructor, constructor, move(arguments)); - if (vm.exception()) - return nullptr; - if (!new_typed_array.is_object() || !new_typed_array.as_object().is_typed_array()) { - vm.throw_exception(global_object, ErrorType::NotAnObjectOfType, "TypedArray"); - return nullptr; - } + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); + + // 2. Perform ? ValidateTypedArray(newTypedArray). + if (!new_typed_array.is_object() || !new_typed_array.as_object().is_typed_array()) + return vm.throw_completion(global_object, ErrorType::NotAnObjectOfType, "TypedArray"); auto& typed_array = static_cast(new_typed_array.as_object()); - if (typed_array.viewed_array_buffer()->is_detached()) { - vm.throw_exception(global_object, ErrorType::DetachedArrayBuffer); - return nullptr; - } - if (argument_count == 1 && first_argument.is_number() && typed_array.array_length() < first_argument.as_double()) { - vm.throw_exception(global_object, ErrorType::InvalidLength, "typed array"); - return nullptr; + TRY(validate_typed_array(global_object, typed_array)); + + // 3. If argumentList is a List of a single Number, then + if (first_argument.has_value() && first_argument->is_number()) { + // a. If newTypedArray.[[ArrayLength]] < ℝ(argumentList[0]), throw a TypeError exception. + if (typed_array.array_length() < first_argument->as_double()) + return vm.throw_completion(global_object, ErrorType::InvalidLength, "typed array"); } + + // 4. Return newTypedArray. return &typed_array; } diff --git a/Userland/Libraries/LibJS/Runtime/TypedArray.h b/Userland/Libraries/LibJS/Runtime/TypedArray.h index d8b4e88805b..1ea28c1a495 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArray.h +++ b/Userland/Libraries/LibJS/Runtime/TypedArray.h @@ -480,7 +480,7 @@ private: virtual bool is_typed_array() const final { return true; } }; -TypedArrayBase* typed_array_create(GlobalObject& global_object, FunctionObject& constructor, MarkedValueList arguments); +ThrowCompletionOr typed_array_create(GlobalObject& global_object, FunctionObject& constructor, MarkedValueList arguments); #define JS_DECLARE_TYPED_ARRAY(ClassName, snake_name, PrototypeName, ConstructorName, Type) \ class ClassName : public TypedArray { \ diff --git a/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp b/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp index a48d2a42b77..35dd3a13f37 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp @@ -85,9 +85,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayConstructor::from) MarkedValueList arguments(vm.heap()); arguments.empend(values.size()); - auto target_object = typed_array_create(global_object, constructor.as_function(), move(arguments)); - if (vm.exception()) - return {}; + auto target_object = TRY_OR_DISCARD(typed_array_create(global_object, constructor.as_function(), move(arguments))); for (size_t k = 0; k < values.size(); ++k) { auto k_value = values[k]; @@ -107,9 +105,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayConstructor::from) MarkedValueList arguments(vm.heap()); arguments.empend(length); - auto target_object = typed_array_create(global_object, constructor.as_function(), move(arguments)); - if (vm.exception()) - return {}; + auto target_object = TRY_OR_DISCARD(typed_array_create(global_object, constructor.as_function(), move(arguments))); for (size_t k = 0; k < length; ++k) { auto k_value = TRY_OR_DISCARD(array_like->get(k)); @@ -135,9 +131,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayConstructor::of) } MarkedValueList arguments(vm.heap()); arguments.append(Value(length)); - auto new_object = typed_array_create(global_object, constructor.as_function(), move(arguments)); - if (vm.exception()) - return {}; + auto new_object = TRY_OR_DISCARD(typed_array_create(global_object, constructor.as_function(), move(arguments))); for (size_t k = 0; k < length; ++k) { auto success = TRY_OR_DISCARD(new_object->set(k, vm.argument(k), Object::ShouldThrowExceptions::Yes)); if (!success) { diff --git a/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp b/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp index db35a32ca46..f56da5285ef 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp @@ -177,9 +177,7 @@ static TypedArrayBase* typed_array_species_create(GlobalObject& global_object, T auto* constructor = TRY_OR_DISCARD(species_constructor(global_object, exemplar, *typed_array_default_constructor)); - auto* result = typed_array_create(global_object, *constructor, move(arguments)); - if (vm.exception()) - return nullptr; + auto* result = TRY_OR_DISCARD(typed_array_create(global_object, *constructor, move(arguments))); if (result->content_type() != exemplar.content_type()) { vm.throw_exception(global_object, ErrorType::TypedArrayContentTypeMismatch, result->class_name(), exemplar.class_name());