mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-11 18:20:43 +09:00
LibJS: Convert ArrayBuffer construction to ThrowCompletionOr
This also allows us to create TypedArrays with an existing buffer thus clearing up an additional FIXME in TextEncoder.
This commit is contained in:
parent
4136cbdb09
commit
de90d54be0
Notes:
sideshowbarker
2024-07-17 19:38:21 +09:00
Author: https://github.com/davidot
Commit: de90d54be0
Pull-request: https://github.com/SerenityOS/serenity/pull/12343
Reviewed-by: https://github.com/linusg
7 changed files with 30 additions and 26 deletions
|
@ -19,7 +19,7 @@ TESTJS_GLOBAL_FUNCTION(read_binary_wasm_file, readBinaryWasmFile)
|
|||
if (file.is_error())
|
||||
return vm.throw_completion<JS::TypeError>(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);
|
||||
}
|
||||
|
|
|
@ -10,13 +10,12 @@
|
|||
|
||||
namespace JS {
|
||||
|
||||
ArrayBuffer* ArrayBuffer::create(GlobalObject& global_object, size_t byte_length)
|
||||
ThrowCompletionOr<ArrayBuffer*> 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<RangeError>(global_object, ErrorType::NotEnoughMemoryToAllocate, byte_length);
|
||||
return nullptr;
|
||||
}
|
||||
if (buffer.is_error())
|
||||
return global_object.vm().throw_completion<RangeError>(global_object, ErrorType::NotEnoughMemoryToAllocate, byte_length);
|
||||
|
||||
return global_object.heap().allocate<ArrayBuffer>(global_object, buffer.release_value(), *global_object.array_buffer_prototype());
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ class ArrayBuffer : public Object {
|
|||
JS_OBJECT(ArrayBuffer, Object);
|
||||
|
||||
public:
|
||||
static ArrayBuffer* create(GlobalObject&, size_t);
|
||||
static ThrowCompletionOr<ArrayBuffer*> create(GlobalObject&, size_t);
|
||||
static ArrayBuffer* create(GlobalObject&, ByteBuffer);
|
||||
static ArrayBuffer* create(GlobalObject&, ByteBuffer*);
|
||||
|
||||
|
|
|
@ -369,16 +369,23 @@ void TypedArrayBase::visit_edges(Visitor& visitor)
|
|||
ThrowCompletionOr<ClassName*> 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<ClassName>(global_object, length, *prototype); \
|
||||
auto* array_buffer = TRY(ArrayBuffer::create(global_object, length * sizeof(UnderlyingBufferDataType))); \
|
||||
return global_object.heap().allocate<ClassName>(global_object, *prototype, length, *array_buffer); \
|
||||
} \
|
||||
\
|
||||
ClassName* ClassName::create(GlobalObject& global_object, u32 length) \
|
||||
ThrowCompletionOr<ClassName*> ClassName::create(GlobalObject& global_object, u32 length) \
|
||||
{ \
|
||||
return global_object.heap().allocate<ClassName>(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<ClassName>(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<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(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())); \
|
||||
|
|
|
@ -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<T>(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<u32>::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<TypedArrayBase*> typed_array_create(GlobalObject& global_objec
|
|||
virtual ~ClassName(); \
|
||||
static ThrowCompletionOr<ClassName*> create( \
|
||||
GlobalObject&, u32 length, FunctionObject& new_target); \
|
||||
static ClassName* create(GlobalObject&, u32 length); \
|
||||
ClassName(u32 length, Object& prototype); \
|
||||
static ThrowCompletionOr<ClassName*> 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 { \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -20,9 +20,10 @@ RefPtr<ImageData> 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);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue