spawnSync shouldn't throw (#15561)

Co-authored-by: Meghan Denny <meghan@bun.sh>
This commit is contained in:
Jarred Sumner
2024-12-03 19:26:36 -08:00
committed by GitHub
parent d27594ecf4
commit 0d5e4e162b
4 changed files with 51 additions and 18 deletions

View File

@@ -1766,13 +1766,13 @@ pub const Subprocess = struct {
if (argv0 == null) {
var path_buf: bun.PathBuffer = undefined;
const resolved = Which.which(&path_buf, PATH, cwd, arg0.slice()) orelse {
return globalThis.throwInvalidArguments("Executable not found in $PATH: \"{s}\"", .{arg0.slice()});
return throwCommandNotFound(globalThis, arg0.slice());
};
argv0 = try allocator.dupeZ(u8, resolved);
} else {
var path_buf: bun.PathBuffer = undefined;
const resolved = Which.which(&path_buf, PATH, cwd, bun.sliceTo(argv0.?, 0)) orelse {
return globalThis.throwInvalidArguments("Executable not found in $PATH: \"{s}\"", .{arg0.slice()});
return throwCommandNotFound(globalThis, arg0.slice());
};
argv0 = try allocator.dupeZ(u8, resolved);
}
@@ -2314,6 +2314,15 @@ pub const Subprocess = struct {
return sync_value;
}
fn throwCommandNotFound(globalThis: *JSC.JSGlobalObject, command: []const u8) bun.JSError {
const message = bun.String.createFormat("Executable not found in $PATH: \"{s}\"", .{command}) catch bun.outOfMemory();
defer message.deref();
const err = message.toZigString().toErrorInstance(globalThis);
err.putZigString(globalThis, JSC.ZigString.static("code"), JSC.ZigString.init("ENOENT").toJS(globalThis));
err.putZigString(globalThis, JSC.ZigString.static("path"), JSC.ZigString.init(command).toJS(globalThis));
return globalThis.throwValue(err);
}
const node_cluster_binding = @import("./../../node/node_cluster_binding.zig");
pub fn handleIPCMessage(

View File

@@ -4197,7 +4197,7 @@ pub const JSValue = enum(i64) {
return cppFn("putRecord", .{ value, global, key, values_array, values_len });
}
fn putZigString(value: JSValue, global: *JSGlobalObject, key: *const ZigString, result: JSC.JSValue) void {
pub fn putZigString(value: JSValue, global: *JSGlobalObject, key: *const ZigString, result: JSC.JSValue) void {
@import("./headers.zig").JSC__JSValue__put(value, global, key, result);
}

View File

@@ -558,20 +558,27 @@ function spawnSync(file, args, options) {
}
}
const {
stdout = null,
stderr = null,
success,
exitCode,
signalCode,
} = Bun.spawnSync({
cmd: options.args,
env: options.env || undefined,
cwd: options.cwd || undefined,
stdio: bunStdio,
windowsVerbatimArguments: options.windowsVerbatimArguments,
windowsHide: options.windowsHide,
});
var error;
try {
var {
stdout = null,
stderr = null,
success,
exitCode,
signalCode,
} = Bun.spawnSync({
cmd: options.args,
env: options.env || undefined,
cwd: options.cwd || undefined,
stdio: bunStdio,
windowsVerbatimArguments: options.windowsVerbatimArguments,
windowsHide: options.windowsHide,
});
} catch (err) {
error = err;
stdout = null;
stderr = null;
}
const result = {
signal: signalCode ?? null,
@@ -580,6 +587,10 @@ function spawnSync(file, args, options) {
output: [null, stdout, stderr],
};
if (error) {
result.error = error;
}
if (stdout && encoding && encoding !== "buffer") {
result.output[1] = result.output[1]?.toString(encoding);
}
@@ -591,8 +602,11 @@ function spawnSync(file, args, options) {
result.stdout = result.output[1];
result.stderr = result.output[2];
if (!success) {
if (!success && error == null) {
result.error = new SystemError(result.output[2], options.file, "spawnSync", -1, result.status);
}
if (result.error) {
result.error.spawnargs = ArrayPrototypeSlice.$call(options.args, 1);
}

View File

@@ -454,3 +454,13 @@ it.if(!isWindows)("spawnSync correctly reports signal codes", () => {
expect(signal).toBe("SIGTRAP");
});
it("spawnSync(does-not-exist)", () => {
const x = spawnSync("does-not-exist");
expect(x.error?.code).toEqual("ENOENT");
expect(x.error.path).toEqual("does-not-exist");
expect(x.signal).toEqual(null);
expect(x.output).toEqual([null, null, null]);
expect(x.stdout).toEqual(null);
expect(x.stderr).toEqual(null);
});