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