blob: 15d40f92ebe53bdfde1648ede7b6634bf4d7c932 [file] [log] [blame]
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
namespace typed_array {
const kBuiltinNameFilter: constexpr string = '%TypedArray%.prototype.filter';
// https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.filter
transitioning javascript builtin TypedArrayPrototypeFilter(
js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
// arguments[0] = callback
// arguments[1] = thisArg
try {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
const array: JSTypedArray = Cast<JSTypedArray>(receiver)
otherwise ThrowTypeError(
MessageTemplate::kNotTypedArray, kBuiltinNameFilter);
const src = typed_array::EnsureAttached(array) otherwise IsDetached;
// 3. Let len be O.[[ArrayLength]].
const len: uintptr = src.length;
// 4. If IsCallable(callbackfn) is false, throw a TypeError exception.
const callbackfn = Cast<Callable>(arguments[0])
otherwise ThrowTypeError(MessageTemplate::kCalledNonCallable, arguments[0]);
// 5. If thisArg is present, let T be thisArg; else let T be undefined.
const thisArg: JSAny = arguments[1];
// 6. Let kept be a new empty List.
// TODO(v8:4153): Support huge TypedArrays here. (growable fixed arrays
// can't be longer than kMaxSmiValue).
let kept = growable_fixed_array::NewGrowableFixedArray();
let witness = typed_array::NewAttachedJSTypedArrayWitness(src);
// 7. Let k be 0.
// 8. Let captured be 0.
// 9. Repeat, while k < len
for (let k: uintptr = 0; k < len; k++) {
witness.Recheck() otherwise IsDetached;
// a. Let Pk be ! ToString(k).
// b. Let kValue be ? Get(O, Pk).
const value: JSAny = witness.Load(k);
// c. Let selected be ToBoolean(? Call(callbackfn, T, « kValue, k, O
// »)).
// TODO(v8:4153): Consider versioning this loop for Smi and non-Smi
// indices to optimize Convert<Number>(k) for the most common case.
const selected: JSAny = Call(
context, callbackfn, thisArg, value, Convert<Number>(k),
witness.GetStable());
// d. If selected is true, then
// i. Append kValue to the end of kept.
// ii. Increase captured by 1.
if (ToBoolean(selected)) kept.Push(value);
// e.Increase k by 1.
}
// 10. Let A be ? TypedArraySpeciesCreate(O, captured).
const typedArray: JSTypedArray = TypedArraySpeciesCreateByLength(
kBuiltinNameFilter, array, Unsigned(kept.length));
// 11. Let n be 0.
// 12. For each element e of kept, do
// a. Perform ! Set(A, ! ToString(n), e, true).
// b. Increment n by 1.
// TODO(v8:4153): Consider passing growable typed array directly to
// TypedArrayCopyElements() to avoid JSArray materialization. Or collect
// indices instead of values the loop above.
const lengthNumber = Convert<Number>(Unsigned(kept.length));
TypedArrayCopyElements(context, typedArray, kept.ToJSArray(), lengthNumber);
// 13. Return A.
return typedArray;
} label IsDetached deferred {
ThrowTypeError(MessageTemplate::kDetachedOperation, kBuiltinNameFilter);
}
}
}