Skip to content

Commit

Permalink
bustDirCache on FileSystemRouter.reload & fix of dir_cache keys in wi…
Browse files Browse the repository at this point in the history
…ndows (#15091)

Co-authored-by: dave caruso <[email protected]>
Co-authored-by: Jarred Sumner <[email protected]>
  • Loading branch information
3 people authored Nov 27, 2024
1 parent bdd0b89 commit 1bb211d
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 6 deletions.
6 changes: 3 additions & 3 deletions src/allocators.zig
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, comptime store_
}

pub fn getOrPut(self: *Self, denormalized_key: []const u8) !Result {
const key = if (comptime remove_trailing_slashes) std.mem.trimRight(u8, denormalized_key, "/") else denormalized_key;
const key = if (comptime remove_trailing_slashes) std.mem.trimRight(u8, denormalized_key, std.fs.path.sep_str) else denormalized_key;
const _key = bun.hash(key);

self.mutex.lock();
Expand Down Expand Up @@ -526,7 +526,7 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, comptime store_
}

pub fn get(self: *Self, denormalized_key: []const u8) ?*ValueType {
const key = if (comptime remove_trailing_slashes) std.mem.trimRight(u8, denormalized_key, "/") else denormalized_key;
const key = if (comptime remove_trailing_slashes) std.mem.trimRight(u8, denormalized_key, std.fs.path.sep_str) else denormalized_key;
const _key = bun.hash(key);
self.mutex.lock();
defer self.mutex.unlock();
Expand Down Expand Up @@ -588,7 +588,7 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, comptime store_
defer self.mutex.unlock();

const key = if (comptime remove_trailing_slashes)
std.mem.trimRight(u8, denormalized_key, "/")
std.mem.trimRight(u8, denormalized_key, std.fs.path.sep_str)
else
denormalized_key;

Expand Down
49 changes: 47 additions & 2 deletions src/bun.js/api/filesystem_router.zig
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ const JSError = Base.JSError;
const JSValue = JSC.JSValue;
const JSGlobalObject = JSC.JSGlobalObject;
const strings = bun.strings;

const To = Base.To;
const Request = WebCore.Request;

const Environment = bun.Environment;
const URLPath = @import("../../http/url_path.zig");
const URL = @import("../../url.zig").URL;
const Log = bun.logger;
Expand Down Expand Up @@ -197,6 +196,50 @@ pub const FileSystemRouter = struct {
return fs_router;
}

threadlocal var win32_normalized_dir_info_cache_buf: if (Environment.isWindows) [bun.MAX_PATH_BYTES * 2]u8 else void = undefined;
pub fn bustDirCacheRecursive(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject, inputPath: []const u8) void {
var vm = globalThis.bunVM();
var path = inputPath;
if (comptime Environment.isWindows) {
path = vm.bundler.resolver.fs.normalizeBuf(&win32_normalized_dir_info_cache_buf, path);
}

const root_dir_info = vm.bundler.resolver.readDirInfo(path) catch {
return;
};

if (root_dir_info) |dir| {
if (dir.getEntriesConst()) |entries| {
var iter = entries.data.iterator();
outer: while (iter.next()) |entry_ptr| {
const entry = entry_ptr.value_ptr.*;
if (entry.base()[0] == '.') {
continue :outer;
}
if (entry.kind(&vm.bundler.fs.fs, false) == .dir) {
inline for (Router.banned_dirs) |banned_dir| {
if (strings.eqlComptime(entry.base(), comptime banned_dir)) {
continue :outer;
}
}

var abs_parts_con = [_]string{ entry.dir, entry.base() };
const full_path = vm.bundler.fs.abs(&abs_parts_con);

_ = vm.bundler.resolver.bustDirCache(strings.withoutTrailingSlashWindowsPath(full_path));
bustDirCacheRecursive(this, globalThis, full_path);
}
}
}
}

_ = vm.bundler.resolver.bustDirCache(path);
}

pub fn bustDirCache(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject) void {
bustDirCacheRecursive(this, globalThis, strings.withoutTrailingSlashWindowsPath(this.router.config.dir));
}

pub fn reload(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSValue {
const this_value = callframe.this();

Expand All @@ -211,6 +254,8 @@ pub const FileSystemRouter = struct {
vm.bundler.resolver.log = &log;
defer vm.bundler.resolver.log = orig_log;

bustDirCache(this, globalThis);

const root_dir_info = vm.bundler.resolver.readDirInfo(this.router.config.dir) catch {
globalThis.throwValue(log.toJS(globalThis, globalThis.allocator(), "reading root directory"));
return .zero;
Expand Down
2 changes: 1 addition & 1 deletion src/router.zig
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ pub fn getNames(this: *const Router) ![]const string {
return this.routes.list.items(.name);
}

const banned_dirs = [_]string{
pub const banned_dirs = [_]string{
"node_modules",
};

Expand Down
25 changes: 25 additions & 0 deletions test/js/bun/util/filesystem_router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,31 @@ it("reload() works", () => {
expect(router.match("/posts")!.name).toBe("/posts");
});

it("reload() works with new dirs/files", () => {
const { dir } = make(["posts.tsx"]);

const router = new Bun.FileSystemRouter({
dir,
style: "nextjs",
assetPrefix: "/_next/static/",
origin: "https://nextjs.org",
});

expect(router.match("/posts")!.name).toBe("/posts");
createTree(dir, ['test/recursive/index.ts']);
router.reload();
expect(router.match("/test/recursive")!.name).toBe("/test/recursive");
rmSync(`${dir}/test/recursive`, {
recursive: true,
force: true
});
router.reload();
expect(router.match("/test/recursive")).toBe(null);
createTree(dir, ['test/test2/index.ts']);
router.reload();
expect(router.match("/test/test2")!.name).toBe("/test/test2");
})

it(".query works with dynamic routes, including params", () => {
// set up the test
const { dir } = make(["posts/[id].tsx"]);
Expand Down

0 comments on commit 1bb211d

Please sign in to comment.