11cb0ef41Sopenharmony_ci// Copyright 2018 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_cinamespace array { 61cb0ef41Sopenharmony_citransitioning javascript builtin 71cb0ef41Sopenharmony_ciArrayForEachLoopEagerDeoptContinuation( 81cb0ef41Sopenharmony_ci js-implicit context: NativeContext, receiver: JSAny)( 91cb0ef41Sopenharmony_ci callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny): JSAny { 101cb0ef41Sopenharmony_ci // All continuation points in the optimized forEach implementation are 111cb0ef41Sopenharmony_ci // after the ToObject(O) call that ensures we are dealing with a 121cb0ef41Sopenharmony_ci // JSReceiver. 131cb0ef41Sopenharmony_ci const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; 141cb0ef41Sopenharmony_ci const callbackfn = Cast<Callable>(callback) otherwise unreachable; 151cb0ef41Sopenharmony_ci const numberK = Cast<Number>(initialK) otherwise unreachable; 161cb0ef41Sopenharmony_ci const numberLength = Cast<Number>(length) otherwise unreachable; 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci return ArrayForEachLoopContinuation( 191cb0ef41Sopenharmony_ci jsreceiver, callbackfn, thisArg, Undefined, jsreceiver, numberK, 201cb0ef41Sopenharmony_ci numberLength, Undefined); 211cb0ef41Sopenharmony_ci} 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_citransitioning javascript builtin 241cb0ef41Sopenharmony_ciArrayForEachLoopLazyDeoptContinuation( 251cb0ef41Sopenharmony_ci js-implicit context: NativeContext, receiver: JSAny)( 261cb0ef41Sopenharmony_ci callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny, 271cb0ef41Sopenharmony_ci _result: JSAny): JSAny { 281cb0ef41Sopenharmony_ci // All continuation points in the optimized forEach implementation are 291cb0ef41Sopenharmony_ci // after the ToObject(O) call that ensures we are dealing with a 301cb0ef41Sopenharmony_ci // JSReceiver. 311cb0ef41Sopenharmony_ci const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; 321cb0ef41Sopenharmony_ci const callbackfn = Cast<Callable>(callback) otherwise unreachable; 331cb0ef41Sopenharmony_ci const numberK = Cast<Number>(initialK) otherwise unreachable; 341cb0ef41Sopenharmony_ci const numberLength = Cast<Number>(length) otherwise unreachable; 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci return ArrayForEachLoopContinuation( 371cb0ef41Sopenharmony_ci jsreceiver, callbackfn, thisArg, Undefined, jsreceiver, numberK, 381cb0ef41Sopenharmony_ci numberLength, Undefined); 391cb0ef41Sopenharmony_ci} 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_citransitioning builtin ArrayForEachLoopContinuation(implicit context: Context)( 421cb0ef41Sopenharmony_ci _receiver: JSReceiver, callbackfn: Callable, thisArg: JSAny, _array: JSAny, 431cb0ef41Sopenharmony_ci o: JSReceiver, initialK: Number, len: Number, _to: JSAny): JSAny { 441cb0ef41Sopenharmony_ci // variables {array} and {to} are ignored. 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci // 5. Let k be 0. 471cb0ef41Sopenharmony_ci // 6. Repeat, while k < len 481cb0ef41Sopenharmony_ci for (let k: Number = initialK; k < len; k = k + 1) { 491cb0ef41Sopenharmony_ci // 6a. Let Pk be ! ToString(k). 501cb0ef41Sopenharmony_ci // k is guaranteed to be a positive integer, hence ToString is 511cb0ef41Sopenharmony_ci // side-effect free and HasProperty/GetProperty do the conversion inline. 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci // 6b. Let kPresent be ? HasProperty(O, Pk). 541cb0ef41Sopenharmony_ci const kPresent: Boolean = HasProperty_Inline(o, k); 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci // 6c. If kPresent is true, then 571cb0ef41Sopenharmony_ci if (kPresent == True) { 581cb0ef41Sopenharmony_ci // 6c. i. Let kValue be ? Get(O, Pk). 591cb0ef41Sopenharmony_ci const kValue: JSAny = GetProperty(o, k); 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci // 6c. ii. Perform ? Call(callbackfn, T, <kValue, k, O>). 621cb0ef41Sopenharmony_ci Call(context, callbackfn, thisArg, kValue, k, o); 631cb0ef41Sopenharmony_ci } 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci // 6d. Increase k by 1. (done by the loop). 661cb0ef41Sopenharmony_ci } 671cb0ef41Sopenharmony_ci return Undefined; 681cb0ef41Sopenharmony_ci} 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_citransitioning macro FastArrayForEach(implicit context: Context)( 711cb0ef41Sopenharmony_ci o: JSReceiver, len: Number, callbackfn: Callable, thisArg: JSAny): JSAny 721cb0ef41Sopenharmony_ci labels Bailout(Smi) { 731cb0ef41Sopenharmony_ci let k: Smi = 0; 741cb0ef41Sopenharmony_ci const smiLen = Cast<Smi>(len) otherwise goto Bailout(k); 751cb0ef41Sopenharmony_ci const fastO = Cast<FastJSArray>(o) otherwise goto Bailout(k); 761cb0ef41Sopenharmony_ci let fastOW = NewFastJSArrayWitness(fastO); 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci // Build a fast loop over the smi array. 791cb0ef41Sopenharmony_ci for (; k < smiLen; k++) { 801cb0ef41Sopenharmony_ci fastOW.Recheck() otherwise goto Bailout(k); 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci // Ensure that we haven't walked beyond a possibly updated length. 831cb0ef41Sopenharmony_ci if (k >= fastOW.Get().length) goto Bailout(k); 841cb0ef41Sopenharmony_ci const value: JSAny = fastOW.LoadElementNoHole(k) 851cb0ef41Sopenharmony_ci otherwise continue; 861cb0ef41Sopenharmony_ci Call(context, callbackfn, thisArg, value, k, fastOW.Get()); 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci return Undefined; 891cb0ef41Sopenharmony_ci} 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ci// https://tc39.github.io/ecma262/#sec-array.prototype.foreach 921cb0ef41Sopenharmony_citransitioning javascript builtin 931cb0ef41Sopenharmony_ciArrayForEach( 941cb0ef41Sopenharmony_ci js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny { 951cb0ef41Sopenharmony_ci try { 961cb0ef41Sopenharmony_ci RequireObjectCoercible(receiver, 'Array.prototype.forEach'); 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci // 1. Let O be ? ToObject(this value). 991cb0ef41Sopenharmony_ci const o: JSReceiver = ToObject_Inline(context, receiver); 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci // 2. Let len be ? ToLength(? Get(O, "length")). 1021cb0ef41Sopenharmony_ci const len: Number = GetLengthProperty(o); 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ci // 3. If IsCallable(callbackfn) is false, throw a TypeError exception. 1051cb0ef41Sopenharmony_ci if (arguments.length == 0) { 1061cb0ef41Sopenharmony_ci goto TypeError; 1071cb0ef41Sopenharmony_ci } 1081cb0ef41Sopenharmony_ci const callbackfn = Cast<Callable>(arguments[0]) otherwise TypeError; 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci // 4. If thisArg is present, let T be thisArg; else let T be undefined. 1111cb0ef41Sopenharmony_ci const thisArg: JSAny = arguments[1]; 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci // Special cases. 1141cb0ef41Sopenharmony_ci let k: Number = 0; 1151cb0ef41Sopenharmony_ci try { 1161cb0ef41Sopenharmony_ci return FastArrayForEach(o, len, callbackfn, thisArg) 1171cb0ef41Sopenharmony_ci otherwise Bailout; 1181cb0ef41Sopenharmony_ci } label Bailout(kValue: Smi) deferred { 1191cb0ef41Sopenharmony_ci k = kValue; 1201cb0ef41Sopenharmony_ci } 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci return ArrayForEachLoopContinuation( 1231cb0ef41Sopenharmony_ci o, callbackfn, thisArg, Undefined, o, k, len, Undefined); 1241cb0ef41Sopenharmony_ci } label TypeError deferred { 1251cb0ef41Sopenharmony_ci ThrowTypeError(MessageTemplate::kCalledNonCallable, arguments[0]); 1261cb0ef41Sopenharmony_ci } 1271cb0ef41Sopenharmony_ci} 1281cb0ef41Sopenharmony_ci} 129