* quickjs-go local await helper. * * Unlike js_std_await from quickjs-libc, this keeps polling in bounded slices * and explicitly polls interrupt state directly so * execute-timeout/interrupt handlers can abort permanently pending promises. */
| 370 | * execute-timeout/interrupt handlers can abort permanently pending promises. |
| 371 | */ |
| 372 | JSValue AwaitValue(JSContext *ctx, JSValue obj) { |
| 373 | JSRuntime *rt = JS_GetRuntime(ctx); |
| 374 | |
| 375 | for (;;) { |
| 376 | if (ThrowUnhandledPromiseRejectionIfAny(ctx)) { |
| 377 | JS_FreeValue(ctx, obj); |
| 378 | return JS_EXCEPTION; |
| 379 | } |
| 380 | |
| 381 | if (isExecuteTimeoutExceeded(rt)) { |
| 382 | JS_FreeValue(ctx, obj); |
| 383 | JS_ThrowInternalError(ctx, "interrupted"); |
| 384 | return JS_EXCEPTION; |
| 385 | } |
| 386 | |
| 387 | int state = JS_PromiseState(ctx, obj); |
| 388 | if (state == JS_PROMISE_FULFILLED) { |
| 389 | JSValue ret = JS_PromiseResult(ctx, obj); |
| 390 | JS_FreeValue(ctx, obj); |
| 391 | return ret; |
| 392 | } |
| 393 | |
| 394 | if (state == JS_PROMISE_REJECTED) { |
| 395 | JSValue ret = JS_Throw(ctx, JS_PromiseResult(ctx, obj)); |
| 396 | JS_FreeValue(ctx, obj); |
| 397 | return ret; |
| 398 | } |
| 399 | |
| 400 | if (state != JS_PROMISE_PENDING) { |
| 401 | return obj; |
| 402 | } |
| 403 | |
| 404 | JSContext *ctx1 = NULL; |
| 405 | int err = JS_ExecutePendingJob(rt, &ctx1); |
| 406 | if (err < 0) { |
| 407 | if (ctx1 != NULL && ctx1 != ctx) { |
| 408 | JSValue ex = JS_GetException(ctx1); |
| 409 | JS_Throw(ctx, ex); |
| 410 | } |
| 411 | JS_FreeValue(ctx, obj); |
| 412 | return JS_EXCEPTION; |
| 413 | } |
| 414 | |
| 415 | /* Bound host IO polling to avoid an uninterruptible blocking wait. */ |
| 416 | if (err == 0) { |
| 417 | /* |
| 418 | * Drive timers/microtasks so promises resolved by setTimeout can |
| 419 | * progress while awaiting. |
| 420 | */ |
| 421 | int loop_once_ret = js_std_loop_once(ctx); |
| 422 | if (loop_once_ret == -2) { |
| 423 | JS_FreeValue(ctx, obj); |
| 424 | return JS_EXCEPTION; |
| 425 | } |
| 426 | if (loop_once_ret == 0) { |
| 427 | continue; |
| 428 | } |
| 429 |
no test coverage detected