diff --git a/src/jsc/bindings/BunObject.cpp b/src/jsc/bindings/BunObject.cpp index 02a1127e00df..d3d19a4399f4 100644 --- a/src/jsc/bindings/BunObject.cpp +++ b/src/jsc/bindings/BunObject.cpp @@ -319,9 +319,6 @@ static JSValue defaultBunSQLObject(VM& vm, JSObject* bunObject) auto scope = DECLARE_THROW_SCOPE(vm); auto* globalObject = defaultGlobalObject(bunObject->globalObject()); JSValue sqlValue = globalObject->internalModuleRegistry()->requireId(globalObject, vm, InternalModuleRegistry::BunSql); -#if BUN_DEBUG - if (scope.exception()) globalObject->reportUncaughtExceptionAtEventLoop(globalObject, scope.exception()); -#endif RETURN_IF_EXCEPTION(scope, {}); RELEASE_AND_RETURN(scope, sqlValue.getObject()->get(globalObject, vm.propertyNames->defaultKeyword)); } @@ -331,9 +328,6 @@ static JSValue constructBunSQLObject(VM& vm, JSObject* bunObject) auto scope = DECLARE_THROW_SCOPE(vm); auto* globalObject = defaultGlobalObject(bunObject->globalObject()); JSValue sqlValue = globalObject->internalModuleRegistry()->requireId(globalObject, vm, InternalModuleRegistry::BunSql); -#if BUN_DEBUG - if (scope.exception()) globalObject->reportUncaughtExceptionAtEventLoop(globalObject, scope.exception()); -#endif RETURN_IF_EXCEPTION(scope, {}); auto clientData = WebCore::clientData(vm); RELEASE_AND_RETURN(scope, sqlValue.getObject()->get(globalObject, clientData->builtinNames().SQLPublicName())); diff --git a/test/js/sql/sql-lazy-load-throw.test.ts b/test/js/sql/sql-lazy-load-throw.test.ts new file mode 100644 index 000000000000..96aebf65e9f9 --- /dev/null +++ b/test/js/sql/sql-lazy-load-throw.test.ts @@ -0,0 +1,31 @@ +import { expect, test } from "bun:test"; +import { bunEnv, bunExe } from "harness"; + +test("Bun.SQL lazy getter propagates module load errors without crashing", async () => { + // The bun:sql internal module reads global `Symbol` at top level. If user + // code has clobbered the global before the first access, evaluating the + // module throws. That exception must propagate back to the caller as a + // normal JS error rather than crashing the process. + await using proc = Bun.spawn({ + cmd: [ + bunExe(), + "-e", + ` + globalThis.Symbol = "i"; + let caught = 0; + try { Bun.sql; } catch { caught++; } + try { Bun.SQL; } catch { caught++; } + console.log("caught=" + caught); + `, + ], + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + + const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); + + expect(stdout.trim()).toBe("caught=2"); + expect(stderr).toBe(""); + expect(exitCode).toBe(0); +});