11cb0ef41Sopenharmony_ci// Copyright 2019 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_ci#include 'src/builtins/builtins-promise-gen.h' 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_cinamespace promise { 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-promise.race 101cb0ef41Sopenharmony_citransitioning javascript builtin 111cb0ef41Sopenharmony_ciPromiseRace( 121cb0ef41Sopenharmony_ci js-implicit context: Context, receiver: JSAny)(iterable: JSAny): JSAny { 131cb0ef41Sopenharmony_ci const receiver = Cast<JSReceiver>(receiver) 141cb0ef41Sopenharmony_ci otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, 'Promise.race'); 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci // This builtin is attached to JSFunction created by the bootstrapper so 171cb0ef41Sopenharmony_ci // `context` is the native context. 181cb0ef41Sopenharmony_ci check(Is<NativeContext>(context)); 191cb0ef41Sopenharmony_ci const nativeContext = UnsafeCast<NativeContext>(context); 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci // Let promiseCapability be ? NewPromiseCapability(C). 221cb0ef41Sopenharmony_ci // Don't fire debugEvent so that forwarding the rejection through all does 231cb0ef41Sopenharmony_ci // not trigger redundant ExceptionEvents 241cb0ef41Sopenharmony_ci const capability = NewPromiseCapability(receiver, False); 251cb0ef41Sopenharmony_ci const resolve = capability.resolve; 261cb0ef41Sopenharmony_ci const reject = capability.reject; 271cb0ef41Sopenharmony_ci const promise = capability.promise; 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci // NewPromiseCapability guarantees that receiver is Constructor. 301cb0ef41Sopenharmony_ci dcheck(Is<Constructor>(receiver)); 311cb0ef41Sopenharmony_ci const constructor = UnsafeCast<Constructor>(receiver); 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci // For catch prediction, don't treat the .then calls as handling it; 341cb0ef41Sopenharmony_ci // instead, recurse outwards. 351cb0ef41Sopenharmony_ci if (IsDebugActive()) deferred { 361cb0ef41Sopenharmony_ci SetPropertyStrict(context, reject, kPromiseForwardingHandlerSymbol, True); 371cb0ef41Sopenharmony_ci } 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci try { 401cb0ef41Sopenharmony_ci let promiseResolveFunction: JSAny; 411cb0ef41Sopenharmony_ci let i: iterator::IteratorRecord; 421cb0ef41Sopenharmony_ci try { 431cb0ef41Sopenharmony_ci // Let promiseResolve be GetPromiseResolve(C). 441cb0ef41Sopenharmony_ci // IfAbruptRejectPromise(promiseResolve, promiseCapability). 451cb0ef41Sopenharmony_ci promiseResolveFunction = GetPromiseResolve(nativeContext, constructor); 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci // Let iterator be GetIterator(iterable). 481cb0ef41Sopenharmony_ci // IfAbruptRejectPromise(iterator, promiseCapability). 491cb0ef41Sopenharmony_ci i = iterator::GetIterator(iterable); 501cb0ef41Sopenharmony_ci } catch (e, _message) deferred { 511cb0ef41Sopenharmony_ci goto Reject(e); 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci // Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability). 551cb0ef41Sopenharmony_ci try { 561cb0ef41Sopenharmony_ci const fastIteratorResultMap = *NativeContextSlot( 571cb0ef41Sopenharmony_ci nativeContext, ContextSlot::ITERATOR_RESULT_MAP_INDEX); 581cb0ef41Sopenharmony_ci while (true) { 591cb0ef41Sopenharmony_ci let nextValue: JSAny; 601cb0ef41Sopenharmony_ci try { 611cb0ef41Sopenharmony_ci // Let next be IteratorStep(iteratorRecord.[[Iterator]]). 621cb0ef41Sopenharmony_ci // If next is an abrupt completion, set iteratorRecord.[[Done]] to 631cb0ef41Sopenharmony_ci // true. ReturnIfAbrupt(next). 641cb0ef41Sopenharmony_ci const next: JSReceiver = iterator::IteratorStep( 651cb0ef41Sopenharmony_ci i, fastIteratorResultMap) otherwise return promise; 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci // Let nextValue be IteratorValue(next). 681cb0ef41Sopenharmony_ci // If nextValue is an abrupt completion, set iteratorRecord.[[Done]] 691cb0ef41Sopenharmony_ci // to true. 701cb0ef41Sopenharmony_ci // ReturnIfAbrupt(nextValue). 711cb0ef41Sopenharmony_ci nextValue = iterator::IteratorValue(next, fastIteratorResultMap); 721cb0ef41Sopenharmony_ci } catch (e, _message) { 731cb0ef41Sopenharmony_ci goto Reject(e); 741cb0ef41Sopenharmony_ci } 751cb0ef41Sopenharmony_ci // Let nextPromise be ? Call(constructor, _promiseResolve_, « 761cb0ef41Sopenharmony_ci // nextValue »). 771cb0ef41Sopenharmony_ci const nextPromise = 781cb0ef41Sopenharmony_ci CallResolve(constructor, promiseResolveFunction, nextValue); 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci // Perform ? Invoke(nextPromise, "then", « resolveElement, 811cb0ef41Sopenharmony_ci // resultCapability.[[Reject]] »). 821cb0ef41Sopenharmony_ci const then = GetProperty(nextPromise, kThenString); 831cb0ef41Sopenharmony_ci const thenResult = Call( 841cb0ef41Sopenharmony_ci context, then, nextPromise, UnsafeCast<JSAny>(resolve), 851cb0ef41Sopenharmony_ci UnsafeCast<JSAny>(reject)); 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci // For catch prediction, mark that rejections here are semantically 881cb0ef41Sopenharmony_ci // handled by the combined Promise. 891cb0ef41Sopenharmony_ci if (IsDebugActive() && !Is<JSPromise>(promise)) deferred { 901cb0ef41Sopenharmony_ci SetPropertyStrict( 911cb0ef41Sopenharmony_ci context, thenResult, kPromiseHandledBySymbol, promise); 921cb0ef41Sopenharmony_ci } 931cb0ef41Sopenharmony_ci } 941cb0ef41Sopenharmony_ci } catch (e, _message) deferred { 951cb0ef41Sopenharmony_ci iterator::IteratorCloseOnException(i); 961cb0ef41Sopenharmony_ci goto Reject(e); 971cb0ef41Sopenharmony_ci } 981cb0ef41Sopenharmony_ci } label Reject(exception: JSAny) deferred { 991cb0ef41Sopenharmony_ci Call(context, UnsafeCast<JSAny>(reject), Undefined, exception); 1001cb0ef41Sopenharmony_ci return promise; 1011cb0ef41Sopenharmony_ci } 1021cb0ef41Sopenharmony_ci unreachable; 1031cb0ef41Sopenharmony_ci} 1041cb0ef41Sopenharmony_ci} 105