1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 06:27:45 +00:00

LibJS: Replace GlobalObject with VM in TypedArray AOs [Part 10/19]

This commit is contained in:
Linus Groh 2022-08-21 17:17:31 +01:00
parent f0b793db74
commit b037894287
5 changed files with 128 additions and 115 deletions

View file

@ -22,7 +22,7 @@ static ThrowCompletionOr<ArrayBuffer*> validate_integer_typed_array(GlobalObject
// 1. If waitable is not present, set waitable to false. // 1. If waitable is not present, set waitable to false.
// 2. Perform ? ValidateTypedArray(typedArray). // 2. Perform ? ValidateTypedArray(typedArray).
TRY(validate_typed_array(global_object, typed_array)); TRY(validate_typed_array(vm, typed_array));
// 3. Let buffer be typedArray.[[ViewedArrayBuffer]]. // 3. Let buffer be typedArray.[[ViewedArrayBuffer]].
auto* buffer = typed_array.viewed_array_buffer(); auto* buffer = typed_array.viewed_array_buffer();
@ -158,7 +158,7 @@ void AtomicsObject::initialize(Realm& realm)
// 25.4.3 Atomics.add ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.add // 25.4.3 Atomics.add ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.add
JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::add) JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::add)
{ {
auto* typed_array = TRY(typed_array_from(global_object, vm.argument(0))); auto* typed_array = TRY(typed_array_from(vm, vm.argument(0)));
auto atomic_add = [](auto* storage, auto value) { return AK::atomic_fetch_add(storage, value); }; auto atomic_add = [](auto* storage, auto value) { return AK::atomic_fetch_add(storage, value); };
@ -174,7 +174,7 @@ JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::add)
// 25.4.4 Atomics.and ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.and // 25.4.4 Atomics.and ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.and
JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::and_) JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::and_)
{ {
auto* typed_array = TRY(typed_array_from(global_object, vm.argument(0))); auto* typed_array = TRY(typed_array_from(vm, vm.argument(0)));
auto atomic_and = [](auto* storage, auto value) { return AK::atomic_fetch_and(storage, value); }; auto atomic_and = [](auto* storage, auto value) { return AK::atomic_fetch_and(storage, value); };
@ -269,7 +269,7 @@ static ThrowCompletionOr<Value> atomic_compare_exchange_impl(GlobalObject& globa
// 25.4.5 Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue ), https://tc39.es/ecma262/#sec-atomics.compareexchange // 25.4.5 Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue ), https://tc39.es/ecma262/#sec-atomics.compareexchange
JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::compare_exchange) JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::compare_exchange)
{ {
auto* typed_array = TRY(typed_array_from(global_object, vm.argument(0))); auto* typed_array = TRY(typed_array_from(vm, vm.argument(0)));
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, Type) \ #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, Type) \
if (is<ClassName>(typed_array)) \ if (is<ClassName>(typed_array)) \
@ -283,7 +283,7 @@ JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::compare_exchange)
// 25.4.6 Atomics.exchange ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.exchange // 25.4.6 Atomics.exchange ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.exchange
JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::exchange) JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::exchange)
{ {
auto* typed_array = TRY(typed_array_from(global_object, vm.argument(0))); auto* typed_array = TRY(typed_array_from(vm, vm.argument(0)));
auto atomic_exchange = [](auto* storage, auto value) { return AK::atomic_exchange(storage, value); }; auto atomic_exchange = [](auto* storage, auto value) { return AK::atomic_exchange(storage, value); };
@ -315,7 +315,7 @@ JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::is_lock_free)
JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::load) JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::load)
{ {
// 1. Let buffer be ? ValidateIntegerTypedArray(typedArray). // 1. Let buffer be ? ValidateIntegerTypedArray(typedArray).
auto* typed_array = TRY(typed_array_from(global_object, vm.argument(0))); auto* typed_array = TRY(typed_array_from(vm, vm.argument(0)));
TRY(validate_integer_typed_array(global_object, *typed_array)); TRY(validate_integer_typed_array(global_object, *typed_array));
// 2. Let indexedPosition be ? ValidateAtomicAccess(typedArray, index). // 2. Let indexedPosition be ? ValidateAtomicAccess(typedArray, index).
@ -335,7 +335,7 @@ JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::load)
// 25.4.9 Atomics.or ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.or // 25.4.9 Atomics.or ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.or
JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::or_) JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::or_)
{ {
auto* typed_array = TRY(typed_array_from(global_object, vm.argument(0))); auto* typed_array = TRY(typed_array_from(vm, vm.argument(0)));
auto atomic_or = [](auto* storage, auto value) { return AK::atomic_fetch_or(storage, value); }; auto atomic_or = [](auto* storage, auto value) { return AK::atomic_fetch_or(storage, value); };
@ -352,7 +352,7 @@ JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::or_)
JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::store) JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::store)
{ {
// 1. Let buffer be ? ValidateIntegerTypedArray(typedArray). // 1. Let buffer be ? ValidateIntegerTypedArray(typedArray).
auto* typed_array = TRY(typed_array_from(global_object, vm.argument(0))); auto* typed_array = TRY(typed_array_from(vm, vm.argument(0)));
TRY(validate_integer_typed_array(global_object, *typed_array)); TRY(validate_integer_typed_array(global_object, *typed_array));
// 2. Let indexedPosition be ? ValidateAtomicAccess(typedArray, index). // 2. Let indexedPosition be ? ValidateAtomicAccess(typedArray, index).
@ -385,7 +385,7 @@ JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::store)
// 25.4.11 Atomics.sub ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.sub // 25.4.11 Atomics.sub ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.sub
JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::sub) JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::sub)
{ {
auto* typed_array = TRY(typed_array_from(global_object, vm.argument(0))); auto* typed_array = TRY(typed_array_from(vm, vm.argument(0)));
auto atomic_sub = [](auto* storage, auto value) { return AK::atomic_fetch_sub(storage, value); }; auto atomic_sub = [](auto* storage, auto value) { return AK::atomic_fetch_sub(storage, value); };
@ -401,7 +401,7 @@ JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::sub)
// 25.4.14 Atomics.xor ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.xor // 25.4.14 Atomics.xor ( typedArray, index, value ), https://tc39.es/ecma262/#sec-atomics.xor
JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::xor_) JS_DEFINE_NATIVE_FUNCTION(AtomicsObject::xor_)
{ {
auto* typed_array = TRY(typed_array_from(global_object, vm.argument(0))); auto* typed_array = TRY(typed_array_from(vm, vm.argument(0)));
auto atomic_xor = [](auto* storage, auto value) { return AK::atomic_fetch_xor(storage, value); }; auto atomic_xor = [](auto* storage, auto value) { return AK::atomic_fetch_xor(storage, value); };

View file

@ -17,10 +17,8 @@
namespace JS { namespace JS {
ThrowCompletionOr<TypedArrayBase*> typed_array_from(GlobalObject& global_object, Value typed_array_value) ThrowCompletionOr<TypedArrayBase*> typed_array_from(VM& vm, Value typed_array_value)
{ {
auto& vm = global_object.vm();
auto* this_object = TRY(typed_array_value.to_object(vm)); auto* this_object = TRY(typed_array_value.to_object(vm));
if (!this_object->is_typed_array()) if (!this_object->is_typed_array())
return vm.throw_completion<TypeError>(ErrorType::NotAnObjectOfType, "TypedArray"); return vm.throw_completion<TypeError>(ErrorType::NotAnObjectOfType, "TypedArray");
@ -29,10 +27,8 @@ ThrowCompletionOr<TypedArrayBase*> typed_array_from(GlobalObject& global_object,
} }
// 23.2.4.3 ValidateTypedArray ( O ), https://tc39.es/ecma262/#sec-validatetypedarray // 23.2.4.3 ValidateTypedArray ( O ), https://tc39.es/ecma262/#sec-validatetypedarray
ThrowCompletionOr<void> validate_typed_array(GlobalObject& global_object, TypedArrayBase& typed_array) ThrowCompletionOr<void> validate_typed_array(VM& vm, TypedArrayBase& typed_array)
{ {
auto& vm = global_object.vm();
// 1. Perform ? RequireInternalSlot(O, [[TypedArrayName]]). // 1. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
if (!typed_array.is_typed_array()) if (!typed_array.is_typed_array())
return vm.throw_completion<TypeError>(ErrorType::NotAnObjectOfType, "TypedArray"); return vm.throw_completion<TypeError>(ErrorType::NotAnObjectOfType, "TypedArray");
@ -50,10 +46,8 @@ ThrowCompletionOr<void> validate_typed_array(GlobalObject& global_object, TypedA
} }
// 22.2.5.1.3 InitializeTypedArrayFromArrayBuffer, https://tc39.es/ecma262/#sec-initializetypedarrayfromarraybuffer // 22.2.5.1.3 InitializeTypedArrayFromArrayBuffer, https://tc39.es/ecma262/#sec-initializetypedarrayfromarraybuffer
static ThrowCompletionOr<void> initialize_typed_array_from_array_buffer(GlobalObject& global_object, TypedArrayBase& typed_array, ArrayBuffer& array_buffer, Value byte_offset, Value length) static ThrowCompletionOr<void> initialize_typed_array_from_array_buffer(VM& vm, TypedArrayBase& typed_array, ArrayBuffer& array_buffer, Value byte_offset, Value length)
{ {
auto& vm = global_object.vm();
// 1. Let elementSize be TypedArrayElementSize(O). // 1. Let elementSize be TypedArrayElementSize(O).
auto element_size = typed_array.element_size(); auto element_size = typed_array.element_size();
@ -132,9 +126,10 @@ static ThrowCompletionOr<void> initialize_typed_array_from_array_buffer(GlobalOb
// 23.2.5.1.2 InitializeTypedArrayFromTypedArray ( O, srcArray ), https://tc39.es/ecma262/#sec-initializetypedarrayfromtypedarray // 23.2.5.1.2 InitializeTypedArrayFromTypedArray ( O, srcArray ), https://tc39.es/ecma262/#sec-initializetypedarrayfromtypedarray
template<typename T> template<typename T>
static ThrowCompletionOr<void> initialize_typed_array_from_typed_array(GlobalObject& global_object, TypedArray<T>& dest_array, TypedArrayBase& src_array) static ThrowCompletionOr<void> initialize_typed_array_from_typed_array(VM& vm, TypedArray<T>& dest_array, TypedArrayBase& src_array)
{ {
auto& vm = global_object.vm(); auto& realm = *vm.current_realm();
auto& global_object = realm.global_object();
// 1. Let srcData be srcArray.[[ViewedArrayBuffer]]. // 1. Let srcData be srcArray.[[ViewedArrayBuffer]].
auto* src_data = src_array.viewed_array_buffer(); auto* src_data = src_array.viewed_array_buffer();
@ -227,9 +222,10 @@ static ThrowCompletionOr<void> initialize_typed_array_from_typed_array(GlobalObj
// 23.2.5.1.6 AllocateTypedArrayBuffer ( O, length ), https://tc39.es/ecma262/#sec-allocatetypedarraybuffer // 23.2.5.1.6 AllocateTypedArrayBuffer ( O, length ), https://tc39.es/ecma262/#sec-allocatetypedarraybuffer
template<typename T> template<typename T>
static ThrowCompletionOr<void> allocate_typed_array_buffer(GlobalObject& global_object, TypedArray<T>& typed_array, size_t length) static ThrowCompletionOr<void> allocate_typed_array_buffer(VM& vm, TypedArray<T>& typed_array, size_t length)
{ {
auto& vm = global_object.vm(); auto& realm = *vm.current_realm();
auto& global_object = realm.global_object();
// Enforce 2GB "Excessive Length" limit // Enforce 2GB "Excessive Length" limit
if (length > NumericLimits<i32>::max() / sizeof(T)) if (length > NumericLimits<i32>::max() / sizeof(T))
@ -266,13 +262,16 @@ static ThrowCompletionOr<void> allocate_typed_array_buffer(GlobalObject& global_
// 23.2.5.1.5 InitializeTypedArrayFromArrayLike, https://tc39.es/ecma262/#sec-initializetypedarrayfromarraylike // 23.2.5.1.5 InitializeTypedArrayFromArrayLike, https://tc39.es/ecma262/#sec-initializetypedarrayfromarraylike
template<typename T> template<typename T>
static ThrowCompletionOr<void> initialize_typed_array_from_array_like(GlobalObject& global_object, TypedArray<T>& typed_array, Object const& array_like) static ThrowCompletionOr<void> initialize_typed_array_from_array_like(VM& vm, TypedArray<T>& typed_array, Object const& array_like)
{ {
auto& realm = *vm.current_realm();
auto& global_object = realm.global_object();
// 1. Let len be ? LengthOfArrayLike(arrayLike). // 1. Let len be ? LengthOfArrayLike(arrayLike).
auto length = TRY(length_of_array_like(global_object, array_like)); auto length = TRY(length_of_array_like(global_object, array_like));
// 2. Perform ? AllocateTypedArrayBuffer(O, len). // 2. Perform ? AllocateTypedArrayBuffer(O, len).
TRY(allocate_typed_array_buffer(global_object, typed_array, length)); TRY(allocate_typed_array_buffer(vm, typed_array, length));
// 3. Let k be 0. // 3. Let k be 0.
// 4. Repeat, while k < len, // 4. Repeat, while k < len,
@ -293,13 +292,13 @@ static ThrowCompletionOr<void> initialize_typed_array_from_array_like(GlobalObje
// 23.2.5.1.4 InitializeTypedArrayFromList, https://tc39.es/ecma262/#sec-initializetypedarrayfromlist // 23.2.5.1.4 InitializeTypedArrayFromList, https://tc39.es/ecma262/#sec-initializetypedarrayfromlist
template<typename T> template<typename T>
static ThrowCompletionOr<void> initialize_typed_array_from_list(GlobalObject& global_object, TypedArray<T>& typed_array, MarkedVector<Value> const& list) static ThrowCompletionOr<void> initialize_typed_array_from_list(VM& vm, TypedArray<T>& typed_array, MarkedVector<Value> const& list)
{ {
// 1. Let len be the number of elements in values. // 1. Let len be the number of elements in values.
auto length = list.size(); auto length = list.size();
// 2. Perform ? AllocateTypedArrayBuffer(O, len). // 2. Perform ? AllocateTypedArrayBuffer(O, len).
TRY(allocate_typed_array_buffer(global_object, typed_array, length)); TRY(allocate_typed_array_buffer(vm, typed_array, length));
// 3. Let k be 0. // 3. Let k be 0.
// 4. Repeat, while k < len, // 4. Repeat, while k < len,
@ -320,9 +319,10 @@ static ThrowCompletionOr<void> initialize_typed_array_from_list(GlobalObject& gl
} }
// 23.2.4.2 TypedArrayCreate ( constructor, argumentList ), https://tc39.es/ecma262/#typedarray-create // 23.2.4.2 TypedArrayCreate ( constructor, argumentList ), https://tc39.es/ecma262/#typedarray-create
ThrowCompletionOr<TypedArrayBase*> typed_array_create(GlobalObject& global_object, FunctionObject& constructor, MarkedVector<Value> arguments) ThrowCompletionOr<TypedArrayBase*> typed_array_create(VM& vm, FunctionObject& constructor, MarkedVector<Value> arguments)
{ {
auto& vm = global_object.vm(); auto& realm = *vm.current_realm();
auto& global_object = realm.global_object();
Optional<Value> first_argument; Optional<Value> first_argument;
if (!arguments.is_empty()) if (!arguments.is_empty())
@ -334,7 +334,7 @@ ThrowCompletionOr<TypedArrayBase*> typed_array_create(GlobalObject& global_objec
if (!new_typed_array->is_typed_array()) if (!new_typed_array->is_typed_array())
return vm.throw_completion<TypeError>(ErrorType::NotAnObjectOfType, "TypedArray"); return vm.throw_completion<TypeError>(ErrorType::NotAnObjectOfType, "TypedArray");
auto& typed_array = *static_cast<TypedArrayBase*>(new_typed_array); auto& typed_array = *static_cast<TypedArrayBase*>(new_typed_array);
TRY(validate_typed_array(global_object, typed_array)); TRY(validate_typed_array(vm, typed_array));
// 3. If argumentList is a List of a single Number, then // 3. If argumentList is a List of a single Number, then
if (first_argument.has_value() && first_argument->is_number()) { if (first_argument.has_value() && first_argument->is_number()) {
@ -348,14 +348,17 @@ ThrowCompletionOr<TypedArrayBase*> typed_array_create(GlobalObject& global_objec
} }
// 1.2.1.1 TypedArrayCreateSameType ( exemplar, argumentList ) https://tc39.es/proposal-change-array-by-copy/#typedarray-create-same-type // 1.2.1.1 TypedArrayCreateSameType ( exemplar, argumentList ) https://tc39.es/proposal-change-array-by-copy/#typedarray-create-same-type
ThrowCompletionOr<TypedArrayBase*> typed_array_create_same_type(GlobalObject& global_object, TypedArrayBase const& exemplar, MarkedVector<Value> arguments) ThrowCompletionOr<TypedArrayBase*> typed_array_create_same_type(VM& vm, TypedArrayBase const& exemplar, MarkedVector<Value> arguments)
{ {
auto& realm = *vm.current_realm();
auto& global_object = realm.global_object();
// 1. Assert: exemplar is an Object that has [[TypedArrayName]] and [[ContentType]] internal slots. // 1. Assert: exemplar is an Object that has [[TypedArrayName]] and [[ContentType]] internal slots.
// 2. Let constructor be the intrinsic object listed in column one of Table 63 (points to Table 72) for exemplar.[[TypedArrayName]]. // 2. Let constructor be the intrinsic object listed in column one of Table 63 (points to Table 72) for exemplar.[[TypedArrayName]].
auto* constructor = (global_object.*exemplar.intrinsic_constructor())(); auto* constructor = (global_object.*exemplar.intrinsic_constructor())();
// 3. Let result be ? TypedArrayCreate(constructor, argumentList). // 3. Let result be ? TypedArrayCreate(constructor, argumentList).
auto* result = TRY(typed_array_create(global_object, *constructor, move(arguments))); auto* result = TRY(typed_array_create(vm, *constructor, move(arguments)));
// 4. Assert: result has [[TypedArrayName]] and [[ContentType]] internal slots. // 4. Assert: result has [[TypedArrayName]] and [[ContentType]] internal slots.
// 5. Assert: result.[[ContentType]] is exemplar.[[ContentType]]. // 5. Assert: result.[[ContentType]] is exemplar.[[ContentType]].
@ -364,9 +367,11 @@ ThrowCompletionOr<TypedArrayBase*> typed_array_create_same_type(GlobalObject& gl
} }
// 1.2.2.1.2 CompareTypedArrayElements ( x, y, comparefn, buffer ), https://tc39.es/proposal-change-array-by-copy/#sec-comparetypedarrayelements // 1.2.2.1.2 CompareTypedArrayElements ( x, y, comparefn, buffer ), https://tc39.es/proposal-change-array-by-copy/#sec-comparetypedarrayelements
ThrowCompletionOr<double> compare_typed_array_elements(GlobalObject& global_object, Value x, Value y, FunctionObject* comparefn, ArrayBuffer& buffer) ThrowCompletionOr<double> compare_typed_array_elements(VM& vm, Value x, Value y, FunctionObject* comparefn, ArrayBuffer& buffer)
{ {
auto& vm = global_object.vm(); auto& realm = *vm.current_realm();
auto& global_object = realm.global_object();
// 1. Assert: Both Type(x) and Type(y) are Number or both are BigInt. // 1. Assert: Both Type(x) and Type(y) are Number or both are BigInt.
VERIFY(((x.is_number() && y.is_number()) || (x.is_bigint() && y.is_bigint()))); VERIFY(((x.is_number() && y.is_number()) || (x.is_bigint() && y.is_bigint())));
@ -530,18 +535,18 @@ void TypedArrayBase::visit_edges(Visitor& visitor)
auto* typed_array = TRY(ClassName::create(realm, 0, new_target)); \ auto* typed_array = TRY(ClassName::create(realm, 0, new_target)); \
if (first_argument.as_object().is_typed_array()) { \ if (first_argument.as_object().is_typed_array()) { \
auto& arg_typed_array = static_cast<TypedArrayBase&>(first_argument.as_object()); \ auto& arg_typed_array = static_cast<TypedArrayBase&>(first_argument.as_object()); \
TRY(initialize_typed_array_from_typed_array(global_object, *typed_array, arg_typed_array)); \ TRY(initialize_typed_array_from_typed_array(vm, *typed_array, arg_typed_array)); \
} else if (is<ArrayBuffer>(first_argument.as_object())) { \ } else if (is<ArrayBuffer>(first_argument.as_object())) { \
auto& array_buffer = static_cast<ArrayBuffer&>(first_argument.as_object()); \ auto& array_buffer = static_cast<ArrayBuffer&>(first_argument.as_object()); \
TRY(initialize_typed_array_from_array_buffer(global_object, *typed_array, array_buffer, \ TRY(initialize_typed_array_from_array_buffer(vm, *typed_array, array_buffer, \
vm.argument(1), vm.argument(2))); \ vm.argument(1), vm.argument(2))); \
} else { \ } else { \
auto iterator = TRY(first_argument.get_method(vm, *vm.well_known_symbol_iterator())); \ auto iterator = TRY(first_argument.get_method(vm, *vm.well_known_symbol_iterator())); \
if (iterator) { \ if (iterator) { \
auto values = TRY(iterable_to_list(vm, first_argument, iterator)); \ auto values = TRY(iterable_to_list(vm, first_argument, iterator)); \
TRY(initialize_typed_array_from_list(global_object, *typed_array, values)); \ TRY(initialize_typed_array_from_list(vm, *typed_array, values)); \
} else { \ } else { \
TRY(initialize_typed_array_from_array_like(global_object, *typed_array, first_argument.as_object())); \ TRY(initialize_typed_array_from_array_like(vm, *typed_array, first_argument.as_object())); \
} \ } \
} \ } \
return typed_array; \ return typed_array; \

View file

@ -20,8 +20,8 @@ namespace JS {
class TypedArrayBase; class TypedArrayBase;
ThrowCompletionOr<TypedArrayBase*> typed_array_from(GlobalObject&, Value); ThrowCompletionOr<TypedArrayBase*> typed_array_from(VM&, Value);
ThrowCompletionOr<void> validate_typed_array(GlobalObject&, TypedArrayBase&); ThrowCompletionOr<void> validate_typed_array(VM&, TypedArrayBase&);
class TypedArrayBase : public Object { class TypedArrayBase : public Object {
JS_OBJECT(TypedArrayBase, Object); JS_OBJECT(TypedArrayBase, Object);
@ -450,9 +450,9 @@ private:
virtual bool is_typed_array() const final { return true; } virtual bool is_typed_array() const final { return true; }
}; };
ThrowCompletionOr<TypedArrayBase*> typed_array_create(GlobalObject& global_object, FunctionObject& constructor, MarkedVector<Value> arguments); ThrowCompletionOr<TypedArrayBase*> typed_array_create(VM&, FunctionObject& constructor, MarkedVector<Value> arguments);
ThrowCompletionOr<TypedArrayBase*> typed_array_create_same_type(GlobalObject& global_object, TypedArrayBase const& exemplar, MarkedVector<Value> arguments); ThrowCompletionOr<TypedArrayBase*> typed_array_create_same_type(VM&, TypedArrayBase const& exemplar, MarkedVector<Value> arguments);
ThrowCompletionOr<double> compare_typed_array_elements(GlobalObject& global_object, Value x, Value y, FunctionObject* comparefn, ArrayBuffer&); ThrowCompletionOr<double> compare_typed_array_elements(VM&, Value x, Value y, FunctionObject* comparefn, ArrayBuffer&);
#define JS_DECLARE_TYPED_ARRAY(ClassName, snake_name, PrototypeName, ConstructorName, Type) \ #define JS_DECLARE_TYPED_ARRAY(ClassName, snake_name, PrototypeName, ConstructorName, Type) \
class ClassName : public TypedArray<Type> { \ class ClassName : public TypedArray<Type> { \

View file

@ -74,7 +74,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayConstructor::from)
MarkedVector<Value> arguments(vm.heap()); MarkedVector<Value> arguments(vm.heap());
arguments.empend(values.size()); arguments.empend(values.size());
auto target_object = TRY(typed_array_create(global_object, constructor.as_function(), move(arguments))); auto target_object = TRY(typed_array_create(vm, constructor.as_function(), move(arguments)));
for (size_t k = 0; k < values.size(); ++k) { for (size_t k = 0; k < values.size(); ++k) {
auto k_value = values[k]; auto k_value = values[k];
@ -94,7 +94,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayConstructor::from)
MarkedVector<Value> arguments(vm.heap()); MarkedVector<Value> arguments(vm.heap());
arguments.empend(length); arguments.empend(length);
auto target_object = TRY(typed_array_create(global_object, constructor.as_function(), move(arguments))); auto target_object = TRY(typed_array_create(vm, constructor.as_function(), move(arguments)));
for (size_t k = 0; k < length; ++k) { for (size_t k = 0; k < length; ++k) {
auto k_value = TRY(array_like->get(k)); auto k_value = TRY(array_like->get(k));
@ -118,7 +118,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayConstructor::of)
return vm.throw_completion<TypeError>(ErrorType::NotAConstructor, constructor.to_string_without_side_effects()); return vm.throw_completion<TypeError>(ErrorType::NotAConstructor, constructor.to_string_without_side_effects());
MarkedVector<Value> arguments(vm.heap()); MarkedVector<Value> arguments(vm.heap());
arguments.append(Value(length)); arguments.append(Value(length));
auto new_object = TRY(typed_array_create(global_object, constructor.as_function(), move(arguments))); auto new_object = TRY(typed_array_create(vm, constructor.as_function(), move(arguments)));
for (size_t k = 0; k < length; ++k) for (size_t k = 0; k < length; ++k)
TRY(new_object->set(k, vm.argument(k), Object::ShouldThrowExceptions::Yes)); TRY(new_object->set(k, vm.argument(k), Object::ShouldThrowExceptions::Yes));
return new_object; return new_object;

View file

@ -71,24 +71,23 @@ void TypedArrayPrototype::initialize(Realm& realm)
define_direct_property(*vm.well_known_symbol_iterator(), get_without_side_effects(vm.names.values), attr); define_direct_property(*vm.well_known_symbol_iterator(), get_without_side_effects(vm.names.values), attr);
} }
static ThrowCompletionOr<TypedArrayBase*> typed_array_from_this(GlobalObject& global_object) static ThrowCompletionOr<TypedArrayBase*> typed_array_from_this(VM& vm)
{ {
auto this_value = global_object.vm().this_value(); auto this_value = vm.this_value();
return typed_array_from(global_object, this_value); return typed_array_from(vm, this_value);
} }
static ThrowCompletionOr<TypedArrayBase*> validate_typed_array_from_this(GlobalObject& global_object) static ThrowCompletionOr<TypedArrayBase*> validate_typed_array_from_this(VM& vm)
{ {
auto* typed_array = TRY(typed_array_from_this(global_object)); auto* typed_array = TRY(typed_array_from_this(vm));
TRY(validate_typed_array(global_object, *typed_array)); TRY(validate_typed_array(vm, *typed_array));
return typed_array; return typed_array;
} }
static ThrowCompletionOr<FunctionObject*> callback_from_args(GlobalObject& global_object, String const& name) static ThrowCompletionOr<FunctionObject*> callback_from_args(VM& vm, String const& name)
{ {
auto& vm = global_object.vm();
if (vm.argument_count() < 1) if (vm.argument_count() < 1)
return vm.throw_completion<TypeError>(ErrorType::TypedArrayPrototypeOneArg, name); return vm.throw_completion<TypeError>(ErrorType::TypedArrayPrototypeOneArg, name);
auto callback = vm.argument(0); auto callback = vm.argument(0);
@ -97,13 +96,16 @@ static ThrowCompletionOr<FunctionObject*> callback_from_args(GlobalObject& globa
return &callback.as_function(); return &callback.as_function();
} }
static ThrowCompletionOr<void> for_each_item(VM& vm, GlobalObject& global_object, String const& name, Function<IterationDecision(size_t index, Value value, Value callback_result)> callback) static ThrowCompletionOr<void> for_each_item(VM& vm, String const& name, Function<IterationDecision(size_t index, Value value, Value callback_result)> callback)
{ {
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto& realm = *vm.current_realm();
auto& global_object = realm.global_object();
auto* typed_array = TRY(validate_typed_array_from_this(vm));
auto initial_length = typed_array->array_length(); auto initial_length = typed_array->array_length();
auto* callback_function = TRY(callback_from_args(global_object, name)); auto* callback_function = TRY(callback_from_args(vm, name));
auto this_value = vm.argument(1); auto this_value = vm.argument(1);
@ -119,13 +121,16 @@ static ThrowCompletionOr<void> for_each_item(VM& vm, GlobalObject& global_object
return {}; return {};
} }
static ThrowCompletionOr<void> for_each_item_from_last(VM& vm, GlobalObject& global_object, String const& name, Function<IterationDecision(size_t index, Value value, Value callback_result)> callback) static ThrowCompletionOr<void> for_each_item_from_last(VM& vm, String const& name, Function<IterationDecision(size_t index, Value value, Value callback_result)> callback)
{ {
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto& realm = *vm.current_realm();
auto& global_object = realm.global_object();
auto* typed_array = TRY(validate_typed_array_from_this(vm));
auto initial_length = typed_array->array_length(); auto initial_length = typed_array->array_length();
auto* callback_function = TRY(callback_from_args(global_object, name)); auto* callback_function = TRY(callback_from_args(vm, name));
auto this_value = vm.argument(1); auto this_value = vm.argument(1);
@ -142,9 +147,10 @@ static ThrowCompletionOr<void> for_each_item_from_last(VM& vm, GlobalObject& glo
} }
// 23.2.4.1 TypedArraySpeciesCreate ( exemplar, argumentList ), https://tc39.es/ecma262/#typedarray-species-create // 23.2.4.1 TypedArraySpeciesCreate ( exemplar, argumentList ), https://tc39.es/ecma262/#typedarray-species-create
static ThrowCompletionOr<TypedArrayBase*> typed_array_species_create(GlobalObject& global_object, TypedArrayBase const& exemplar, MarkedVector<Value> arguments) static ThrowCompletionOr<TypedArrayBase*> typed_array_species_create(VM& vm, TypedArrayBase const& exemplar, MarkedVector<Value> arguments)
{ {
auto& vm = global_object.vm(); auto& realm = *vm.current_realm();
auto& global_object = realm.global_object();
// 1. Let defaultConstructor be the intrinsic object listed in column one of Table 72 for exemplar.[[TypedArrayName]]. // 1. Let defaultConstructor be the intrinsic object listed in column one of Table 72 for exemplar.[[TypedArrayName]].
auto* default_constructor = (global_object.*exemplar.intrinsic_constructor())(); auto* default_constructor = (global_object.*exemplar.intrinsic_constructor())();
@ -153,7 +159,7 @@ static ThrowCompletionOr<TypedArrayBase*> typed_array_species_create(GlobalObjec
auto* constructor = TRY(species_constructor(global_object, exemplar, *default_constructor)); auto* constructor = TRY(species_constructor(global_object, exemplar, *default_constructor));
// 3. Let result be ? TypedArrayCreate(constructor, argumentList). // 3. Let result be ? TypedArrayCreate(constructor, argumentList).
auto* result = TRY(typed_array_create(global_object, *constructor, move(arguments))); auto* result = TRY(typed_array_create(vm, *constructor, move(arguments)));
// 4. Assert: result has [[TypedArrayName]] and [[ContentType]] internal slots. // 4. Assert: result has [[TypedArrayName]] and [[ContentType]] internal slots.
// 5. If result.[[ContentType]] ≠ exemplar.[[ContentType]], throw a TypeError exception. // 5. If result.[[ContentType]] ≠ exemplar.[[ContentType]], throw a TypeError exception.
@ -167,7 +173,7 @@ static ThrowCompletionOr<TypedArrayBase*> typed_array_species_create(GlobalObjec
// 23.2.3.1 %TypedArray%.prototype.at ( index ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.at // 23.2.3.1 %TypedArray%.prototype.at ( index ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.at
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::at) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::at)
{ {
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(vm));
auto length = typed_array->array_length(); auto length = typed_array->array_length();
auto relative_index = TRY(vm.argument(0).to_integer_or_infinity(vm)); auto relative_index = TRY(vm.argument(0).to_integer_or_infinity(vm));
if (Value(relative_index).is_infinity()) if (Value(relative_index).is_infinity())
@ -187,7 +193,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::at)
// 23.2.3.2 get %TypedArray%.prototype.buffer, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.buffer // 23.2.3.2 get %TypedArray%.prototype.buffer, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.buffer
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::buffer_getter) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::buffer_getter)
{ {
auto* typed_array = TRY(typed_array_from_this(global_object)); auto* typed_array = TRY(typed_array_from_this(vm));
auto* array_buffer = typed_array->viewed_array_buffer(); auto* array_buffer = typed_array->viewed_array_buffer();
VERIFY(array_buffer); VERIFY(array_buffer);
return Value(array_buffer); return Value(array_buffer);
@ -196,7 +202,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::buffer_getter)
// 23.2.3.3 get %TypedArray%.prototype.byteLength, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.bytelength // 23.2.3.3 get %TypedArray%.prototype.byteLength, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.bytelength
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::byte_length_getter) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::byte_length_getter)
{ {
auto* typed_array = TRY(typed_array_from_this(global_object)); auto* typed_array = TRY(typed_array_from_this(vm));
auto* array_buffer = typed_array->viewed_array_buffer(); auto* array_buffer = typed_array->viewed_array_buffer();
VERIFY(array_buffer); VERIFY(array_buffer);
if (array_buffer->is_detached()) if (array_buffer->is_detached())
@ -207,7 +213,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::byte_length_getter)
// 23.2.3.4 get %TypedArray%.prototype.byteOffset, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.byteoffset // 23.2.3.4 get %TypedArray%.prototype.byteOffset, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.byteoffset
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::byte_offset_getter) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::byte_offset_getter)
{ {
auto* typed_array = TRY(typed_array_from_this(global_object)); auto* typed_array = TRY(typed_array_from_this(vm));
auto* array_buffer = typed_array->viewed_array_buffer(); auto* array_buffer = typed_array->viewed_array_buffer();
VERIFY(array_buffer); VERIFY(array_buffer);
if (array_buffer->is_detached()) if (array_buffer->is_detached())
@ -220,7 +226,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::copy_within)
{ {
// 1. Let O be the this value. // 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O). // 2. Perform ? ValidateTypedArray(O).
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(vm));
// 3. Let len be O.[[ArrayLength]]. // 3. Let len be O.[[ArrayLength]].
auto length = typed_array->array_length(); auto length = typed_array->array_length();
@ -388,7 +394,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::entries)
{ {
auto& realm = *global_object.associated_realm(); auto& realm = *global_object.associated_realm();
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(vm));
return ArrayIterator::create(realm, typed_array, Object::PropertyKind::KeyAndValue); return ArrayIterator::create(realm, typed_array, Object::PropertyKind::KeyAndValue);
} }
@ -396,7 +402,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::entries)
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::every) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::every)
{ {
auto result = true; auto result = true;
TRY(for_each_item(vm, global_object, "every", [&](auto, auto, auto callback_result) { TRY(for_each_item(vm, "every", [&](auto, auto, auto callback_result) {
if (!callback_result.to_boolean()) { if (!callback_result.to_boolean()) {
result = false; result = false;
return IterationDecision::Break; return IterationDecision::Break;
@ -409,7 +415,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::every)
// 23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.fill // 23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.fill
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::fill) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::fill)
{ {
auto typed_array = TRY(validate_typed_array_from_this(global_object)); auto typed_array = TRY(validate_typed_array_from_this(vm));
auto length = typed_array->array_length(); auto length = typed_array->array_length();
@ -457,13 +463,13 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::filter)
{ {
// 1. Let O be the this value. // 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O). // 2. Perform ? ValidateTypedArray(O).
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(vm));
// 3. Let len be O.[[ArrayLength]]. // 3. Let len be O.[[ArrayLength]].
auto initial_length = typed_array->array_length(); auto initial_length = typed_array->array_length();
// 4. If IsCallable(callbackfn) is false, throw a TypeError exception. // 4. If IsCallable(callbackfn) is false, throw a TypeError exception.
auto* callback_function = TRY(callback_from_args(global_object, "filter")); auto* callback_function = TRY(callback_from_args(vm, "filter"));
// 5. Let kept be a new empty List. // 5. Let kept be a new empty List.
MarkedVector<Value> kept(vm.heap()); MarkedVector<Value> kept(vm.heap());
@ -498,7 +504,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::filter)
// 9. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(captured) »). // 9. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(captured) »).
MarkedVector<Value> arguments(vm.heap()); MarkedVector<Value> arguments(vm.heap());
arguments.empend(captured); arguments.empend(captured);
auto* filter_array = TRY(typed_array_species_create(global_object, *typed_array, move(arguments))); auto* filter_array = TRY(typed_array_species_create(vm, *typed_array, move(arguments)));
// 10. Let n be 0. // 10. Let n be 0.
size_t index = 0; size_t index = 0;
@ -520,7 +526,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::filter)
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find)
{ {
auto result = js_undefined(); auto result = js_undefined();
TRY(for_each_item(vm, global_object, "find", [&](auto, auto value, auto callback_result) { TRY(for_each_item(vm, "find", [&](auto, auto value, auto callback_result) {
if (callback_result.to_boolean()) { if (callback_result.to_boolean()) {
result = value; result = value;
return IterationDecision::Break; return IterationDecision::Break;
@ -534,7 +540,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find)
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find_index) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find_index)
{ {
auto result_index = -1; auto result_index = -1;
TRY(for_each_item(vm, global_object, "findIndex", [&](auto index, auto, auto callback_result) { TRY(for_each_item(vm, "findIndex", [&](auto index, auto, auto callback_result) {
if (callback_result.to_boolean()) { if (callback_result.to_boolean()) {
result_index = index; result_index = index;
return IterationDecision::Break; return IterationDecision::Break;
@ -548,7 +554,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find_index)
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find_last) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find_last)
{ {
auto result = js_undefined(); auto result = js_undefined();
TRY(for_each_item_from_last(vm, global_object, "findLast", [&](auto, auto value, auto callback_result) { TRY(for_each_item_from_last(vm, "findLast", [&](auto, auto value, auto callback_result) {
if (callback_result.to_boolean()) { if (callback_result.to_boolean()) {
result = value; result = value;
return IterationDecision::Break; return IterationDecision::Break;
@ -562,7 +568,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find_last)
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find_last_index) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find_last_index)
{ {
auto result_index = -1; auto result_index = -1;
TRY(for_each_item_from_last(vm, global_object, "findLastIndex", [&](auto index, auto, auto callback_result) { TRY(for_each_item_from_last(vm, "findLastIndex", [&](auto index, auto, auto callback_result) {
if (callback_result.to_boolean()) { if (callback_result.to_boolean()) {
result_index = index; result_index = index;
return IterationDecision::Break; return IterationDecision::Break;
@ -575,7 +581,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::find_last_index)
// 23.2.3.15 %TypedArray%.prototype.forEach ( callbackfn [ , thisArg ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.foreach // 23.2.3.15 %TypedArray%.prototype.forEach ( callbackfn [ , thisArg ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.foreach
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::for_each) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::for_each)
{ {
TRY(for_each_item(vm, global_object, "forEach", [](auto, auto, auto) { TRY(for_each_item(vm, "forEach", [](auto, auto, auto) {
return IterationDecision::Continue; return IterationDecision::Continue;
})); }));
return js_undefined(); return js_undefined();
@ -584,7 +590,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::for_each)
// 23.2.3.16 %TypedArray%.prototype.includes ( searchElement [ , fromIndex ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.includes // 23.2.3.16 %TypedArray%.prototype.includes ( searchElement [ , fromIndex ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.includes
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::includes) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::includes)
{ {
auto typed_array = TRY(validate_typed_array_from_this(global_object)); auto typed_array = TRY(validate_typed_array_from_this(vm));
auto length = typed_array->array_length(); auto length = typed_array->array_length();
@ -623,7 +629,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::includes)
// 23.2.3.17 %TypedArray%.prototype.indexOf ( searchElement [ , fromIndex ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.indexof // 23.2.3.17 %TypedArray%.prototype.indexOf ( searchElement [ , fromIndex ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.indexof
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::index_of) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::index_of)
{ {
auto typed_array = TRY(validate_typed_array_from_this(global_object)); auto typed_array = TRY(validate_typed_array_from_this(vm));
auto length = typed_array->array_length(); auto length = typed_array->array_length();
@ -665,7 +671,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::index_of)
// 23.2.3.18 %TypedArray%.prototype.join ( separator ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.join // 23.2.3.18 %TypedArray%.prototype.join ( separator ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.join
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::join) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::join)
{ {
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(vm));
auto length = typed_array->array_length(); auto length = typed_array->array_length();
String separator = ","; String separator = ",";
if (!vm.argument(0).is_undefined()) if (!vm.argument(0).is_undefined())
@ -690,14 +696,14 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::keys)
{ {
auto& realm = *global_object.associated_realm(); auto& realm = *global_object.associated_realm();
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(vm));
return ArrayIterator::create(realm, typed_array, Object::PropertyKind::Key); return ArrayIterator::create(realm, typed_array, Object::PropertyKind::Key);
} }
// 23.2.3.20 %TypedArray%.prototype.lastIndexOf ( searchElement [ , fromIndex ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.lastindexof // 23.2.3.20 %TypedArray%.prototype.lastIndexOf ( searchElement [ , fromIndex ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.lastindexof
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::last_index_of) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::last_index_of)
{ {
auto typed_array = TRY(validate_typed_array_from_this(global_object)); auto typed_array = TRY(validate_typed_array_from_this(vm));
auto length = typed_array->array_length(); auto length = typed_array->array_length();
@ -740,7 +746,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::last_index_of)
// 23.2.3.21 get %TypedArray%.prototype.length, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.length // 23.2.3.21 get %TypedArray%.prototype.length, https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.length
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::length_getter) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::length_getter)
{ {
auto* typed_array = TRY(typed_array_from_this(global_object)); auto* typed_array = TRY(typed_array_from_this(vm));
auto* array_buffer = typed_array->viewed_array_buffer(); auto* array_buffer = typed_array->viewed_array_buffer();
VERIFY(array_buffer); VERIFY(array_buffer);
if (array_buffer->is_detached()) if (array_buffer->is_detached())
@ -753,18 +759,18 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::map)
{ {
// 1. Let O be the this value. // 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O). // 2. Perform ? ValidateTypedArray(O).
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(vm));
// 3. Let len be O.[[ArrayLength]]. // 3. Let len be O.[[ArrayLength]].
auto initial_length = typed_array->array_length(); auto initial_length = typed_array->array_length();
// 4. If IsCallable(callbackfn) is false, throw a TypeError exception. // 4. If IsCallable(callbackfn) is false, throw a TypeError exception.
auto* callback_function = TRY(callback_from_args(global_object, "map")); auto* callback_function = TRY(callback_from_args(vm, "map"));
// 5. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(len) »). // 5. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(len) »).
MarkedVector<Value> arguments(vm.heap()); MarkedVector<Value> arguments(vm.heap());
arguments.empend(initial_length); arguments.empend(initial_length);
auto* return_array = TRY(typed_array_species_create(global_object, *typed_array, move(arguments))); auto* return_array = TRY(typed_array_species_create(vm, *typed_array, move(arguments)));
auto this_value = vm.argument(1); auto this_value = vm.argument(1);
@ -791,11 +797,11 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::map)
// 23.2.3.23 %TypedArray%.prototype.reduce ( callbackfn [ , initialValue ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduce // 23.2.3.23 %TypedArray%.prototype.reduce ( callbackfn [ , initialValue ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduce
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reduce) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reduce)
{ {
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(vm));
auto length = typed_array->array_length(); auto length = typed_array->array_length();
auto* callback_function = TRY(callback_from_args(global_object, vm.names.reduce.as_string())); auto* callback_function = TRY(callback_from_args(vm, vm.names.reduce.as_string()));
if (length == 0 && vm.argument_count() <= 1) if (length == 0 && vm.argument_count() <= 1)
return vm.throw_completion<TypeError>(ErrorType::ReduceNoInitial); return vm.throw_completion<TypeError>(ErrorType::ReduceNoInitial);
@ -821,11 +827,11 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reduce)
// 23.2.3.24 %TypedArray%.prototype.reduceRight ( callbackfn [ , initialValue ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduce // 23.2.3.24 %TypedArray%.prototype.reduceRight ( callbackfn [ , initialValue ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduce
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reduce_right) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reduce_right)
{ {
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(vm));
auto length = typed_array->array_length(); auto length = typed_array->array_length();
auto* callback_function = TRY(callback_from_args(global_object, vm.names.reduce.as_string())); auto* callback_function = TRY(callback_from_args(vm, vm.names.reduce.as_string()));
if (length == 0 && vm.argument_count() <= 1) if (length == 0 && vm.argument_count() <= 1)
return vm.throw_completion<TypeError>(ErrorType::ReduceNoInitial); return vm.throw_completion<TypeError>(ErrorType::ReduceNoInitial);
@ -853,7 +859,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reverse)
{ {
// 1. Let O be the this value. // 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O). // 2. Perform ? ValidateTypedArray(O).
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(vm));
// 3. Let len be O.[[ArrayLength]]. // 3. Let len be O.[[ArrayLength]].
auto length = typed_array->array_length(); auto length = typed_array->array_length();
@ -889,9 +895,10 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reverse)
} }
// 23.2.3.26.1 SetTypedArrayFromTypedArray ( target, targetOffset, source ), https://tc39.es/ecma262/#sec-settypedarrayfromtypedarray // 23.2.3.26.1 SetTypedArrayFromTypedArray ( target, targetOffset, source ), https://tc39.es/ecma262/#sec-settypedarrayfromtypedarray
static ThrowCompletionOr<void> set_typed_array_from_typed_array(GlobalObject& global_object, TypedArrayBase& target, double target_offset, TypedArrayBase& source) static ThrowCompletionOr<void> set_typed_array_from_typed_array(VM& vm, TypedArrayBase& target, double target_offset, TypedArrayBase& source)
{ {
auto& vm = global_object.vm(); auto& realm = *vm.current_realm();
auto& global_object = realm.global_object();
// 1. Let targetBuffer be target.[[ViewedArrayBuffer]]. // 1. Let targetBuffer be target.[[ViewedArrayBuffer]].
auto* target_buffer = target.viewed_array_buffer(); auto* target_buffer = target.viewed_array_buffer();
@ -1011,9 +1018,10 @@ static ThrowCompletionOr<void> set_typed_array_from_typed_array(GlobalObject& gl
} }
// 23.2.3.26.2 SetTypedArrayFromArrayLike ( target, targetOffset, source ), https://tc39.es/ecma262/#sec-settypedarrayfromarraylike // 23.2.3.26.2 SetTypedArrayFromArrayLike ( target, targetOffset, source ), https://tc39.es/ecma262/#sec-settypedarrayfromarraylike
static ThrowCompletionOr<void> set_typed_array_from_array_like(GlobalObject& global_object, TypedArrayBase& target, double target_offset, Value source) static ThrowCompletionOr<void> set_typed_array_from_array_like(VM& vm, TypedArrayBase& target, double target_offset, Value source)
{ {
auto& vm = global_object.vm(); auto& realm = *vm.current_realm();
auto& global_object = realm.global_object();
// 1. Let targetBuffer be target.[[ViewedArrayBuffer]]. // 1. Let targetBuffer be target.[[ViewedArrayBuffer]].
auto* target_buffer = target.viewed_array_buffer(); auto* target_buffer = target.viewed_array_buffer();
@ -1076,7 +1084,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::set)
// 1. Let target be the this value. // 1. Let target be the this value.
// 2. Perform ? RequireInternalSlot(target, [[TypedArrayName]]). // 2. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
auto* typed_array = TRY(typed_array_from_this(global_object)); auto* typed_array = TRY(typed_array_from_this(vm));
// 3. Assert: target has a [[ViewedArrayBuffer]] internal slot. // 3. Assert: target has a [[ViewedArrayBuffer]] internal slot.
@ -1092,12 +1100,12 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::set)
auto& source_typed_array = static_cast<TypedArrayBase&>(source.as_object()); auto& source_typed_array = static_cast<TypedArrayBase&>(source.as_object());
// a. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source). // a. Perform ? SetTypedArrayFromTypedArray(target, targetOffset, source).
TRY(set_typed_array_from_typed_array(global_object, *typed_array, target_offset, source_typed_array)); TRY(set_typed_array_from_typed_array(vm, *typed_array, target_offset, source_typed_array));
} }
// 7. Else, // 7. Else,
else { else {
// a. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source). // a. Perform ? SetTypedArrayFromArrayLike(target, targetOffset, source).
TRY(set_typed_array_from_array_like(global_object, *typed_array, target_offset, source)); TRY(set_typed_array_from_array_like(vm, *typed_array, target_offset, source));
} }
// 8. Return undefined. // 8. Return undefined.
@ -1112,7 +1120,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::slice)
// 1. Let O be the this value. // 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O). // 2. Perform ? ValidateTypedArray(O).
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(vm));
// 3. Let len be O.[[ArrayLength]]. // 3. Let len be O.[[ArrayLength]].
auto length = typed_array->array_length(); auto length = typed_array->array_length();
@ -1158,7 +1166,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::slice)
// 13. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(count) »). // 13. Let A be ? TypedArraySpeciesCreate(O, « 𝔽(count) »).
MarkedVector<Value> arguments(vm.heap()); MarkedVector<Value> arguments(vm.heap());
arguments.empend(count); arguments.empend(count);
auto* new_array = TRY(typed_array_species_create(global_object, *typed_array, move(arguments))); auto* new_array = TRY(typed_array_species_create(vm, *typed_array, move(arguments)));
// 14. If count > 0, then // 14. If count > 0, then
if (count > 0) { if (count > 0) {
@ -1244,7 +1252,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::slice)
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::some) JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::some)
{ {
auto result = false; auto result = false;
TRY(for_each_item(vm, global_object, "some", [&](auto, auto, auto callback_result) { TRY(for_each_item(vm, "some", [&](auto, auto, auto callback_result) {
if (callback_result.to_boolean()) { if (callback_result.to_boolean()) {
result = true; result = true;
return IterationDecision::Break; return IterationDecision::Break;
@ -1265,7 +1273,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::sort)
// 2. Let obj be the this value. // 2. Let obj be the this value.
// 3. Perform ? ValidateTypedArray(obj). // 3. Perform ? ValidateTypedArray(obj).
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(vm));
// 4. Let len be obj.[[ArrayLength]]. // 4. Let len be obj.[[ArrayLength]].
auto length = typed_array->array_length(); auto length = typed_array->array_length();
@ -1354,7 +1362,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::subarray)
// 1. Let O be the this value. // 1. Let O be the this value.
// 2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]). // 2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
auto* typed_array = TRY(typed_array_from_this(global_object)); auto* typed_array = TRY(typed_array_from_this(vm));
// 3. Assert: O has a [[ViewedArrayBuffer]] internal slot. // 3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
// 4. Let buffer be O.[[ViewedArrayBuffer]]. // 4. Let buffer be O.[[ViewedArrayBuffer]].
@ -1419,7 +1427,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::subarray)
arguments.empend(new_length); arguments.empend(new_length);
// 19. Return ? TypedArraySpeciesCreate(O, argumentsList). // 19. Return ? TypedArraySpeciesCreate(O, argumentsList).
return TRY(typed_array_species_create(global_object, *typed_array, move(arguments))); return TRY(typed_array_species_create(vm, *typed_array, move(arguments)));
} }
// 23.2.3.31 %TypedArray%.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.tolocalestring // 23.2.3.31 %TypedArray%.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.tolocalestring
@ -1431,7 +1439,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_locale_string)
// This function is not generic. ValidateTypedArray is applied to the this value prior to evaluating the algorithm. // This function is not generic. ValidateTypedArray is applied to the this value prior to evaluating the algorithm.
// If its result is an abrupt completion that exception is thrown instead of evaluating the algorithm. // If its result is an abrupt completion that exception is thrown instead of evaluating the algorithm.
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(vm));
// 1. Let array be ? ToObject(this value). // 1. Let array be ? ToObject(this value).
// NOTE: Handled by ValidateTypedArray // NOTE: Handled by ValidateTypedArray
@ -1481,7 +1489,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_reversed)
{ {
// 1. Let O be the this value. // 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O). // 2. Perform ? ValidateTypedArray(O).
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(vm));
// 3. Let length be O.[[ArrayLength]]. // 3. Let length be O.[[ArrayLength]].
auto length = typed_array->array_length(); auto length = typed_array->array_length();
@ -1489,7 +1497,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_reversed)
// 4. Let A be ? TypedArrayCreateSameType(O, « 𝔽(length) »). // 4. Let A be ? TypedArrayCreateSameType(O, « 𝔽(length) »).
MarkedVector<Value> arguments(vm.heap()); MarkedVector<Value> arguments(vm.heap());
arguments.empend(length); arguments.empend(length);
auto* return_array = TRY(typed_array_create_same_type(global_object, *typed_array, move(arguments))); auto* return_array = TRY(typed_array_create_same_type(vm, *typed_array, move(arguments)));
// 5. Let k be 0. // 5. Let k be 0.
// 6. Repeat, while k < length // 6. Repeat, while k < length
@ -1525,7 +1533,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_sorted)
auto* object = TRY(vm.this_value().to_object(vm)); auto* object = TRY(vm.this_value().to_object(vm));
// 3. Perform ? ValidateTypedArray(O). // 3. Perform ? ValidateTypedArray(O).
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(vm));
// 4. Let buffer be obj.[[ViewedArrayBuffer]]. // 4. Let buffer be obj.[[ViewedArrayBuffer]].
auto* array_buffer = typed_array->viewed_array_buffer(); auto* array_buffer = typed_array->viewed_array_buffer();
@ -1537,13 +1545,13 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_sorted)
// 6. Let A be ? TypedArrayCreateSameType(O, « 𝔽(len) »). // 6. Let A be ? TypedArrayCreateSameType(O, « 𝔽(len) »).
MarkedVector<Value> arguments(vm.heap()); MarkedVector<Value> arguments(vm.heap());
arguments.empend(length); arguments.empend(length);
auto* return_array = TRY(typed_array_create_same_type(global_object, *typed_array, move(arguments))); auto* return_array = TRY(typed_array_create_same_type(vm, *typed_array, move(arguments)));
// 7. NOTE: The following closure performs a numeric comparison rather than the string comparison used in Array.prototype.toSorted // 7. NOTE: The following closure performs a numeric comparison rather than the string comparison used in Array.prototype.toSorted
// 8. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparefn and buffer and performs the following steps when called: // 8. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparefn and buffer and performs the following steps when called:
Function<ThrowCompletionOr<double>(Value, Value)> sort_compare = [&](auto x, auto y) -> ThrowCompletionOr<double> { Function<ThrowCompletionOr<double>(Value, Value)> sort_compare = [&](auto x, auto y) -> ThrowCompletionOr<double> {
// a. Return ? CompareTypedArrayElements(x, y, comparefn, buffer). // a. Return ? CompareTypedArrayElements(x, y, comparefn, buffer).
return TRY(compare_typed_array_elements(global_object, x, y, comparefn.is_undefined() ? nullptr : &comparefn.as_function(), *return_array->viewed_array_buffer())); return TRY(compare_typed_array_elements(vm, x, y, comparefn.is_undefined() ? nullptr : &comparefn.as_function(), *return_array->viewed_array_buffer()));
}; };
// 9. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, false). // 9. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, false).
@ -1568,7 +1576,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::with)
// 1. Let O be the this value. // 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O). // 2. Perform ? ValidateTypedArray(O).
auto* typed_array = TRY(validate_typed_array_from_this(global_object)); auto* typed_array = TRY(validate_typed_array_from_this(vm));
// 3. Let len be O.[[ArrayLength]]. // 3. Let len be O.[[ArrayLength]].
auto length = typed_array->array_length(); auto length = typed_array->array_length();
@ -1597,7 +1605,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::with)
// 10. Let A be ? TypedArrayCreateSameType(O, « 𝔽(len) »). // 10. Let A be ? TypedArrayCreateSameType(O, « 𝔽(len) »).
MarkedVector<Value> arguments(vm.heap()); MarkedVector<Value> arguments(vm.heap());
arguments.empend(length); arguments.empend(length);
auto* return_array = TRY(typed_array_create_same_type(global_object, *typed_array, move(arguments))); auto* return_array = TRY(typed_array_create_same_type(vm, *typed_array, move(arguments)));
// 11. Let k be 0. // 11. Let k be 0.
// 12. Repeat, while k < len, // 12. Repeat, while k < len,
@ -1628,7 +1636,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::values)
{ {
auto& realm = *global_object.associated_realm(); auto& realm = *global_object.associated_realm();
auto* typed_array = TRY(typed_array_from_this(global_object)); auto* typed_array = TRY(typed_array_from_this(vm));
return ArrayIterator::create(realm, typed_array, Object::PropertyKind::Value); return ArrayIterator::create(realm, typed_array, Object::PropertyKind::Value);
} }