mirror of
https://github.com/oven-sh/bun
synced 2026-02-11 03:18:53 +00:00
fix: prevent crash when throwing expect error with pending exception
When a JavaScript exception (like stack overflow from recursive constructor calls) is caught but not fully cleared from JSC's internal state, subsequent calls to Bun.jest().expect() matchers would crash with an assertion failure in debug builds. The crash occurred because: 1. DECLARE_THROW_SCOPE in C++ asserts there's no pending exception 2. VM.throwError in Zig asserts no exception before throwing This fix adds early-return checks in: - deepEqualsWrapperImpl: returns false if exception pending - JSC__JSValue__isStrictEqual: returns false if exception pending - JSC__JSValue__jestDeepMatch: returns false if exception pending - VM.throwError: returns JSError if exception already pending The existing exception will propagate correctly through the CatchScope in the calling Zig code. Fixes ENG-21977 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -160,7 +160,12 @@ pub const VM = opaque {
|
||||
var scope: bun.jsc.ExceptionValidationScope = undefined;
|
||||
scope.init(global_object, @src());
|
||||
defer scope.deinit();
|
||||
scope.assertNoException();
|
||||
// If there's already an exception pending (e.g., from a caught stack overflow
|
||||
// in JavaScript that wasn't fully cleared), just return the error without
|
||||
// asserting or throwing a new exception. The existing exception will propagate.
|
||||
if (scope.hasExceptionOrFalseWhenAssertionsAreDisabled()) {
|
||||
return error.JSError;
|
||||
}
|
||||
JSC__VM__throwError(vm, global_object, value);
|
||||
scope.assertExceptionPresenceMatches(true);
|
||||
return error.JSError;
|
||||
|
||||
@@ -1716,6 +1716,12 @@ template<bool isStrict, bool enableAsymmetricMatchers>
|
||||
inline bool deepEqualsWrapperImpl(JSC::EncodedJSValue a, JSC::EncodedJSValue b, JSC::JSGlobalObject* global)
|
||||
{
|
||||
auto& vm = global->vm();
|
||||
// If there's already an exception pending (e.g., from a caught stack overflow),
|
||||
// return false immediately to avoid triggering assertion failures when creating
|
||||
// a ThrowScope. The caller (fromJSHostCallGeneric in Zig) has a CatchScope that
|
||||
// will handle propagating the exception.
|
||||
if (vm.exceptionForInspection())
|
||||
return false;
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
Vector<std::pair<JSC::JSValue, JSC::JSValue>, 16> stack;
|
||||
MarkedArgumentBuffer args;
|
||||
@@ -2636,6 +2642,10 @@ size_t JSC__VM__heapSize(JSC::VM* arg0)
|
||||
bool JSC__JSValue__isStrictEqual(JSC::EncodedJSValue l, JSC::EncodedJSValue r, JSC::JSGlobalObject* globalObject)
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
// If there's already an exception pending, return false immediately to avoid
|
||||
// triggering assertion failures when creating a ThrowScope.
|
||||
if (vm.exceptionForInspection())
|
||||
return false;
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
RELEASE_AND_RETURN(scope, JSC::JSValue::strictEqual(globalObject, JSC::JSValue::decode(l), JSC::JSValue::decode(r)));
|
||||
}
|
||||
@@ -2672,10 +2682,16 @@ bool JSC__JSValue__jestStrictDeepEquals(JSC::EncodedJSValue JSValue0, JSC::Encod
|
||||
|
||||
bool JSC__JSValue__jestDeepMatch(JSC::EncodedJSValue JSValue0, JSC::EncodedJSValue JSValue1, JSC::JSGlobalObject* globalObject, bool replacePropsWithAsymmetricMatchers)
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
// If there's already an exception pending, return false immediately to avoid
|
||||
// triggering assertion failures when creating a ThrowScope.
|
||||
if (vm.exceptionForInspection())
|
||||
return false;
|
||||
|
||||
JSValue obj = JSValue::decode(JSValue0);
|
||||
JSValue subset = JSValue::decode(JSValue1);
|
||||
|
||||
ThrowScope scope = DECLARE_THROW_SCOPE(globalObject->vm());
|
||||
ThrowScope scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
std::set<EncodedJSValue> objVisited;
|
||||
std::set<EncodedJSValue> subsetVisited;
|
||||
|
||||
Reference in New Issue
Block a user