11cb0ef41Sopenharmony_ci// Copyright 2017 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/base/optional.h" 61cb0ef41Sopenharmony_ci#include "src/builtins/builtins-async-gen.h" 71cb0ef41Sopenharmony_ci#include "src/builtins/builtins-utils-gen.h" 81cb0ef41Sopenharmony_ci#include "src/builtins/builtins.h" 91cb0ef41Sopenharmony_ci#include "src/codegen/code-factory.h" 101cb0ef41Sopenharmony_ci#include "src/codegen/code-stub-assembler.h" 111cb0ef41Sopenharmony_ci#include "src/execution/frames-inl.h" 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_cinamespace v8 { 141cb0ef41Sopenharmony_cinamespace internal { 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_cinamespace { 171cb0ef41Sopenharmony_ciclass AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler { 181cb0ef41Sopenharmony_ci public: 191cb0ef41Sopenharmony_ci // The 'next' and 'return' take an optional value parameter, and the 'throw' 201cb0ef41Sopenharmony_ci // method take an optional reason parameter. 211cb0ef41Sopenharmony_ci static const int kValueOrReasonArg = 0; 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ci explicit AsyncFromSyncBuiltinsAssembler(compiler::CodeAssemblerState* state) 241cb0ef41Sopenharmony_ci : AsyncBuiltinsAssembler(state) {} 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ci void ThrowIfNotAsyncFromSyncIterator(const TNode<Context> context, 271cb0ef41Sopenharmony_ci const TNode<Object> object, 281cb0ef41Sopenharmony_ci Label* if_exception, 291cb0ef41Sopenharmony_ci TVariable<Object>* var_exception, 301cb0ef41Sopenharmony_ci const char* method_name); 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci using UndefinedMethodHandler = 331cb0ef41Sopenharmony_ci std::function<void(const TNode<NativeContext> native_context, 341cb0ef41Sopenharmony_ci const TNode<JSPromise> promise, Label* if_exception)>; 351cb0ef41Sopenharmony_ci using SyncIteratorNodeGenerator = 361cb0ef41Sopenharmony_ci std::function<TNode<Object>(TNode<JSReceiver>)>; 371cb0ef41Sopenharmony_ci void Generate_AsyncFromSyncIteratorMethod( 381cb0ef41Sopenharmony_ci CodeStubArguments* args, const TNode<Context> context, 391cb0ef41Sopenharmony_ci const TNode<Object> iterator, const TNode<Object> sent_value, 401cb0ef41Sopenharmony_ci const SyncIteratorNodeGenerator& get_method, 411cb0ef41Sopenharmony_ci const UndefinedMethodHandler& if_method_undefined, 421cb0ef41Sopenharmony_ci const char* operation_name, 431cb0ef41Sopenharmony_ci Label::Type reject_label_type = Label::kDeferred, 441cb0ef41Sopenharmony_ci base::Optional<TNode<Object>> initial_exception_value = base::nullopt); 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci void Generate_AsyncFromSyncIteratorMethod( 471cb0ef41Sopenharmony_ci CodeStubArguments* args, const TNode<Context> context, 481cb0ef41Sopenharmony_ci const TNode<Object> iterator, const TNode<Object> sent_value, 491cb0ef41Sopenharmony_ci Handle<String> name, const UndefinedMethodHandler& if_method_undefined, 501cb0ef41Sopenharmony_ci const char* operation_name, 511cb0ef41Sopenharmony_ci Label::Type reject_label_type = Label::kDeferred, 521cb0ef41Sopenharmony_ci base::Optional<TNode<Object>> initial_exception_value = base::nullopt) { 531cb0ef41Sopenharmony_ci auto get_method = [=](const TNode<JSReceiver> sync_iterator) { 541cb0ef41Sopenharmony_ci return GetProperty(context, sync_iterator, name); 551cb0ef41Sopenharmony_ci }; 561cb0ef41Sopenharmony_ci return Generate_AsyncFromSyncIteratorMethod( 571cb0ef41Sopenharmony_ci args, context, iterator, sent_value, get_method, if_method_undefined, 581cb0ef41Sopenharmony_ci operation_name, reject_label_type, initial_exception_value); 591cb0ef41Sopenharmony_ci } 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci // Load "value" and "done" from an iterator result object. If an exception 621cb0ef41Sopenharmony_ci // is thrown at any point, jumps to the `if_exception` label with exception 631cb0ef41Sopenharmony_ci // stored in `var_exception`. 641cb0ef41Sopenharmony_ci // 651cb0ef41Sopenharmony_ci // Returns a Pair of Nodes, whose first element is the value of the "value" 661cb0ef41Sopenharmony_ci // property, and whose second element is the value of the "done" property, 671cb0ef41Sopenharmony_ci // converted to a Boolean if needed. 681cb0ef41Sopenharmony_ci std::pair<TNode<Object>, TNode<Oddball>> LoadIteratorResult( 691cb0ef41Sopenharmony_ci const TNode<Context> context, const TNode<NativeContext> native_context, 701cb0ef41Sopenharmony_ci const TNode<Object> iter_result, Label* if_exception, 711cb0ef41Sopenharmony_ci TVariable<Object>* var_exception); 721cb0ef41Sopenharmony_ci}; 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_civoid AsyncFromSyncBuiltinsAssembler::ThrowIfNotAsyncFromSyncIterator( 751cb0ef41Sopenharmony_ci const TNode<Context> context, const TNode<Object> object, 761cb0ef41Sopenharmony_ci Label* if_exception, TVariable<Object>* var_exception, 771cb0ef41Sopenharmony_ci const char* method_name) { 781cb0ef41Sopenharmony_ci Label if_receiverisincompatible(this, Label::kDeferred), done(this); 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(object), &if_receiverisincompatible); 811cb0ef41Sopenharmony_ci Branch(HasInstanceType(CAST(object), JS_ASYNC_FROM_SYNC_ITERATOR_TYPE), &done, 821cb0ef41Sopenharmony_ci &if_receiverisincompatible); 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci BIND(&if_receiverisincompatible); 851cb0ef41Sopenharmony_ci { 861cb0ef41Sopenharmony_ci // If Type(O) is not Object, or if O does not have a [[SyncIterator]] 871cb0ef41Sopenharmony_ci // internal slot, then 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci // Let badIteratorError be a new TypeError exception. 901cb0ef41Sopenharmony_ci TNode<HeapObject> error = 911cb0ef41Sopenharmony_ci MakeTypeError(MessageTemplate::kIncompatibleMethodReceiver, context, 921cb0ef41Sopenharmony_ci StringConstant(method_name), object); 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ci // Perform ! Call(promiseCapability.[[Reject]], undefined, 951cb0ef41Sopenharmony_ci // « badIteratorError »). 961cb0ef41Sopenharmony_ci *var_exception = error; 971cb0ef41Sopenharmony_ci Goto(if_exception); 981cb0ef41Sopenharmony_ci } 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci BIND(&done); 1011cb0ef41Sopenharmony_ci} 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_civoid AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod( 1041cb0ef41Sopenharmony_ci CodeStubArguments* args, const TNode<Context> context, 1051cb0ef41Sopenharmony_ci const TNode<Object> iterator, const TNode<Object> sent_value, 1061cb0ef41Sopenharmony_ci const SyncIteratorNodeGenerator& get_method, 1071cb0ef41Sopenharmony_ci const UndefinedMethodHandler& if_method_undefined, 1081cb0ef41Sopenharmony_ci const char* operation_name, Label::Type reject_label_type, 1091cb0ef41Sopenharmony_ci base::Optional<TNode<Object>> initial_exception_value) { 1101cb0ef41Sopenharmony_ci const TNode<NativeContext> native_context = LoadNativeContext(context); 1111cb0ef41Sopenharmony_ci const TNode<JSPromise> promise = NewJSPromise(context); 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci TVARIABLE( 1141cb0ef41Sopenharmony_ci Object, var_exception, 1151cb0ef41Sopenharmony_ci initial_exception_value ? *initial_exception_value : UndefinedConstant()); 1161cb0ef41Sopenharmony_ci Label reject_promise(this, reject_label_type); 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci ThrowIfNotAsyncFromSyncIterator(context, iterator, &reject_promise, 1191cb0ef41Sopenharmony_ci &var_exception, operation_name); 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ci TNode<JSAsyncFromSyncIterator> async_iterator = CAST(iterator); 1221cb0ef41Sopenharmony_ci const TNode<JSReceiver> sync_iterator = LoadObjectField<JSReceiver>( 1231cb0ef41Sopenharmony_ci async_iterator, JSAsyncFromSyncIterator::kSyncIteratorOffset); 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci TNode<Object> method = get_method(sync_iterator); 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci if (if_method_undefined) { 1281cb0ef41Sopenharmony_ci Label if_isnotundefined(this); 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci GotoIfNot(IsNullOrUndefined(method), &if_isnotundefined); 1311cb0ef41Sopenharmony_ci if_method_undefined(native_context, promise, &reject_promise); 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci BIND(&if_isnotundefined); 1341cb0ef41Sopenharmony_ci } 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ci TVARIABLE(Object, iter_result); 1371cb0ef41Sopenharmony_ci { 1381cb0ef41Sopenharmony_ci Label has_sent_value(this), no_sent_value(this), merge(this); 1391cb0ef41Sopenharmony_ci ScopedExceptionHandler handler(this, &reject_promise, &var_exception); 1401cb0ef41Sopenharmony_ci Branch(IntPtrGreaterThan(args->GetLengthWithoutReceiver(), 1411cb0ef41Sopenharmony_ci IntPtrConstant(kValueOrReasonArg)), 1421cb0ef41Sopenharmony_ci &has_sent_value, &no_sent_value); 1431cb0ef41Sopenharmony_ci BIND(&has_sent_value); 1441cb0ef41Sopenharmony_ci { 1451cb0ef41Sopenharmony_ci iter_result = Call(context, method, sync_iterator, sent_value); 1461cb0ef41Sopenharmony_ci Goto(&merge); 1471cb0ef41Sopenharmony_ci } 1481cb0ef41Sopenharmony_ci BIND(&no_sent_value); 1491cb0ef41Sopenharmony_ci { 1501cb0ef41Sopenharmony_ci iter_result = Call(context, method, sync_iterator); 1511cb0ef41Sopenharmony_ci Goto(&merge); 1521cb0ef41Sopenharmony_ci } 1531cb0ef41Sopenharmony_ci BIND(&merge); 1541cb0ef41Sopenharmony_ci } 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci TNode<Object> value; 1571cb0ef41Sopenharmony_ci TNode<Oddball> done; 1581cb0ef41Sopenharmony_ci std::tie(value, done) = 1591cb0ef41Sopenharmony_ci LoadIteratorResult(context, native_context, iter_result.value(), 1601cb0ef41Sopenharmony_ci &reject_promise, &var_exception); 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci const TNode<JSFunction> promise_fun = 1631cb0ef41Sopenharmony_ci CAST(LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX)); 1641cb0ef41Sopenharmony_ci CSA_DCHECK(this, IsConstructor(promise_fun)); 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci // Let valueWrapper be PromiseResolve(%Promise%, « value »). 1671cb0ef41Sopenharmony_ci // IfAbruptRejectPromise(valueWrapper, promiseCapability). 1681cb0ef41Sopenharmony_ci TNode<Object> value_wrapper; 1691cb0ef41Sopenharmony_ci { 1701cb0ef41Sopenharmony_ci ScopedExceptionHandler handler(this, &reject_promise, &var_exception); 1711cb0ef41Sopenharmony_ci value_wrapper = CallBuiltin(Builtin::kPromiseResolve, native_context, 1721cb0ef41Sopenharmony_ci promise_fun, value); 1731cb0ef41Sopenharmony_ci } 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci // Let onFulfilled be a new built-in function object as defined in 1761cb0ef41Sopenharmony_ci // Async Iterator Value Unwrap Functions. 1771cb0ef41Sopenharmony_ci // Set onFulfilled.[[Done]] to throwDone. 1781cb0ef41Sopenharmony_ci const TNode<JSFunction> on_fulfilled = 1791cb0ef41Sopenharmony_ci CreateUnwrapClosure(native_context, done); 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci // Perform ! PerformPromiseThen(valueWrapper, 1821cb0ef41Sopenharmony_ci // onFulfilled, undefined, promiseCapability). 1831cb0ef41Sopenharmony_ci args->PopAndReturn(CallBuiltin(Builtin::kPerformPromiseThen, context, 1841cb0ef41Sopenharmony_ci value_wrapper, on_fulfilled, 1851cb0ef41Sopenharmony_ci UndefinedConstant(), promise)); 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci BIND(&reject_promise); 1881cb0ef41Sopenharmony_ci { 1891cb0ef41Sopenharmony_ci const TNode<Object> exception = var_exception.value(); 1901cb0ef41Sopenharmony_ci CallBuiltin(Builtin::kRejectPromise, context, promise, exception, 1911cb0ef41Sopenharmony_ci TrueConstant()); 1921cb0ef41Sopenharmony_ci args->PopAndReturn(promise); 1931cb0ef41Sopenharmony_ci } 1941cb0ef41Sopenharmony_ci} 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_cistd::pair<TNode<Object>, TNode<Oddball>> 1971cb0ef41Sopenharmony_ciAsyncFromSyncBuiltinsAssembler::LoadIteratorResult( 1981cb0ef41Sopenharmony_ci const TNode<Context> context, const TNode<NativeContext> native_context, 1991cb0ef41Sopenharmony_ci const TNode<Object> iter_result, Label* if_exception, 2001cb0ef41Sopenharmony_ci TVariable<Object>* var_exception) { 2011cb0ef41Sopenharmony_ci Label if_fastpath(this), if_slowpath(this), merge(this), to_boolean(this), 2021cb0ef41Sopenharmony_ci done(this), if_notanobject(this, Label::kDeferred); 2031cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(iter_result), &if_notanobject); 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ci const TNode<Map> iter_result_map = LoadMap(CAST(iter_result)); 2061cb0ef41Sopenharmony_ci GotoIfNot(IsJSReceiverMap(iter_result_map), &if_notanobject); 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci const TNode<Object> fast_iter_result_map = 2091cb0ef41Sopenharmony_ci LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX); 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_ci TVARIABLE(Object, var_value); 2121cb0ef41Sopenharmony_ci TVARIABLE(Object, var_done); 2131cb0ef41Sopenharmony_ci Branch(TaggedEqual(iter_result_map, fast_iter_result_map), &if_fastpath, 2141cb0ef41Sopenharmony_ci &if_slowpath); 2151cb0ef41Sopenharmony_ci 2161cb0ef41Sopenharmony_ci BIND(&if_fastpath); 2171cb0ef41Sopenharmony_ci { 2181cb0ef41Sopenharmony_ci TNode<JSObject> fast_iter_result = CAST(iter_result); 2191cb0ef41Sopenharmony_ci var_done = LoadObjectField(fast_iter_result, JSIteratorResult::kDoneOffset); 2201cb0ef41Sopenharmony_ci var_value = 2211cb0ef41Sopenharmony_ci LoadObjectField(fast_iter_result, JSIteratorResult::kValueOffset); 2221cb0ef41Sopenharmony_ci Goto(&merge); 2231cb0ef41Sopenharmony_ci } 2241cb0ef41Sopenharmony_ci 2251cb0ef41Sopenharmony_ci BIND(&if_slowpath); 2261cb0ef41Sopenharmony_ci { 2271cb0ef41Sopenharmony_ci ScopedExceptionHandler handler(this, if_exception, var_exception); 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci // Let nextDone be IteratorComplete(nextResult). 2301cb0ef41Sopenharmony_ci // IfAbruptRejectPromise(nextDone, promiseCapability). 2311cb0ef41Sopenharmony_ci const TNode<Object> iter_result_done = 2321cb0ef41Sopenharmony_ci GetProperty(context, iter_result, factory()->done_string()); 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_ci // Let nextValue be IteratorValue(nextResult). 2351cb0ef41Sopenharmony_ci // IfAbruptRejectPromise(nextValue, promiseCapability). 2361cb0ef41Sopenharmony_ci const TNode<Object> iter_result_value = 2371cb0ef41Sopenharmony_ci GetProperty(context, iter_result, factory()->value_string()); 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci var_value = iter_result_value; 2401cb0ef41Sopenharmony_ci var_done = iter_result_done; 2411cb0ef41Sopenharmony_ci Goto(&merge); 2421cb0ef41Sopenharmony_ci } 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_ci BIND(&if_notanobject); 2451cb0ef41Sopenharmony_ci { 2461cb0ef41Sopenharmony_ci // Sync iterator result is not an object --- Produce a TypeError and jump 2471cb0ef41Sopenharmony_ci // to the `if_exception` path. 2481cb0ef41Sopenharmony_ci const TNode<Object> error = MakeTypeError( 2491cb0ef41Sopenharmony_ci MessageTemplate::kIteratorResultNotAnObject, context, iter_result); 2501cb0ef41Sopenharmony_ci *var_exception = error; 2511cb0ef41Sopenharmony_ci Goto(if_exception); 2521cb0ef41Sopenharmony_ci } 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ci BIND(&merge); 2551cb0ef41Sopenharmony_ci // Ensure `iterResult.done` is a Boolean. 2561cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(var_done.value()), &to_boolean); 2571cb0ef41Sopenharmony_ci Branch(IsBoolean(CAST(var_done.value())), &done, &to_boolean); 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci BIND(&to_boolean); 2601cb0ef41Sopenharmony_ci { 2611cb0ef41Sopenharmony_ci const TNode<Object> result = 2621cb0ef41Sopenharmony_ci CallBuiltin(Builtin::kToBoolean, context, var_done.value()); 2631cb0ef41Sopenharmony_ci var_done = result; 2641cb0ef41Sopenharmony_ci Goto(&done); 2651cb0ef41Sopenharmony_ci } 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ci BIND(&done); 2681cb0ef41Sopenharmony_ci return std::make_pair(var_value.value(), CAST(var_done.value())); 2691cb0ef41Sopenharmony_ci} 2701cb0ef41Sopenharmony_ci 2711cb0ef41Sopenharmony_ci} // namespace 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_ci// https://tc39.github.io/proposal-async-iteration/ 2741cb0ef41Sopenharmony_ci// Section #sec-%asyncfromsynciteratorprototype%.next 2751cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncFromSyncIteratorPrototypeNext, AsyncFromSyncBuiltinsAssembler) { 2761cb0ef41Sopenharmony_ci TNode<IntPtrT> argc = ChangeInt32ToIntPtr( 2771cb0ef41Sopenharmony_ci UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount)); 2781cb0ef41Sopenharmony_ci CodeStubArguments args(this, argc); 2791cb0ef41Sopenharmony_ci 2801cb0ef41Sopenharmony_ci const TNode<Object> iterator = args.GetReceiver(); 2811cb0ef41Sopenharmony_ci const TNode<Object> value = args.GetOptionalArgumentValue(kValueOrReasonArg); 2821cb0ef41Sopenharmony_ci const auto context = Parameter<Context>(Descriptor::kContext); 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_ci auto get_method = [=](const TNode<JSReceiver> unused) { 2851cb0ef41Sopenharmony_ci return LoadObjectField(CAST(iterator), 2861cb0ef41Sopenharmony_ci JSAsyncFromSyncIterator::kNextOffset); 2871cb0ef41Sopenharmony_ci }; 2881cb0ef41Sopenharmony_ci Generate_AsyncFromSyncIteratorMethod( 2891cb0ef41Sopenharmony_ci &args, context, iterator, value, get_method, UndefinedMethodHandler(), 2901cb0ef41Sopenharmony_ci "[Async-from-Sync Iterator].prototype.next"); 2911cb0ef41Sopenharmony_ci} 2921cb0ef41Sopenharmony_ci 2931cb0ef41Sopenharmony_ci// https://tc39.github.io/proposal-async-iteration/ 2941cb0ef41Sopenharmony_ci// Section #sec-%asyncfromsynciteratorprototype%.return 2951cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncFromSyncIteratorPrototypeReturn, 2961cb0ef41Sopenharmony_ci AsyncFromSyncBuiltinsAssembler) { 2971cb0ef41Sopenharmony_ci TNode<IntPtrT> argc = ChangeInt32ToIntPtr( 2981cb0ef41Sopenharmony_ci UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount)); 2991cb0ef41Sopenharmony_ci CodeStubArguments args(this, argc); 3001cb0ef41Sopenharmony_ci 3011cb0ef41Sopenharmony_ci const TNode<Object> iterator = args.GetReceiver(); 3021cb0ef41Sopenharmony_ci const TNode<Object> value = args.GetOptionalArgumentValue(kValueOrReasonArg); 3031cb0ef41Sopenharmony_ci const auto context = Parameter<Context>(Descriptor::kContext); 3041cb0ef41Sopenharmony_ci 3051cb0ef41Sopenharmony_ci auto if_return_undefined = [=, &args]( 3061cb0ef41Sopenharmony_ci const TNode<NativeContext> native_context, 3071cb0ef41Sopenharmony_ci const TNode<JSPromise> promise, 3081cb0ef41Sopenharmony_ci Label* if_exception) { 3091cb0ef41Sopenharmony_ci // If return is undefined, then 3101cb0ef41Sopenharmony_ci // Let iterResult be ! CreateIterResultObject(value, true) 3111cb0ef41Sopenharmony_ci const TNode<Object> iter_result = CallBuiltin( 3121cb0ef41Sopenharmony_ci Builtin::kCreateIterResultObject, context, value, TrueConstant()); 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_ci // Perform ! Call(promiseCapability.[[Resolve]], undefined, « iterResult »). 3151cb0ef41Sopenharmony_ci // IfAbruptRejectPromise(nextDone, promiseCapability). 3161cb0ef41Sopenharmony_ci // Return promiseCapability.[[Promise]]. 3171cb0ef41Sopenharmony_ci CallBuiltin(Builtin::kResolvePromise, context, promise, iter_result); 3181cb0ef41Sopenharmony_ci args.PopAndReturn(promise); 3191cb0ef41Sopenharmony_ci }; 3201cb0ef41Sopenharmony_ci 3211cb0ef41Sopenharmony_ci Generate_AsyncFromSyncIteratorMethod( 3221cb0ef41Sopenharmony_ci &args, context, iterator, value, factory()->return_string(), 3231cb0ef41Sopenharmony_ci if_return_undefined, "[Async-from-Sync Iterator].prototype.return"); 3241cb0ef41Sopenharmony_ci} 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci// https://tc39.github.io/proposal-async-iteration/ 3271cb0ef41Sopenharmony_ci// Section #sec-%asyncfromsynciteratorprototype%.throw 3281cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncFromSyncIteratorPrototypeThrow, 3291cb0ef41Sopenharmony_ci AsyncFromSyncBuiltinsAssembler) { 3301cb0ef41Sopenharmony_ci TNode<IntPtrT> argc = ChangeInt32ToIntPtr( 3311cb0ef41Sopenharmony_ci UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount)); 3321cb0ef41Sopenharmony_ci CodeStubArguments args(this, argc); 3331cb0ef41Sopenharmony_ci 3341cb0ef41Sopenharmony_ci const TNode<Object> iterator = args.GetReceiver(); 3351cb0ef41Sopenharmony_ci const TNode<Object> reason = args.GetOptionalArgumentValue(kValueOrReasonArg); 3361cb0ef41Sopenharmony_ci const auto context = Parameter<Context>(Descriptor::kContext); 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_ci auto if_throw_undefined = [=](const TNode<NativeContext> native_context, 3391cb0ef41Sopenharmony_ci const TNode<JSPromise> promise, 3401cb0ef41Sopenharmony_ci Label* if_exception) { Goto(if_exception); }; 3411cb0ef41Sopenharmony_ci 3421cb0ef41Sopenharmony_ci Generate_AsyncFromSyncIteratorMethod( 3431cb0ef41Sopenharmony_ci &args, context, iterator, reason, factory()->throw_string(), 3441cb0ef41Sopenharmony_ci if_throw_undefined, "[Async-from-Sync Iterator].prototype.throw", 3451cb0ef41Sopenharmony_ci Label::kNonDeferred, reason); 3461cb0ef41Sopenharmony_ci} 3471cb0ef41Sopenharmony_ci 3481cb0ef41Sopenharmony_ci} // namespace internal 3491cb0ef41Sopenharmony_ci} // namespace v8 350