mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 19:07:35 +00:00
LibJS: Add spec comments to TypedArrayConstructor
This commit is contained in:
parent
81c6ad047a
commit
aefa053473
1 changed files with 112 additions and 26 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2020-2023, Linus Groh <linusg@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -49,86 +49,172 @@ ThrowCompletionOr<Value> TypedArrayConstructor::call()
|
|||
// 23.2.1.1 %TypedArray% ( ), https://tc39.es/ecma262/#sec-%typedarray%
|
||||
ThrowCompletionOr<NonnullGCPtr<Object>> TypedArrayConstructor::construct(FunctionObject&)
|
||||
{
|
||||
// 1. Throw a TypeError exception.
|
||||
return vm().throw_completion<TypeError>(ErrorType::ClassIsAbstract, "TypedArray");
|
||||
}
|
||||
|
||||
// 23.2.2.1 %TypedArray%.from ( source [ , mapfn [ , thisArg ] ] ), https://tc39.es/ecma262/#sec-%typedarray%.from
|
||||
JS_DEFINE_NATIVE_FUNCTION(TypedArrayConstructor::from)
|
||||
{
|
||||
auto source = vm.argument(0);
|
||||
auto map_fn_value = vm.argument(1);
|
||||
auto this_arg = vm.argument(2);
|
||||
|
||||
// 1. Let C be the this value.
|
||||
auto constructor = vm.this_value();
|
||||
|
||||
// 2. If IsConstructor(C) is false, throw a TypeError exception.
|
||||
if (!constructor.is_constructor())
|
||||
return vm.throw_completion<TypeError>(ErrorType::NotAConstructor, TRY_OR_THROW_OOM(vm, constructor.to_string_without_side_effects()));
|
||||
|
||||
FunctionObject* map_fn = nullptr;
|
||||
if (!vm.argument(1).is_undefined()) {
|
||||
auto callback = vm.argument(1);
|
||||
if (!callback.is_function())
|
||||
return vm.throw_completion<TypeError>(ErrorType::NotAFunction, TRY_OR_THROW_OOM(vm, callback.to_string_without_side_effects()));
|
||||
map_fn = &callback.as_function();
|
||||
// 3. If mapfn is undefined, let mapping be false.
|
||||
GCPtr<FunctionObject> map_fn;
|
||||
|
||||
// 4. Else,
|
||||
if (!map_fn_value.is_undefined()) {
|
||||
// a. If IsCallable(mapfn) is false, throw a TypeError exception.
|
||||
if (!map_fn_value.is_function())
|
||||
return vm.throw_completion<TypeError>(ErrorType::NotAFunction, TRY_OR_THROW_OOM(vm, map_fn_value.to_string_without_side_effects()));
|
||||
|
||||
// b. Let mapping be true.
|
||||
map_fn = &map_fn_value.as_function();
|
||||
}
|
||||
|
||||
auto source = vm.argument(0);
|
||||
auto this_arg = vm.argument(2);
|
||||
// 5. Let usingIterator be ? GetMethod(source, @@iterator).
|
||||
auto* using_iterator = TRY(source.get_method(vm, *vm.well_known_symbol_iterator()));
|
||||
|
||||
auto using_iterator = TRY(source.get_method(vm, *vm.well_known_symbol_iterator()));
|
||||
// 6. If usingIterator is not undefined, then
|
||||
if (using_iterator) {
|
||||
// a. Let values be ? IteratorToList(? GetIteratorFromMethod(source, usingIterator)).
|
||||
auto values = TRY(iterable_to_list(vm, source, using_iterator));
|
||||
|
||||
MarkedVector<Value> arguments(vm.heap());
|
||||
arguments.empend(values.size());
|
||||
auto target_object = TRY(typed_array_create(vm, constructor.as_function(), move(arguments)));
|
||||
// b. Let len be the number of elements in values.
|
||||
auto length = values.size();
|
||||
|
||||
for (size_t k = 0; k < values.size(); ++k) {
|
||||
// c. Let targetObj be ? TypedArrayCreate(C, « 𝔽(len) »).
|
||||
MarkedVector<Value> arguments(vm.heap());
|
||||
arguments.empend(length);
|
||||
auto* target_object = TRY(typed_array_create(vm, constructor.as_function(), move(arguments)));
|
||||
|
||||
// d. Let k be 0.
|
||||
// e. Repeat, while k < len,
|
||||
for (size_t k = 0; k < length; ++k) {
|
||||
// i. Let Pk be ! ToString(𝔽(k)).
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// ii. Let kValue be the first element of values.
|
||||
// iii. Remove the first element from values.
|
||||
auto k_value = values[k];
|
||||
|
||||
Value mapped_value;
|
||||
if (map_fn)
|
||||
|
||||
// iv. If mapping is true, then
|
||||
if (map_fn) {
|
||||
// 1. Let mappedValue be ? Call(mapfn, thisArg, « kValue, 𝔽(k) »).
|
||||
mapped_value = TRY(JS::call(vm, *map_fn, this_arg, k_value, Value(k)));
|
||||
else
|
||||
}
|
||||
// v. Else, let mappedValue be kValue.
|
||||
else {
|
||||
mapped_value = k_value;
|
||||
TRY(target_object->set(k, mapped_value, Object::ShouldThrowExceptions::Yes));
|
||||
}
|
||||
|
||||
// vi. Perform ? Set(targetObj, Pk, mappedValue, true).
|
||||
TRY(target_object->set(property_key, mapped_value, Object::ShouldThrowExceptions::Yes));
|
||||
|
||||
// vii. Set k to k + 1.
|
||||
}
|
||||
|
||||
// f. Assert: values is now an empty List.
|
||||
// NOTE: We don't actually empty the list.
|
||||
|
||||
// g. Return targetObj.
|
||||
return target_object;
|
||||
}
|
||||
|
||||
auto array_like = MUST(source.to_object(vm));
|
||||
// 7. NOTE: source is not an Iterable so assume it is already an array-like object.
|
||||
// 8. Let arrayLike be ! ToObject(source).
|
||||
auto* array_like = MUST(source.to_object(vm));
|
||||
|
||||
// 9. Let len be ? LengthOfArrayLike(arrayLike).
|
||||
auto length = TRY(length_of_array_like(vm, *array_like));
|
||||
|
||||
// 10. Let targetObj be ? TypedArrayCreate(C, « 𝔽(len) »).
|
||||
MarkedVector<Value> arguments(vm.heap());
|
||||
arguments.empend(length);
|
||||
auto target_object = TRY(typed_array_create(vm, constructor.as_function(), move(arguments)));
|
||||
auto* target_object = TRY(typed_array_create(vm, constructor.as_function(), move(arguments)));
|
||||
|
||||
// 11. Let k be 0.
|
||||
// 12. Repeat, while k < len,
|
||||
for (size_t k = 0; k < length; ++k) {
|
||||
auto k_value = TRY(array_like->get(k));
|
||||
// a. Let Pk be ! ToString(𝔽(k)).
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// b. Let kValue be ? Get(arrayLike, Pk).
|
||||
auto k_value = TRY(array_like->get(property_key));
|
||||
|
||||
Value mapped_value;
|
||||
if (map_fn)
|
||||
|
||||
// c. If mapping is true, then
|
||||
if (map_fn) {
|
||||
// i. Let mappedValue be ? Call(mapfn, thisArg, « kValue, 𝔽(k) »).
|
||||
mapped_value = TRY(JS::call(vm, *map_fn, this_arg, k_value, Value(k)));
|
||||
else
|
||||
}
|
||||
// d. Else, let mappedValue be kValue.
|
||||
else {
|
||||
mapped_value = k_value;
|
||||
TRY(target_object->set(k, mapped_value, Object::ShouldThrowExceptions::Yes));
|
||||
}
|
||||
|
||||
// e. Perform ? Set(targetObj, Pk, mappedValue, true).
|
||||
TRY(target_object->set(property_key, mapped_value, Object::ShouldThrowExceptions::Yes));
|
||||
|
||||
// f. Set k to k + 1.
|
||||
}
|
||||
|
||||
// 13. Return targetObj.
|
||||
return target_object;
|
||||
}
|
||||
|
||||
// 23.2.2.2 %TypedArray%.of ( ...items ), https://tc39.es/ecma262/#sec-%typedarray%.of
|
||||
JS_DEFINE_NATIVE_FUNCTION(TypedArrayConstructor::of)
|
||||
{
|
||||
// 1. Let len be the number of elements in items.
|
||||
auto length = vm.argument_count();
|
||||
|
||||
// 2. Let C be the this value.
|
||||
auto constructor = vm.this_value();
|
||||
|
||||
// 3. If IsConstructor(C) is false, throw a TypeError exception.
|
||||
if (!constructor.is_constructor())
|
||||
return vm.throw_completion<TypeError>(ErrorType::NotAConstructor, TRY_OR_THROW_OOM(vm, constructor.to_string_without_side_effects()));
|
||||
|
||||
// 4. Let newObj be ? TypedArrayCreate(C, « 𝔽(len) »).
|
||||
MarkedVector<Value> arguments(vm.heap());
|
||||
arguments.append(Value(length));
|
||||
auto new_object = TRY(typed_array_create(vm, constructor.as_function(), move(arguments)));
|
||||
for (size_t k = 0; k < length; ++k)
|
||||
TRY(new_object->set(k, vm.argument(k), Object::ShouldThrowExceptions::Yes));
|
||||
auto* new_object = TRY(typed_array_create(vm, constructor.as_function(), move(arguments)));
|
||||
|
||||
// 5. Let k be 0.
|
||||
// 6. Repeat, while k < len,
|
||||
for (size_t k = 0; k < length; ++k) {
|
||||
// a. Let kValue be items[k].
|
||||
auto k_value = vm.argument(k);
|
||||
|
||||
// b. Let Pk be ! ToString(𝔽(k)).
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// c. Perform ? Set(newObj, Pk, kValue, true).
|
||||
TRY(new_object->set(property_key, k_value, Object::ShouldThrowExceptions::Yes));
|
||||
|
||||
// d. Set k to k + 1.
|
||||
}
|
||||
|
||||
// 7. Return newObj.
|
||||
return new_object;
|
||||
}
|
||||
|
||||
// 23.2.2.4 get %TypedArray% [ @@species ], https://tc39.es/ecma262/#sec-get-%typedarray%-@@species
|
||||
JS_DEFINE_NATIVE_FUNCTION(TypedArrayConstructor::symbol_species_getter)
|
||||
{
|
||||
// 1. Return the this value.
|
||||
return vm.this_value();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue