aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-04-20 05:30:35 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-04-20 05:30:35 -0700
commitaa4d47fe2de93e7c7c4b2bd0b8b7c97414885133 (patch)
treecaf383454989363d564c94fee5ae894dd3b364d8 /src
parent3a68ca775f3d41334df3e27fccb57d65072db413 (diff)
downloadbun-aa4d47fe2de93e7c7c4b2bd0b8b7c97414885133.tar.gz
bun-aa4d47fe2de93e7c7c4b2bd0b8b7c97414885133.tar.zst
bun-aa4d47fe2de93e7c7c4b2bd0b8b7c97414885133.zip
Improve error message when failing to read a file
Diffstat (limited to 'src')
-rw-r--r--src/bun.zig6
-rw-r--r--src/bundler/bundle_v2.zig26
-rw-r--r--src/string_immutable.zig54
3 files changed, 84 insertions, 2 deletions
diff --git a/src/bun.zig b/src/bun.zig
index 9fe21a05a..1999e43d5 100644
--- a/src/bun.zig
+++ b/src/bun.zig
@@ -30,6 +30,12 @@ pub const path = @import("./resolver/resolve_path.zig");
pub const fmt = struct {
pub usingnamespace std.fmt;
+ pub fn quote(self: string) strings.QuotedFormatter {
+ return strings.QuotedFormatter{
+ .text = self,
+ };
+ }
+
pub fn formatIp(address: std.net.Address, into: []u8) ![]u8 {
// std.net.Address.format includes `:<port>` and square brackets (IPv6)
// while Node does neither. This uses format then strips these to bring
diff --git a/src/bundler/bundle_v2.zig b/src/bundler/bundle_v2.zig
index b0ce41fb8..44a6489cd 100644
--- a/src/bundler/bundle_v2.zig
+++ b/src/bundler/bundle_v2.zig
@@ -914,7 +914,7 @@ const ParseTask = struct {
.contents = NodeFallbackModules.contentsFromPath(file_path.text) orelse "",
};
- break :brk try resolver.caches.fs.readFile(
+ break :brk resolver.caches.fs.readFile(
bundler.fs,
file_path.text,
task.contents_or_fd.fd.dir,
@@ -923,7 +923,29 @@ const ParseTask = struct {
task.contents_or_fd.fd.file
else
null,
- );
+ ) catch |err| {
+ switch (err) {
+ error.FileNotFound => {
+ log.addErrorFmt(
+ &Logger.Source.initEmptyFile(file_path.text),
+ Logger.Loc.Empty,
+ allocator,
+ "File not found {}",
+ .{bun.fmt.quote(file_path.text)},
+ ) catch {};
+ },
+ else => {
+ log.addErrorFmt(
+ &Logger.Source.initEmptyFile(file_path.text),
+ Logger.Loc.Empty,
+ allocator,
+ "{s} reading file: {}",
+ .{ @errorName(err), bun.fmt.quote(file_path.text) },
+ ) catch {};
+ },
+ }
+ return err;
+ };
},
.contents => |contents| CacheEntry{
.contents = contents,
diff --git a/src/string_immutable.zig b/src/string_immutable.zig
index 15e0fc032..2527b6898 100644
--- a/src/string_immutable.zig
+++ b/src/string_immutable.zig
@@ -686,6 +686,25 @@ pub fn endsWithAny(self: string, str: string) bool {
return false;
}
+pub fn quotedWriter(writer: anytype, self: string) !void {
+ var remain = self;
+ if (strings.containsNewlineOrNonASCIIOrQuote(remain)) {
+ try bun.js_printer.writeJSONString(self, @TypeOf(writer), writer, strings.Encoding.utf8);
+ } else {
+ try writer.writeAll("\"");
+ try writer.writeAll(self);
+ try writer.writeAll("\"");
+ }
+}
+
+pub const QuotedFormatter = struct {
+ text: []const u8,
+
+ pub fn format(this: QuotedFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
+ try strings.quotedWriter(writer, this.text);
+ }
+};
+
pub fn quotedAlloc(allocator: std.mem.Allocator, self: string) !string {
var count: usize = 0;
for (self) |char| {
@@ -3214,6 +3233,41 @@ pub fn indexOfNewlineOrNonASCIICheckStart(slice_: []const u8, offset: u32, compt
return null;
}
+pub fn containsNewlineOrNonASCIIOrQuote(slice_: []const u8) bool {
+ const slice = slice_;
+ var remaining = slice;
+
+ if (remaining.len == 0)
+ return false;
+
+ if (comptime Environment.enableSIMD) {
+ while (remaining.len >= ascii_vector_size) {
+ const vec: AsciiVector = remaining[0..ascii_vector_size].*;
+ const cmp = @bitCast(AsciiVectorU1, (vec > max_16_ascii)) | @bitCast(AsciiVectorU1, (vec < min_16_ascii)) |
+ @bitCast(AsciiVectorU1, vec == @splat(ascii_vector_size, @as(u8, '\r'))) |
+ @bitCast(AsciiVectorU1, vec == @splat(ascii_vector_size, @as(u8, '\n'))) |
+ @bitCast(AsciiVectorU1, vec == @splat(ascii_vector_size, @as(u8, '"')));
+
+ if (@reduce(.Max, cmp) > 0) {
+ return true;
+ }
+
+ remaining = remaining[ascii_vector_size..];
+ }
+
+ if (comptime Environment.allow_assert) std.debug.assert(remaining.len < ascii_vector_size);
+ }
+
+ for (remaining) |*char_| {
+ const char = char_.*;
+ if (char > 127 or char < 0x20 or char == '\n' or char == '\r' or char == '"') {
+ return true;
+ }
+ }
+
+ return false;
+}
+
pub fn indexOfNeedsEscape(slice: []const u8) ?u32 {
var remaining = slice;
if (remaining.len == 0)