aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred SUmner <jarred@jarredsumner.com> 2022-01-01 03:11:36 -0800
committerGravatar Jarred SUmner <jarred@jarredsumner.com> 2022-01-01 03:11:36 -0800
commit87e78e2a48632a2be237c35c9d053c1104de0a41 (patch)
treec5a2d2049a78c980510dfeb5e9962039570e5e62
parent6ac9b5fa9d4a4d1eb4045852b88e25b18ae466bd (diff)
downloadbun-87e78e2a48632a2be237c35c9d053c1104de0a41.tar.gz
bun-87e78e2a48632a2be237c35c9d053c1104de0a41.tar.zst
bun-87e78e2a48632a2be237c35c9d053c1104de0a41.zip
Handle more edgecases
-rw-r--r--src/http.zig98
1 files changed, 51 insertions, 47 deletions
diff --git a/src/http.zig b/src/http.zig
index afca8c57c..184f1f7a2 100644
--- a/src/http.zig
+++ b/src/http.zig
@@ -2559,6 +2559,7 @@ pub const Server = struct {
}
}
+ var _on_file_update_path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
fn _onFileUpdate(
ctx: *Server,
events: []watcher.WatchEvent,
@@ -2661,65 +2662,67 @@ pub const Server = struct {
},
.directory => {
const affected = event.names(changed_files);
-
+ var entries_option: ?*Fs.FileSystem.RealFS.EntriesOption = null;
if (affected.len > 0) {
- if (rfs.entries.get(file_path)) |dir_ent| {
- var last_file_hash: Watcher.HashType = std.math.maxInt(Watcher.HashType);
- var already_had_all_affected = true;
- for (affected) |changed_name_ptr| {
- const changed_name: []const u8 = std.mem.span((changed_name_ptr orelse continue));
- const loader = (ctx.bundler.options.loaders.get(Fs.PathName.init(changed_name).ext) orelse .file);
- if (loader.isJavaScriptLikeOrJSON() or loader == .css) {
- if (dir_ent.entries.get(changed_name)) |file_ent| {
- const abs_path = file_ent.entry.abs_path.slice();
- const file_hash = Watcher.getHash(abs_path);
+ entries_option = rfs.entries.get(file_path);
+ }
+
+ rfs.bustEntriesCache(file_path);
+ ctx.bundler.resolver.dir_cache.remove(file_path);
- // skip consecutive duplicates
- if (last_file_hash == file_hash) continue;
- last_file_hash = file_hash;
+ if (entries_option) |dir_ent| {
+ var last_file_hash: Watcher.HashType = std.math.maxInt(Watcher.HashType);
+ for (affected) |changed_name_ptr| {
+ const changed_name: []const u8 = std.mem.span((changed_name_ptr orelse continue));
+ if (changed_name.len == 0 or changed_name[0] == '~' or changed_name[0] == '.') continue;
+ const loader = (ctx.bundler.options.loaders.get(Fs.PathName.init(changed_name).ext) orelse .file);
+ if (loader.isJavaScriptLikeOrJSON() or loader == .css) {
+ var path_string: _global.PathString = undefined;
+ const abs_path: string = brk: {
+ if (dir_ent.entries.get(changed_name)) |file_ent| {
// reset the file descriptor
file_ent.entry.cache.fd = 0;
file_ent.entry.need_stat = true;
+ path_string = file_ent.entry.abs_path;
- const change_message = Api.WebsocketMessageFileChangeNotification{
- .id = file_hash,
- .loader = loader.toAPI(),
- };
-
- var content_writer = ByteApiWriter.init(&hinted_content_fbs);
- change_message.encode(&content_writer) catch unreachable;
- const change_buf = hinted_content_fbs.getWritten();
- const written_buf = filechange_buf_hinted[0 .. header.len + change_buf.len];
- RequestContext.WebsocketHandler.broadcast(written_buf) catch |err| {
- Output.prettyErrorln("Error writing change notification: {s}<r>", .{@errorName(err)});
- };
- if (comptime is_emoji_enabled) {
- Output.prettyErrorln("<r>📜 <d>File change: {s}<r>", .{ctx.bundler.fs.relativeTo(abs_path)});
- } else {
- Output.prettyErrorln("<r> <d>File change: {s}<r>", .{ctx.bundler.fs.relativeTo(abs_path)});
- }
+ break :brk path_string.slice();
} else {
- already_had_all_affected = false;
+ var file_path_without_trailing_slash = std.mem.trimRight(u8, file_path, std.fs.path.sep_str);
+ @memcpy(&_on_file_update_path_buf, file_path_without_trailing_slash.ptr, file_path_without_trailing_slash.len);
+ _on_file_update_path_buf[file_path_without_trailing_slash.len] = std.fs.path.sep;
+
+ @memcpy(_on_file_update_path_buf[file_path_without_trailing_slash.len + 1 ..].ptr, changed_name.ptr, changed_name.len);
+ break :brk _on_file_update_path_buf[0 .. file_path_without_trailing_slash.len + changed_name.len + 1];
}
- }
- }
+ };
+ const file_hash = Watcher.getHash(abs_path);
+
+ // skip consecutive duplicates
+ if (last_file_hash == file_hash) continue;
+ last_file_hash = file_hash;
+
+ const change_message = Api.WebsocketMessageFileChangeNotification{
+ .id = file_hash,
+ .loader = loader.toAPI(),
+ };
- // When the only operation in a directory was moving new files into it, and we were already watching the existing files
- // We don't need to invalidate the directory entries
- // We only need to invalidate the file descriptor
- if (already_had_all_affected and event.op.move_to and !event.op.delete and
- !event.op.rename and
- !event.op.write)
- {
- continue;
+ var content_writer = ByteApiWriter.init(&hinted_content_fbs);
+ change_message.encode(&content_writer) catch unreachable;
+ const change_buf = hinted_content_fbs.getWritten();
+ const written_buf = filechange_buf_hinted[0 .. header.len + change_buf.len];
+ RequestContext.WebsocketHandler.broadcast(written_buf) catch |err| {
+ Output.prettyErrorln("Error writing change notification: {s}<r>", .{@errorName(err)});
+ };
+ if (comptime is_emoji_enabled) {
+ Output.prettyErrorln("<r>📜 <d>File change: {s}<r>", .{ctx.bundler.fs.relativeTo(abs_path)});
+ } else {
+ Output.prettyErrorln("<r> <d>File change: {s}<r>", .{ctx.bundler.fs.relativeTo(abs_path)});
+ }
}
}
}
- rfs.bustEntriesCache(file_path);
- ctx.bundler.resolver.dir_cache.remove(file_path);
-
// if (event.op.delete or event.op.rename)
// ctx.watcher.removeAtIndex(event.index, hashes[event.index], parent_hashes, .directory);
if (comptime is_emoji_enabled) {
@@ -3138,11 +3141,12 @@ pub const Server = struct {
// If there's a .bun, don't even read the filesystem
// Just use the .bun
if (this.bundler.options.node_modules_bundle) |node_modules_bundle| {
- const package_name = runtime[0..strings.indexOfChar(runtime, '/') orelse runtime.len];
- if (node_modules_bundle.getPackageIDByName(package_name) != null) return;
+ const package_name = runtime[0 .. strings.indexOfChar(runtime, '/') orelse runtime.len];
+ if (node_modules_bundle.getPackageIDByName(package_name) != null) return;
}
_ = this.bundler.resolver.resolve(this.bundler.fs.top_level_dir, runtime, .internal) catch {
+ // 2. Try react refresh from import source perspective
this.bundler.options.jsx.supports_fast_refresh = false;
return;
};