1// Copyright 2021 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5namespace array { 6// https://tc39.es/proposal-array-find-from-last/index.html#sec-array.prototype.findlastindex 7transitioning builtin ArrayFindLastIndexLoopContinuation( 8 implicit context: Context)( 9 predicate: Callable, thisArg: JSAny, o: JSReceiver, 10 initialK: Number): Number { 11 // 5. Repeat, while k >= 0 12 for (let k: Number = initialK; k >= 0; k--) { 13 // 5a. Let Pk be ! ToString((k)). 14 // k is guaranteed to be a positive integer, hence ToString is 15 // side-effect free and HasProperty/GetProperty do the conversion inline. 16 17 // 5b. Let kValue be ? Get(O, Pk). 18 const value: JSAny = GetProperty(o, k); 19 20 // 5c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 21 // (k), O »)). 22 const testResult: JSAny = Call(context, predicate, thisArg, value, k, o); 23 24 // 5d. If testResult is true, return (k). 25 if (ToBoolean(testResult)) { 26 return k; 27 } 28 29 // 5e. Set k to k - 1. (done by the loop). 30 } 31 32 // 6. Return -1. 33 return Convert<Smi>(-1); 34} 35 36// https://tc39.es/proposal-array-find-from-last/index.html#sec-array.prototype.findlastindex 37transitioning macro FastArrayFindLastIndex(implicit context: Context)( 38 o: JSReceiver, len: Number, predicate: Callable, thisArg: JSAny): Number 39 labels Bailout(Number) { 40 const smiLen = Cast<Smi>(len) otherwise goto Bailout(len - 1); 41 // 4. Let k be len - 1. 42 let k: Smi = smiLen - 1; 43 const fastO = Cast<FastJSArray>(o) otherwise goto Bailout(k); 44 let fastOW = NewFastJSArrayWitness(fastO); 45 46 // 5. Repeat, while k ≥ 0 47 // Build a fast loop over the smi array. 48 for (; k >= 0; k--) { 49 fastOW.Recheck() otherwise goto Bailout(k); 50 51 // Ensure that we haven't walked beyond a possibly updated length. 52 if (k >= fastOW.Get().length) goto Bailout(k); 53 54 // 5a. Let Pk be ! ToString((k)). 55 // k is guaranteed to be a positive integer, hence there is no need to 56 // cast ToString for LoadElementOrUndefined. 57 58 // 5b. Let kValue be ? Get(O, Pk). 59 const value: JSAny = fastOW.LoadElementOrUndefined(k); 60 // 5c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 61 // (k), O »)). 62 const testResult: JSAny = 63 Call(context, predicate, thisArg, value, k, fastOW.Get()); 64 // 5d. If testResult is true, return (k). 65 if (ToBoolean(testResult)) { 66 return k; 67 } 68 69 // 5e. Set k to k - 1. (done by the loop). 70 } 71 72 // 6. Return -1. 73 return -1; 74} 75 76// https://tc39.es/proposal-array-find-from-last/index.html#sec-array.prototype.findlastindex 77transitioning javascript builtin 78ArrayPrototypeFindLastIndex( 79 js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny { 80 try { 81 RequireObjectCoercible(receiver, 'Array.prototype.findLastIndex'); 82 83 // 1. Let O be ? ToObject(this value). 84 const o: JSReceiver = ToObject_Inline(context, receiver); 85 86 // 2. Let len be ? LengthOfArrayLike(O). 87 const len: Number = GetLengthProperty(o); 88 89 // 3. If IsCallable(predicate) is false, throw a TypeError exception. 90 if (arguments.length == 0) { 91 goto NotCallableError; 92 } 93 const predicate = Cast<Callable>(arguments[0]) otherwise NotCallableError; 94 95 // If a thisArg parameter is provided, it will be used as the this value for 96 // each invocation of predicate. If it is not provided, undefined is used 97 // instead. 98 const thisArg: JSAny = arguments[1]; 99 100 // Special cases. 101 try { 102 return FastArrayFindLastIndex(o, len, predicate, thisArg) 103 otherwise Bailout; 104 } label Bailout(k: Number) deferred { 105 return ArrayFindLastIndexLoopContinuation(predicate, thisArg, o, k); 106 } 107 } label NotCallableError deferred { 108 ThrowTypeError(MessageTemplate::kCalledNonCallable, arguments[0]); 109 } 110} 111} 112