diff options
author | 2023-04-20 05:30:35 -0700 | |
---|---|---|
committer | 2023-04-20 05:30:35 -0700 | |
commit | aa4d47fe2de93e7c7c4b2bd0b8b7c97414885133 (patch) | |
tree | caf383454989363d564c94fee5ae894dd3b364d8 /src | |
parent | 3a68ca775f3d41334df3e27fccb57d65072db413 (diff) | |
download | bun-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.zig | 6 | ||||
-rw-r--r-- | src/bundler/bundle_v2.zig | 26 | ||||
-rw-r--r-- | src/string_immutable.zig | 54 |
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) |