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