Fix unhandled exception in JSC__JSPromise__wrap when resolving promise (#23961)

### What does this PR do?

Previously, `JSC__JSPromise__wrap` would call
`JSC::JSPromise::resolvedPromise(globalObject, result)` without checking
if an exception was thrown during promise resolution. This
could happen in certain edge cases, such as when the result value is a
thenable that triggers stack overflow, or when the promise resolution
mechanism itself encounters an error.
When such exceptions occurred, they would escape back to the Zig code,
causing the CatchScope assertion to fail with "ASSERTION FAILED:
Unexpected exception observed on thread"
instead of being properly handled.

This PR adds an exception check immediately after calling
`JSC::JSPromise::resolvedPromise()` and before the `RELEASE_AND_RETURN`
macro. If an exception is detected, the function
now clears it and returns a rejected promise with the exception value,
ensuring consistent error handling behavior. This matches the pattern
already used earlier in the function
for the initial function call exception handling.

### How did you verify your code works?

new and existing tests

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
SUZUKI Sosuke
2025-10-25 13:36:33 +09:00
committed by GitHub
parent cfe561a083
commit f4b6396eac
2 changed files with 23 additions and 2 deletions

View File

@@ -3397,7 +3397,14 @@ JSC::EncodedJSValue JSC__JSPromise__wrap(JSC::JSGlobalObject* globalObject, void
RELEASE_AND_RETURN(scope, JSValue::encode(JSC::JSPromise::rejectedPromise(globalObject, err)));
}
RELEASE_AND_RETURN(scope, JSValue::encode(JSC::JSPromise::resolvedPromise(globalObject, result)));
JSValue resolved = JSC::JSPromise::resolvedPromise(globalObject, result);
if (scope.exception()) [[unlikely]] {
auto* exception = scope.exception();
scope.clearException();
RELEASE_AND_RETURN(scope, JSValue::encode(JSC::JSPromise::rejectedPromise(globalObject, exception->value())));
}
RELEASE_AND_RETURN(scope, JSValue::encode(resolved));
}
[[ZIG_EXPORT(check_slow)]] void JSC__JSPromise__reject(JSC::JSPromise* arg0, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue JSValue2)