diff --git a/src/jsc/bindings/BunPlugin.cpp b/src/jsc/bindings/BunPlugin.cpp index 5773394aed3..e9117400dc9 100644 --- a/src/jsc/bindings/BunPlugin.cpp +++ b/src/jsc/bindings/BunPlugin.cpp @@ -304,11 +304,13 @@ static inline JSC::EncodedJSValue setupBunPlugin(JSC::JSGlobalObject* globalObje if (targetValue) { if (auto* targetJSString = targetValue.toStringOrNull(globalObject)) { String targetString = targetJSString->value(globalObject); + RETURN_IF_EXCEPTION(throwScope, {}); if (!(targetString == "node"_s || targetString == "bun"_s || targetString == "browser"_s)) { JSC::throwTypeError(globalObject, throwScope, "plugin target must be one of 'node', 'bun' or 'browser'"_s); return {}; } } + RETURN_IF_EXCEPTION(throwScope, {}); } JSObject* builderObject = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 4); diff --git a/test/js/bun/plugin/plugins.test.ts b/test/js/bun/plugin/plugins.test.ts index 1ccd453b224..70ae31e289c 100644 --- a/test/js/bun/plugin/plugins.test.ts +++ b/test/js/bun/plugin/plugins.test.ts @@ -366,6 +366,44 @@ describe("errors", () => { }).toThrow("plugin target must be one of 'node', 'bun' or 'browser'"); }); + it("throws when target Symbol.toPrimitive returns an object", () => { + expect(() => { + plugin({ + target: { + [Symbol.toPrimitive]() { + return {}; + }, + }, + setup() {}, + } as any); + }).toThrow(TypeError); + }); + + it("propagates exceptions thrown while coercing target to string", () => { + const err = new Error("boom"); + expect(() => { + plugin({ + target: { + [Symbol.toPrimitive]() { + throw err; + }, + }, + setup() {}, + } as any); + }).toThrow(err); + + expect(() => { + plugin({ + target: { + toString() { + throw err; + }, + }, + setup() {}, + } as any); + }).toThrow(err); + }); + it("invalid loaders throw", () => { const invalidLoaders = ["blah", "blah2", "blah3", "blah4"]; const inputs = ["body { background: red; }", "