diff --git a/Tests/LibWasm/test-wasm.cpp b/Tests/LibWasm/test-wasm.cpp index b25555ea75..926ddfdabe 100644 --- a/Tests/LibWasm/test-wasm.cpp +++ b/Tests/LibWasm/test-wasm.cpp @@ -19,7 +19,7 @@ TESTJS_GLOBAL_FUNCTION(read_binary_wasm_file, readBinaryWasmFile) if (file.is_error()) return vm.throw_completion(global_object, strerror(file.error().code())); auto contents = file.value()->read_all(); - auto array = JS::Uint8Array::create(global_object, contents.size()); + auto* array = TRY(JS::Uint8Array::create(global_object, contents.size())); contents.span().copy_to(array->data()); return JS::Value(array); } diff --git a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp index 2d03c0f743..8cfae30b8c 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp +++ b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp @@ -10,13 +10,12 @@ namespace JS { -ArrayBuffer* ArrayBuffer::create(GlobalObject& global_object, size_t byte_length) +ThrowCompletionOr ArrayBuffer::create(GlobalObject& global_object, size_t byte_length) { auto buffer = ByteBuffer::create_zeroed(byte_length); - if (buffer.is_error()) { - global_object.vm().throw_exception(global_object, ErrorType::NotEnoughMemoryToAllocate, byte_length); - return nullptr; - } + if (buffer.is_error()) + return global_object.vm().throw_completion(global_object, ErrorType::NotEnoughMemoryToAllocate, byte_length); + return global_object.heap().allocate(global_object, buffer.release_value(), *global_object.array_buffer_prototype()); } diff --git a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h index 0cf1369fe8..5fc60f2d3c 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h +++ b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h @@ -25,7 +25,7 @@ class ArrayBuffer : public Object { JS_OBJECT(ArrayBuffer, Object); public: - static ArrayBuffer* create(GlobalObject&, size_t); + static ThrowCompletionOr create(GlobalObject&, size_t); static ArrayBuffer* create(GlobalObject&, ByteBuffer); static ArrayBuffer* create(GlobalObject&, ByteBuffer*); diff --git a/Userland/Libraries/LibJS/Runtime/TypedArray.cpp b/Userland/Libraries/LibJS/Runtime/TypedArray.cpp index 05fc7dcfd4..0c760f1b97 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArray.cpp +++ b/Userland/Libraries/LibJS/Runtime/TypedArray.cpp @@ -369,16 +369,23 @@ void TypedArrayBase::visit_edges(Visitor& visitor) ThrowCompletionOr ClassName::create(GlobalObject& global_object, u32 length, FunctionObject& new_target) \ { \ auto* prototype = TRY(get_prototype_from_constructor(global_object, new_target, &GlobalObject::snake_name##_prototype)); \ - return global_object.heap().allocate(global_object, length, *prototype); \ + auto* array_buffer = TRY(ArrayBuffer::create(global_object, length * sizeof(UnderlyingBufferDataType))); \ + return global_object.heap().allocate(global_object, *prototype, length, *array_buffer); \ } \ \ - ClassName* ClassName::create(GlobalObject& global_object, u32 length) \ + ThrowCompletionOr ClassName::create(GlobalObject& global_object, u32 length) \ { \ - return global_object.heap().allocate(global_object, length, *global_object.snake_name##_prototype()); \ + auto* array_buffer = TRY(ArrayBuffer::create(global_object, length * sizeof(UnderlyingBufferDataType))); \ + return create(global_object, length, *array_buffer); \ } \ \ - ClassName::ClassName(u32 length, Object& prototype) \ - : TypedArray(length, prototype) \ + ClassName* ClassName::create(GlobalObject& global_object, u32 length, ArrayBuffer& array_buffer) \ + { \ + return global_object.heap().allocate(global_object, *global_object.snake_name##_prototype(), length, array_buffer); \ + } \ + \ + ClassName::ClassName(Object& prototype, u32 length, ArrayBuffer& array_buffer) \ + : TypedArray(prototype, length, array_buffer) \ { \ if constexpr (StringView { #ClassName }.is_one_of("BigInt64Array", "BigUint64Array")) \ m_content_type = ContentType::BigInt; \ @@ -450,9 +457,7 @@ void TypedArrayBase::visit_edges(Visitor& visitor) TRY(initialize_typed_array_from_typed_array(global_object(), *typed_array, arg_typed_array)); \ } else if (is(first_argument.as_object())) { \ auto& array_buffer = static_cast(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(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(first_argument.get_method(global_object(), *vm.well_known_symbol_iterator())); \ diff --git a/Userland/Libraries/LibJS/Runtime/TypedArray.h b/Userland/Libraries/LibJS/Runtime/TypedArray.h index 7cf6c9abc8..631c254999 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArray.h +++ b/Userland/Libraries/LibJS/Runtime/TypedArray.h @@ -454,11 +454,11 @@ public: Value get_modify_set_value_in_buffer(size_t byte_index, Value value, ReadWriteModifyFunction operation, bool is_little_endian = true) override { return viewed_array_buffer()->template get_modify_set_value(byte_index, value, move(operation), is_little_endian); } protected: - TypedArray(u32 array_length, Object& prototype) + TypedArray(Object& prototype, u32 array_length, ArrayBuffer& array_buffer) : TypedArrayBase(prototype) { VERIFY(!Checked::multiplication_would_overflow(array_length, sizeof(UnderlyingBufferDataType))); - m_viewed_array_buffer = ArrayBuffer::create(global_object(), array_length * sizeof(UnderlyingBufferDataType)); + m_viewed_array_buffer = &array_buffer; if (array_length) VERIFY(!data().is_null()); m_array_length = array_length; @@ -479,8 +479,9 @@ ThrowCompletionOr typed_array_create(GlobalObject& global_objec virtual ~ClassName(); \ static ThrowCompletionOr create( \ GlobalObject&, u32 length, FunctionObject& new_target); \ - static ClassName* create(GlobalObject&, u32 length); \ - ClassName(u32 length, Object& prototype); \ + static ThrowCompletionOr create(GlobalObject&, u32 length); \ + static ClassName* create(GlobalObject&, u32 length, ArrayBuffer& buffer); \ + ClassName(Object& prototype, u32 length, ArrayBuffer& array_buffer); \ virtual String element_name() const override; \ }; \ class PrototypeName final : public Object { \ diff --git a/Userland/Libraries/LibWeb/Encoding/TextEncoder.cpp b/Userland/Libraries/LibWeb/Encoding/TextEncoder.cpp index 16a2205df1..bd3af0bb55 100644 --- a/Userland/Libraries/LibWeb/Encoding/TextEncoder.cpp +++ b/Userland/Libraries/LibWeb/Encoding/TextEncoder.cpp @@ -27,11 +27,9 @@ JS::Uint8Array* TextEncoder::encode(String const& input) const // 4. If result is finished, then convert output into a byte sequence and return a Uint8Array object wrapping an ArrayBuffer containing output. auto byte_buffer = input.to_byte_buffer(); - - // FIXME: Support `TypedArray::create()` with existing `ArrayBuffer`, so that we don't have to allocate two `ByteBuffer`s. - auto* typed_array = JS::Uint8Array::create(global_object, byte_buffer.size()); - typed_array->viewed_array_buffer()->buffer() = move(byte_buffer); - return typed_array; + auto array_length = byte_buffer.size(); + auto* array_buffer = JS::ArrayBuffer::create(global_object, move(byte_buffer)); + return JS::Uint8Array::create(global_object, array_length, *array_buffer); } // https://encoding.spec.whatwg.org/#dom-textencoder-encoding diff --git a/Userland/Libraries/LibWeb/HTML/ImageData.cpp b/Userland/Libraries/LibWeb/HTML/ImageData.cpp index c5b8714735..c76ec71a10 100644 --- a/Userland/Libraries/LibWeb/HTML/ImageData.cpp +++ b/Userland/Libraries/LibWeb/HTML/ImageData.cpp @@ -20,9 +20,10 @@ RefPtr ImageData::create_with_size(JS::GlobalObject& global_object, i dbgln("Creating ImageData with {}x{}", width, height); - auto* data = JS::Uint8ClampedArray::create(global_object, width * height * 4); - if (!data) + auto data_or_error = JS::Uint8ClampedArray::create(global_object, width * height * 4); + if (data_or_error.is_error()) return nullptr; + auto* data = data_or_error.release_value(); auto data_handle = JS::make_handle(data);