diff options
author | 2022-01-01 03:11:36 -0800 | |
---|---|---|
committer | 2022-01-01 03:11:36 -0800 | |
commit | 87e78e2a48632a2be237c35c9d053c1104de0a41 (patch) | |
tree | c5a2d2049a78c980510dfeb5e9962039570e5e62 | |
parent | 6ac9b5fa9d4a4d1eb4045852b88e25b18ae466bd (diff) | |
download | bun-87e78e2a48632a2be237c35c9d053c1104de0a41.tar.gz bun-87e78e2a48632a2be237c35c9d053c1104de0a41.tar.zst bun-87e78e2a48632a2be237c35c9d053c1104de0a41.zip |
Handle more edgecases
-rw-r--r-- | src/http.zig | 98 |
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; }; |