| // 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_filter { |
| const kBuiltinName: constexpr string = '%TypedArray%.prototype.filter'; |
| |
| extern runtime TypedArrayCopyElements(Context, JSTypedArray, Object, Number): |
| void; |
| |
| // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.filter |
| transitioning javascript builtin TypedArrayPrototypeFilter( |
| js-implicit context: Context, receiver: Object)(...arguments): Object { |
| // 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(kNotTypedArray, kBuiltinName); |
| const src = typed_array::EnsureAttached(array) otherwise IsDetached; |
| |
| // 3. Let len be O.[[ArrayLength]]. |
| // TODO(v8:4153): Support huge TypedArrays here. |
| const len = Cast<Smi>(Convert<Number>(src.length)) otherwise unreachable; |
| |
| // 4. If IsCallable(callbackfn) is false, throw a TypeError exception. |
| const callbackfn = Cast<Callable>(arguments[0]) |
| otherwise ThrowTypeError(kCalledNonCallable, arguments[0]); |
| |
| // 5. If thisArg is present, let T be thisArg; else let T be undefined. |
| const thisArg: Object = arguments[1]; |
| |
| // 6. Let kept be a new empty List. |
| 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: Smi = 0; k < len; k++) { |
| witness.Recheck() otherwise IsDetached; |
| |
| // a. Let Pk be ! ToString(k). |
| // b. Let kValue be ? Get(O, Pk). |
| const value: Object = witness.Load(k); |
| |
| // c. Let selected be ToBoolean(? Call(callbackfn, T, « kValue, k, O |
| // »)). |
| const selected: Object = |
| Call(context, callbackfn, thisArg, value, k, witness.GetStable()); |
| |
| // d. If selected is true, then |
| // i. Append kValue to the end of kept. |
| // ii. Increase captured by 1. |
| if (BranchIfToBooleanIsTrue(selected)) kept.Push(value); |
| |
| // e.Increase k by 1. |
| } |
| |
| // 10. Let A be ? TypedArraySpeciesCreate(O, captured). |
| const lengthSmi = Convert<PositiveSmi>(kept.length); |
| const typedArray: JSTypedArray = |
| typed_array_createtypedarray::TypedArraySpeciesCreateByLength( |
| kBuiltinName, array, lengthSmi); |
| |
| // 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. |
| TypedArrayCopyElements(context, typedArray, kept.ToJSArray(), lengthSmi); |
| |
| // 13. Return A. |
| return typedArray; |
| } |
| label IsDetached deferred { |
| ThrowTypeError(kDetachedOperation, kBuiltinName); |
| } |
| } |
| } |