mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 05:27:43 +00:00
LibJS: Implement initializing a TypedArray from an array-like object
Used by twitch.tv and based on the following specification: https://tc39.es/ecma262/#sec-initializetypedarrayfromarraylike
This commit is contained in:
parent
c9196995be
commit
06a2173586
2 changed files with 54 additions and 2 deletions
|
@ -135,6 +135,37 @@ static void initialize_typed_array_from_typed_array(GlobalObject& global_object,
|
||||||
dest_array.put_by_index(i, v);
|
dest_array.put_by_index(i, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
template<typename T>
|
||||||
|
static void initialize_typed_array_from_array_like(GlobalObject& global_object, TypedArray<T>& typed_array, const Object& array_like)
|
||||||
|
{
|
||||||
|
// 23.2.5.1.5 InitializeTypedArrayFromArrayLike, https://tc39.es/ecma262/#sec-initializetypedarrayfromarraylike
|
||||||
|
|
||||||
|
auto& vm = global_object.vm();
|
||||||
|
auto length = length_of_array_like(global_object, array_like);
|
||||||
|
if (vm.exception())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto element_size = typed_array.element_size();
|
||||||
|
if (Checked<size_t>::multiplication_would_overflow(element_size, length)) {
|
||||||
|
vm.throw_exception<RangeError>(global_object, ErrorType::InvalidLength, "typed array");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto byte_length = element_size * length;
|
||||||
|
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(length);
|
||||||
|
|
||||||
|
for (size_t k = 0; k < length; k++) {
|
||||||
|
auto value = array_like.get(k).value_or(js_undefined());
|
||||||
|
if (vm.exception())
|
||||||
|
return;
|
||||||
|
typed_array.put_by_index(k, value);
|
||||||
|
if (vm.exception())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TypedArrayBase::visit_edges(Visitor& visitor)
|
void TypedArrayBase::visit_edges(Visitor& visitor)
|
||||||
{
|
{
|
||||||
|
@ -199,8 +230,17 @@ void TypedArrayBase::visit_edges(Visitor& visitor)
|
||||||
if (vm.exception()) \
|
if (vm.exception()) \
|
||||||
return {}; \
|
return {}; \
|
||||||
} else { \
|
} else { \
|
||||||
/* FIXME: Initialize from Iterator or Array-like object */ \
|
auto iterator = first_argument.as_object().get(vm.well_known_symbol_iterator()); \
|
||||||
TODO(); \
|
if (vm.exception()) \
|
||||||
|
return {}; \
|
||||||
|
if (iterator.is_function()) { \
|
||||||
|
/* FIXME: Initialize from Iterator */ \
|
||||||
|
TODO(); \
|
||||||
|
} else { \
|
||||||
|
initialize_typed_array_from_array_like(global_object(), *typed_array, first_argument.as_object()); \
|
||||||
|
} \
|
||||||
|
if (vm.exception()) \
|
||||||
|
return {}; \
|
||||||
} \
|
} \
|
||||||
return typed_array; \
|
return typed_array; \
|
||||||
} \
|
} \
|
||||||
|
|
|
@ -183,6 +183,18 @@ test("typed array created from TypedArray do not share buffer", () => {
|
||||||
expect(u8Array[1]).toBe(2);
|
expect(u8Array[1]).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("typed array from Array-Like", () => {
|
||||||
|
TYPED_ARRAYS.forEach(T => {
|
||||||
|
function func() {
|
||||||
|
const newTypedArray = new T(arguments);
|
||||||
|
expect(newTypedArray[0]).toBe(1);
|
||||||
|
expect(newTypedArray[1]).toBe(2);
|
||||||
|
expect(newTypedArray[2]).toBe(3);
|
||||||
|
}
|
||||||
|
func(1, 2, 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