19class AsyncFromSyncBuiltinsAssembler :
public AsyncBuiltinsAssembler {
25 explicit AsyncFromSyncBuiltinsAssembler(compiler::CodeAssemblerState* state)
26 : AsyncBuiltinsAssembler(state) {}
28 using UndefinedMethodHandler = std::function<void(
29 const TNode<NativeContext>
native_context,
const TNode<JSPromise> promise,
30 const TNode<JSReceiver> sync_iterator, Label* if_exception)>;
31 using SyncIteratorNodeGenerator =
32 std::function<TNode<Object>(TNode<JSReceiver>)>;
33 enum CloseOnRejectionOption { kDoNotCloseOnRejection, kCloseOnRejection };
34 void Generate_AsyncFromSyncIteratorMethod(
35 CodeStubArguments*
args,
const TNode<Context> context,
36 const TNode<Object> iterator,
const TNode<Object> sent_value,
37 const SyncIteratorNodeGenerator& get_method,
38 const UndefinedMethodHandler& if_method_undefined,
39 const char* operation_name, CloseOnRejectionOption close_on_rejection,
40 Label::Type reject_label_type = Label::kDeferred,
41 std::optional<TNode<Object>> initial_exception_value = std::nullopt);
43 void Generate_AsyncFromSyncIteratorMethod(
44 CodeStubArguments*
args,
const TNode<Context> context,
45 const TNode<Object> iterator,
const TNode<Object> sent_value,
46 Handle<String> name,
const UndefinedMethodHandler& if_method_undefined,
47 const char* operation_name, CloseOnRejectionOption close_on_rejection,
48 Label::Type reject_label_type = Label::kDeferred,
49 std::optional<TNode<Object>> initial_exception_value = std::nullopt) {
50 auto get_method = [=,
this](
const TNode<JSReceiver> sync_iterator) {
51 return GetProperty(context, sync_iterator, name);
53 return Generate_AsyncFromSyncIteratorMethod(
54 args, context, iterator, sent_value, get_method, if_method_undefined,
55 operation_name, close_on_rejection, reject_label_type,
56 initial_exception_value);
66 std::pair<TNode<Object>, TNode<Boolean>> LoadIteratorResult(
67 const TNode<Context> context,
const TNode<NativeContext>
native_context,
68 const TNode<JSAny> iter_result, Label* if_exception,
73 struct AsyncFromSyncIteratorCloseSyncAndRethrowContext {
77 TNode<JSFunction> CreateAsyncFromSyncIteratorCloseSyncAndRethrowClosure(
78 TNode<NativeContext>
native_context, TNode<JSReceiver> sync_iterator);
80 TNode<Context> AllocateAsyncFromSyncIteratorCloseSyncAndRethrowContext(
81 TNode<NativeContext>
native_context, TNode<JSReceiver> sync_iterator);
88void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod(
89 CodeStubArguments*
args,
const TNode<Context> context,
90 const TNode<Object> iterator,
const TNode<Object> sent_value,
91 const SyncIteratorNodeGenerator& get_method,
92 const UndefinedMethodHandler& if_method_undefined,
93 const char* operation_name, CloseOnRejectionOption close_on_rejection,
94 Label::Type reject_label_type,
95 std::optional<TNode<Object>> initial_exception_value) {
96 const TNode<NativeContext>
native_context = LoadNativeContext(context);
97 const TNode<JSPromise> promise = NewJSPromise(context);
100 Object, var_exception,
102 Label maybe_close_sync_then_reject_promise(
this, reject_label_type);
103 Label maybe_close_sync_if_not_done_then_reject_promise(
this,
109 HasInstanceType(
CAST(iterator), JS_ASYNC_FROM_SYNC_ITERATOR_TYPE));
110 TNode<JSAsyncFromSyncIterator> async_iterator =
CAST(iterator);
111 const TNode<JSReceiver> sync_iterator = LoadObjectField<JSReceiver>(
112 async_iterator, JSAsyncFromSyncIterator::kSyncIteratorOffset);
114 TNode<Object>
method = get_method(sync_iterator);
116 if (if_method_undefined) {
117 Label if_isnotundefined(
this);
120 if_method_undefined(native_context, promise, sync_iterator,
121 &maybe_close_sync_then_reject_promise);
123 BIND(&if_isnotundefined);
128 Label has_sent_value(
this), no_sent_value(
this), merge(
this);
129 ScopedExceptionHandler
handler(
this, &maybe_close_sync_then_reject_promise,
131 Branch(IntPtrGreaterThan(
args->GetLengthWithoutReceiver(),
133 &has_sent_value, &no_sent_value);
134 BIND(&has_sent_value);
136 iter_result = Call(context,
method, sync_iterator, sent_value);
139 BIND(&no_sent_value);
141 iter_result = Call(context,
method, sync_iterator);
149 std::tie(value, done) =
150 LoadIteratorResult(context, native_context, iter_result.value(),
151 &maybe_close_sync_then_reject_promise, &var_exception);
153 const TNode<JSFunction> promise_fun =
154 CAST(LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX));
159 TNode<Object> value_wrapper;
161 ScopedExceptionHandler
handler(
162 this, &maybe_close_sync_if_not_done_then_reject_promise,
164 value_wrapper = CallBuiltin(Builtin::kPromiseResolve, native_context,
169 const TNode<JSFunction> on_fulfilled =
170 CreateUnwrapClosure(native_context, done);
177 TNode<Object> on_rejected;
178 if (close_on_rejection == kCloseOnRejection) {
179 on_rejected = Select<Object>(
182 return CreateAsyncFromSyncIteratorCloseSyncAndRethrowClosure(
183 native_context, sync_iterator);
191 args->PopAndReturn(CallBuiltin<JSAny>(Builtin::kPerformPromiseThen, context,
192 value_wrapper, on_fulfilled,
193 on_rejected, promise));
195 Label reject_promise(
this);
196 BIND(&maybe_close_sync_if_not_done_then_reject_promise);
198 if (close_on_rejection == kCloseOnRejection) {
199 GotoIf(IsFalse(done), &maybe_close_sync_then_reject_promise);
201 Goto(&reject_promise);
203 BIND(&maybe_close_sync_then_reject_promise);
205 if (close_on_rejection == kCloseOnRejection) {
210 TorqueStructIteratorRecord sync_iterator_record = {sync_iterator, {}};
211 IteratorCloseOnException(context, sync_iterator_record.object);
213 Goto(&reject_promise);
215 BIND(&reject_promise);
217 const TNode<Object> exception = var_exception.value();
218 CallBuiltin(Builtin::kRejectPromise, context, promise, exception,
220 args->PopAndReturn(promise);
224std::pair<TNode<Object>, TNode<Boolean>>
225AsyncFromSyncBuiltinsAssembler::LoadIteratorResult(
226 const TNode<Context> context,
const TNode<NativeContext>
native_context,
227 const TNode<JSAny> iter_result, Label* if_exception,
229 Label if_fastpath(
this), if_slowpath(
this), merge(
this), to_boolean(
this),
230 done(
this), if_notanobject(
this, Label::kDeferred);
231 GotoIf(TaggedIsSmi(iter_result), &if_notanobject);
233 const TNode<Map> iter_result_map = LoadMap(
CAST(iter_result));
234 GotoIfNot(JSAnyIsNotPrimitiveMap(iter_result_map), &if_notanobject);
236 const TNode<Object> fast_iter_result_map =
237 LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
241 Branch(TaggedEqual(iter_result_map, fast_iter_result_map), &if_fastpath,
246 TNode<JSObject> fast_iter_result =
CAST(iter_result);
247 var_done = LoadObjectField(fast_iter_result, JSIteratorResult::kDoneOffset);
249 LoadObjectField(fast_iter_result, JSIteratorResult::kValueOffset);
255 ScopedExceptionHandler
handler(
this, if_exception, var_exception);
259 const TNode<Object> iter_result_done =
260 GetProperty(context, iter_result, factory()->done_string());
264 const TNode<Object> iter_result_value =
265 GetProperty(context, iter_result, factory()->value_string());
267 var_value = iter_result_value;
268 var_done = iter_result_done;
272 BIND(&if_notanobject);
276 const TNode<Object> error = MakeTypeError(
277 MessageTemplate::kIteratorResultNotAnObject, context, iter_result);
278 *var_exception = error;
284 GotoIf(TaggedIsSmi(var_done.value()), &to_boolean);
285 Branch(IsBoolean(
CAST(var_done.value())), &done, &to_boolean);
289 const TNode<Object>
result =
290 CallBuiltin(Builtin::kToBoolean, context, var_done.value());
296 return std::make_pair(var_value.value(),
CAST(var_done.value()));
299TNode<JSFunction> AsyncFromSyncBuiltinsAssembler::
300 CreateAsyncFromSyncIteratorCloseSyncAndRethrowClosure(
301 TNode<NativeContext>
native_context, TNode<JSReceiver> sync_iterator) {
302 const TNode<Context> closure_context =
303 AllocateAsyncFromSyncIteratorCloseSyncAndRethrowContext(native_context,
305 return AllocateRootFunctionWithContext(
306 RootIndex::kAsyncFromSyncIteratorCloseSyncAndRethrowSharedFun,
307 closure_context, native_context);
310TNode<Context> AsyncFromSyncBuiltinsAssembler::
311 AllocateAsyncFromSyncIteratorCloseSyncAndRethrowContext(
312 TNode<NativeContext>
native_context, TNode<JSReceiver> sync_iterator) {
313 TNode<Context> context = AllocateSyntheticFunctionContext(
314 native_context, AsyncFromSyncIteratorCloseSyncAndRethrowContext::kLength);
315 StoreContextElementNoWriteBarrier(
316 context, AsyncFromSyncIteratorCloseSyncAndRethrowContext::kSyncIterator,
324TF_BUILTIN(AsyncFromSyncIteratorPrototypeNext, AsyncFromSyncBuiltinsAssembler) {
326 UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount));
331 const auto context = Parameter<Context>(Descriptor::kContext);
334 return LoadObjectField(
CAST(iterator),
335 JSAsyncFromSyncIterator::kNextOffset);
337 Generate_AsyncFromSyncIteratorMethod(
338 &
args, context, iterator, value, get_method, UndefinedMethodHandler(),
339 "[Async-from-Sync Iterator].prototype.next", kCloseOnRejection);
344 AsyncFromSyncBuiltinsAssembler) {
346 UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount));
351 const auto context = Parameter<Context>(Descriptor::kContext);
353 auto if_return_undefined = [=,
this, &
args](
357 Label* if_exception) {
361 Builtin::kCreateIterResultObject, context, value, TrueConstant());
366 CallBuiltin(Builtin::kResolvePromise, context, promise, iter_result);
367 args.PopAndReturn(promise);
370 Generate_AsyncFromSyncIteratorMethod(
371 &
args, context, iterator, value, factory()->return_string(),
372 if_return_undefined,
"[Async-from-Sync Iterator].prototype.return",
373 kDoNotCloseOnRejection);
378 AsyncFromSyncBuiltinsAssembler) {
380 UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount));
385 const auto context = Parameter<Context>(Descriptor::kContext);
388 auto if_throw_undefined =
392 Label* if_exception) {
402 TorqueStructIteratorRecord sync_iterator_record = {sync_iterator, {}};
403 IteratorClose(context, sync_iterator_record);
417 MakeTypeError(MessageTemplate::kThrowMethodMissing, context);
420 CallBuiltin(Builtin::kRejectPromise, context, promise,
421 var_reject_value.value(), TrueConstant());
422 args.PopAndReturn(promise);
425 Generate_AsyncFromSyncIteratorMethod(
426 &
args, context, iterator, reason, factory()->throw_string(),
427 if_throw_undefined,
"[Async-from-Sync Iterator].prototype.throw",
428 kCloseOnRejection, Label::kNonDeferred, reason);
432 AsyncFromSyncBuiltinsAssembler) {
442 auto error = Parameter<Object>(Descriptor::kError);
443 auto context = Parameter<Context>(Descriptor::kContext);
446 context, AsyncFromSyncIteratorCloseSyncAndRethrowContext::kSyncIterator));
448 TorqueStructIteratorRecord sync_iterator_record = {sync_iterator, {}};
449 IteratorCloseOnException(context, sync_iterator_record.object);
450 Return(
CallRuntime(Runtime::kReThrow, context, error));
#define CSA_DCHECK(csa,...)
#define CSA_CHECK(csa, x)
static const int kValueOrReasonArg
#define TF_BUILTIN(Name, AssemblerBase)
base::Vector< const DirectHandle< Object > > args
ZoneVector< RpoNumber > & result
TNode< Oddball > UndefinedConstant(JSGraph *jsgraph)
compiler::TypedCodeAssemblerVariable< T > TVariable
bool IsNullOrUndefined(Tagged< Object > obj, Isolate *isolate)
!IsContextMap !IsContextMap native_context
std::unique_ptr< ValueMirror > value