Compare commits

...

8 Commits

Author SHA1 Message Date
Jarred Sumner
a8e4722bd1 Check that the pid matches 2023-09-12 03:37:09 -07:00
Jarred Sumner
6dcdd2026a Add a couple tests 2023-09-12 02:27:16 -07:00
Jarred Sumner
169794902b Handle quotes in error messages a little better 2023-09-12 02:27:09 -07:00
Jarred Sumner
a3a02ea381 Don't print build errors twice 2023-09-12 02:26:55 -07:00
Jarred Sumner
d607d1d459 Bump 2023-09-12 02:25:19 -07:00
Jarred Sumner
53cd95a29e Make this error message better 2023-09-12 01:58:07 -07:00
Jarred Sumner
41237c874a [bun run] don't parse tsconfig.json for package.json scripts 2023-09-12 01:58:01 -07:00
Jarred Sumner
2b92d94b4d Clean up some error handling when loading tsconfig.json 2023-09-12 01:57:09 -07:00
8 changed files with 137 additions and 29 deletions

View File

@@ -1 +1 @@
0
1

View File

@@ -1462,25 +1462,54 @@ pub const Subprocess = struct {
const kernel = @import("../../../analytics.zig").GenerateHeader.GeneratePlatform.kernelVersion();
// pidfd_nonblock only supported in 5.10+
const pidfd_flags: u32 = if (!is_sync and kernel.orderWithoutTag(.{ .major = 5, .minor = 10, .patch = 0 }).compare(.gte))
var pidfd_flags: u32 = if (!is_sync and kernel.orderWithoutTag(.{ .major = 5, .minor = 10, .patch = 0 }).compare(.gte))
std.os.O.NONBLOCK
else
0;
const fd = std.os.linux.pidfd_open(
var fd: std.os.linux.fd_t = std.os.linux.pidfd_open(
pid,
pidfd_flags,
);
switch (std.os.linux.getErrno(fd)) {
.SUCCESS => break :brk @as(std.os.fd_t, @intCast(fd)),
else => |err| {
globalThis.throwValue(bun.sys.Error.fromCode(err, .open).toJSC(globalThis));
var status: u32 = 0;
// ensure we don't leak the child process on error
_ = std.os.linux.waitpid(pid, &status, 0);
return .zero;
},
while (true) {
switch (std.os.linux.getErrno(fd)) {
.SUCCESS => break :brk @as(std.os.fd_t, @intCast(fd)),
.INTR => continue,
else => |err| {
if (err == .INVAL) {
if (pidfd_flags != 0) {
fd = std.os.linux.pidfd_open(
pid,
0,
);
pidfd_flags = 0;
continue;
}
}
const error_instance = brk2: {
if (err == .NOSYS) {
break :brk2 globalThis.createErrorInstance(
\\"pidfd_open(2)" system call is not supported by your Linux kernel
\\To fix this error, either:
\\- Upgrade your Linux kernel to a newer version (current: {})
\\- Ensure the seccomp filter allows \"pidfd_open\"
,
.{
kernel.fmt(""),
},
);
}
break :brk2 bun.sys.Error.fromCode(err, .open).toJSC(globalThis);
};
globalThis.throwValue(error_instance);
var status: u32 = 0;
// ensure we don't leak the child process on error
_ = std.os.linux.waitpid(pid, &status, 0);
return .zero;
},
}
}
};
@@ -1682,14 +1711,16 @@ pub const Subprocess = struct {
this.waitpid_err = err;
},
.result => |result| {
if (std.os.W.IFEXITED(result.status)) {
this.exit_code = @as(u8, @truncate(std.os.W.EXITSTATUS(result.status)));
}
if (result.pid == pid) {
if (std.os.W.IFEXITED(result.status)) {
this.exit_code = @as(u8, @truncate(std.os.W.EXITSTATUS(result.status)));
}
if (std.os.W.IFSIGNALED(result.status)) {
this.signal_code = @as(SignalCode, @enumFromInt(@as(u8, @truncate(std.os.W.TERMSIG(result.status)))));
} else if (std.os.W.IFSTOPPED(result.status)) {
this.signal_code = @as(SignalCode, @enumFromInt(@as(u8, @truncate(std.os.W.STOPSIG(result.status)))));
if (std.os.W.IFSIGNALED(result.status)) {
this.signal_code = @as(SignalCode, @enumFromInt(@as(u8, @truncate(std.os.W.TERMSIG(result.status)))));
} else if (std.os.W.IFSTOPPED(result.status)) {
this.signal_code = @as(SignalCode, @enumFromInt(@as(u8, @truncate(std.os.W.STOPSIG(result.status)))));
}
}
if (!this.hasExited()) {

View File

@@ -273,6 +273,7 @@ pub const Run = struct {
} else {
vm.log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), false) catch {};
}
vm.log.msgs.items.len = 0;
Output.prettyErrorln("\n", .{});
Output.flush();
}

View File

@@ -482,6 +482,10 @@ pub const RunCommand = struct {
this_bundler.resolver.care_about_bin_folder = true;
this_bundler.resolver.care_about_scripts = true;
this_bundler.resolver.opts.load_tsconfig_json = false;
this_bundler.options.load_tsconfig_json = false;
this_bundler.configureLinker();
var root_dir_info = this_bundler.resolver.readDirInfo(this_bundler.fs.top_level_dir) catch |err| {
@@ -491,7 +495,7 @@ pub const RunCommand = struct {
} else {
ctx.log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), false) catch {};
}
Output.prettyErrorln("Error loading directory: \"{s}\"", .{@errorName(err)});
Output.prettyErrorln("<r><red>error<r><d>:<r> <b>{s}<r> loading directory {}", .{ @errorName(err), strings.QuotedFormatter{ .text = this_bundler.fs.top_level_dir } });
Output.flush();
return err;
} orelse {
@@ -500,7 +504,7 @@ pub const RunCommand = struct {
} else {
ctx.log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), false) catch {};
}
Output.prettyErrorln("Error loading current directory", .{});
Output.prettyErrorln("error loading current directory", .{});
Output.flush();
return error.CouldntReadCurrentDirectory;
};

View File

@@ -1246,7 +1246,15 @@ const PackageInstall = struct {
std.os.mkdirat(destination_dir_.dir.fd, entry.path, 0o755) catch {};
},
.file => {
try std.os.linkat(entry.dir.dir.fd, entry.basename, destination_dir_.dir.fd, entry.path, 0);
std.os.linkat(entry.dir.dir.fd, entry.basename, destination_dir_.dir.fd, entry.path, 0) catch |err| {
if (err != error.PathAlreadyExists) {
return err;
}
std.os.unlinkat(destination_dir_.dir.fd, entry.path, 0) catch {};
try std.os.linkat(entry.dir.dir.fd, entry.basename, destination_dir_.dir.fd, entry.path, 0);
};
real_file_count += 1;
},
else => {},

View File

@@ -1419,6 +1419,7 @@ pub const BundleOptions = struct {
transform_options: Api.TransformOptions,
polyfill_node_globals: bool = false,
transform_only: bool = false,
load_tsconfig_json: bool = true,
rewrite_jest_for_tests: bool = false,

View File

@@ -3840,7 +3840,7 @@ pub const Resolver = struct {
}
// Record if this directory has a tsconfig.json or jsconfig.json file
{
if (r.opts.load_tsconfig_json) {
var tsconfig_path: ?string = null;
if (r.opts.tsconfig_override == null) {
if (entries.getComptimeQuery("tsconfig.json")) |lookup| {
@@ -3871,10 +3871,10 @@ pub const Resolver = struct {
) catch |err| brk: {
const pretty = r.prettyPath(Path.init(tsconfigpath));
if (err == error.ENOENT) {
r.log.addErrorFmt(null, logger.Loc.Empty, r.allocator, "Cannot find tsconfig file \"{s}\"", .{pretty}) catch unreachable;
} else if (err != error.ParseErrorAlreadyLogged and err != error.IsDir) {
r.log.addErrorFmt(null, logger.Loc.Empty, r.allocator, "Cannot read file \"{s}\": {s}", .{ pretty, @errorName(err) }) catch unreachable;
if (err == error.ENOENT or err == error.FileNotFound) {
r.log.addErrorFmt(null, logger.Loc.Empty, r.allocator, "Cannot find tsconfig file {}", .{bun.strings.QuotedFormatter{ .text = pretty }}) catch {};
} else if (err != error.ParseErrorAlreadyLogged and err != error.IsDir and err != error.EISDIR) {
r.log.addErrorFmt(null, logger.Loc.Empty, r.allocator, "Cannot read file {}: {s}", .{ bun.strings.QuotedFormatter{ .text = pretty }, @errorName(err) }) catch {};
}
break :brk null;
};
@@ -3886,7 +3886,12 @@ pub const Resolver = struct {
var ts_dir_name = Dirname.dirname(current.abs_path);
// not sure why this needs cwd but we'll just pass in the dir of the tsconfig...
var abs_path = ResolvePath.joinAbsStringBuf(ts_dir_name, bufs(.tsconfig_path_abs), &[_]string{ ts_dir_name, current.extends }, .auto);
var parent_config_maybe = try r.parseTSConfig(abs_path, 0);
var parent_config_maybe = r.parseTSConfig(abs_path, 0) catch |err| {
r.log.addWarningFmt(null, logger.Loc.Empty, r.allocator, "{s} loading tsconfig.json extends {}", .{ @errorName(err), strings.QuotedFormatter{
.text = abs_path,
} }) catch {};
break;
};
if (parent_config_maybe) |parent_config| {
try parent_configs.append(parent_config);
current = parent_config;

View File

@@ -62,6 +62,64 @@ for (let withRun of [false, true]) {
expect(exitCode).toBe(0);
});
it("invalid tsconfig.json is ignored", async () => {
await writeFile(
join(run_dir, "package.json"),
JSON.stringify({
name: "test",
version: "0.0.0",
scripts: {
"boop": "echo 'hi'",
},
}),
);
await writeFile(join(run_dir, "tsconfig.json"), "!!!bad!!!");
const { stdout, stderr, exitCode } = spawnSync({
cmd: [bunExe(), "--silent", withRun ? "run" : "", "boop"].filter(Boolean),
cwd: run_dir,
env: bunEnv,
});
expect(stderr.toString()).toBe("");
expect(stdout.toString()).toBe("hi\n");
expect(exitCode).toBe(0);
});
it("valid tsconfig.json with invalid extends doesn't crash", async () => {
await writeFile(
join(run_dir, "package.json"),
JSON.stringify({
name: "test",
version: "0.0.0",
scripts: {},
}),
);
await writeFile(
join(run_dir, "tsconfig.json"),
JSON.stringify(
{
extends: "!!!bad!!!",
},
null,
2,
),
);
await writeFile(join(run_dir, "index.js"), "console.log('hi')");
const { stdout, stderr, exitCode } = spawnSync({
cmd: [bunExe(), "--silent", withRun ? "run" : "", "./index.js"].filter(Boolean),
cwd: run_dir,
env: bunEnv,
});
expect(stderr.toString().trim()).toContain("FileNotFound loading tsconfig.json extends");
expect(stdout.toString()).toBe("hi\n");
expect(exitCode).toBe(0);
});
it("falling back to index with no package.json", async () => {
await writeFile(join(run_dir, "index.ts"), "console.log('Hello, world!');");