mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 07:07:34 +00:00
LibJS: Implement initializing a TypedArray from an iterable object
Based on these specifications (which required IterableToList as well): https://tc39.es/ecma262/#sec-typedarray https://tc39.es/ecma262/#sec-initializetypedarrayfromlist
This commit is contained in:
parent
06a2173586
commit
e3c634fdd0
4 changed files with 61 additions and 5 deletions
|
@ -92,6 +92,21 @@ void iterator_close([[maybe_unused]] Object& iterator)
|
||||||
TODO();
|
TODO();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MarkedValueList iterable_to_list(GlobalObject& global_object, Value iterable, Value method)
|
||||||
|
{
|
||||||
|
auto& vm = global_object.vm();
|
||||||
|
MarkedValueList values(vm.heap());
|
||||||
|
get_iterator_values(
|
||||||
|
global_object, iterable, [&](auto value) {
|
||||||
|
if (vm.exception())
|
||||||
|
return IterationDecision::Break;
|
||||||
|
values.append(value);
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
},
|
||||||
|
method);
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
Value create_iterator_result_object(GlobalObject& global_object, Value value, bool done)
|
Value create_iterator_result_object(GlobalObject& global_object, Value value, bool done)
|
||||||
{
|
{
|
||||||
auto& vm = global_object.vm();
|
auto& vm = global_object.vm();
|
||||||
|
@ -101,11 +116,11 @@ Value create_iterator_result_object(GlobalObject& global_object, Value value, bo
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_iterator_values(GlobalObject& global_object, Value value, AK::Function<IterationDecision(Value)> callback)
|
void get_iterator_values(GlobalObject& global_object, Value value, AK::Function<IterationDecision(Value)> callback, Value method)
|
||||||
{
|
{
|
||||||
auto& vm = global_object.vm();
|
auto& vm = global_object.vm();
|
||||||
|
|
||||||
auto iterator = get_iterator(global_object, value);
|
auto iterator = get_iterator(global_object, value, "sync", method);
|
||||||
if (!iterator)
|
if (!iterator)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,8 @@ Value create_iterator_result_object(GlobalObject&, Value value, bool done);
|
||||||
Object* iterator_next(Object& iterator, Value value = {});
|
Object* iterator_next(Object& iterator, Value value = {});
|
||||||
void iterator_close(Object& iterator);
|
void iterator_close(Object& iterator);
|
||||||
|
|
||||||
void get_iterator_values(GlobalObject&, Value value, AK::Function<IterationDecision(Value)> callback);
|
MarkedValueList iterable_to_list(GlobalObject&, Value iterable, Value method = {});
|
||||||
|
|
||||||
|
void get_iterator_values(GlobalObject&, Value value, AK::Function<IterationDecision(Value)> callback, Value method = {});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <AK/Checked.h>
|
#include <AK/Checked.h>
|
||||||
#include <LibJS/Runtime/ArrayBuffer.h>
|
#include <LibJS/Runtime/ArrayBuffer.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
|
#include <LibJS/Runtime/IteratorOperations.h>
|
||||||
#include <LibJS/Runtime/TypedArray.h>
|
#include <LibJS/Runtime/TypedArray.h>
|
||||||
#include <LibJS/Runtime/TypedArrayConstructor.h>
|
#include <LibJS/Runtime/TypedArrayConstructor.h>
|
||||||
|
|
||||||
|
@ -166,6 +167,31 @@ static void initialize_typed_array_from_array_like(GlobalObject& global_object,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
template<typename T>
|
||||||
|
static void initialize_typed_array_from_list(GlobalObject& global_object, TypedArray<T>& typed_array, const MarkedValueList& list)
|
||||||
|
{
|
||||||
|
// 23.2.5.1.4 InitializeTypedArrayFromList, https://tc39.es/ecma262/#sec-initializetypedarrayfromlist
|
||||||
|
|
||||||
|
auto element_size = typed_array.element_size();
|
||||||
|
if (Checked<size_t>::multiplication_would_overflow(element_size, list.size())) {
|
||||||
|
global_object.vm().throw_exception<RangeError>(global_object, ErrorType::InvalidLength, "typed array");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto byte_length = element_size * list.size();
|
||||||
|
auto array_buffer = ArrayBuffer::create(global_object, byte_length);
|
||||||
|
typed_array.set_viewed_array_buffer(array_buffer);
|
||||||
|
typed_array.set_byte_length(byte_length);
|
||||||
|
typed_array.set_byte_offset(0);
|
||||||
|
typed_array.set_array_length(list.size());
|
||||||
|
|
||||||
|
auto& vm = global_object.vm();
|
||||||
|
for (size_t k = 0; k < list.size(); k++) {
|
||||||
|
auto value = list[k];
|
||||||
|
typed_array.put_by_index(k, value);
|
||||||
|
if (vm.exception())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TypedArrayBase::visit_edges(Visitor& visitor)
|
void TypedArrayBase::visit_edges(Visitor& visitor)
|
||||||
{
|
{
|
||||||
|
@ -234,8 +260,10 @@ void TypedArrayBase::visit_edges(Visitor& visitor)
|
||||||
if (vm.exception()) \
|
if (vm.exception()) \
|
||||||
return {}; \
|
return {}; \
|
||||||
if (iterator.is_function()) { \
|
if (iterator.is_function()) { \
|
||||||
/* FIXME: Initialize from Iterator */ \
|
auto values = iterable_to_list(global_object(), first_argument, iterator); \
|
||||||
TODO(); \
|
if (vm.exception()) \
|
||||||
|
return {}; \
|
||||||
|
initialize_typed_array_from_list(global_object(), *typed_array, values); \
|
||||||
} else { \
|
} else { \
|
||||||
initialize_typed_array_from_array_like(global_object(), *typed_array, first_argument.as_object()); \
|
initialize_typed_array_from_array_like(global_object(), *typed_array, first_argument.as_object()); \
|
||||||
} \
|
} \
|
||||||
|
|
|
@ -195,6 +195,17 @@ test("typed array from Array-Like", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("typed array from Iterable", () => {
|
||||||
|
const from = new String("123");
|
||||||
|
|
||||||
|
TYPED_ARRAYS.forEach(T => {
|
||||||
|
const newTypedArray = new T(from);
|
||||||
|
expect(newTypedArray[0]).toBe(1);
|
||||||
|
expect(newTypedArray[1]).toBe(2);
|
||||||
|
expect(newTypedArray[2]).toBe(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test("TypedArray is not exposed on the global object", () => {
|
test("TypedArray is not exposed on the global object", () => {
|
||||||
expect(globalThis.TypedArray).toBeUndefined();
|
expect(globalThis.TypedArray).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue