mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
wip
This commit is contained in:
@@ -404,32 +404,45 @@ export function runOnResolvePlugins(this: BundlerPlugin, specifier, inputNamespa
|
||||
|
||||
for (let [filter, callback] of results) {
|
||||
if (filter.test(inputPath)) {
|
||||
var result = callback({
|
||||
path: inputPath,
|
||||
importer,
|
||||
namespace: inputNamespace,
|
||||
resolveDir: inputNamespace === "file" ? require("node:path").dirname(importer) : undefined,
|
||||
kind,
|
||||
// pluginData
|
||||
});
|
||||
var result;
|
||||
try {
|
||||
result = callback({
|
||||
path: inputPath,
|
||||
importer,
|
||||
namespace: inputNamespace,
|
||||
resolveDir: inputNamespace === "file" ? require("node:path").dirname(importer) : undefined,
|
||||
kind,
|
||||
// pluginData
|
||||
});
|
||||
|
||||
while (
|
||||
result &&
|
||||
$isPromise(result) &&
|
||||
($getPromiseInternalField(result, $promiseFieldFlags) & $promiseStateMask) === $promiseStateFulfilled
|
||||
) {
|
||||
result = $getPromiseInternalField(result, $promiseFieldReactionsOrResult);
|
||||
}
|
||||
|
||||
if (result && $isPromise(result)) {
|
||||
result = await result;
|
||||
}
|
||||
|
||||
if (!result || !$isObject(result)) {
|
||||
// Handle promise resolution carefully with explicit undefined handling
|
||||
if ($isPromise(result)) {
|
||||
try {
|
||||
const promiseResult = await result;
|
||||
// Explicitly handle undefined/null promise results
|
||||
if (promiseResult === undefined || promiseResult === null) {
|
||||
continue;
|
||||
}
|
||||
result = promiseResult;
|
||||
} catch (e) {
|
||||
// If promise rejection, continue to next plugin
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// If callback throws or causes internal error, continue to next plugin
|
||||
continue;
|
||||
}
|
||||
|
||||
var { path, namespace: userNamespace = inputNamespace, external } = result;
|
||||
// Explicitly handle undefined return values from plugins
|
||||
if (result === undefined || result === null || !$isObject(result)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Safely extract properties with explicit undefined checks
|
||||
var path = result.path;
|
||||
var userNamespace = result.namespace !== undefined ? result.namespace : inputNamespace;
|
||||
var external = result.external;
|
||||
if (path !== undefined && typeof path !== "string") {
|
||||
throw new TypeError("onResolve plugins 'path' field must be a string if provided");
|
||||
}
|
||||
|
||||
153
test/regression/issue/22199.test.ts
Normal file
153
test/regression/issue/22199.test.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
import { describe, test, expect } from "bun:test";
|
||||
import { bunEnv, bunExe, tempDirWithFiles } from "harness";
|
||||
|
||||
// Regression test for issue #22199: segmentation fault when build.onResolve returns undefined
|
||||
describe("issue #22199", () => {
|
||||
test("onResolve returning undefined should not crash - sync", async () => {
|
||||
const tempDir = tempDirWithFiles("plugin-test", {
|
||||
"plugin.ts": /* ts */ `
|
||||
Bun.plugin({
|
||||
name: "test-plugin",
|
||||
setup(build) {
|
||||
build.onResolve({ filter: /.*\.(ts|tsx|js|jsx)$/ }, (args) => {
|
||||
return undefined; // This should not crash
|
||||
});
|
||||
},
|
||||
});
|
||||
`,
|
||||
"index.ts": /* ts */ `
|
||||
console.log("Hello, World");
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "--preload", "plugin.ts", "index.ts"],
|
||||
cwd: tempDir,
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
proc.stdout.text(),
|
||||
proc.stderr.text(),
|
||||
proc.exited,
|
||||
]);
|
||||
|
||||
// Should not crash with segmentation fault
|
||||
expect(exitCode).toBe(0);
|
||||
expect(stdout.trim()).toBe("Hello, World");
|
||||
expect(stderr).toBe("");
|
||||
});
|
||||
|
||||
test("onResolve returning undefined should not crash - async", async () => {
|
||||
const tempDir = tempDirWithFiles("plugin-test-async", {
|
||||
"plugin.ts": /* ts */ `
|
||||
Bun.plugin({
|
||||
name: "test-plugin",
|
||||
setup(build) {
|
||||
build.onResolve({ filter: /.*\.(ts|tsx|js|jsx)$/ }, async (args) => {
|
||||
return undefined; // This should not crash
|
||||
});
|
||||
},
|
||||
});
|
||||
`,
|
||||
"index.ts": /* ts */ `
|
||||
console.log("Hello, World");
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "--preload", "plugin.ts", "index.ts"],
|
||||
cwd: tempDir,
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
proc.stdout.text(),
|
||||
proc.stderr.text(),
|
||||
proc.exited,
|
||||
]);
|
||||
|
||||
// Should not crash with segmentation fault
|
||||
expect(exitCode).toBe(0);
|
||||
expect(stdout.trim()).toBe("Hello, World");
|
||||
expect(stderr).toBe("");
|
||||
});
|
||||
|
||||
test("onResolve returning Promise.resolve(undefined) should not crash", async () => {
|
||||
const tempDir = tempDirWithFiles("plugin-test-promise", {
|
||||
"plugin.ts": /* ts */ `
|
||||
Bun.plugin({
|
||||
name: "test-plugin",
|
||||
setup(build) {
|
||||
build.onResolve({ filter: /.*\.(ts|tsx|js|jsx)$/ }, (args) => {
|
||||
return Promise.resolve(undefined); // This should not crash
|
||||
});
|
||||
},
|
||||
});
|
||||
`,
|
||||
"index.ts": /* ts */ `
|
||||
console.log("Hello, World");
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "--preload", "plugin.ts", "index.ts"],
|
||||
cwd: tempDir,
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
proc.stdout.text(),
|
||||
proc.stderr.text(),
|
||||
proc.exited,
|
||||
]);
|
||||
|
||||
// Should not crash with segmentation fault
|
||||
expect(exitCode).toBe(0);
|
||||
expect(stdout.trim()).toBe("Hello, World");
|
||||
expect(stderr).toBe("");
|
||||
});
|
||||
|
||||
test("onResolve returning null should not crash - async", async () => {
|
||||
const tempDir = tempDirWithFiles("plugin-test-null", {
|
||||
"plugin.ts": /* ts */ `
|
||||
Bun.plugin({
|
||||
name: "test-plugin",
|
||||
setup(build) {
|
||||
build.onResolve({ filter: /.*\.(ts|tsx|js|jsx)$/ }, async (args) => {
|
||||
return null; // This should not crash
|
||||
});
|
||||
},
|
||||
});
|
||||
`,
|
||||
"index.ts": /* ts */ `
|
||||
console.log("Hello, World");
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "--preload", "plugin.ts", "index.ts"],
|
||||
cwd: tempDir,
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
proc.stdout.text(),
|
||||
proc.stderr.text(),
|
||||
proc.exited,
|
||||
]);
|
||||
|
||||
// Should not crash with segmentation fault
|
||||
expect(exitCode).toBe(0);
|
||||
expect(stdout.trim()).toBe("Hello, World");
|
||||
expect(stderr).toBe("");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user