diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index db24591323..a3153d67e1 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -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) diff --git a/test/js/web/fetch/response.test.ts b/test/js/web/fetch/response.test.ts index c5a249f6d1..cdbdfd42a9 100644 --- a/test/js/web/fetch/response.test.ts +++ b/test/js/web/fetch/response.test.ts @@ -49,7 +49,7 @@ describe("2-arg form", () => { test("print size", () => { expect(normalizeBunSnapshot(Bun.inspect(new Response(Bun.file(import.meta.filename)))), import.meta.dir) .toMatchInlineSnapshot(` - "Response (3.82 KB) { + "Response (4.15 KB) { ok: true, url: "", status: 200, @@ -109,3 +109,17 @@ test("new Response(123, { method: 456 }) does not throw", () => { // @ts-expect-error expect(() => new Response("123", { method: 456 })).not.toThrow(); }); + +test("handle stack overflow", () => { + function f0(a1, a2) { + const v4 = new Response(); + // @ts-ignore + const v5 = v4.text(a2, a2, v4, f0, f0); + a1(a1); // Recursive call causes stack overflow + return v5; + } + expect(() => { + // @ts-ignore + f0(f0); + }).toThrow("Maximum call stack size exceeded."); +});