const bun = @import("bun");
const string = bun.string;
const Output = bun.Output;
const Environment = bun.Environment;
const strings = bun.strings;
const MutableString = bun.MutableString;
const FeatureFlags = bun.FeatureFlags;
const PathString = bun.PathString;
const default_allocator = bun.default_allocator;
const FD = bun.FD;

const ast = @import("../import_record.zig");
const logger = bun.logger;
const options = @import("../options.zig");
const Fs = @import("../fs.zig");
const std = @import("std");
const cache = @import("../cache.zig");
const TSConfigJSON = @import("./tsconfig_json.zig").TSConfigJSON;
const PackageJSON = @import("./package_json.zig").PackageJSON;
const ESModule = @import("./package_json.zig").ESModule;
const BrowserMap = @import("./package_json.zig").BrowserMap;
const CacheSet = cache.Set;
pub const DataURL = @import("./data_url.zig").DataURL;
pub const DirInfo = @import("./dir_info.zig");
const ResolvePath = @import("./resolve_path.zig");
const NodeFallbackModules = @import("../node_fallbacks.zig");
const Mutex = bun.Mutex;
const FileDescriptorType = bun.FileDescriptor;
const JSC = bun.JSC;

const allocators = @import("../allocators.zig");
const Msg = logger.Msg;
const Path = Fs.Path;
const debuglog = Output.scoped(.Resolver, true);
const PackageManager = @import("../install/install.zig").PackageManager;
const Dependency = @import("../install/dependency.zig");
const Install = @import("../install/install.zig");
const Package = @import("../install/lockfile.zig").Package;
const Resolution = @import("../install/resolution.zig").Resolution;
const Semver = bun.Semver;
const DotEnv = @import("../env_loader.zig");

pub fn isPackagePath(path: string) bool {
    // Always check for posix absolute paths (starts with "/")
    // But don't check window's style on posix
    // For a more in depth explanation, look above where `isPackagePathNotAbsolute` is used.
    return !std.fs.path.isAbsolute(path) and @call(bun.callmod_inline, isPackagePathNotAbsolute, .{path});
}

pub fn isPackagePathNotAbsolute(non_absolute_path: string) bool {
    if (Environment.allow_assert) {
        assert(!std.fs.path.isAbsolute(non_absolute_path));
        assert(!strings.startsWith(non_absolute_path, "/"));
    }

    return !strings.startsWith(non_absolute_path, "./") and
        !strings.startsWith(non_absolute_path, "../") and
        !strings.eql(non_absolute_path, ".") and
        !strings.eql(non_absolute_path, "..") and if (Environment.isWindows)
        (!strings.startsWith(non_absolute_path, ".\\") and
            !strings.startsWith(non_absolute_path, "..\\"))
    else
        true;
}

pub const SideEffectsData = struct {
    source: *logger.Source,
    range: logger.Range,

    // If true, "sideEffects" was an array. If false, "sideEffects" was false.
    is_side_effects_array_in_json: bool = false,
};

/// A temporary threadlocal buffer with a lifetime more than the current
/// function call.
const bufs = struct {
    // Experimenting with making this one struct instead of a bunch of different
    // threadlocal vars yielded no performance improvement on macOS when
    // bundling 10 copies of Three.js. It may be worthwhile for more complicated
    // packages but we lack a decent module resolution benchmark right now.
    // Potentially revisit after https://github.com/oven-sh/bun/issues/2716
    pub threadlocal var extension_path: [512]u8 = undefined;
    pub threadlocal var tsconfig_match_full_buf: bun.PathBuffer = undefined;
    pub threadlocal var tsconfig_match_full_buf2: bun.PathBuffer = undefined;
    pub threadlocal var tsconfig_match_full_buf3: bun.PathBuffer = undefined;

    pub threadlocal var esm_subpath: [512]u8 = undefined;
    pub threadlocal var esm_absolute_package_path: bun.PathBuffer = undefined;
    pub threadlocal var esm_absolute_package_path_joined: bun.PathBuffer = undefined;

    pub threadlocal var dir_entry_paths_to_resolve: [256]DirEntryResolveQueueItem = undefined;
    pub threadlocal var open_dirs: [256]std.fs.Dir = undefined;
    pub threadlocal var resolve_without_remapping: bun.PathBuffer = undefined;
    pub threadlocal var index: bun.PathBuffer = undefined;
    pub threadlocal var dir_info_uncached_filename: bun.PathBuffer = undefined;
    pub threadlocal var node_bin_path: bun.PathBuffer = undefined;
    pub threadlocal var dir_info_uncached_path: bun.PathBuffer = undefined;
    pub threadlocal var tsconfig_base_url: bun.PathBuffer = undefined;
    pub threadlocal var relative_abs_path: bun.PathBuffer = undefined;
    pub threadlocal var load_as_file_or_directory_via_tsconfig_base_path: bun.PathBuffer = undefined;
    pub threadlocal var node_modules_check: bun.PathBuffer = undefined;
    pub threadlocal var field_abs_path: bun.PathBuffer = undefined;
    pub threadlocal var tsconfig_path_abs: bun.PathBuffer = undefined;
    pub threadlocal var check_browser_map: bun.PathBuffer = undefined;
    pub threadlocal var remap_path: bun.PathBuffer = undefined;
    pub threadlocal var load_as_file: bun.PathBuffer = undefined;
    pub threadlocal var remap_path_trailing_slash: bun.PathBuffer = undefined;
    pub threadlocal var path_in_global_disk_cache: bun.PathBuffer = undefined;
    pub threadlocal var abs_to_rel: bun.PathBuffer = undefined;
    pub threadlocal var node_modules_paths_buf: bun.PathBuffer = undefined;
    pub threadlocal var import_path_for_standalone_module_graph: bun.PathBuffer = undefined;

    pub inline fn bufs(comptime field: std.meta.DeclEnum(@This())) *@TypeOf(@field(@This(), @tagName(field))) {
        return &@field(@This(), @tagName(field));
    }
}.bufs;

pub const PathPair = struct {
    primary: Path,
    secondary: ?Path = null,

    pub const Iter = struct {
        index: u2,
        ctx: *PathPair,
        pub fn next(i: *Iter) ?*Path {
            if (i.next_()) |path_| {
                if (path_.is_disabled) {
                    return i.next();
                }
                return path_;
            }

            return null;
        }
        fn next_(i: *Iter) ?*Path {
            const ind = i.index;
            i.index +|= 1;

            switch (ind) {
                0 => return &i.ctx.primary,
                1 => return if (i.ctx.secondary) |*sec| sec else null,
                else => return null,
            }
        }
    };

    pub fn iter(p: *PathPair) Iter {
        return Iter{ .ctx = p, .index = 0 };
    }
};

pub const SideEffects = enum {
    /// The default value conservatively considers all files to have side effects.
    has_side_effects,

    /// This file was listed as not having side effects by a "package.json"
    /// file in one of our containing directories with a "sideEffects" field.
    no_side_effects__package_json,

    /// This file is considered to have no side effects because the AST was empty
    /// after parsing finished. This should be the case for ".d.ts" files.
    no_side_effects__empty_ast,

    /// This file was loaded using a data-oriented loader (e.g. "text") that is
    /// known to not have side effects.
    no_side_effects__pure_data,

    // /// Same as above but it came from a plugin. We don't want to warn about
    // /// unused imports to these files since running the plugin is a side effect.
    // /// Removing the import would not call the plugin which is observable.
    // no_side_effects__pure_data_from_plugin,
};

pub const Result = struct {
    path_pair: PathPair,

    jsx: options.JSX.Pragma = options.JSX.Pragma{},

    package_json: ?*PackageJSON = null,

    is_external: bool = false,

    is_external_and_rewrite_import_path: bool = false,

    is_standalone_module: bool = false,

    // This is true when the package was loaded from within the node_modules directory.
    is_from_node_modules: bool = false,

    diff_case: ?Fs.FileSystem.Entry.Lookup.DifferentCase = null,

    // If present, any ES6 imports to this file can be considered to have no side
    // effects. This means they should be removed if unused.
    primary_side_effects_data: SideEffects = SideEffects.has_side_effects,

    // If true, unused imports are retained in TypeScript code. This matches the
    // behavior of the "importsNotUsedAsValues" field in "tsconfig.json" when the
    // value is not "remove".
    preserve_unused_imports_ts: bool = false,

    // This is the "type" field from "package.json"
    module_type: options.ModuleType = options.ModuleType.unknown,

    emit_decorator_metadata: bool = false,

    debug_meta: ?DebugMeta = null,

    dirname_fd: FD = .invalid,
    file_fd: FD = .invalid,
    import_kind: ast.ImportKind = undefined,

    pub const Union = union(enum) {
        success: Result,
        failure: anyerror,
        pending: PendingResolution,
        not_found: void,
    };

    pub fn path(this: *Result) ?*Path {
        if (!this.path_pair.primary.is_disabled)
            return &this.path_pair.primary;

        if (this.path_pair.secondary) |*second| {
            if (!second.is_disabled) return second;
        }

        return null;
    }

    pub fn pathConst(this: *const Result) ?*const Path {
        if (!this.path_pair.primary.is_disabled)
            return &this.path_pair.primary;

        if (this.path_pair.secondary) |*second| {
            if (!second.is_disabled) return second;
        }

        return null;
    }

    // remember: non-node_modules can have package.json
    // checking package.json may not be relevant
    pub fn isLikelyNodeModule(this: *const Result) bool {
        const path_ = this.pathConst() orelse return false;
        return this.is_from_node_modules or strings.indexOf(path_.text, "/node_modules/") != null;
    }

    // Most NPM modules are CommonJS
    // If unspecified, assume CommonJS.
    // If internal app code, assume ESM.
    pub fn shouldAssumeCommonJS(r: *const Result, kind: ast.ImportKind) bool {
        switch (r.module_type) {
            .esm => return false,
            .cjs => return true,
            else => {
                if (kind == .require or kind == .require_resolve) {
                    return true;
                }

                // If we rely just on isPackagePath, we mess up tsconfig.json baseUrl paths.
                return r.isLikelyNodeModule();
            },
        }
    }

    pub const DebugMeta = struct {
        notes: std.ArrayList(logger.Data),
        suggestion_text: string = "",
        suggestion_message: string = "",
        suggestion_range: SuggestionRange,

        pub const SuggestionRange = enum { full, end };

        pub fn init(allocator: std.mem.Allocator) DebugMeta {
            return DebugMeta{ .notes = std.ArrayList(logger.Data).init(allocator) };
        }

        pub fn logErrorMsg(m: *DebugMeta, log: *logger.Log, _source: ?*const logger.Source, r: logger.Range, comptime fmt: string, args: anytype) !void {
            if (_source != null and m.suggestion_message.len > 0) {
                const suggestion_range = if (m.suggestion_range == .end)
                    logger.Range{ .loc = logger.Loc{ .start = r.endI() - 1 } }
                else
                    r;
                const data = logger.rangeData(_source.?, suggestion_range, m.suggestion_message);
                data.location.?.suggestion = m.suggestion_text;
                try m.notes.append(data);
            }

            try log.addMsg(Msg{
                .kind = .err,
                .data = logger.rangeData(_source, r, std.fmt.allocPrint(m.notes.allocator, fmt, args)),
                .notes = try m.toOwnedSlice(),
            });
        }
    };

    pub fn hash(this: *const Result, _: string, _: options.Loader) u32 {
        const module = this.path_pair.primary.text;
        const node_module_root = std.fs.path.sep_str ++ "node_modules" ++ std.fs.path.sep_str;
        if (strings.lastIndexOf(module, node_module_root)) |end_| {
            const end: usize = end_ + node_module_root.len;

            return @as(u32, @truncate(bun.hash(module[end..])));
        }

        return @as(u32, @truncate(bun.hash(this.path_pair.primary.text)));
    }
};

pub const DirEntryResolveQueueItem = struct {
    result: allocators.Result,
    unsafe_path: string,
    safe_path: string = "",
    fd: FD = .invalid,
};

pub const DebugLogs = struct {
    what: string = "",
    indent: MutableString,
    notes: std.ArrayList(logger.Data),

    pub const FlushMode = enum { fail, success };

    pub fn init(allocator: std.mem.Allocator) !DebugLogs {
        const mutable = try MutableString.init(allocator, 0);
        return DebugLogs{
            .indent = mutable,
            .notes = std.ArrayList(logger.Data).init(allocator),
        };
    }

    pub fn deinit(d: DebugLogs) void {
        d.notes.deinit();
        // d.indent.deinit();
    }

    pub fn increaseIndent(d: *DebugLogs) void {
        @branchHint(.cold);
        d.indent.append(" ") catch unreachable;
    }

    pub fn decreaseIndent(d: *DebugLogs) void {
        @branchHint(.cold);
        d.indent.list.shrinkRetainingCapacity(d.indent.list.items.len - 1);
    }

    pub fn addNote(d: *DebugLogs, _text: string) void {
        @branchHint(.cold);
        var text = _text;
        const len = d.indent.len();
        if (len > 0) {
            var __text = d.notes.allocator.alloc(u8, text.len + len) catch unreachable;
            bun.copy(u8, __text, d.indent.list.items);
            bun.copy(u8, __text[len..], _text);
            text = __text;
            d.notes.allocator.free(_text);
        }

        d.notes.append(logger.rangeData(null, logger.Range.None, text)) catch unreachable;
    }

    pub fn addNoteFmt(d: *DebugLogs, comptime fmt: string, args: anytype) void {
        @branchHint(.cold);
        return d.addNote(std.fmt.allocPrint(d.notes.allocator, fmt, args) catch unreachable);
    }
};

pub const MatchResult = struct {
    path_pair: PathPair,
    dirname_fd: FD = .invalid,
    file_fd: FD = .invalid,
    is_node_module: bool = false,
    package_json: ?*PackageJSON = null,
    diff_case: ?Fs.FileSystem.Entry.Lookup.DifferentCase = null,
    dir_info: ?*DirInfo = null,
    module_type: options.ModuleType = .unknown,
    is_external: bool = false,

    pub const Union = union(enum) {
        not_found: void,
        success: MatchResult,
        pending: PendingResolution,
        failure: anyerror,
    };
};

pub const PendingResolution = struct {
    esm: ESModule.Package.External = .{},
    dependency: Dependency.Version = .{},
    resolution_id: Install.PackageID = Install.invalid_package_id,
    root_dependency_id: Install.DependencyID = Install.invalid_package_id,
    import_record_id: u32 = std.math.maxInt(u32),
    string_buf: []u8 = "",
    tag: Tag,

    pub const List = std.MultiArrayList(PendingResolution);

    pub fn deinitListItems(list_: List, allocator: std.mem.Allocator) void {
        var list = list_;
        const dependencies = list.items(.dependency);
        const string_bufs = list.items(.string_buf);
        for (dependencies) |*dependency| {
            dependency.deinit();
        }

        for (string_bufs) |string_buf| {
            allocator.free(string_buf);
        }
    }

    pub fn deinit(this: *PendingResolution, allocator: std.mem.Allocator) void {
        this.dependency.deinit();
        allocator.free(this.string_buf);
    }

    pub const Tag = enum {
        download,
        resolve,
        done,
    };

    pub fn init(
        allocator: std.mem.Allocator,
        esm: ESModule.Package,
        dependency: Dependency.Version,
        resolution_id: Install.PackageID,
    ) !PendingResolution {
        return PendingResolution{
            .esm = try esm.copy(allocator),
            .dependency = dependency,
            .resolution_id = resolution_id,
        };
    }
};

pub const LoadResult = struct {
    path: string,
    diff_case: ?Fs.FileSystem.Entry.Lookup.DifferentCase,
    dirname_fd: FD = .invalid,
    file_fd: FD = .invalid,
    dir_info: ?*DirInfo = null,
};

// This is a global so even if multiple resolvers are created, the mutex will still work
var resolver_Mutex: Mutex = undefined;
var resolver_Mutex_loaded: bool = false;

const BinFolderArray = std.BoundedArray(string, 128);
var bin_folders: BinFolderArray = undefined;
var bin_folders_lock: Mutex = .{};
var bin_folders_loaded: bool = false;

const Timer = @import("../system_timer.zig").Timer;

pub const AnyResolveWatcher = struct {
    context: *anyopaque,
    callback: *const (fn (*anyopaque, dir_path: string, dir_fd: FD) void) = undefined,

    pub fn watch(this: @This(), dir_path: string, fd: FD) void {
        return this.callback(this.context, dir_path, fd);
    }
};

pub fn ResolveWatcher(comptime Context: type, comptime onWatch: anytype) type {
    return struct {
        pub fn init(context: Context) AnyResolveWatcher {
            return AnyResolveWatcher{
                .context = context,
                .callback = watch,
            };
        }
        pub fn watch(this: *anyopaque, dir_path: string, fd: FD) void {
            onWatch(bun.cast(Context, this), dir_path, fd);
        }
    };
}

pub const Resolver = struct {
    const ThisResolver = @This();
    opts: options.BundleOptions,
    fs: *Fs.FileSystem,
    log: *logger.Log,
    allocator: std.mem.Allocator,
    extension_order: []const string = undefined,
    timer: Timer = undefined,

    care_about_bin_folder: bool = false,
    care_about_scripts: bool = false,

    /// Read the "browser" field in package.json files?
    /// For Bun's runtime, we don't.
    care_about_browser_field: bool = true,

    debug_logs: ?DebugLogs = null,
    elapsed: u64 = 0, // tracing

    watcher: ?AnyResolveWatcher = null,

    caches: CacheSet,
    generation: bun.Generation = 0,

    package_manager: ?*PackageManager = null,
    onWakePackageManager: PackageManager.WakeHandler = .{},
    env_loader: ?*DotEnv.Loader = null,
    store_fd: bool = false,

    standalone_module_graph: ?*bun.StandaloneModuleGraph = null,

    // These are sets that represent various conditions for the "exports" field
    // in package.json.
    // esm_conditions_default: bun.StringHashMap(bool),
    // esm_conditions_import: bun.StringHashMap(bool),
    // esm_conditions_require: bun.StringHashMap(bool),

    // A special filtered import order for CSS "@import" imports.
    //
    // The "resolve extensions" setting determines the order of implicit
    // extensions to try when resolving imports with the extension omitted.
    // Sometimes people create a JavaScript/TypeScript file and a CSS file with
    // the same name when they create a component. At a high level, users expect
    // implicit extensions to resolve to the JS file when being imported from JS
    // and to resolve to the CSS file when being imported from CSS.
    //
    // Different bundlers handle this in different ways. Parcel handles this by
    // having the resolver prefer the same extension as the importing file in
    // front of the configured "resolve extensions" order. Webpack's "css-loader"
    // plugin just explicitly configures a special "resolve extensions" order
    // consisting of only ".css" for CSS files.
    //
    // It's unclear what behavior is best here. What we currently do is to create
    // a special filtered version of the configured "resolve extensions" order
    // for CSS files that filters out any extension that has been explicitly
    // configured with a non-CSS loader. This still gives users control over the
    // order but avoids the scenario where we match an import in a CSS file to a
    // JavaScript-related file. It's probably not perfect with plugins in the
    // picture but it's better than some alternatives and probably pretty good.
    // atImportExtensionOrder []string

    // This mutex serves two purposes. First of all, it guards access to "dirCache"
    // which is potentially mutated during path resolution. But this mutex is also
    // necessary for performance. The "React admin" benchmark mysteriously runs
    // twice as fast when this mutex is locked around the whole resolve operation
    // instead of around individual accesses to "dirCache". For some reason,
    // reducing parallelism in the resolver helps the rest of the bundler go
    // faster. I'm not sure why this is but please don't change this unless you
    // do a lot of testing with various benchmarks and there aren't any regressions.
    mutex: *Mutex,

    /// This cache maps a directory path to information about that directory and
    /// all parent directories. When interacting with this structure, make sure
    /// to validate your keys with `Resolver.assertValidCacheKey`
    dir_cache: *DirInfo.HashMap,

    /// This is set to false for the runtime. The runtime should choose "main"
    /// over "module" in package.json
    prefer_module_field: bool = true,

    /// This is an array of paths to resolve against. Used for passing an
    /// object '{ paths: string[] }' to `require` and `resolve`; This field
    /// is overwritten while the resolution happens.
    ///
    /// When this is null, it is as if it is set to `&.{ path.dirname(referrer) }`.
    custom_dir_paths: ?[]const bun.String = null,

    pub fn getPackageManager(this: *Resolver) *PackageManager {
        return this.package_manager orelse brk: {
            bun.HTTPThread.init(&.{});
            const pm = PackageManager.initWithRuntime(
                this.log,
                this.opts.install,

                // This cannot be the threadlocal allocator. It goes to the HTTP thread.
                bun.default_allocator,

                .{},
                this.env_loader.?,
            );
            pm.onWake = this.onWakePackageManager;
            this.package_manager = pm;
            break :brk pm;
        };
    }

    pub inline fn usePackageManager(self: *const ThisResolver) bool {
        // TODO(@paperclover): make this configurable. the rationale for disabling
        // auto-install in standalone mode is that such executable must either:
        //
        // - bundle the dependency itself. dynamic `require`/`import` could be
        //   changed to bundle potential dependencies specified in package.json
        //
        // - want to load the user's node_modules, which is what currently happens.
        //
        // auto install, as of writing, is also quite buggy and untested, it always
        // installs the latest version regardless of a user's package.json or specifier.
        // in addition to being not fully stable, it is completely unexpected to invoke
        // a package manager after bundling an executable. if enough people run into
        // this, we could implement point 1
        if (self.standalone_module_graph) |_| return false;

        return self.opts.global_cache.isEnabled();
    }

    pub fn init1(
        allocator: std.mem.Allocator,
        log: *logger.Log,
        _fs: *Fs.FileSystem,
        opts: options.BundleOptions,
    ) ThisResolver {
        if (!resolver_Mutex_loaded) {
            resolver_Mutex = .{};
            resolver_Mutex_loaded = true;
        }

        return ThisResolver{
            .allocator = allocator,
            .dir_cache = DirInfo.HashMap.init(bun.default_allocator),
            .mutex = &resolver_Mutex,
            .caches = CacheSet.init(allocator),
            .opts = opts,
            .timer = Timer.start() catch @panic("Timer fail"),
            .fs = _fs,
            .log = log,
            .extension_order = opts.extension_order.default.default,
            .care_about_browser_field = opts.target == .browser,
        };
    }

    pub fn isExternalPattern(r: *ThisResolver, import_path: string) bool {
        if (r.opts.packages == .external and isPackagePath(import_path)) {
            return true;
        }
        for (r.opts.external.patterns) |pattern| {
            if (import_path.len >= pattern.prefix.len + pattern.suffix.len and (strings.startsWith(
                import_path,
                pattern.prefix,
            ) and strings.endsWith(
                import_path,
                pattern.suffix,
            ))) {
                return true;
            }
        }
        return false;
    }

    pub fn flushDebugLogs(r: *ThisResolver, flush_mode: DebugLogs.FlushMode) !void {
        if (r.debug_logs) |*debug| {
            if (flush_mode == DebugLogs.FlushMode.fail) {
                try r.log.addRangeDebugWithNotes(null, logger.Range{ .loc = logger.Loc{} }, debug.what, try debug.notes.toOwnedSlice());
            } else if (@intFromEnum(r.log.level) <= @intFromEnum(logger.Log.Level.verbose)) {
                try r.log.addVerboseWithNotes(null, logger.Loc.Empty, debug.what, try debug.notes.toOwnedSlice());
            }
        }
    }

    var tracing_start: i128 = if (FeatureFlags.tracing) 0 else undefined;
    pub fn resolveAndAutoInstall(
        r: *ThisResolver,
        source_dir: string,
        import_path: string,
        kind: ast.ImportKind,
        global_cache: GlobalCache,
    ) Result.Union {
        const tracer = bun.perf.trace("ModuleResolver.resolve");
        defer tracer.end();

        // Only setting 'current_action' in debug mode because module resolution
        // is done very often, and has a very low crash rate.
        const prev_action = if (Environment.show_crash_trace) bun.crash_handler.current_action;
        if (Environment.show_crash_trace) bun.crash_handler.current_action = .{ .resolver = .{
            .source_dir = source_dir,
            .import_path = import_path,
            .kind = kind,
        } };
        defer if (Environment.show_crash_trace) {
            bun.crash_handler.current_action = prev_action;
        };

        if (Environment.show_crash_trace and bun.CLI.debug_flags.hasResolveBreakpoint(import_path)) {
            bun.Output.debug("Resolving <green>{s}<r> from <blue>{s}<r>", .{
                import_path,
                source_dir,
            });
            @breakpoint();
        }

        const original_order = r.extension_order;
        defer r.extension_order = original_order;
        r.extension_order = switch (kind) {
            .url, .at_conditional, .at => options.BundleOptions.Defaults.CSSExtensionOrder[0..],
            .entry_point_build, .entry_point_run, .stmt, .dynamic => r.opts.extension_order.default.esm,
            else => r.opts.extension_order.default.default,
        };

        if (FeatureFlags.tracing) {
            r.timer.reset();
        }

        defer {
            if (FeatureFlags.tracing) {
                r.elapsed += r.timer.read();
            }
        }
        if (r.log.level == .verbose) {
            if (r.debug_logs != null) {
                r.debug_logs.?.deinit();
            }

            r.debug_logs = DebugLogs.init(r.allocator) catch unreachable;
        }

        if (import_path.len == 0) return .{ .not_found = {} };

        if (r.opts.mark_builtins_as_external) {
            if (strings.hasPrefixComptime(import_path, "node:") or
                strings.hasPrefixComptime(import_path, "bun:") or
                bun.jsc.ModuleLoader.HardcodedModule.Alias.has(import_path, r.opts.target))
            {
                return .{
                    .success = Result{
                        .import_kind = kind,
                        .path_pair = PathPair{
                            .primary = Path.init(import_path),
                        },
                        .is_external = true,
                        .module_type = .cjs,
                        .primary_side_effects_data = .no_side_effects__pure_data,
                    },
                };
            }
        }

        // Certain types of URLs default to being external for convenience,
        // while these rules should not be applied to the entrypoint as it is never external (#12734)
        if (kind != .entry_point_build and kind != .entry_point_run and
            (r.isExternalPattern(import_path) or
                // "fill: url(#filter);"
                (kind.isFromCSS() and strings.startsWith(import_path, "#")) or

                // "background: url(http://example.com/images/image.png);"
                strings.startsWith(import_path, "http://") or

                // "background: url(https://example.com/images/image.png);"
                strings.startsWith(import_path, "https://") or

                // "background: url(//example.com/images/image.png);"
                strings.startsWith(import_path, "//")))
        {
            if (r.debug_logs) |*debug| {
                debug.addNote("Marking this path as implicitly external");
                r.flushDebugLogs(.success) catch {};
            }

            return .{
                .success = Result{
                    .import_kind = kind,
                    .path_pair = PathPair{
                        .primary = Path.init(import_path),
                    },
                    .is_external = true,
                    .module_type = if (!kind.isFromCSS()) .esm else .unknown,
                },
            };
        }

        if (DataURL.parse(import_path) catch {
            return .{ .failure = error.InvalidDataURL };
        }) |data_url| {
            // "import 'data:text/javascript,console.log(123)';"
            // "@import 'data:text/css,body{background:white}';"
            const mime = data_url.decodeMimeType();
            if (mime.category == .javascript or mime.category == .css or mime.category == .json or mime.category == .text) {
                if (r.debug_logs) |*debug| {
                    debug.addNote("Putting this path in the \"dataurl\" namespace");
                    r.flushDebugLogs(.success) catch {};
                }

                return .{
                    .success = Result{ .path_pair = PathPair{ .primary = Path.initWithNamespace(import_path, "dataurl") } },
                };
            }

            // "background: url(data:image/png;base64,iVBORw0KGgo=);"
            if (r.debug_logs) |*debug| {
                debug.addNote("Marking this \"dataurl\" as external");
                r.flushDebugLogs(.success) catch {};
            }

            return .{
                .success = Result{
                    .path_pair = PathPair{ .primary = Path.initWithNamespace(import_path, "dataurl") },
                    .is_external = true,
                },
            };
        }

        // When using `bun build --compile`, module resolution is never
        // relative to our special /$bunfs/ directory.
        //
        // It's always relative to the current working directory of the project root.
        //
        // ...unless you pass a relative path that exists in the standalone module graph executable.
        var source_dir_resolver: bun.path.PosixToWinNormalizer = .{};
        const source_dir_normalized = brk: {
            if (r.standalone_module_graph) |graph| {
                if (bun.StandaloneModuleGraph.isBunStandaloneFilePath(import_path)) {
                    if (graph.findAssumeStandalonePath(import_path) != null) {
                        return .{
                            .success = Result{
                                .import_kind = kind,
                                .path_pair = PathPair{
                                    .primary = Path.init(import_path),
                                },
                                .is_standalone_module = true,
                                .module_type = .esm,
                            },
                        };
                    }

                    return .{ .not_found = {} };
                } else if (bun.StandaloneModuleGraph.isBunStandaloneFilePath(source_dir)) {
                    if (import_path.len > 2 and isDotSlash(import_path[0..2])) {
                        const buf = bufs(.import_path_for_standalone_module_graph);
                        const joined = bun.path.joinAbsStringBuf(source_dir, buf, &.{import_path}, .loose);

                        // Support relative paths in the graph
                        if (graph.findAssumeStandalonePath(joined)) |file| {
                            return .{
                                .success = Result{
                                    .import_kind = kind,
                                    .path_pair = PathPair{
                                        .primary = Path.init(file.name),
                                    },
                                    .is_standalone_module = true,
                                    .module_type = .esm,
                                },
                            };
                        }
                    }
                    break :brk Fs.FileSystem.instance.top_level_dir;
                }
            }

            // Fail now if there is no directory to resolve in. This can happen for
            // virtual modules (e.g. stdin) if a resolve directory is not specified.
            //
            // TODO: This is skipped for now because it is impossible to set a
            // resolveDir so we default to the top level directory instead (this
            // is backwards compat with Bun 1.0 behavior)
            // See https://github.com/oven-sh/bun/issues/8994 for more details.
            if (source_dir.len == 0) {
                // if (r.debug_logs) |*debug| {
                //     debug.addNote("Cannot resolve this path without a directory");
                //     r.flushDebugLogs(.fail) catch {};
                // }

                // return .{ .failure = error.MissingResolveDir };
                break :brk Fs.FileSystem.instance.top_level_dir;
            }

            // This can also be hit if you use plugins with non-file namespaces,
            // or call the module resolver from javascript (Bun.resolveSync)
            // with a faulty parent specifier.
            if (!std.fs.path.isAbsolute(source_dir)) {
                // if (r.debug_logs) |*debug| {
                //     debug.addNote("Cannot resolve this path without an absolute directory");
                //     r.flushDebugLogs(.fail) catch {};
                // }

                // return .{ .failure = error.InvalidResolveDir };
                break :brk Fs.FileSystem.instance.top_level_dir;
            }

            break :brk source_dir_resolver.resolveCWD(source_dir) catch @panic("Failed to query CWD");
        };

        // r.mutex.lock();
        // defer r.mutex.unlock();
        errdefer (r.flushDebugLogs(.fail) catch {});

        // A path with a null byte cannot exist on the filesystem. Continuing
        // anyways would cause assertion failures.
        if (bun.strings.containsChar(import_path, 0)) {
            r.flushDebugLogs(.fail) catch {};
            return .{ .not_found = {} };
        }

        var tmp = r.resolveWithoutSymlinks(source_dir_normalized, import_path, kind, global_cache);

        // Fragments in URLs in CSS imports are technically expected to work
        if (tmp == .not_found and kind.isFromCSS()) try_without_suffix: {
            // If resolution failed, try again with the URL query and/or hash removed
            const maybe_suffix = bun.strings.indexOfAny(import_path, "?#");
            if (maybe_suffix == null or maybe_suffix.? < 1)
                break :try_without_suffix;

            const suffix = maybe_suffix.?;
            if (r.debug_logs) |*debug| {
                debug.addNoteFmt("Retrying resolution after removing the suffix {s}", .{import_path[suffix..]});
            }
            const result2 = r.resolveWithoutSymlinks(source_dir_normalized, import_path[0..suffix], kind, global_cache);
            if (result2 == .not_found) break :try_without_suffix;
            tmp = result2;
        }

        switch (tmp) {
            .success => |*result| {
                if (!strings.eqlComptime(result.path_pair.primary.namespace, "node") and !result.is_standalone_module)
                    r.finalizeResult(result, kind) catch |err| return .{ .failure = err };

                r.flushDebugLogs(.success) catch {};
                result.import_kind = kind;
                return .{ .success = result.* };
            },
            .failure => |e| {
                r.flushDebugLogs(.fail) catch {};
                return .{ .failure = e };
            },
            .pending => |pending| {
                r.flushDebugLogs(.fail) catch {};
                return .{ .pending = pending };
            },
            .not_found => {
                r.flushDebugLogs(.fail) catch {};
                return .{ .not_found = {} };
            },
        }
    }

    pub fn resolve(r: *ThisResolver, source_dir: string, import_path: string, kind: ast.ImportKind) !Result {
        switch (r.resolveAndAutoInstall(source_dir, import_path, kind, GlobalCache.disable)) {
            .success => |result| return result,
            .pending, .not_found => return error.ModuleNotFound,

            .failure => |e| return e,
        }
    }

    /// Runs a resolution but also checking if a Bun Bake framework has an
    /// override. This is used in one place in the bundler.
    pub fn resolveWithFramework(r: *ThisResolver, source_dir: string, import_path: string, kind: ast.ImportKind) !Result {
        if (r.opts.framework) |f| {
            if (f.built_in_modules.get(import_path)) |mod| {
                switch (mod) {
                    .code => {
                        return .{
                            .import_kind = kind,
                            .path_pair = .{ .primary = Fs.Path.initWithNamespace(import_path, "node") },
                            .is_external = false,
                            .module_type = .esm,
                            .primary_side_effects_data = .no_side_effects__pure_data,
                        };
                    },
                    .import => |path| return r.resolve(r.fs.top_level_dir, path, .entry_point_build),
                }
                return .{};
            }
        }
        return r.resolve(source_dir, import_path, kind);
    }

    const ModuleTypeMap = bun.ComptimeStringMap(options.ModuleType, .{
        .{ ".mjs", options.ModuleType.esm },
        .{ ".mts", options.ModuleType.esm },
        .{ ".cjs", options.ModuleType.cjs },
        .{ ".cts", options.ModuleType.cjs },
    });

    pub fn finalizeResult(r: *ThisResolver, result: *Result, kind: ast.ImportKind) !void {
        if (result.is_external) return;

        var iter = result.path_pair.iter();
        var module_type = result.module_type;
        while (iter.next()) |path| {
            var dir: *DirInfo = (r.readDirInfo(path.name.dir) catch continue) orelse continue;
            var needs_side_effects = true;
            if (result.package_json) |existing| {
                // if we don't have it here, they might put it in a sideEfffects
                // map of the parent package.json
                // TODO: check if webpack also does this parent lookup
                needs_side_effects = existing.side_effects == .unspecified;

                result.primary_side_effects_data = switch (existing.side_effects) {
                    .unspecified => .has_side_effects,
                    .false => .no_side_effects__package_json,
                    .map => |map| if (map.contains(bun.StringHashMapUnowned.Key.init(path.text))) .has_side_effects else .no_side_effects__package_json,
                };

                if (existing.name.len == 0 or r.care_about_bin_folder) result.package_json = null;
            }

            result.package_json = result.package_json orelse dir.enclosing_package_json;

            if (needs_side_effects) {
                if (result.package_json) |package_json| {
                    result.primary_side_effects_data = switch (package_json.side_effects) {
                        .unspecified => .has_side_effects,
                        .false => .no_side_effects__package_json,
                        .map => |map| if (map.contains(bun.StringHashMapUnowned.Key.init(path.text))) .has_side_effects else .no_side_effects__package_json,
                    };
                }
            }

            if (dir.enclosing_tsconfig_json) |tsconfig| {
                result.jsx = tsconfig.mergeJSX(result.jsx);
                result.emit_decorator_metadata = result.emit_decorator_metadata or tsconfig.emit_decorator_metadata;
            }

            // If you use mjs or mts, then you're using esm
            // If you use cjs or cts, then you're using cjs
            // This should win out over the module type from package.json
            if (!kind.isFromCSS() and module_type == .unknown and path.name.ext.len == 4) {
                module_type = ModuleTypeMap.getWithLength(path.name.ext, 4) orelse .unknown;
            }

            if (dir.getEntries(r.generation)) |entries| {
                if (entries.get(path.name.filename)) |query| {
                    const symlink_path = query.entry.symlink(&r.fs.fs, r.store_fd);
                    if (symlink_path.len > 0) {
                        path.setRealpath(symlink_path);
                        if (!result.file_fd.isValid()) result.file_fd = query.entry.cache.fd;

                        if (r.debug_logs) |*debug| {
                            debug.addNoteFmt("Resolved symlink \"{s}\" to \"{s}\"", .{ path.text, symlink_path });
                        }
                    } else if (dir.abs_real_path.len > 0) {
                        var parts = [_]string{ dir.abs_real_path, query.entry.base() };
                        var buf: bun.PathBuffer = undefined;

                        var out = r.fs.absBuf(&parts, &buf);

                        const store_fd = r.store_fd;

                        if (!query.entry.cache.fd.isValid()) {
                            buf[out.len] = 0;
                            const span = buf[0..out.len :0];
                            var file: bun.FD = if (store_fd)
                                .fromStdFile(try std.fs.openFileAbsoluteZ(span, .{ .mode = .read_only }))
                            else
                                .fromStdFile(try bun.openFileForPath(span));

                            if (!store_fd) {
                                assert(file.stdioTag() == null);
                                out = try file.getFdPath(&buf);
                                file.close();
                                query.entry.cache.fd = .invalid;
                            } else {
                                query.entry.cache.fd = file;
                                Fs.FileSystem.setMaxFd(file.native());
                            }
                        }

                        defer {
                            if (r.fs.fs.needToCloseFiles()) {
                                if (query.entry.cache.fd.isValid()) {
                                    var file = query.entry.cache.fd.stdFile();
                                    file.close();
                                    query.entry.cache.fd = .invalid;
                                }
                            }
                        }

                        if (store_fd) {
                            out = try bun.getFdPath(query.entry.cache.fd, &buf);
                        }

                        const symlink = try Fs.FileSystem.FilenameStore.instance.append(@TypeOf(out), out);
                        if (r.debug_logs) |*debug| {
                            debug.addNoteFmt("Resolved symlink \"{s}\" to \"{s}\"", .{ symlink, path.text });
                        }
                        query.entry.cache.symlink = PathString.init(symlink);
                        if (!result.file_fd.isValid() and store_fd) result.file_fd = query.entry.cache.fd;

                        path.setRealpath(symlink);
                    }
                }
            }
        }

        if (!kind.isFromCSS() and module_type == .unknown) {
            if (result.package_json) |package| {
                module_type = package.module_type;
            }
        }

        result.module_type = module_type;
    }

    pub fn resolveWithoutSymlinks(
        r: *ThisResolver,
        source_dir: string,
        input_import_path: string,
        kind: ast.ImportKind,
        global_cache: GlobalCache,
    ) Result.Union {
        assert(std.fs.path.isAbsolute(source_dir));

        var import_path = input_import_path;

        // This implements the module resolution algorithm from node.js, which is
        // described here: https://nodejs.org/api/modules.html#modules_all_together
        var result: Result = Result{
            .path_pair = PathPair{
                .primary = Path.empty,
            },
            .jsx = r.opts.jsx,
        };

        // Return early if this is already an absolute path. In addition to asking
        // the file system whether this is an absolute path, we also explicitly check
        // whether it starts with a "/" and consider that an absolute path too. This
        // is because relative paths can technically start with a "/" on Windows
        // because it's not an absolute path on Windows. Then people might write code
        // with imports that start with a "/" that works fine on Windows only to
        // experience unexpected build failures later on other operating systems.
        // Treating these paths as absolute paths on all platforms means Windows
        // users will not be able to accidentally make use of these paths.
        if (std.fs.path.isAbsolute(import_path)) {
            // Collapse relative directory specifiers if they exist. Extremely
            // loose check to avoid always doing this copy, but avoid spending
            // too much time on the check.
            if (bun.strings.indexOf(import_path, "..") != null) {
                const platform = bun.path.Platform.auto;
                const ends_with_dir = platform.isSeparator(import_path[import_path.len - 1]) or
                    (import_path.len > 3 and
                        platform.isSeparator(import_path[import_path.len - 3]) and
                        import_path[import_path.len - 2] == '.' and
                        import_path[import_path.len - 1] == '.');
                const buf = bufs(.relative_abs_path);
                import_path = r.fs.absBuf(&.{import_path}, buf);
                if (ends_with_dir) {
                    buf[import_path.len] = platform.separator();
                    import_path.len += 1;
                }
            }

            if (r.debug_logs) |*debug| {
                debug.addNoteFmt("The import \"{s}\" is being treated as an absolute path", .{import_path});
            }

            // First, check path overrides from the nearest enclosing TypeScript "tsconfig.json" file
            if ((r.dirInfoCached(source_dir) catch null)) |_dir_info| {
                const dir_info: *DirInfo = _dir_info;
                if (dir_info.enclosing_tsconfig_json) |tsconfig| {
                    if (tsconfig.paths.count() > 0) {
                        if (r.matchTSConfigPaths(tsconfig, import_path, kind)) |res| {

                            // We don't set the directory fd here because it might remap an entirely different directory
                            return .{
                                .success = Result{
                                    .path_pair = res.path_pair,
                                    .diff_case = res.diff_case,
                                    .package_json = res.package_json,
                                    .dirname_fd = res.dirname_fd,
                                    .file_fd = res.file_fd,
                                    .jsx = tsconfig.mergeJSX(result.jsx),
                                },
                            };
                        }
                    }
                }
            }

            if (r.opts.external.abs_paths.count() > 0 and r.opts.external.abs_paths.contains(import_path)) {
                // If the string literal in the source text is an absolute path and has
                // been marked as an external module, mark it as *not* an absolute path.
                // That way we preserve the literal text in the output and don't generate
                // a relative path from the output directory to that path.
                if (r.debug_logs) |*debug| {
                    debug.addNoteFmt("The path \"{s}\" is marked as external by the user", .{import_path});
                }

                return .{
                    .success = Result{
                        .path_pair = .{ .primary = Path.init(import_path) },
                        .is_external = true,
                    },
                };
            }

            // Run node's resolution rules (e.g. adding ".js")
            var normalizer = ResolvePath.PosixToWinNormalizer{};
            if (r.loadAsFileOrDirectory(normalizer.resolve(source_dir, import_path), kind)) |entry| {
                return .{
                    .success = Result{
                        .dirname_fd = entry.dirname_fd,
                        .path_pair = entry.path_pair,
                        .diff_case = entry.diff_case,
                        .package_json = entry.package_json,
                        .file_fd = entry.file_fd,
                        .jsx = r.opts.jsx,
                    },
                };
            }

            return .{ .not_found = {} };
        }

        // Check both relative and package paths for CSS URL tokens, with relative
        // paths taking precedence over package paths to match Webpack behavior.
        const is_package_path = kind != .entry_point_run and isPackagePathNotAbsolute(import_path);
        const check_relative = !is_package_path or kind.isFromCSS();
        const check_package = is_package_path;

        if (check_relative) {
            if (r.custom_dir_paths) |custom_paths| {
                @branchHint(.unlikely);
                for (custom_paths) |custom_path| {
                    const custom_utf8 = custom_path.toUTF8WithoutRef(bun.default_allocator);
                    defer custom_utf8.deinit();
                    switch (r.checkRelativePath(custom_utf8.slice(), import_path, kind, global_cache)) {
                        .success => |res| return .{ .success = res },
                        .pending => |p| return .{ .pending = p },
                        .failure => |p| return .{ .failure = p },
                        .not_found => {},
                    }
                }
                bun.debugAssert(!check_package); // always from JavaScript
                return .{ .not_found = {} }; // bail out now since there isn't anywhere else to check
            } else {
                switch (r.checkRelativePath(source_dir, import_path, kind, global_cache)) {
                    .success => |res| return .{ .success = res },
                    .pending => |p| return .{ .pending = p },
                    .failure => |p| return .{ .failure = p },
                    .not_found => {},
                }
            }
        }

        if (check_package) {
            if (r.opts.polyfill_node_globals) {
                const had_node_prefix = strings.hasPrefixComptime(import_path, "node:");
                const import_path_without_node_prefix = if (had_node_prefix) import_path["node:".len..] else import_path;

                if (NodeFallbackModules.Map.get(import_path_without_node_prefix)) |*fallback_module| {
                    result.path_pair.primary = fallback_module.path;
                    result.module_type = .cjs;
                    result.package_json = @as(*PackageJSON, @ptrFromInt(@intFromPtr(fallback_module.package_json)));
                    result.is_from_node_modules = true;
                    return .{ .success = result };
                }

                if (had_node_prefix) {
                    // Module resolution fails automatically for unknown node builtins
                    if (!bun.JSC.ModuleLoader.HardcodedModule.Alias.has(import_path_without_node_prefix, .node)) {
                        return .{ .not_found = {} };
                    }

                    // Valid node:* modules becomes {} in the output
                    result.path_pair.primary.namespace = "node";
                    result.path_pair.primary.text = import_path_without_node_prefix;
                    result.path_pair.primary.name = Fs.PathName.init(import_path_without_node_prefix);
                    result.module_type = .cjs;
                    result.path_pair.primary.is_disabled = true;
                    result.is_from_node_modules = true;
                    result.primary_side_effects_data = .no_side_effects__pure_data;
                    return .{ .success = result };
                }

                // Always mark "fs" as disabled, matching Webpack v4 behavior
                if (strings.hasPrefixComptime(import_path_without_node_prefix, "fs") and
                    (import_path_without_node_prefix.len == 2 or
                        import_path_without_node_prefix[2] == '/'))
                {
                    result.path_pair.primary.namespace = "node";
                    result.path_pair.primary.text = import_path_without_node_prefix;
                    result.path_pair.primary.name = Fs.PathName.init(import_path_without_node_prefix);
                    result.module_type = .cjs;
                    result.path_pair.primary.is_disabled = true;
                    result.is_from_node_modules = true;
                    result.primary_side_effects_data = .no_side_effects__pure_data;
                    return .{ .success = result };
                }
            }

            // Check for external packages first
            if (r.opts.external.node_modules.count() > 0 and
                // Imports like "process/" need to resolve to the filesystem, not a builtin
                !strings.hasSuffixComptime(import_path, "/"))
            {
                var query = import_path;
                while (true) {
                    if (r.opts.external.node_modules.contains(query)) {
                        if (r.debug_logs) |*debug| {
                            debug.addNoteFmt("The path \"{s}\" was marked as external by the user", .{query});
                        }
                        return .{
                            .success = Result{
                                .path_pair = .{ .primary = Path.init(query) },
                                .is_external = true,
                            },
                        };
                    }

                    // If the module "foo" has been marked as external, we also want to treat
                    // paths into that module such as "foo/bar" as external too.
                    const slash = strings.lastIndexOfChar(query, '/') orelse break;
                    query = query[0..slash];
                }
            }

            if (r.custom_dir_paths) |custom_paths| {
                @branchHint(.unlikely);
                for (custom_paths) |custom_path| {
                    const custom_utf8 = custom_path.toUTF8WithoutRef(bun.default_allocator);
                    defer custom_utf8.deinit();
                    switch (r.checkPackagePath(custom_utf8.slice(), import_path, kind, global_cache)) {
                        .success => |res| return .{ .success = res },
                        .pending => |p| return .{ .pending = p },
                        .failure => |p| return .{ .failure = p },
                        .not_found => {},
                    }
                }
            } else {
                switch (r.checkPackagePath(source_dir, import_path, kind, global_cache)) {
                    .success => |res| return .{ .success = res },
                    .pending => |p| return .{ .pending = p },
                    .failure => |p| return .{ .failure = p },
                    .not_found => {},
                }
            }
        }

        return .{ .not_found = {} };
    }

    pub fn checkRelativePath(r: *ThisResolver, source_dir: string, import_path: string, kind: ast.ImportKind, global_cache: GlobalCache) Result.Union {
        const parts = [_]string{ source_dir, import_path };
        const abs_path = r.fs.absBuf(&parts, bufs(.relative_abs_path));

        if (r.opts.external.abs_paths.count() > 0 and r.opts.external.abs_paths.contains(abs_path)) {
            // If the string literal in the source text is an absolute path and has
            // been marked as an external module, mark it as *not* an absolute path.
            // That way we preserve the literal text in the output and don't generate
            // a relative path from the output directory to that path.
            if (r.debug_logs) |*debug| {
                debug.addNoteFmt("The path \"{s}\" is marked as external by the user", .{abs_path});
            }

            return .{ .success = .{
                .path_pair = .{ .primary = Path.init(r.fs.dirname_store.append(@TypeOf(abs_path), abs_path) catch bun.outOfMemory()) },
                .is_external = true,
            } };
        }

        // Check the "browser" map
        if (r.care_about_browser_field) {
            if (r.dirInfoCached(std.fs.path.dirname(abs_path) orelse unreachable) catch null) |_import_dir_info| {
                if (_import_dir_info.getEnclosingBrowserScope()) |import_dir_info| {
                    const pkg = import_dir_info.package_json.?;
                    if (r.checkBrowserMap(
                        import_dir_info,
                        abs_path,
                        .AbsolutePath,
                    )) |remap| {
                        // Is the path disabled?
                        if (remap.len == 0) {
                            var _path = Path.init(r.fs.dirname_store.append(string, abs_path) catch unreachable);
                            _path.is_disabled = true;
                            return .{
                                .success = Result{
                                    .path_pair = PathPair{
                                        .primary = _path,
                                    },
                                },
                            };
                        }

                        switch (r.resolveWithoutRemapping(import_dir_info, remap, kind, global_cache)) {
                            .success => |result| {
                                return .{ .success = .{
                                    .path_pair = result.path_pair,
                                    .diff_case = result.diff_case,
                                    .dirname_fd = result.dirname_fd,
                                    .package_json = pkg,
                                    .jsx = r.opts.jsx,
                                    .module_type = result.module_type,
                                    .is_external = result.is_external,
                                    .is_external_and_rewrite_import_path = result.is_external,
                                } };
                            },
                            else => {},
                        }
                    }
                }
            }
        }

        const prev_extension_order = r.extension_order;
        defer r.extension_order = prev_extension_order;
        if (strings.pathContainsNodeModulesFolder(abs_path)) {
            r.extension_order = r.opts.extension_order.kind(kind, true);
        }
        if (r.loadAsFileOrDirectory(abs_path, kind)) |res| {
            return .{ .success = .{
                .path_pair = res.path_pair,
                .diff_case = res.diff_case,
                .dirname_fd = res.dirname_fd,
                .package_json = res.package_json,
                .jsx = r.opts.jsx,
            } };
        } else {
            return .{ .not_found = {} };
        }
    }

    pub fn checkPackagePath(r: *ThisResolver, source_dir: string, unremapped_import_path: string, kind: ast.ImportKind, global_cache: GlobalCache) Result.Union {
        var import_path = unremapped_import_path;
        var source_dir_info = r.dirInfoCached(source_dir) catch (return .{ .not_found = {} }) orelse dir: {
            // It is possible to resolve with a source file that does not exist:
            // A. Bundler plugin refers to a non-existing `resolveDir`.
            // B. `createRequire()` is called with a path that does not exist. This was
            //    hit in Nuxt, specifically the `vite-node` dependency [1].
            //
            // Normally it would make sense to always bail here, but in the case of
            // resolving "hello" from "/project/nonexistent_dir/index.ts", resolution
            // should still query "/project/node_modules" and "/node_modules"
            //
            // For case B in Node.js, they use `_resolveLookupPaths` in
            // combination with `_nodeModulePaths` to collect a listing of
            // all possible parent `node_modules` [2]. Bun has a much smarter
            // approach that caches directory entries, but it (correctly) does
            // not cache non-existing directories. To successfully resolve this,
            // Bun finds the nearest existing directory, and uses that as the base
            // for `node_modules` resolution. Since that directory entry knows how
            // to resolve concrete node_modules, this iteration stops at the first
            // existing directory, regardless of what it is.
            //
            // The resulting `source_dir_info` cannot resolve relative files.
            //
            // [1]: https://github.com/oven-sh/bun/issues/16705
            // [2]: https://github.com/nodejs/node/blob/e346323109b49fa6b9a4705f4e3816fc3a30c151/lib/internal/modules/cjs/loader.js#L1934
            if (Environment.allow_assert)
                bun.assert(isPackagePath(import_path));
            var closest_dir = source_dir;
            // Use std.fs.path.dirname to get `null` once the entire
            // directory tree has been visited. `null` is theoretically
            // impossible since the drive root should always exist.
            while (std.fs.path.dirname(closest_dir)) |current| : (closest_dir = current) {
                if (r.dirInfoCached(current) catch return .{ .not_found = {} }) |dir|
                    break :dir dir;
            }
            return .{ .not_found = {} };
        };

        if (r.care_about_browser_field) {
            // Support remapping one package path to another via the "browser" field
            if (source_dir_info.getEnclosingBrowserScope()) |browser_scope| {
                if (browser_scope.package_json) |package_json| {
                    if (r.checkBrowserMap(
                        browser_scope,
                        import_path,
                        .PackagePath,
                    )) |remapped| {
                        if (remapped.len == 0) {
                            // "browser": {"module": false}
                            // does the module exist in the filesystem?
                            switch (r.loadNodeModules(import_path, kind, source_dir_info, global_cache, false)) {
                                .success => |node_module| {
                                    var pair = node_module.path_pair;
                                    pair.primary.is_disabled = true;
                                    if (pair.secondary != null) {
                                        pair.secondary.?.is_disabled = true;
                                    }
                                    return .{
                                        .success = Result{
                                            .path_pair = pair,
                                            .dirname_fd = node_module.dirname_fd,
                                            .diff_case = node_module.diff_case,
                                            .package_json = package_json,
                                            .jsx = r.opts.jsx,
                                        },
                                    };
                                },
                                else => {
                                    // "browser": {"module": false}
                                    // the module doesn't exist and it's disabled
                                    // so we should just not try to load it
                                    var primary = Path.init(import_path);
                                    primary.is_disabled = true;
                                    return .{
                                        .success = Result{
                                            .path_pair = PathPair{ .primary = primary },
                                            .diff_case = null,
                                            .jsx = r.opts.jsx,
                                        },
                                    };
                                },
                            }
                        }

                        import_path = remapped;
                        source_dir_info = browser_scope;
                    }
                }
            }
        }

        switch (r.resolveWithoutRemapping(source_dir_info, import_path, kind, global_cache)) {
            .success => |res| {
                var result: Result = Result{
                    .path_pair = PathPair{
                        .primary = Path.empty,
                    },
                    .jsx = r.opts.jsx,
                };
                result.path_pair = res.path_pair;
                result.dirname_fd = res.dirname_fd;
                result.file_fd = res.file_fd;
                result.package_json = res.package_json;
                result.diff_case = res.diff_case;
                result.is_from_node_modules = result.is_from_node_modules or res.is_node_module;
                result.jsx = r.opts.jsx;
                result.module_type = res.module_type;
                result.is_external = res.is_external;
                // Potentially rewrite the import path if it's external that
                // was remapped to a different path
                result.is_external_and_rewrite_import_path = result.is_external;

                if (res.path_pair.primary.is_disabled and res.path_pair.secondary == null) {
                    return .{ .success = result };
                }

                if (res.package_json != null and r.care_about_browser_field) {
                    var base_dir_info = res.dir_info orelse (r.readDirInfo(res.path_pair.primary.name.dir) catch null) orelse return .{ .success = result };
                    if (base_dir_info.getEnclosingBrowserScope()) |browser_scope| {
                        if (r.checkBrowserMap(
                            browser_scope,
                            res.path_pair.primary.text,
                            .AbsolutePath,
                        )) |remap| {
                            if (remap.len == 0) {
                                result.path_pair.primary.is_disabled = true;
                                result.path_pair.primary = Fs.Path.initWithNamespace(remap, "file");
                            } else {
                                switch (r.resolveWithoutRemapping(browser_scope, remap, kind, global_cache)) {
                                    .success => |remapped| {
                                        result.path_pair = remapped.path_pair;
                                        result.dirname_fd = remapped.dirname_fd;
                                        result.file_fd = remapped.file_fd;
                                        result.package_json = remapped.package_json;
                                        result.diff_case = remapped.diff_case;
                                        result.module_type = remapped.module_type;
                                        result.is_external = remapped.is_external;

                                        // Potentially rewrite the import path if it's external that
                                        // was remapped to a different path
                                        result.is_external_and_rewrite_import_path = result.is_external;

                                        result.is_from_node_modules = result.is_from_node_modules or remapped.is_node_module;
                                        return .{ .success = result };
                                    },
                                    else => {},
                                }
                            }
                        }
                    }
                }

                return .{ .success = result };
            },
            .pending => |p| return .{ .pending = p },
            .failure => |p| return .{ .failure = p },
            else => return .{ .not_found = {} },
        }
    }

    // This is a fallback, hopefully not called often. It should be relatively quick because everything should be in the cache.
    pub fn packageJSONForResolvedNodeModule(
        r: *ThisResolver,
        result: *const Result,
    ) ?*const PackageJSON {
        var dir_info = (r.dirInfoCached(result.path_pair.primary.name.dir) catch null) orelse return null;
        while (true) {
            if (dir_info.package_json) |pkg| {
                // if it doesn't have a name, assume it's something just for adjusting the main fields (react-bootstrap does this)
                // In that case, we really would like the top-level package that you download from NPM
                // so we ignore any unnamed packages
                return pkg;
            }

            dir_info = dir_info.getParent() orelse return null;
        }

        unreachable;
    }
    const node_module_root_string = std.fs.path.sep_str ++ "node_modules" ++ std.fs.path.sep_str;

    pub fn rootNodeModulePackageJSON(
        r: *ThisResolver,
        result: *const Result,
    ) ?RootPathPair {
        const path = (result.pathConst() orelse return null);
        var absolute = path.text;
        // /foo/node_modules/@babel/standalone/index.js
        //     ^------------^
        var end = strings.lastIndexOf(absolute, node_module_root_string) orelse brk: {
            // try non-symlinked version
            if (path.pretty.len != absolute.len) {
                absolute = path.pretty;
                break :brk strings.lastIndexOf(absolute, node_module_root_string);
            }

            break :brk null;
        } orelse return null;
        end += node_module_root_string.len;

        const is_scoped_package = absolute[end] == '@';
        end += strings.indexOfChar(absolute[end..], std.fs.path.sep) orelse return null;

        // /foo/node_modules/@babel/standalone/index.js
        //                   ^
        if (is_scoped_package) {
            end += 1;
            end += strings.indexOfChar(absolute[end..], std.fs.path.sep) orelse return null;
        }

        end += 1;

        // /foo/node_modules/@babel/standalone/index.js
        //                                    ^
        const slice = absolute[0..end];

        // Try to avoid the hash table lookup whenever possible
        // That can cause filesystem lookups in parent directories and it requires a lock
        if (result.package_json) |pkg| {
            if (strings.eql(slice, pkg.source.path.name.dirWithTrailingSlash())) {
                return RootPathPair{
                    .package_json = pkg,
                    .base_path = slice,
                };
            }
        }

        {
            const dir_info = (r.dirInfoCached(slice) catch null) orelse return null;
            return RootPathPair{
                .base_path = slice,
                .package_json = dir_info.package_json orelse return null,
            };
        }
    }

    const dev = Output.scoped(.Resolver, false);

    /// Directory cache keys must follow the following rules. If the rules are broken,
    /// then there will be conflicting cache entries, and trying to bust the cache may not work.
    ///
    /// When an incorrect cache key is used, this assertion will trip; ignoring it allows
    /// very very subtle cache invalidation issues to happen, which will cause modules to
    /// mysteriously fail to resolve.
    ///
    /// The rules for this changed in https://github.com/oven-sh/bun/pull/9144 after multiple
    /// cache issues were found on Windows. These issues extended to other platforms because
    /// we never checked if the cache key was following the rules.
    ///
    /// CACHE KEY RULES:
    /// A cache key must use native slashes, and must NOT end with a trailing slash.
    /// But drive roots MUST have a trailing slash ('/' and 'C:\')
    /// UNC paths, even if the root, must not have the trailing slash.
    ///
    /// The helper function bun.strings.withoutTrailingSlashWindowsPath can be used
    /// to remove the trailing slash from a path
    pub fn assertValidCacheKey(path: []const u8) void {
        if (Environment.allow_assert) {
            if (path.len > 1 and strings.charIsAnySlash(path[path.len - 1]) and !if (Environment.isWindows)
                path.len == 3 and path[1] == ':'
            else
                path.len == 1)
            {
                std.debug.panic("Internal Assertion Failure: Invalid cache key \"{s}\"\nSee Resolver.assertValidCacheKey for details.", .{path});
            }
        }
    }

    /// Bust the directory cache for the given path.
    /// See `assertValidCacheKey` for requirements on the input
    pub fn bustDirCache(r: *ThisResolver, path: string) bool {
        assertValidCacheKey(path);
        const first_bust = r.fs.fs.bustEntriesCache(path);
        const second_bust = r.dir_cache.remove(path);
        dev("Bust {s} = {}, {}", .{ path, first_bust, second_bust });
        return first_bust or second_bust;
    }

    /// bust both the named file and a parent directory, because `./hello` can resolve
    /// to `./hello.js` or `./hello/index.js`
    pub fn bustDirCacheFromSpecifier(r: *ThisResolver, import_source_file: []const u8, specifier: []const u8) bool {
        if (std.fs.path.isAbsolute(specifier)) {
            const dir = bun.path.dirname(specifier, .auto);
            const a = r.bustDirCache(dir);
            const b = r.bustDirCache(specifier);
            return a or b;
        }

        if (!(bun.strings.startsWith(specifier, "./") or
            bun.strings.startsWith(specifier, "../"))) return false;
        if (!std.fs.path.isAbsolute(import_source_file))
            return false;

        const joined = bun.path.joinAbs(bun.path.dirname(import_source_file, .auto), .auto, specifier);
        const dir = bun.path.dirname(joined, .auto);

        const a = r.bustDirCache(dir);
        const b = r.bustDirCache(joined);
        return a or b;
    }

    pub fn loadNodeModules(
        r: *ThisResolver,
        import_path: string,
        kind: ast.ImportKind,
        _dir_info: *DirInfo,
        global_cache: GlobalCache,
        forbid_imports: bool,
    ) MatchResult.Union {
        var dir_info = _dir_info;
        if (r.debug_logs) |*debug| {
            debug.addNoteFmt("Searching for {s} in \"node_modules\" directories starting from \"{s}\"", .{ import_path, dir_info.abs_path });
            debug.increaseIndent();
        }

        defer {
            if (r.debug_logs) |*debug| {
                debug.decreaseIndent();
            }
        }

        // First, check path overrides from the nearest enclosing TypeScript "tsconfig.json" file

        if (dir_info.enclosing_tsconfig_json) |tsconfig| {
            // Try path substitutions first
            if (tsconfig.paths.count() > 0) {
                if (r.matchTSConfigPaths(tsconfig, import_path, kind)) |res| {
                    return .{ .success = res };
                }
            }

            // Try looking up the path relative to the base URL
            if (tsconfig.hasBaseURL()) {
                const base = tsconfig.base_url;
                const paths = [_]string{ base, import_path };
                const abs = r.fs.absBuf(&paths, bufs(.load_as_file_or_directory_via_tsconfig_base_path));

                if (r.loadAsFileOrDirectory(abs, kind)) |res| {
                    return .{ .success = res };
                }
                // r.allocator.free(abs);
            }
        }

        var is_self_reference = false;

        // Find the parent directory with the "package.json" file
        var dir_info_package_json: ?*DirInfo = dir_info;
        while (dir_info_package_json != null and dir_info_package_json.?.package_json == null)
            dir_info_package_json = dir_info_package_json.?.getParent();

        // Check for subpath imports: https://nodejs.org/api/packages.html#subpath-imports
        if (dir_info_package_json) |_dir_info_package_json| {
            const package_json = _dir_info_package_json.package_json.?;

            if (strings.hasPrefixComptime(import_path, "#") and !forbid_imports and package_json.imports != null) {
                return r.loadPackageImports(import_path, _dir_info_package_json, kind, global_cache);
            }

            // https://nodejs.org/api/packages.html#packages_self_referencing_a_package_using_its_name
            const package_name = ESModule.Package.parseName(import_path);
            if (package_name) |_package_name| {
                if (strings.eql(_package_name, package_json.name) and package_json.exports != null) {
                    if (r.debug_logs) |*debug| {
                        debug.addNoteFmt("\"{s}\" is a self-reference", .{import_path});
                    }
                    dir_info = _dir_info_package_json;
                    is_self_reference = true;
                }
            }
        }

        const esm_ = ESModule.Package.parse(import_path, bufs(.esm_subpath));

        const source_dir_info = dir_info;
        var any_node_modules_folder = false;
        const use_node_module_resolver = global_cache != .force;

        // Then check for the package in any enclosing "node_modules" directories
        // or in the package root directory if it's a self-reference
        while (use_node_module_resolver) {
            // Skip directories that are themselves called "node_modules", since we
            // don't ever want to search for "node_modules/node_modules"
            if (dir_info.hasNodeModules() or is_self_reference) {
                any_node_modules_folder = true;
                const abs_path = if (is_self_reference)
                    dir_info.abs_path
                else brk: {
                    var _parts = [_]string{ dir_info.abs_path, "node_modules", import_path };
                    break :brk r.fs.absBuf(&_parts, bufs(.node_modules_check));
                };
                if (r.debug_logs) |*debug| {
                    debug.addNoteFmt("Checking for a package in the directory \"{s}\"", .{abs_path});
                }

                const prev_extension_order = r.extension_order;
                defer r.extension_order = prev_extension_order;

                if (esm_) |esm| {
                    const abs_package_path = brk: {
                        if (is_self_reference) break :brk dir_info.abs_path;
                        var parts = [_]string{ dir_info.abs_path, "node_modules", esm.name };
                        break :brk r.fs.absBuf(&parts, bufs(.esm_absolute_package_path));
                    };

                    if (r.dirInfoCached(abs_package_path) catch null) |pkg_dir_info| {
                        r.extension_order = switch (kind) {
                            .url, .at_conditional, .at => options.BundleOptions.Defaults.CSSExtensionOrder[0..],
                            else => r.opts.extension_order.kind(kind, true),
                        };

                        if (pkg_dir_info.package_json) |package_json| {
                            if (package_json.exports) |*exports_map| {

                                // The condition set is determined by the kind of import
                                var module_type = package_json.module_type;
                                const esmodule = ESModule{
                                    .conditions = switch (kind) {
                                        ast.ImportKind.require, ast.ImportKind.require_resolve => r.opts.conditions.require,
                                        ast.ImportKind.at, ast.ImportKind.at_conditional => r.opts.conditions.style,
                                        else => r.opts.conditions.import,
                                    },
                                    .allocator = r.allocator,
                                    .debug_logs = if (r.debug_logs) |*debug| debug else null,
                                    .module_type = &module_type,
                                };

                                // Resolve against the path "/", then join it with the absolute
                                // directory path. This is done because ESM package resolution uses
                                // URLs while our path resolution uses file system paths. We don't
                                // want problems due to Windows paths, which are very unlike URL
                                // paths. We also want to avoid any "%" characters in the absolute
                                // directory path accidentally being interpreted as URL escapes.
                                {
                                    const esm_resolution = esmodule.resolve("/", esm.subpath, exports_map.root);

                                    if (r.handleESMResolution(esm_resolution, abs_package_path, kind, package_json, esm.subpath)) |result| {
                                        var result_copy = result;
                                        result_copy.is_node_module = true;
                                        result_copy.module_type = module_type;
                                        return .{ .success = result_copy };
                                    }
                                }

                                // Some popular packages forget to include the extension in their
                                // exports map, so we try again without the extension.
                                //
                                // This is useful for browser-like environments
                                // where you want a file extension in the URL
                                // pathname by convention. Vite does this.
                                //
                                // React is an example of a package that doesn't include file extensions.
                                // {
                                //     "exports": {
                                //         ".": "./index.js",
                                //         "./jsx-runtime": "./jsx-runtime.js",
                                //     }
                                // }
                                //
                                // We limit this behavior just to ".js" files.
                                const extname = std.fs.path.extension(esm.subpath);
                                if (strings.eqlComptime(extname, ".js") and esm.subpath.len > 3) {
                                    const esm_resolution = esmodule.resolve("/", esm.subpath[0 .. esm.subpath.len - 3], exports_map.root);
                                    if (r.handleESMResolution(esm_resolution, abs_package_path, kind, package_json, esm.subpath)) |result| {
                                        var result_copy = result;
                                        result_copy.is_node_module = true;
                                        result_copy.module_type = module_type;
                                        return .{ .success = result_copy };
                                    }
                                }

                                // if they hid "package.json" from "exports", still allow importing it.
                                if (strings.eqlComptime(esm.subpath, "./package.json")) {
                                    return .{
                                        .success = .{
                                            .path_pair = .{ .primary = package_json.source.path },
                                            .dirname_fd = pkg_dir_info.getFileDescriptor(),
                                            .file_fd = .invalid,
                                            .is_node_module = package_json.source.path.isNodeModule(),
                                            .package_json = package_json,
                                            .dir_info = dir_info,
                                        },
                                    };
                                }

                                return .{ .not_found = {} };
                            }
                        }
                    }
                }

                if (r.loadAsFileOrDirectory(abs_path, kind)) |res| {
                    return .{ .success = res };
                }
            }

            dir_info = dir_info.getParent() orelse break;
        }

        // try resolve from `NODE_PATH`
        // https://nodejs.org/api/modules.html#loading-from-the-global-folders
        const node_path: []const u8 = if (r.env_loader) |env_loader| env_loader.get("NODE_PATH") orelse "" else "";
        if (node_path.len > 0) {
            var it = std.mem.tokenizeScalar(u8, node_path, if (Environment.isWindows) ';' else ':');
            while (it.next()) |path| {
                const abs_path = r.fs.absBuf(&[_]string{ path, import_path }, bufs(.node_modules_check));
                if (r.debug_logs) |*debug| {
                    debug.addNoteFmt("Checking for a package in the NODE_PATH directory \"{s}\"", .{abs_path});
                }
                if (r.loadAsFileOrDirectory(abs_path, kind)) |res| {
                    return .{ .success = res };
                }
            }
        }

        dir_info = source_dir_info;

        // this is the magic!
        if (global_cache.canUse(any_node_modules_folder) and r.usePackageManager() and esm_ != null) {
            if (comptime bun.fast_debug_build_mode and bun.fast_debug_build_cmd != .RunCommand) unreachable;
            const esm = esm_.?.withAutoVersion();
            load_module_from_cache: {
                // If the source directory doesn't have a node_modules directory, we can
                // check the global cache directory for a package.json file.
                const manager = r.getPackageManager();
                var dependency_version = Dependency.Version{};
                var dependency_behavior: Dependency.Behavior = .{ .prod = true };
                var string_buf = esm.version;

                // const initial_pending_tasks = manager.pending_tasks;
                var resolved_package_id: Install.PackageID = brk: {
                    // check if the package.json in the source directory was already added to the lockfile
                    // and try to look up the dependency from there
                    if (dir_info.package_json_for_dependencies) |package_json| {
                        var dependencies_list: []const Dependency = &[_]Dependency{};
                        const resolve_from_lockfile = package_json.package_manager_package_id != Install.invalid_package_id;

                        if (resolve_from_lockfile) {
                            const dependencies = &manager.lockfile.packages.items(.dependencies)[package_json.package_manager_package_id];

                            // try to find this package name in the dependencies of the enclosing package
                            dependencies_list = dependencies.get(manager.lockfile.buffers.dependencies.items);
                            string_buf = manager.lockfile.buffers.string_bytes.items;
                        } else if (esm_.?.version.len == 0) {
                            // If you don't specify a version, default to the one chosen in your package.json
                            dependencies_list = package_json.dependencies.map.values();
                            string_buf = package_json.dependencies.source_buf;
                        }

                        for (dependencies_list, 0..) |dependency, dependency_id| {
                            if (!strings.eqlLong(dependency.name.slice(string_buf), esm.name, true)) {
                                continue;
                            }

                            dependency_version = dependency.version;
                            dependency_behavior = dependency.behavior;

                            if (resolve_from_lockfile) {
                                const resolutions = &manager.lockfile.packages.items(.resolutions)[package_json.package_manager_package_id];

                                // found it!
                                break :brk resolutions.get(manager.lockfile.buffers.resolutions.items)[dependency_id];
                            }

                            break;
                        }
                    }

                    // If we get here, it means that the lockfile doesn't have this package at all.
                    // we know nothing
                    break :brk Install.invalid_package_id;
                };

                // Now, there are two possible states:
                // 1) We have resolved the package ID, either from the
                //    lockfile globally OR from the particular package.json
                //    dependencies list
                //
                // 2) We parsed the Dependency.Version but there is no
                //    existing resolved package ID

                // If its an exact version, we can just immediately look it up in the global cache and resolve from there
                // If the resolved package ID is _not_ invalid, we can just check

                // If this returns null, then it means we need to *resolve* the package
                // Even after resolution, we might still need to download the package
                // There are two steps here! Two steps!
                const resolution: Resolution = brk: {
                    if (resolved_package_id == Install.invalid_package_id) {
                        if (dependency_version.tag == .uninitialized) {
                            const sliced_string = Semver.SlicedString.init(esm.version, esm.version);
                            if (esm_.?.version.len > 0 and dir_info.enclosing_package_json != null and global_cache.allowVersionSpecifier()) {
                                return .{ .failure = error.VersionSpecifierNotAllowedHere };
                            }
                            string_buf = esm.version;
                            dependency_version = Dependency.parse(
                                r.allocator,
                                Semver.String.init(esm.name, esm.name),
                                null,
                                esm.version,
                                &sliced_string,
                                r.log,
                                manager,
                            ) orelse break :load_module_from_cache;
                        }

                        if (manager.lockfile.resolvePackageFromNameAndVersion(esm.name, dependency_version)) |id| {
                            resolved_package_id = id;
                        }
                    }

                    if (resolved_package_id != Install.invalid_package_id) {
                        break :brk manager.lockfile.packages.items(.resolution)[resolved_package_id];
                    }

                    // unsupported or not found dependency, we might need to install it to the cache
                    switch (r.enqueueDependencyToResolve(
                        dir_info.package_json_for_dependencies orelse dir_info.package_json,
                        esm,
                        dependency_behavior,
                        &resolved_package_id,
                        dependency_version,
                        string_buf,
                    )) {
                        .resolution => |res| break :brk res,
                        .pending => |pending| return .{ .pending = pending },
                        .failure => |err| return .{ .failure = err },
                        // this means we looked it up in the registry and the package doesn't exist or the version doesn't exist
                        .not_found => return .{ .not_found = {} },
                    }
                };

                const dir_path_for_resolution = manager.pathForResolution(resolved_package_id, resolution, bufs(.path_in_global_disk_cache)) catch |err| {
                    // if it's missing, we need to install it
                    if (err == error.FileNotFound) {
                        switch (manager.getPreinstallState(resolved_package_id)) {
                            .done => {
                                var path = Fs.Path.init(import_path);
                                path.is_disabled = true;
                                // this might mean the package is disabled
                                return .{
                                    .success = .{
                                        .path_pair = .{
                                            .primary = path,
                                        },
                                    },
                                };
                            },
                            .extract, .extracting => |st| {
                                if (!global_cache.canInstall()) {
                                    return .{ .not_found = {} };
                                }
                                var builder = Semver.String.Builder{};
                                esm.count(&builder);
                                builder.allocate(manager.allocator) catch unreachable;
                                const cloned = esm.clone(&builder);

                                if (st == .extract)
                                    manager.enqueuePackageForDownload(
                                        esm.name,
                                        manager.lockfile.buffers.legacyPackageToDependencyID(null, resolved_package_id) catch unreachable,
                                        resolved_package_id,
                                        resolution.value.npm.version,
                                        manager.lockfile.str(&resolution.value.npm.url),
                                        .{
                                            .root_request_id = 0,
                                        },
                                        null,
                                    ) catch |enqueue_download_err| return .{ .failure = enqueue_download_err };

                                return .{
                                    .pending = .{
                                        .esm = cloned,
                                        .dependency = dependency_version,
                                        .resolution_id = resolved_package_id,

                                        .string_buf = builder.allocatedSlice(),
                                        .tag = .download,
                                    },
                                };
                            },
                            else => {},
                        }
                    }

                    return .{ .failure = err };
                };

                if (r.dirInfoForResolution(dir_path_for_resolution, resolved_package_id)) |dir_info_to_use_| {
                    if (dir_info_to_use_) |pkg_dir_info| {
                        const abs_package_path = pkg_dir_info.abs_path;
                        var module_type = options.ModuleType.unknown;
                        if (pkg_dir_info.package_json) |package_json| {
                            if (package_json.exports) |exports_map| {
                                // The condition set is determined by the kind of import
                                const esmodule = ESModule{
                                    .conditions = switch (kind) {
                                        ast.ImportKind.require,
                                        ast.ImportKind.require_resolve,
                                        => r.opts.conditions.require,
                                        else => r.opts.conditions.import,
                                    },
                                    .allocator = r.allocator,
                                    .module_type = &module_type,
                                    .debug_logs = if (r.debug_logs) |*debug|
                                        debug
                                    else
                                        null,
                                };

                                // Resolve against the path "/", then join it with the absolute
                                // directory path. This is done because ESM package resolution uses
                                // URLs while our path resolution uses file system paths. We don't
                                // want problems due to Windows paths, which are very unlike URL
                                // paths. We also want to avoid any "%" characters in the absolute
                                // directory path accidentally being interpreted as URL escapes.
                                {
                                    const esm_resolution = esmodule.resolve("/", esm.subpath, exports_map.root);

                                    if (r.handleESMResolution(esm_resolution, abs_package_path, kind, package_json, esm.subpath)) |result| {
                                        var result_copy = result;
                                        result_copy.is_node_module = true;
                                        return .{ .success = result_copy };
                                    }
                                }

                                // Some popular packages forget to include the extension in their
                                // exports map, so we try again without the extension.
                                //
                                // This is useful for browser-like environments
                                // where you want a file extension in the URL
                                // pathname by convention. Vite does this.
                                //
                                // React is an example of a package that doesn't include file extensions.
                                // {
                                //     "exports": {
                                //         ".": "./index.js",
                                //         "./jsx-runtime": "./jsx-runtime.js",
                                //     }
                                // }
                                //
                                // We limit this behavior just to ".js" files.
                                const extname = std.fs.path.extension(esm.subpath);
                                if (strings.eqlComptime(extname, ".js") and esm.subpath.len > 3) {
                                    const esm_resolution = esmodule.resolve("/", esm.subpath[0 .. esm.subpath.len - 3], exports_map.root);
                                    if (r.handleESMResolution(esm_resolution, abs_package_path, kind, package_json, esm.subpath)) |result| {
                                        var result_copy = result;
                                        result_copy.is_node_module = true;
                                        return .{ .success = result_copy };
                                    }
                                }

                                // if they hid "package.json" from "exports", still allow importing it.
                                if (strings.eqlComptime(esm.subpath, "./package.json")) {
                                    return .{
                                        .success = .{
                                            .path_pair = .{ .primary = package_json.source.path },
                                            .dirname_fd = pkg_dir_info.getFileDescriptor(),
                                            .file_fd = .invalid,
                                            .is_node_module = package_json.source.path.isNodeModule(),
                                            .package_json = package_json,
                                            .dir_info = dir_info,
                                        },
                                    };
                                }

                                return .{ .not_found = {} };
                            }
                        }

                        var _paths = [_]string{ pkg_dir_info.abs_path, esm.subpath };
                        const abs_path = r.fs.absBuf(&_paths, bufs(.node_modules_check));
                        if (r.debug_logs) |*debug| {
                            debug.addNoteFmt("Checking for a package in the directory \"{s}\"", .{abs_path});
                        }

                        var tmp = r.loadAsFileOrDirectory(abs_path, kind);
                        if (tmp) |*res| {
                            res.is_node_module = true;
                            return .{ .success = res.* };
                        }
                    }
                } else |err| {
                    return .{ .failure = err };
                }
            }
        }

        return .{ .not_found = {} };
    }
    fn dirInfoForResolution(
        r: *ThisResolver,
        dir_path_maybe_trail_slash: string,
        package_id: Install.PackageID,
    ) !?*DirInfo {
        assert(r.package_manager != null);

        const dir_path = strings.withoutTrailingSlashWindowsPath(dir_path_maybe_trail_slash);

        assertValidCacheKey(dir_path);
        var dir_cache_info_result = r.dir_cache.getOrPut(dir_path) catch bun.outOfMemory();
        if (dir_cache_info_result.status == .exists) {
            // we've already looked up this package before
            return r.dir_cache.atIndex(dir_cache_info_result.index).?;
        }
        var rfs = &r.fs.fs;
        var cached_dir_entry_result = rfs.entries.getOrPut(dir_path) catch bun.outOfMemory();

        var dir_entries_option: *Fs.FileSystem.RealFS.EntriesOption = undefined;
        var needs_iter = true;
        var in_place: ?*Fs.FileSystem.DirEntry = null;
        const open_dir = bun.openDirForIteration(std.fs.cwd(), dir_path) catch |err| {
            // TODO: handle this error better
            r.log.addErrorFmt(
                null,
                logger.Loc.Empty,
                r.allocator,
                "Unable to open directory: {s}",
                .{bun.asByteSlice(@errorName(err))},
            ) catch unreachable;
            return err;
        };

        if (rfs.entries.atIndex(cached_dir_entry_result.index)) |cached_entry| {
            if (cached_entry.* == .entries) {
                if (cached_entry.entries.generation >= r.generation) {
                    dir_entries_option = cached_entry;
                    needs_iter = false;
                } else {
                    in_place = cached_entry.entries;
                }
            }
        }

        if (needs_iter) {
            const allocator = bun.fs_allocator;
            var new_entry = Fs.FileSystem.DirEntry.init(
                if (in_place) |existing| existing.dir else Fs.FileSystem.DirnameStore.instance.append(string, dir_path) catch unreachable,
                r.generation,
            );

            var dir_iterator = bun.iterateDir(open_dir);
            while (dir_iterator.next().unwrap() catch null) |_value| {
                new_entry.addEntry(
                    if (in_place) |existing| &existing.data else null,
                    &_value,
                    allocator,
                    void,
                    {},
                ) catch unreachable;
            }
            if (in_place) |existing| {
                existing.data.clearAndFree(allocator);
            }

            var dir_entries_ptr = in_place orelse allocator.create(Fs.FileSystem.DirEntry) catch unreachable;
            dir_entries_ptr.* = new_entry;

            if (r.store_fd) {
                dir_entries_ptr.fd = .fromStdDir(open_dir);
            }

            bun.fs.debug("readdir({}, {s}) = {d}", .{ bun.FD.fromStdDir(open_dir), dir_path, dir_entries_ptr.data.count() });

            dir_entries_option = rfs.entries.put(&cached_dir_entry_result, .{
                .entries = dir_entries_ptr,
            }) catch unreachable;
        }

        // We must initialize it as empty so that the result index is correct.
        // This is important so that browser_scope has a valid index.
        const dir_info_ptr = r.dir_cache.put(&dir_cache_info_result, .{}) catch unreachable;

        try r.dirInfoUncached(
            dir_info_ptr,
            dir_path,
            dir_entries_option,
            dir_cache_info_result,
            cached_dir_entry_result.index,
            // Packages in the global disk cache are top-level, we shouldn't try
            // to check for a parent package.json
            null,
            allocators.NotFound,
            .fromStdDir(open_dir),
            package_id,
        );
        return dir_info_ptr;
    }

    const DependencyToResolve = union(enum) {
        not_found: void,
        pending: PendingResolution,
        failure: anyerror,
        resolution: Resolution,
    };

    fn enqueueDependencyToResolve(
        r: *ThisResolver,
        package_json_: ?*PackageJSON,
        esm: ESModule.Package,
        behavior: Dependency.Behavior,
        input_package_id_: *Install.PackageID,
        version: Dependency.Version,
        version_buf: []const u8,
    ) DependencyToResolve {
        if (r.debug_logs) |*debug| {
            debug.addNoteFmt("Enqueueing pending dependency \"{s}@{s}\"", .{ esm.name, esm.version });
        }

        const input_package_id = input_package_id_.*;
        var pm = r.getPackageManager();
        if (comptime Environment.allow_assert) {
            // we should never be trying to resolve a dependency that is already resolved
            assert(pm.lockfile.resolvePackageFromNameAndVersion(esm.name, version) == null);
        }

        // Add the containing package to the lockfile

        var package: Package = .{};

        const is_main = pm.lockfile.packages.len == 0 and input_package_id == Install.invalid_package_id;
        if (is_main) {
            if (package_json_) |package_json| {
                package = Package.fromPackageJSON(
                    pm.lockfile,
                    pm,
                    package_json,
                    Install.Features{
                        .dev_dependencies = true,
                        .is_main = true,
                        .dependencies = true,
                        .optional_dependencies = true,
                    },
                ) catch |err| {
                    return .{ .failure = err };
                };
                package.meta.setHasInstallScript(package.scripts.hasAny());
                package = pm.lockfile.appendPackage(package) catch |err| {
                    return .{ .failure = err };
                };
                package_json.package_manager_package_id = package.meta.id;
            } else {
                // we're resolving an unknown package
                // the unknown package is the root package
                package = Package{
                    .name = Semver.String.from(""),
                    .resolution = .{
                        .tag = .root,
                        .value = .{ .root = {} },
                    },
                };
                package.meta.setHasInstallScript(package.scripts.hasAny());
                package = pm.lockfile.appendPackage(package) catch |err| {
                    return .{ .failure = err };
                };
            }
        }

        if (r.opts.prefer_offline_install) {
            if (pm.resolveFromDiskCache(esm.name, version)) |package_id| {
                input_package_id_.* = package_id;
                return .{ .resolution = pm.lockfile.packages.items(.resolution)[package_id] };
            }
        }

        if (input_package_id == Install.invalid_package_id or input_package_id == 0) {

            // All packages are enqueued to the root
            // because we download all the npm package dependencies
            switch (pm.enqueueDependencyToRoot(esm.name, &version, version_buf, behavior)) {
                .resolution => |result| {
                    input_package_id_.* = result.package_id;
                    return .{ .resolution = result.resolution };
                },
                .pending => |id| {
                    var builder = Semver.String.Builder{};
                    esm.count(&builder);
                    builder.allocate(pm.allocator) catch unreachable;
                    const cloned = esm.clone(&builder);

                    return .{
                        .pending = .{
                            .esm = cloned,
                            .dependency = version,
                            .root_dependency_id = id,
                            .string_buf = builder.allocatedSlice(),
                            .tag = .resolve,
                        },
                    };
                },
                .not_found => {
                    return .{ .not_found = {} };
                },
                .failure => |err| {
                    return .{ .failure = err };
                },
            }
        }

        bun.unreachablePanic("TODO: implement enqueueDependencyToResolve for non-root packages", .{});
    }

    fn handleESMResolution(r: *ThisResolver, esm_resolution_: ESModule.Resolution, abs_package_path: string, kind: ast.ImportKind, package_json: *PackageJSON, package_subpath: string) ?MatchResult {
        var esm_resolution = esm_resolution_;
        if (!((esm_resolution.status == .Inexact or esm_resolution.status == .Exact or esm_resolution.status == .ExactEndsWithStar) and
            esm_resolution.path.len > 0 and esm_resolution.path[0] == std.fs.path.sep))
            return null;

        const abs_esm_path: string = brk: {
            var parts = [_]string{
                abs_package_path,
                strings.withoutLeadingPathSeparator(esm_resolution.path),
            };
            break :brk r.fs.absBuf(&parts, bufs(.esm_absolute_package_path_joined));
        };

        var missing_suffix: string = "";

        switch (esm_resolution.status) {
            .Exact, .ExactEndsWithStar => {
                const resolved_dir_info = (r.dirInfoCached(std.fs.path.dirname(abs_esm_path).?) catch null) orelse {
                    esm_resolution.status = .ModuleNotFound;
                    return null;
                };
                const entries = resolved_dir_info.getEntries(r.generation) orelse {
                    esm_resolution.status = .ModuleNotFound;
                    return null;
                };
                const extension_order = if (kind == .at or kind == .at_conditional)
                    r.extension_order
                else
                    r.opts.extension_order.kind(kind, resolved_dir_info.isInsideNodeModules());

                const base = std.fs.path.basename(abs_esm_path);
                const entry_query = entries.get(base) orelse {
                    const ends_with_star = esm_resolution.status == .ExactEndsWithStar;
                    esm_resolution.status = .ModuleNotFound;

                    // Try to have a friendly error message if people forget the extension
                    if (ends_with_star) {
                        bun.copy(u8, bufs(.load_as_file), base);
                        for (extension_order) |ext| {
                            var file_name = bufs(.load_as_file)[0 .. base.len + ext.len];
                            bun.copy(u8, file_name[base.len..], ext);
                            if (entries.get(file_name) != null) {
                                if (r.debug_logs) |*debug| {
                                    const parts = [_]string{ package_json.name, package_subpath };
                                    debug.addNoteFmt("The import {s} is missing the extension {s}", .{ ResolvePath.join(parts, .auto), ext });
                                }
                                esm_resolution.status = .ModuleNotFoundMissingExtension;
                                missing_suffix = ext;
                                break;
                            }
                        }
                    }
                    return null;
                };

                if (entry_query.entry.kind(&r.fs.fs, r.store_fd) == .dir) {
                    const ends_with_star = esm_resolution.status == .ExactEndsWithStar;
                    esm_resolution.status = .UnsupportedDirectoryImport;

                    // Try to have a friendly error message if people forget the "/index.js" suffix
                    if (ends_with_star) {
                        if (r.dirInfoCached(abs_esm_path) catch null) |dir_info| {
                            if (dir_info.getEntries(r.generation)) |dir_entries| {
                                const index = "index";
                                bun.copy(u8, bufs(.load_as_file), index);
                                for (extension_order) |ext| {
                                    var file_name = bufs(.load_as_file)[0 .. index.len + ext.len];
                                    bun.copy(u8, file_name[index.len..], ext);
                                    const index_query = dir_entries.get(file_name);
                                    if (index_query != null and index_query.?.entry.kind(&r.fs.fs, r.store_fd) == .file) {
                                        if (r.debug_logs) |*debug| {
                                            missing_suffix = std.fmt.allocPrint(r.allocator, "/{s}", .{file_name}) catch unreachable;
                                            defer r.allocator.free(missing_suffix);
                                            const parts = [_]string{ package_json.name, package_subpath };
                                            debug.addNoteFmt("The import {s} is missing the suffix {s}", .{ ResolvePath.join(parts, .auto), missing_suffix });
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    return null;
                }

                const absolute_out_path = brk: {
                    if (entry_query.entry.abs_path.isEmpty()) {
                        entry_query.entry.abs_path =
                            PathString.init(r.fs.dirname_store.append(@TypeOf(abs_esm_path), abs_esm_path) catch unreachable);
                    }
                    break :brk entry_query.entry.abs_path.slice();
                };
                const module_type = if (resolved_dir_info.package_json) |pkg| pkg.module_type else .unknown;

                return MatchResult{
                    .path_pair = PathPair{
                        .primary = Path.initWithNamespace(absolute_out_path, "file"),
                    },
                    .dirname_fd = entries.fd,
                    .file_fd = entry_query.entry.cache.fd,
                    .dir_info = resolved_dir_info,
                    .diff_case = entry_query.diff_case,
                    .is_node_module = true,
                    .package_json = resolved_dir_info.package_json orelse package_json,
                    .module_type = module_type,
                };
            },
            .Inexact => {
                // If this was resolved against an expansion key ending in a "/"
                // instead of a "*", we need to try CommonJS-style implicit
                // extension and/or directory detection.
                if (r.loadAsFileOrDirectory(abs_esm_path, kind)) |res| {
                    var res_copy = res;
                    res_copy.is_node_module = true;
                    res_copy.package_json = res.package_json orelse package_json;
                    return res_copy;
                }
                esm_resolution.status = .ModuleNotFound;
                return null;
            },
            else => unreachable,
        }
    }

    pub fn resolveWithoutRemapping(
        r: *ThisResolver,
        source_dir_info: *DirInfo,
        import_path: string,
        kind: ast.ImportKind,
        global_cache: GlobalCache,
    ) MatchResult.Union {
        if (isPackagePath(import_path)) {
            return r.loadNodeModules(import_path, kind, source_dir_info, global_cache, false);
        } else {
            const paths = [_]string{ source_dir_info.abs_path, import_path };
            const resolved = r.fs.absBuf(&paths, bufs(.resolve_without_remapping));
            if (r.loadAsFileOrDirectory(resolved, kind)) |result| {
                return .{ .success = result };
            }
            return .{ .not_found = {} };
        }
    }

    pub fn parseTSConfig(
        r: *ThisResolver,
        file: string,
        dirname_fd: FD,
    ) !?*TSConfigJSON {
        // Since tsconfig.json is cached permanently, in our DirEntries cache
        // we must use the global allocator
        var entry = try r.caches.fs.readFileWithAllocator(
            bun.fs_allocator,
            r.fs,
            file,
            dirname_fd,
            false,
            null,
        );
        defer _ = entry.closeFD();

        // The file name needs to be persistent because it can have errors
        // and if those errors need to print the filename
        // then it will be undefined memory if we parse another tsconfig.json late
        const key_path = Fs.Path.init(r.fs.dirname_store.append(string, file) catch unreachable);

        const source = logger.Source.initPathString(key_path.text, entry.contents);
        const file_dir = source.path.sourceDir();

        var result = (try TSConfigJSON.parse(bun.default_allocator, r.log, source, &r.caches.json)) orelse return null;

        if (result.hasBaseURL()) {

            // this might leak
            if (!std.fs.path.isAbsolute(result.base_url)) {
                const paths = [_]string{ file_dir, result.base_url };
                result.base_url = r.fs.dirname_store.append(string, r.fs.absBuf(&paths, bufs(.tsconfig_base_url))) catch unreachable;
            }
        }

        if (result.paths.count() > 0 and (result.base_url_for_paths.len == 0 or !std.fs.path.isAbsolute(result.base_url_for_paths))) {
            // this might leak
            const paths = [_]string{ file_dir, result.base_url };
            result.base_url_for_paths = r.fs.dirname_store.append(string, r.fs.absBuf(&paths, bufs(.tsconfig_base_url))) catch unreachable;
        }

        return result;
    }

    pub fn binDirs(_: *const ThisResolver) []const string {
        if (!bin_folders_loaded) return &[_]string{};
        return bin_folders.constSlice();
    }

    pub fn parsePackageJSON(
        r: *ThisResolver,
        file: string,
        dirname_fd: FD,
        package_id: ?Install.PackageID,
        comptime allow_dependencies: bool,
    ) !?*PackageJSON {
        var pkg: PackageJSON = undefined;
        if (!r.care_about_scripts) {
            pkg = PackageJSON.parse(
                r,
                file,
                dirname_fd,
                package_id,
                .ignore_scripts,
                if (allow_dependencies) .local else .none,
            ) orelse return null;
        } else {
            pkg = PackageJSON.parse(
                r,
                file,
                dirname_fd,
                package_id,
                .include_scripts,
                if (allow_dependencies) .local else .none,
            ) orelse return null;
        }

        return PackageJSON.new(pkg);
    }

    fn dirInfoCached(r: *ThisResolver, path: string) !?*DirInfo {
        return try r.dirInfoCachedMaybeLog(path, true, true);
    }

    pub fn readDirInfo(r: *ThisResolver, path: string) !?*DirInfo {
        return try r.dirInfoCachedMaybeLog(path, false, true);
    }

    /// Like `readDirInfo`, but returns `null` instead of throwing an error.
    pub fn readDirInfoIgnoreError(r: *ThisResolver, path: string) ?*const DirInfo {
        return r.dirInfoCachedMaybeLog(path, false, true) catch null;
    }

    inline fn isDotSlash(path: string) bool {
        return switch (Environment.os) {
            else => strings.eqlComptime(path, "./"),
            .windows => path.len == 2 and path[0] == '.' and strings.charIsAnySlash(path[1]),
        };
    }

    threadlocal var win32_normalized_dir_info_cache_buf: if (Environment.isWindows) [bun.MAX_PATH_BYTES * 2]u8 else void = undefined;
    fn dirInfoCachedMaybeLog(r: *ThisResolver, raw_input_path: string, comptime enable_logging: bool, comptime follow_symlinks: bool) !?*DirInfo {
        r.mutex.lock();
        defer r.mutex.unlock();
        var input_path = raw_input_path;

        if (isDotSlash(input_path) or strings.eqlComptime(input_path, ".")) {
            input_path = r.fs.top_level_dir;
        }

        if (comptime Environment.isWindows) {
            input_path = r.fs.normalizeBuf(&win32_normalized_dir_info_cache_buf, input_path);
            // kind of a patch on the fact normalizeBuf isn't 100% perfect what we want
            if ((input_path.len == 2 and input_path[1] == ':') or
                (input_path.len == 3 and input_path[1] == ':' and input_path[2] == '.'))
            {
                bun.unsafeAssert(input_path.ptr == &win32_normalized_dir_info_cache_buf);
                win32_normalized_dir_info_cache_buf[2] = '\\';
                input_path.len = 3;
            }

            // Filter out \\hello\, a UNC server path but without a share.
            // When there isn't a share name, such path is not considered to exist.
            if (bun.strings.hasPrefixComptime(input_path, "\\\\")) {
                const first_slash = bun.strings.indexOfChar(input_path[2..], '\\') orelse
                    return null;
                _ = bun.strings.indexOfChar(input_path[2 + first_slash ..], '\\') orelse
                    return null;
            }
        }

        bun.assertf(std.fs.path.isAbsolute(input_path), "cannot resolve DirInfo for non-absolute path: {s}", .{input_path});

        const path_without_trailing_slash = strings.withoutTrailingSlashWindowsPath(input_path);
        assertValidCacheKey(path_without_trailing_slash);
        const top_result = try r.dir_cache.getOrPut(path_without_trailing_slash);
        if (top_result.status != .unknown) {
            return r.dir_cache.atIndex(top_result.index);
        }

        var dir_info_uncached_path_buf = bufs(.dir_info_uncached_path);

        var i: i32 = 1;
        bun.copy(u8, dir_info_uncached_path_buf, input_path);
        var path = dir_info_uncached_path_buf[0..input_path.len];

        bufs(.dir_entry_paths_to_resolve)[0] = DirEntryResolveQueueItem{ .result = top_result, .unsafe_path = path, .safe_path = "" };
        var top = Dirname.dirname(path);

        var top_parent: allocators.Result = allocators.Result{
            .index = allocators.NotFound,
            .hash = 0,
            .status = .not_found,
        };
        const root_path = if (Environment.isWindows)
            bun.strings.withoutTrailingSlashWindowsPath(ResolvePath.windowsFilesystemRoot(path))
        else
            // we cannot just use "/"
            // we will write to the buffer past the ptr len so it must be a non-const buffer
            path[0..1];
        assertValidCacheKey(root_path);

        const rfs = &r.fs.fs;

        rfs.entries_mutex.lock();
        defer rfs.entries_mutex.unlock();

        while (top.len > root_path.len) : (top = Dirname.dirname(top)) {
            assert(top.ptr == root_path.ptr);
            const result = try r.dir_cache.getOrPut(top);

            if (result.status != .unknown) {
                top_parent = result;
                break;
            }
            bufs(.dir_entry_paths_to_resolve)[@as(usize, @intCast(i))] = DirEntryResolveQueueItem{
                .unsafe_path = top,
                .result = result,
                .fd = .invalid,
            };

            if (rfs.entries.get(top)) |top_entry| {
                switch (top_entry.*) {
                    .entries => {
                        bufs(.dir_entry_paths_to_resolve)[@as(usize, @intCast(i))].safe_path = top_entry.entries.dir;
                        bufs(.dir_entry_paths_to_resolve)[@as(usize, @intCast(i))].fd = top_entry.entries.fd;
                    },
                    .err => |err| {
                        debuglog("Failed to load DirEntry {s}  {s} - {s}", .{ top, @errorName(err.original_err), @errorName(err.canonical_error) });
                        break;
                    },
                }
            }
            i += 1;
        }

        if (strings.eql(top, root_path)) {
            const result = try r.dir_cache.getOrPut(root_path);
            if (result.status != .unknown) {
                top_parent = result;
            } else {
                bufs(.dir_entry_paths_to_resolve)[@as(usize, @intCast(i))] = DirEntryResolveQueueItem{
                    .unsafe_path = root_path,
                    .result = result,
                    .fd = .invalid,
                };
                if (rfs.entries.get(top)) |top_entry| {
                    switch (top_entry.*) {
                        .entries => {
                            bufs(.dir_entry_paths_to_resolve)[@as(usize, @intCast(i))].safe_path = top_entry.entries.dir;
                            bufs(.dir_entry_paths_to_resolve)[@as(usize, @intCast(i))].fd = top_entry.entries.fd;
                        },
                        .err => |err| {
                            debuglog("Failed to load DirEntry {s}  {s} - {s}", .{ top, @errorName(err.original_err), @errorName(err.canonical_error) });
                            return err.canonical_error;
                        },
                    }
                }

                i += 1;
            }
        }

        var queue_slice: []DirEntryResolveQueueItem = bufs(.dir_entry_paths_to_resolve)[0..@as(usize, @intCast(i))];
        if (Environment.allow_assert) assert(queue_slice.len > 0);
        var open_dir_count: usize = 0;

        // When this function halts, any item not processed means it's not found.
        defer {
            if (open_dir_count > 0 and (!r.store_fd or r.fs.fs.needToCloseFiles())) {
                const open_dirs: []std.fs.Dir = bufs(.open_dirs)[0..open_dir_count];
                for (open_dirs) |open_dir| {
                    bun.FD.fromStdDir(open_dir).close();
                }
            }
        }

        // We want to walk in a straight line from the topmost directory to the desired directory
        // For each directory we visit, we get the entries, but not traverse into child directories
        // (unless those child directories are in the queue)
        // We go top-down instead of bottom-up to increase odds of reusing previously open file handles
        // "/home/jarred/Code/node_modules/react/cjs/react.development.js"
        //       ^
        // If we start there, we will traverse all of /home/jarred, including e.g. /home/jarred/Downloads
        // which is completely irrelevant.

        // After much experimentation...
        // - fts_open is not the fastest way to read directories. fts actually just uses readdir!!
        // - remember
        var _safe_path: ?string = null;

        // Start at the top.
        while (queue_slice.len > 0) {
            var queue_top = queue_slice[queue_slice.len - 1];
            defer top_parent = queue_top.result;
            queue_slice.len -= 1;

            const open_dir: std.fs.Dir = if (queue_top.fd.isValid())
                queue_top.fd.stdDir()
            else open_dir: {
                // This saves us N copies of .toPosixPath
                // which was likely the perf gain from resolving directories relative to the parent directory, anyway.
                const prev_char = path.ptr[queue_top.unsafe_path.len];
                path.ptr[queue_top.unsafe_path.len] = 0;
                defer path.ptr[queue_top.unsafe_path.len] = prev_char;
                const sentinel = path.ptr[0..queue_top.unsafe_path.len :0];

                const open_req = if (comptime Environment.isPosix)
                    std.fs.openDirAbsoluteZ(
                        sentinel,
                        .{ .no_follow = !follow_symlinks, .iterate = true },
                    )
                else if (comptime Environment.isWindows) open_req: {
                    const dirfd_result = bun.sys.openDirAtWindowsA(bun.invalid_fd, sentinel, .{
                        .iterable = true,
                        .no_follow = !follow_symlinks,
                        .read_only = true,
                    });
                    if (dirfd_result.unwrap()) |result| {
                        break :open_req result.stdDir();
                    } else |err| {
                        break :open_req err;
                    }
                };

                bun.fs.debug("open({s}) = {any}", .{ sentinel, open_req });

                break :open_dir open_req catch |err| switch (@as(anyerror, err)) {
                    // Ignore "ENOTDIR" here so that calling "ReadDirectory" on a file behaves
                    // as if there is nothing there at all instead of causing an error due to
                    // the directory actually being a file. This is a workaround for situations
                    // where people try to import from a path containing a file as a parent
                    // directory. The "pnpm" package manager generates a faulty "NODE_PATH"
                    // list which contains such paths and treating them as missing means we just
                    // ignore them during path resolution.
                    error.ENOENT,
                    error.ENOTDIR,
                    error.IsDir,
                    error.NotDir,
                    error.FileNotFound,
                    => return null,

                    else => {
                        const cached_dir_entry_result = rfs.entries.getOrPut(queue_top.unsafe_path) catch unreachable;
                        r.dir_cache.markNotFound(queue_top.result);
                        rfs.entries.markNotFound(cached_dir_entry_result);
                        if (comptime enable_logging) {
                            const pretty = queue_top.unsafe_path;

                            r.log.addErrorFmt(
                                null,
                                logger.Loc{},
                                r.allocator,
                                "Cannot read directory \"{s}\": {s}",
                                .{
                                    pretty,
                                    @errorName(err),
                                },
                            ) catch {};
                        }
                        return null;
                    },
                };
            };

            if (!queue_top.fd.isValid()) {
                Fs.FileSystem.setMaxFd(open_dir.fd);
                // these objects mostly just wrap the file descriptor, so it's fine to keep it.
                bufs(.open_dirs)[open_dir_count] = open_dir;
                open_dir_count += 1;
            }

            const dir_path = if (queue_top.safe_path.len > 0) queue_top.safe_path else brk: {

                // ensure trailing slash
                if (_safe_path == null) {
                    // Now that we've opened the topmost directory successfully, it's reasonable to store the slice.
                    if (path[path.len - 1] != std.fs.path.sep) {
                        const parts = [_]string{ path, std.fs.path.sep_str };
                        _safe_path = try r.fs.dirname_store.append(@TypeOf(parts), parts);
                    } else {
                        _safe_path = try r.fs.dirname_store.append(string, path);
                    }
                }

                const safe_path = _safe_path.?;

                const dir_path_i = std.mem.indexOf(u8, safe_path, queue_top.unsafe_path) orelse unreachable;
                var end = dir_path_i +
                    queue_top.unsafe_path.len;

                // Directories must always end in a trailing slash or else various bugs can occur.
                // This covers "what happens when the trailing"
                end += @as(usize, @intCast(@intFromBool(safe_path.len > end and end > 0 and safe_path[end - 1] != std.fs.path.sep and safe_path[end] == std.fs.path.sep)));
                break :brk safe_path[dir_path_i..end];
            };

            var cached_dir_entry_result = rfs.entries.getOrPut(dir_path) catch unreachable;

            var dir_entries_option: *Fs.FileSystem.RealFS.EntriesOption = undefined;
            var needs_iter: bool = true;
            var in_place: ?*Fs.FileSystem.DirEntry = null;

            if (rfs.entries.atIndex(cached_dir_entry_result.index)) |cached_entry| {
                if (cached_entry.entries.generation >= r.generation) {
                    dir_entries_option = cached_entry;
                    needs_iter = false;
                } else {
                    in_place = cached_entry.entries;
                }
            }

            if (needs_iter) {
                const allocator = bun.fs_allocator;
                var new_entry = Fs.FileSystem.DirEntry.init(
                    if (in_place) |existing| existing.dir else Fs.FileSystem.DirnameStore.instance.append(string, dir_path) catch unreachable,
                    r.generation,
                );

                var dir_iterator = bun.iterateDir(open_dir);
                while (dir_iterator.next().unwrap() catch null) |_value| {
                    new_entry.addEntry(
                        if (in_place) |existing| &existing.data else null,
                        &_value,
                        allocator,
                        void,
                        {},
                    ) catch unreachable;
                }
                if (in_place) |existing| {
                    existing.data.clearAndFree(allocator);
                }
                new_entry.fd = if (r.store_fd) .fromStdDir(open_dir) else .invalid;
                var dir_entries_ptr = in_place orelse allocator.create(Fs.FileSystem.DirEntry) catch unreachable;
                dir_entries_ptr.* = new_entry;
                dir_entries_option = try rfs.entries.put(&cached_dir_entry_result, .{
                    .entries = dir_entries_ptr,
                });
                bun.fs.debug("readdir({}, {s}) = {d}", .{ bun.FD.fromStdDir(open_dir), dir_path, dir_entries_ptr.data.count() });
            }

            // We must initialize it as empty so that the result index is correct.
            // This is important so that browser_scope has a valid index.
            const dir_info_ptr = try r.dir_cache.put(&queue_top.result, DirInfo{});

            try r.dirInfoUncached(
                dir_info_ptr,
                dir_path,
                dir_entries_option,
                queue_top.result,
                cached_dir_entry_result.index,
                r.dir_cache.atIndex(top_parent.index),
                top_parent.index,
                .fromStdDir(open_dir),
                null,
            );

            if (queue_slice.len == 0) {
                return dir_info_ptr;

                // Is the directory we're searching for actually a file?
            } else if (queue_slice.len == 1) {
                // const next_in_queue = queue_slice[0];
                // const next_basename = std.fs.path.basename(next_in_queue.unsafe_path);
                // if (dir_info_ptr.getEntries(r.generation)) |entries| {
                //     if (entries.get(next_basename) != null) {
                //         return null;
                //     }
                // }
            }
        }

        unreachable;
    }

    // This closely follows the behavior of "tryLoadModuleUsingPaths()" in the
    // official TypeScript compiler
    pub fn matchTSConfigPaths(r: *ThisResolver, tsconfig: *const TSConfigJSON, path: string, kind: ast.ImportKind) ?MatchResult {
        if (r.debug_logs) |*debug| {
            debug.addNoteFmt("Matching \"{s}\" against \"paths\" in \"{s}\"", .{ path, tsconfig.abs_path });
        }

        var abs_base_url = tsconfig.base_url_for_paths;

        // The explicit base URL should take precedence over the implicit base URL
        // if present. This matters when a tsconfig.json file overrides "baseUrl"
        // from another extended tsconfig.json file but doesn't override "paths".
        if (tsconfig.hasBaseURL()) {
            abs_base_url = tsconfig.base_url;
        }

        if (r.debug_logs) |*debug| {
            debug.addNoteFmt("Using \"{s}\" as \"baseURL\"", .{abs_base_url});
        }

        // Check for exact matches first
        {
            var iter = tsconfig.paths.iterator();
            while (iter.next()) |entry| {
                const key = entry.key_ptr.*;

                if (strings.eqlLong(key, path, true)) {
                    for (entry.value_ptr.*) |original_path| {
                        var absolute_original_path = original_path;

                        if (!std.fs.path.isAbsolute(absolute_original_path)) {
                            const parts = [_]string{ abs_base_url, original_path };
                            absolute_original_path = r.fs.absBuf(&parts, bufs(.tsconfig_path_abs));
                        }

                        if (r.loadAsFileOrDirectory(absolute_original_path, kind)) |res| {
                            return res;
                        }
                    }
                }
            }
        }

        const TSConfigMatch = struct {
            prefix: string,
            suffix: string,
            original_paths: []string,
        };

        var longest_match: TSConfigMatch = undefined;
        var longest_match_prefix_length: i32 = -1;
        var longest_match_suffix_length: i32 = -1;

        var iter = tsconfig.paths.iterator();
        while (iter.next()) |entry| {
            const key = entry.key_ptr.*;
            const original_paths = entry.value_ptr.*;

            if (strings.indexOfChar(key, '*')) |star| {
                const prefix = if (star == 0) "" else key[0..star];
                const suffix = if (star == key.len - 1) "" else key[star + 1 ..];

                // Find the match with the longest prefix. If two matches have the same
                // prefix length, pick the one with the longest suffix. This second edge
                // case isn't handled by the TypeScript compiler, but we handle it
                // because we want the output to always be deterministic
                if (strings.startsWith(path, prefix) and
                    strings.endsWith(path, suffix) and
                    (prefix.len > longest_match_prefix_length or
                        (prefix.len == longest_match_prefix_length and suffix.len > longest_match_suffix_length)))
                {
                    longest_match_prefix_length = @as(i32, @intCast(prefix.len));
                    longest_match_suffix_length = @as(i32, @intCast(suffix.len));
                    longest_match = TSConfigMatch{ .prefix = prefix, .suffix = suffix, .original_paths = original_paths };
                }
            }
        }

        // If there is at least one match, only consider the one with the longest
        // prefix. This matches the behavior of the TypeScript compiler.
        if (longest_match_prefix_length != -1) {
            if (r.debug_logs) |*debug| {
                debug.addNoteFmt("Found a fuzzy match for \"{s}*{s}\" in \"paths\"", .{ longest_match.prefix, longest_match.suffix });
            }

            for (longest_match.original_paths) |original_path| {
                // Swap out the "*" in the original path for whatever the "*" matched
                const matched_text = path[longest_match.prefix.len .. path.len - longest_match.suffix.len];

                const total_length: ?u32 = strings.indexOfChar(original_path, '*');
                var prefix_parts = [_]string{ abs_base_url, original_path[0 .. total_length orelse original_path.len] };

                // Concatenate the matched text with the suffix from the wildcard path
                var matched_text_with_suffix = bufs(.tsconfig_match_full_buf3);
                var matched_text_with_suffix_len: usize = 0;
                if (total_length != null) {
                    const suffix = std.mem.trimLeft(u8, original_path[total_length orelse original_path.len ..], "*");
                    matched_text_with_suffix_len = matched_text.len + suffix.len;
                    bun.concat(u8, matched_text_with_suffix, &.{ matched_text, suffix });
                }

                // 1. Normalize the base path
                // so that "/Users/foo/project/", "../components/*" => "/Users/foo/components/""
                const prefix = r.fs.absBuf(&prefix_parts, bufs(.tsconfig_match_full_buf2));

                // 2. Join the new base path with the matched result
                // so that "/Users/foo/components/", "/foo/bar" => /Users/foo/components/foo/bar
                var parts = [_]string{
                    prefix,
                    if (matched_text_with_suffix_len > 0) std.mem.trimLeft(u8, matched_text_with_suffix[0..matched_text_with_suffix_len], "/") else "",
                    std.mem.trimLeft(u8, longest_match.suffix, "/"),
                };
                const absolute_original_path = r.fs.absBuf(
                    &parts,
                    bufs(.tsconfig_match_full_buf),
                );

                if (r.loadAsFileOrDirectory(absolute_original_path, kind)) |res| {
                    return res;
                }
            }
        }

        return null;
    }

    pub fn loadPackageImports(r: *ThisResolver, import_path: string, dir_info: *DirInfo, kind: ast.ImportKind, global_cache: GlobalCache) MatchResult.Union {
        const package_json = dir_info.package_json.?;
        if (r.debug_logs) |*debug| {
            debug.addNoteFmt("Looking for {s} in \"imports\" map in {s}", .{ import_path, package_json.source.path.text });
            debug.increaseIndent();
            defer debug.decreaseIndent();
        }
        const imports_map = package_json.imports.?;

        if (import_path.len == 1 or strings.hasPrefix(import_path, "#/")) {
            if (r.debug_logs) |*debug| {
                debug.addNoteFmt("The path \"{s}\" must not equal \"#\" and must not start with \"#/\"", .{import_path});
            }
            return .{ .not_found = {} };
        }
        var module_type = options.ModuleType.unknown;

        const esmodule = ESModule{
            .conditions = switch (kind) {
                ast.ImportKind.require,
                ast.ImportKind.require_resolve,
                => r.opts.conditions.require,
                else => r.opts.conditions.import,
            },
            .allocator = r.allocator,
            .debug_logs = if (r.debug_logs) |*debug| debug else null,
            .module_type = &module_type,
        };

        const esm_resolution = esmodule.resolveImports(import_path, imports_map.root);

        if (esm_resolution.status == .PackageResolve) {
            // https://github.com/oven-sh/bun/issues/4972
            // Resolve a subpath import to a Bun or Node.js builtin
            //
            // Code example:
            //
            //     import { readFileSync } from '#fs';
            //
            // package.json:
            //
            //     "imports": {
            //       "#fs": "node:fs"
            //     }
            //
            if (r.opts.mark_builtins_as_external or r.opts.target.isBun()) {
                if (JSC.ModuleLoader.HardcodedModule.Alias.get(esm_resolution.path, r.opts.target)) |alias| {
                    return .{
                        .success = .{
                            .path_pair = .{ .primary = bun.fs.Path.init(alias.path) },
                            .is_external = true,
                        },
                    };
                }
            }

            return r.loadNodeModules(
                esm_resolution.path,
                kind,
                dir_info,
                global_cache,
                true,
            );
        }

        if (r.handleESMResolution(esm_resolution, package_json.source.path.name.dir, kind, package_json, "")) |result| {
            return .{ .success = result };
        }

        return .{ .not_found = {} };
    }

    const BrowserMapPath = struct {
        remapped: string = "",
        cleaned: string = "",
        input_path: string = "",
        extension_order: []const string,
        map: BrowserMap,

        pub const Kind = enum { PackagePath, AbsolutePath };

        pub fn checkPath(
            this: *BrowserMapPath,
            path_to_check: string,
        ) bool {
            const map = this.map;

            const cleaned = this.cleaned;
            // Check for equality
            if (this.map.get(path_to_check)) |result| {
                this.remapped = result;
                this.input_path = path_to_check;
                return true;
            }

            var ext_buf = bufs(.extension_path);

            bun.copy(u8, ext_buf, cleaned);

            // If that failed, try adding implicit extensions
            for (this.extension_order) |ext| {
                bun.copy(u8, ext_buf[cleaned.len..], ext);
                const new_path = ext_buf[0 .. cleaned.len + ext.len];
                // if (r.debug_logs) |*debug| {
                //     debug.addNoteFmt("Checking for \"{s}\" ", .{new_path});
                // }
                if (map.get(new_path)) |_remapped| {
                    this.remapped = _remapped;
                    this.cleaned = new_path;
                    this.input_path = new_path;
                    return true;
                }
            }

            // If that failed, try assuming this is a directory and looking for an "index" file

            var index_path: string = "";
            {
                var parts = [_]string{ std.mem.trimRight(u8, path_to_check, std.fs.path.sep_str), std.fs.path.sep_str ++ "index" };
                index_path = ResolvePath.joinStringBuf(bufs(.tsconfig_base_url), &parts, .auto);
            }

            if (map.get(index_path)) |_remapped| {
                this.remapped = _remapped;
                this.input_path = index_path;
                return true;
            }

            bun.copy(u8, ext_buf, index_path);

            for (this.extension_order) |ext| {
                bun.copy(u8, ext_buf[index_path.len..], ext);
                const new_path = ext_buf[0 .. index_path.len + ext.len];
                // if (r.debug_logs) |*debug| {
                //     debug.addNoteFmt("Checking for \"{s}\" ", .{new_path});
                // }
                if (map.get(new_path)) |_remapped| {
                    this.remapped = _remapped;
                    this.cleaned = new_path;
                    this.input_path = new_path;
                    return true;
                }
            }

            return false;
        }
    };

    pub fn checkBrowserMap(
        r: *ThisResolver,
        dir_info: *const DirInfo,
        input_path_: string,
        comptime kind: BrowserMapPath.Kind,
    ) ?string {
        const package_json = dir_info.package_json orelse return null;
        const browser_map = package_json.browser_map;

        if (browser_map.count() == 0) return null;

        var input_path = input_path_;

        if (comptime kind == .AbsolutePath) {
            const abs_path = dir_info.abs_path;
            // Turn absolute paths into paths relative to the "browser" map location
            if (!strings.startsWith(input_path, abs_path)) {
                return null;
            }

            input_path = input_path[abs_path.len..];
        }

        if (input_path.len == 0 or (input_path.len == 1 and (input_path[0] == '.' or input_path[0] == std.fs.path.sep))) {
            // No bundler supports remapping ".", so we don't either
            return null;
        }

        // Normalize the path so we can compare against it without getting confused by "./"
        const cleaned = r.fs.normalizeBuf(bufs(.check_browser_map), input_path);

        if (cleaned.len == 1 and cleaned[0] == '.') {
            // No bundler supports remapping ".", so we don't either
            return null;
        }

        var checker = BrowserMapPath{
            .remapped = "",
            .cleaned = cleaned,
            .input_path = input_path,
            .extension_order = r.extension_order,
            .map = package_json.browser_map,
        };

        if (checker.checkPath(input_path)) {
            return checker.remapped;
        }

        // First try the import path as a package path
        if (isPackagePath(checker.input_path)) {
            var abs_to_rel = bufs(.abs_to_rel);
            switch (comptime kind) {
                .AbsolutePath => {
                    abs_to_rel[0..2].* = "./".*;
                    bun.copy(u8, abs_to_rel[2..], checker.input_path);
                    if (checker.checkPath(abs_to_rel[0 .. checker.input_path.len + 2])) {
                        return checker.remapped;
                    }
                },
                .PackagePath => {
                    // Browserify allows a browser map entry of "./pkg" to override a package
                    // path of "require('pkg')". This is weird, and arguably a bug. But we
                    // replicate this bug for compatibility. However, Browserify only allows
                    // this within the same package. It does not allow such an entry in a
                    // parent package to override this in a child package. So this behavior
                    // is disallowed if there is a "node_modules" folder in between the child
                    // package and the parent package.
                    const isInSamePackage = brk: {
                        const parent = dir_info.getParent() orelse break :brk true;
                        break :brk !parent.isNodeModules();
                    };

                    if (isInSamePackage) {
                        abs_to_rel[0..2].* = "./".*;
                        bun.copy(u8, abs_to_rel[2..], checker.input_path);

                        if (checker.checkPath(abs_to_rel[0 .. checker.input_path.len + 2])) {
                            return checker.remapped;
                        }
                    }
                },
            }
        }

        return null;
    }

    pub fn loadFromMainField(r: *ThisResolver, path: string, dir_info: *DirInfo, _field_rel_path: string, field: string, extension_order: []const string) ?MatchResult {
        var field_rel_path = _field_rel_path;
        // Is this a directory?
        if (r.debug_logs) |*debug| {
            debug.addNoteFmt("Found main field \"{s}\" with path \"{s}\"", .{ field, field_rel_path });
            debug.increaseIndent();
        }

        defer {
            if (r.debug_logs) |*debug| {
                debug.decreaseIndent();
            }
        }

        if (r.care_about_browser_field) {
            // Potentially remap using the "browser" field
            if (dir_info.getEnclosingBrowserScope()) |browser_scope| {
                if (browser_scope.package_json) |browser_json| {
                    if (r.checkBrowserMap(
                        browser_scope,
                        field_rel_path,
                        .AbsolutePath,
                    )) |remap| {
                        // Is the path disabled?
                        if (remap.len == 0) {
                            const paths = [_]string{ path, field_rel_path };
                            const new_path = r.fs.absAlloc(r.allocator, &paths) catch unreachable;
                            var _path = Path.init(new_path);
                            _path.is_disabled = true;
                            return MatchResult{
                                .path_pair = PathPair{
                                    .primary = _path,
                                },
                                .package_json = browser_json,
                            };
                        }

                        field_rel_path = remap;
                    }
                }
            }
        }
        const _paths = [_]string{ path, field_rel_path };
        const field_abs_path = r.fs.absBuf(&_paths, bufs(.field_abs_path));

        // Is this a file?
        if (r.loadAsFile(field_abs_path, extension_order)) |result| {
            if (dir_info.package_json) |package_json| {
                return MatchResult{
                    .path_pair = PathPair{ .primary = Fs.Path.init(result.path) },
                    .package_json = package_json,
                    .dirname_fd = result.dirname_fd,
                };
            }

            return MatchResult{
                .path_pair = PathPair{ .primary = Fs.Path.init(result.path) },
                .dirname_fd = result.dirname_fd,
                .diff_case = result.diff_case,
            };
        }

        // Is it a directory with an index?
        const field_dir_info = (r.dirInfoCached(field_abs_path) catch null) orelse {
            return null;
        };

        return r.loadAsIndexWithBrowserRemapping(field_dir_info, field_abs_path, extension_order) orelse {
            return null;
        };
    }

    pub fn nodeModulePathsForJS(globalThis: *bun.JSC.JSGlobalObject, callframe: *bun.JSC.CallFrame) bun.JSError!JSC.JSValue {
        bun.JSC.markBinding(@src());
        const argument: bun.JSC.JSValue = callframe.argument(0);

        if (argument == .zero or !argument.isString()) {
            return globalThis.throwInvalidArgumentType("nodeModulePaths", "path", "string");
        }

        const in_str = try argument.toBunString(globalThis);
        defer in_str.deref();
        return nodeModulePathsJSValue(in_str, globalThis, false);
    }

    pub export fn Resolver__propForRequireMainPaths(globalThis: *bun.JSC.JSGlobalObject) callconv(.C) JSC.JSValue {
        bun.JSC.markBinding(@src());

        const in_str = bun.String.init(".");
        return nodeModulePathsJSValue(in_str, globalThis, false);
    }

    pub fn nodeModulePathsJSValue(in_str: bun.String, globalObject: *bun.JSC.JSGlobalObject, use_dirname: bool) callconv(.C) bun.JSC.JSValue {
        var arena = std.heap.ArenaAllocator.init(bun.default_allocator);
        defer arena.deinit();
        var stack_fallback_allocator = std.heap.stackFallback(1024, arena.allocator());
        const alloc = stack_fallback_allocator.get();

        var list = std.ArrayList(bun.String).init(alloc);
        defer list.deinit();

        const sliced = in_str.toUTF8(bun.default_allocator);
        defer sliced.deinit();
        const base_path = if (use_dirname) std.fs.path.dirname(sliced.slice()) orelse sliced.slice() else sliced.slice();
        const buf = bufs(.node_modules_paths_buf);

        const full_path = bun.path.joinAbsStringBuf(
            bun.fs.FileSystem.instance.top_level_dir,
            buf,
            &.{base_path},
            .auto,
        );
        const root_index = switch (bun.Environment.os) {
            .windows => bun.path.windowsFilesystemRoot(full_path).len,
            else => 1,
        };
        var root_path: []const u8 = full_path[0..root_index];
        if (full_path.len > root_path.len) {
            var it = std.mem.splitBackwardsScalar(u8, full_path[root_index..], std.fs.path.sep);
            while (it.next()) |part| {
                if (strings.eqlComptime(part, "node_modules"))
                    continue;

                list.append(bun.String.createFormat(
                    "{s}{s}" ++ std.fs.path.sep_str ++ "node_modules",
                    .{
                        root_path,
                        it.buffer[0 .. (if (it.index) |i| i + 1 else 0) + part.len],
                    },
                ) catch bun.outOfMemory()) catch bun.outOfMemory();
            }
        }

        while (root_path.len > 0 and bun.path.Platform.auto.isSeparator(root_path[root_path.len - 1])) {
            root_path.len -= 1;
        }

        list.append(bun.String.createFormat(
            "{s}" ++ std.fs.path.sep_str ++ "node_modules",
            .{root_path},
        ) catch bun.outOfMemory()) catch bun.outOfMemory();

        return bun.String.toJSArray(globalObject, list.items);
    }

    pub fn loadAsIndex(r: *ThisResolver, dir_info: *DirInfo, extension_order: []const string) ?MatchResult {
        // Try the "index" file with extensions
        for (extension_order) |ext| {
            if (loadIndexWithExtension(r, dir_info, ext)) |result| {
                return result;
            }
        }
        for (r.opts.extra_cjs_extensions) |ext| {
            if (loadIndexWithExtension(r, dir_info, ext)) |result| {
                return result;
            }
        }

        return null;
    }

    fn loadIndexWithExtension(r: *ThisResolver, dir_info: *DirInfo, ext: string) ?MatchResult {
        const rfs = &r.fs.fs;

        var ext_buf = bufs(.extension_path);

        var base = ext_buf[0 .. "index".len + ext.len];
        base[0.."index".len].* = "index".*;
        bun.copy(u8, base["index".len..], ext);

        if (dir_info.getEntries(r.generation)) |entries| {
            if (entries.get(base)) |lookup| {
                if (lookup.entry.kind(rfs, r.store_fd) == .file) {
                    const out_buf = brk: {
                        if (lookup.entry.abs_path.isEmpty()) {
                            const parts = [_]string{ dir_info.abs_path, base };
                            const out_buf_ = r.fs.absBuf(&parts, bufs(.index));
                            lookup.entry.abs_path =
                                PathString.init(r.fs.dirname_store.append(@TypeOf(out_buf_), out_buf_) catch unreachable);
                        }
                        break :brk lookup.entry.abs_path.slice();
                    };

                    if (r.debug_logs) |*debug| {
                        debug.addNoteFmt("Found file: \"{s}\"", .{out_buf});
                    }

                    if (dir_info.package_json) |package_json| {
                        return MatchResult{
                            .path_pair = .{ .primary = Path.init(out_buf) },
                            .diff_case = lookup.diff_case,
                            .package_json = package_json,
                            .dirname_fd = dir_info.getFileDescriptor(),
                        };
                    }

                    return MatchResult{
                        .path_pair = .{ .primary = Path.init(out_buf) },
                        .diff_case = lookup.diff_case,

                        .dirname_fd = dir_info.getFileDescriptor(),
                    };
                }
            }
        }

        if (r.debug_logs) |*debug| {
            debug.addNoteFmt("Failed to find file: \"{s}/{s}\"", .{ dir_info.abs_path, base });
        }

        return null;
    }

    pub fn loadAsIndexWithBrowserRemapping(r: *ThisResolver, dir_info: *DirInfo, path_: string, extension_order: []const string) ?MatchResult {
        // In order for our path handling logic to be correct, it must end with a trailing slash.
        var path = path_;
        if (!strings.endsWithChar(path_, std.fs.path.sep)) {
            var path_buf = bufs(.remap_path_trailing_slash);
            bun.copy(u8, path_buf, path);
            path_buf[path.len] = std.fs.path.sep;
            path_buf[path.len + 1] = 0;
            path = path_buf[0 .. path.len + 1];
        }

        if (r.care_about_browser_field) {
            if (dir_info.getEnclosingBrowserScope()) |browser_scope| {
                const field_rel_path = comptime "index";

                if (browser_scope.package_json) |browser_json| {
                    if (r.checkBrowserMap(
                        browser_scope,
                        field_rel_path,
                        .AbsolutePath,
                    )) |remap| {

                        // Is the path disabled?
                        if (remap.len == 0) {
                            const paths = [_]string{ path, field_rel_path };
                            const new_path = r.fs.absBuf(&paths, bufs(.remap_path));
                            var _path = Path.init(new_path);
                            _path.is_disabled = true;
                            return MatchResult{
                                .path_pair = PathPair{
                                    .primary = _path,
                                },
                                .package_json = browser_json,
                            };
                        }

                        const new_paths = [_]string{ path, remap };
                        const remapped_abs = r.fs.absBuf(&new_paths, bufs(.remap_path));

                        // Is this a file
                        if (r.loadAsFile(remapped_abs, extension_order)) |file_result| {
                            return MatchResult{ .dirname_fd = file_result.dirname_fd, .path_pair = .{ .primary = Path.init(file_result.path) }, .diff_case = file_result.diff_case };
                        }

                        // Is it a directory with an index?
                        if (r.dirInfoCached(remapped_abs) catch null) |new_dir| {
                            if (r.loadAsIndex(new_dir, extension_order)) |absolute| {
                                return absolute;
                            }
                        }

                        return null;
                    }
                }
            }
        }

        return r.loadAsIndex(dir_info, extension_order);
    }

    pub fn loadAsFileOrDirectory(r: *ThisResolver, path: string, kind: ast.ImportKind) ?MatchResult {
        const extension_order = r.extension_order;

        // Is this a file?
        if (r.loadAsFile(path, extension_order)) |file| {
            // Determine the package folder by looking at the last node_modules/ folder in the path
            if (strings.lastIndexOf(file.path, "node_modules" ++ std.fs.path.sep_str)) |last_node_modules_folder| {
                const node_modules_folder_offset = last_node_modules_folder + ("node_modules" ++ std.fs.path.sep_str).len;
                // Determine the package name by looking at the next separator
                if (strings.indexOfChar(file.path[node_modules_folder_offset..], std.fs.path.sep)) |package_name_length| {
                    if ((r.dirInfoCached(file.path[0 .. node_modules_folder_offset + package_name_length]) catch null)) |package_dir_info| {
                        if (package_dir_info.package_json) |package_json| {
                            return MatchResult{
                                .path_pair = .{ .primary = Path.init(file.path) },
                                .diff_case = file.diff_case,
                                .dirname_fd = file.dirname_fd,
                                .package_json = package_json,
                                .file_fd = file.file_fd,
                            };
                        }
                    }
                }
            }

            if (Environment.allow_assert) {
                assert(std.fs.path.isAbsolute(file.path));
            }

            return MatchResult{
                .path_pair = .{ .primary = Path.init(file.path) },
                .diff_case = file.diff_case,
                .dirname_fd = file.dirname_fd,
                .file_fd = file.file_fd,
            };
        }

        // Is this a directory?
        if (r.debug_logs) |*debug| {
            debug.addNoteFmt("Attempting to load \"{s}\" as a directory", .{path});
            debug.increaseIndent();
        }
        defer if (r.debug_logs) |*debug| {
            debug.decreaseIndent();
        };

        const dir_info = (r.dirInfoCached(path) catch |err| {
            if (comptime Environment.isDebug) Output.prettyErrorln("err: {s} reading {s}", .{ @errorName(err), path });
            return null;
        }) orelse return null;
        var package_json: ?*PackageJSON = null;

        // Try using the main field(s) from "package.json"
        if (dir_info.package_json) |pkg_json| {
            package_json = pkg_json;
            if (pkg_json.main_fields.count() > 0) {
                const main_field_values = pkg_json.main_fields;
                const main_field_keys = r.opts.main_fields;
                // TODO: check this works right. Not sure this will really work.
                const auto_main = r.opts.main_fields.ptr == options.Target.DefaultMainFields.get(r.opts.target).ptr;

                if (r.debug_logs) |*debug| {
                    debug.addNoteFmt("Searching for main fields in \"{s}\"", .{pkg_json.source.path.text});
                }

                for (main_field_keys) |key| {
                    const field_rel_path = (main_field_values.get(key)) orelse {
                        if (r.debug_logs) |*debug| {
                            debug.addNoteFmt("Did not find main field \"{s}\"", .{key});
                        }
                        continue;
                    };

                    var _result = r.loadFromMainField(
                        path,
                        dir_info,
                        field_rel_path,
                        key,
                        if (strings.eqlComptime(key, "main")) r.opts.main_field_extension_order else extension_order,
                    ) orelse continue;

                    // If the user did not manually configure a "main" field order, then
                    // use a special per-module automatic algorithm to decide whether to
                    // use "module" or "main" based on whether the package is imported
                    // using "import" or "require".
                    if (auto_main and strings.eqlComptime(key, "module")) {
                        var absolute_result: ?MatchResult = null;

                        if (main_field_values.get("main")) |main_rel_path| {
                            if (main_rel_path.len > 0) {
                                absolute_result = r.loadFromMainField(path, dir_info, main_rel_path, "main", r.opts.main_field_extension_order);
                            }
                        } else {
                            // Some packages have a "module" field without a "main" field but
                            // still have an implicit "index.js" file. In that case, treat that
                            // as the value for "main".
                            absolute_result = r.loadAsIndexWithBrowserRemapping(dir_info, path, r.opts.main_field_extension_order);
                        }

                        if (absolute_result) |auto_main_result| {
                            // If both the "main" and "module" fields exist, use "main" if the
                            // path is for "require" and "module" if the path is for "import".
                            // If we're using "module", return enough information to be able to
                            // fall back to "main" later if something ended up using "require()"
                            // with this same path. The goal of this code is to avoid having
                            // both the "module" file and the "main" file in the bundle at the
                            // same time.
                            //
                            // Additionally, if this is for the runtime, use the "main" field.
                            // If it doesn't exist, the "module" field will be used.
                            if (r.prefer_module_field and kind != ast.ImportKind.require) {
                                if (r.debug_logs) |*debug| {
                                    debug.addNoteFmt("Resolved to \"{s}\" using the \"module\" field in \"{s}\"", .{ auto_main_result.path_pair.primary.text, pkg_json.source.path.text });

                                    debug.addNoteFmt("The fallback path in case of \"require\" is {s}", .{auto_main_result.path_pair.primary.text});
                                }

                                return MatchResult{
                                    .path_pair = .{
                                        .primary = _result.path_pair.primary,
                                        .secondary = auto_main_result.path_pair.primary,
                                    },
                                    .diff_case = _result.diff_case,
                                    .dirname_fd = _result.dirname_fd,
                                    .package_json = package_json,
                                    .file_fd = auto_main_result.file_fd,
                                };
                            } else {
                                if (r.debug_logs) |*debug| {
                                    debug.addNoteFmt("Resolved to \"{s}\" using the \"{s}\" field in \"{s}\"", .{
                                        auto_main_result.path_pair.primary.text,
                                        key,
                                        pkg_json.source.path.text,
                                    });
                                }
                                var _auto_main_result = auto_main_result;
                                _auto_main_result.package_json = package_json;
                                return _auto_main_result;
                            }
                        }
                    }

                    _result.package_json = _result.package_json orelse package_json;
                    return _result;
                }
            }
        }

        // Look for an "index" file with known extensions
        if (r.loadAsIndexWithBrowserRemapping(dir_info, path, extension_order)) |res| {
            var res_copy = res;
            res_copy.package_json = res.package_json orelse package_json;
            return res_copy;
        }

        return null;
    }

    pub fn loadAsFile(r: *ThisResolver, path: string, extension_order: []const string) ?LoadResult {
        const rfs: *Fs.FileSystem.RealFS = &r.fs.fs;

        if (r.debug_logs) |*debug| {
            debug.addNoteFmt("Attempting to load \"{s}\" as a file", .{path});
            debug.increaseIndent();
        }
        defer {
            if (r.debug_logs) |*debug| {
                debug.decreaseIndent();
            }
        }

        const dir_path = bun.strings.withoutTrailingSlashWindowsPath(Dirname.dirname(path));
        bun.strings.assertIsValidWindowsPath(u8, dir_path);

        const dir_entry: *Fs.FileSystem.RealFS.EntriesOption = rfs.readDirectory(
            dir_path,
            null,
            r.generation,
            r.store_fd,
        ) catch {
            return null;
        };

        if (@as(Fs.FileSystem.RealFS.EntriesOption.Tag, dir_entry.*) == .err) {
            if (dir_entry.err.original_err != error.ENOENT) {
                r.log.addErrorFmt(
                    null,
                    logger.Loc.Empty,
                    r.allocator,
                    "Cannot read directory \"{s}\": {s}",
                    .{
                        dir_path,
                        @errorName(dir_entry.err.original_err),
                    },
                ) catch {};
            }
            return null;
        }

        const entries = dir_entry.entries;

        const base = std.fs.path.basename(path);

        // Try the plain path without any extensions
        if (r.debug_logs) |*debug| {
            debug.addNoteFmt("Checking for file \"{s}\" ", .{base});
        }

        if (entries.get(base)) |query| {
            if (query.entry.kind(rfs, r.store_fd) == .file) {
                if (r.debug_logs) |*debug| {
                    debug.addNoteFmt("Found file \"{s}\" ", .{base});
                }

                const abs_path = brk: {
                    if (query.entry.abs_path.isEmpty()) {
                        const abs_path_parts = [_]string{ query.entry.dir, query.entry.base() };
                        query.entry.abs_path = PathString.init(r.fs.dirname_store.append(string, r.fs.absBuf(&abs_path_parts, bufs(.load_as_file))) catch unreachable);
                    }

                    break :brk query.entry.abs_path.slice();
                };

                return LoadResult{
                    .path = abs_path,
                    .diff_case = query.diff_case,
                    .dirname_fd = entries.fd,
                    .file_fd = query.entry.cache.fd,
                };
            }
        }

        // Try the path with extensions
        bun.copy(u8, bufs(.load_as_file), path);
        for (extension_order) |ext| {
            if (loadExtension(r, base, path, ext, entries)) |result| {
                return result;
            }
        }

        for (r.opts.extra_cjs_extensions) |ext| {
            if (loadExtension(r, base, path, ext, entries)) |result| {
                return result;
            }
        }

        // TypeScript-specific behavior: if the extension is ".js" or ".jsx", try
        // replacing it with ".ts" or ".tsx". At the time of writing this specific
        // behavior comes from the function "loadModuleFromFile()" in the file
        // "moduleNameThisResolver.ts" in the TypeScript compiler source code. It
        // contains this comment:
        //
        //   If that didn't work, try stripping a ".js" or ".jsx" extension and
        //   replacing it with a TypeScript one; e.g. "./foo.js" can be matched
        //   by "./foo.ts" or "./foo.d.ts"
        //
        // We don't care about ".d.ts" files because we can't do anything with
        // those, so we ignore that part of the behavior.
        //
        // See the discussion here for more historical context:
        // https://github.com/microsoft/TypeScript/issues/4595
        if (strings.lastIndexOfChar(base, '.')) |last_dot| {
            const ext = base[last_dot..base.len];
            if ((strings.eqlComptime(ext, ".js") or strings.eqlComptime(ext, ".jsx") or strings.eqlComptime(ext, ".mjs") and
                (!FeatureFlags.disable_auto_js_to_ts_in_node_modules or !strings.pathContainsNodeModulesFolder(path))))
            {
                const segment = base[0..last_dot];
                var tail = bufs(.load_as_file)[path.len - base.len ..];
                bun.copy(u8, tail, segment);

                const exts: []const string = if (strings.eqlComptime(ext, ".mjs"))
                    &.{".mts"}
                else
                    &.{ ".ts", ".tsx", ".mts" };

                for (exts) |ext_to_replace| {
                    var buffer = tail[0 .. segment.len + ext_to_replace.len];
                    @memcpy(buffer[segment.len..buffer.len][0..ext_to_replace.len], ext_to_replace);

                    if (entries.get(buffer)) |query| {
                        if (query.entry.kind(rfs, r.store_fd) == .file) {
                            if (r.debug_logs) |*debug| {
                                debug.addNoteFmt("Rewrote to \"{s}\" ", .{buffer});
                            }

                            return LoadResult{
                                .path = brk: {
                                    if (query.entry.abs_path.isEmpty()) {
                                        if (query.entry.dir.len > 0 and query.entry.dir[query.entry.dir.len - 1] == std.fs.path.sep) {
                                            const parts = [_]string{ query.entry.dir, buffer };
                                            query.entry.abs_path = PathString.init(r.fs.filename_store.append(@TypeOf(parts), parts) catch unreachable);
                                            // the trailing path CAN be missing here
                                        } else {
                                            const parts = [_]string{ query.entry.dir, std.fs.path.sep_str, buffer };
                                            query.entry.abs_path = PathString.init(r.fs.filename_store.append(@TypeOf(parts), parts) catch unreachable);
                                        }
                                    }

                                    break :brk query.entry.abs_path.slice();
                                },
                                .diff_case = query.diff_case,
                                .dirname_fd = entries.fd,
                                .file_fd = query.entry.cache.fd,
                            };
                        }
                    }
                    if (r.debug_logs) |*debug| {
                        debug.addNoteFmt("Failed to rewrite \"{s}\" ", .{base});
                    }
                }
            }
        }

        if (r.debug_logs) |*debug| {
            debug.addNoteFmt("Failed to find \"{s}\" ", .{path});
        }

        if (comptime FeatureFlags.watch_directories) {
            // For existent directories which don't find a match
            // Start watching it automatically,
            if (r.watcher) |watcher| {
                watcher.watch(entries.dir, entries.fd);
            }
        }
        return null;
    }

    fn loadExtension(r: *ThisResolver, base: string, path: string, ext: string, entries: *Fs.FileSystem.DirEntry) ?LoadResult {
        const rfs: *Fs.FileSystem.RealFS = &r.fs.fs;
        const buffer = bufs(.load_as_file)[0 .. path.len + ext.len];
        bun.copy(u8, buffer[path.len..], ext);
        const file_name = buffer[path.len - base.len .. buffer.len];

        if (r.debug_logs) |*debug| {
            debug.addNoteFmt("Checking for file \"{s}\" ", .{buffer});
        }

        if (entries.get(file_name)) |query| {
            if (query.entry.kind(rfs, r.store_fd) == .file) {
                if (r.debug_logs) |*debug| {
                    debug.addNoteFmt("Found file \"{s}\" ", .{buffer});
                }

                // now that we've found it, we allocate it.
                return .{
                    .path = brk: {
                        query.entry.abs_path = if (query.entry.abs_path.isEmpty())
                            PathString.init(r.fs.dirname_store.append(@TypeOf(buffer), buffer) catch unreachable)
                        else
                            query.entry.abs_path;

                        break :brk query.entry.abs_path.slice();
                    },
                    .diff_case = query.diff_case,
                    .dirname_fd = entries.fd,
                    .file_fd = query.entry.cache.fd,
                };
            }
        }

        return null;
    }

    fn dirInfoUncached(
        r: *ThisResolver,
        info: *DirInfo,
        path: string,
        _entries: *Fs.FileSystem.RealFS.EntriesOption,
        _result: allocators.Result,
        dir_entry_index: allocators.IndexType,
        parent: ?*DirInfo,
        parent_index: allocators.IndexType,
        fd: FileDescriptorType,
        package_id: ?Install.PackageID,
    ) anyerror!void {
        const result = _result;

        const rfs: *Fs.FileSystem.RealFS = &r.fs.fs;
        var entries = _entries.entries;

        info.* = DirInfo{
            .abs_path = path,
            // .abs_real_path = path,
            .parent = parent_index,
            .entries = dir_entry_index,
        };

        // A "node_modules" directory isn't allowed to directly contain another "node_modules" directory
        var base = std.fs.path.basename(path);

        // base must
        if (base.len > 1 and base[base.len - 1] == std.fs.path.sep) base = base[0 .. base.len - 1];

        info.flags.setPresent(.is_node_modules, strings.eqlComptime(base, "node_modules"));

        // if (entries != null) {
        if (!info.isNodeModules()) {
            if (entries.getComptimeQuery("node_modules")) |entry| {
                info.flags.setPresent(.has_node_modules, (entry.entry.kind(rfs, r.store_fd)) == .dir);
            }
        }

        if (r.care_about_bin_folder) {
            append_bin_dir: {
                if (info.hasNodeModules()) {
                    if (entries.hasComptimeQuery("node_modules")) {
                        if (!bin_folders_loaded) {
                            bin_folders_loaded = true;
                            bin_folders = BinFolderArray.init(0) catch unreachable;
                        }

                        const this_dir = fd.stdDir();
                        var file = bun.FD.fromStdDir(this_dir.openDirZ(bun.pathLiteral("node_modules/.bin"), .{}) catch
                            break :append_bin_dir);
                        defer file.close();
                        const bin_path = file.getFdPath(bufs(.node_bin_path)) catch break :append_bin_dir;
                        bin_folders_lock.lock();
                        defer bin_folders_lock.unlock();

                        for (bin_folders.constSlice()) |existing_folder| {
                            if (strings.eql(existing_folder, bin_path)) {
                                break :append_bin_dir;
                            }
                        }

                        bin_folders.append(r.fs.dirname_store.append([]u8, bin_path) catch break :append_bin_dir) catch {};
                    }
                }

                if (info.isNodeModules()) {
                    if (entries.getComptimeQuery(".bin")) |q| {
                        if (q.entry.kind(rfs, r.store_fd) == .dir) {
                            if (!bin_folders_loaded) {
                                bin_folders_loaded = true;
                                bin_folders = BinFolderArray.init(0) catch unreachable;
                            }

                            const this_dir = fd.stdDir();
                            var file = this_dir.openDirZ(".bin", .{}) catch break :append_bin_dir;
                            defer file.close();
                            const bin_path = bun.getFdPath(.fromStdDir(file), bufs(.node_bin_path)) catch break :append_bin_dir;
                            bin_folders_lock.lock();
                            defer bin_folders_lock.unlock();

                            for (bin_folders.constSlice()) |existing_folder| {
                                if (strings.eql(existing_folder, bin_path)) {
                                    break :append_bin_dir;
                                }
                            }

                            bin_folders.append(r.fs.dirname_store.append([]u8, bin_path) catch break :append_bin_dir) catch {};
                        }
                    }
                }
            }
        }
        // }

        if (parent) |parent_| {
            // Propagate the browser scope into child directories
            info.enclosing_browser_scope = parent_.enclosing_browser_scope;
            info.package_json_for_browser_field = parent_.package_json_for_browser_field;
            info.enclosing_tsconfig_json = parent_.enclosing_tsconfig_json;

            if (parent_.package_json) |parent_package_json| {
                // https://github.com/oven-sh/bun/issues/229
                if (parent_package_json.name.len > 0 or r.care_about_bin_folder) {
                    info.enclosing_package_json = parent_package_json;
                }

                if (parent_package_json.dependencies.map.count() > 0 or parent_package_json.package_manager_package_id != Install.invalid_package_id) {
                    info.package_json_for_dependencies = parent_package_json;
                }
            }

            info.enclosing_package_json = info.enclosing_package_json orelse parent_.enclosing_package_json;
            info.package_json_for_dependencies = info.package_json_for_dependencies orelse parent_.package_json_for_dependencies;

            // Make sure "absRealPath" is the real path of the directory (resolving any symlinks)
            if (!r.opts.preserve_symlinks) {
                if (parent_.getEntries(r.generation)) |parent_entries| {
                    if (parent_entries.get(base)) |lookup| {
                        if (entries.fd.isValid() and !lookup.entry.cache.fd.isValid() and r.store_fd) lookup.entry.cache.fd = entries.fd;
                        const entry = lookup.entry;

                        var symlink = entry.symlink(rfs, r.store_fd);
                        if (symlink.len > 0) {
                            if (r.debug_logs) |*logs| {
                                logs.addNote(std.fmt.allocPrint(r.allocator, "Resolved symlink \"{s}\" to \"{s}\"", .{ path, symlink }) catch unreachable);
                            }
                            info.abs_real_path = symlink;
                        } else if (parent_.abs_real_path.len > 0) {
                            // this might leak a little i'm not sure
                            const parts = [_]string{ parent.?.abs_real_path, base };
                            symlink = r.fs.dirname_store.append(string, r.fs.absBuf(&parts, bufs(.dir_info_uncached_filename))) catch unreachable;

                            if (r.debug_logs) |*logs| {
                                logs.addNote(std.fmt.allocPrint(r.allocator, "Resolved symlink \"{s}\" to \"{s}\"", .{ path, symlink }) catch unreachable);
                            }
                            lookup.entry.cache.symlink = PathString.init(symlink);
                            info.abs_real_path = symlink;
                        }
                    }
                }
            }

            if (parent_.isNodeModules() or parent_.isInsideNodeModules()) {
                info.flags.setPresent(.inside_node_modules, true);
            }
        }

        // Record if this directory has a package.json file
        if (entries.getComptimeQuery("package.json")) |lookup| {
            const entry = lookup.entry;
            if (entry.kind(rfs, r.store_fd) == .file) {
                info.package_json = if (r.usePackageManager() and !info.hasNodeModules() and !info.isNodeModules())
                    r.parsePackageJSON(path, if (FeatureFlags.store_file_descriptors) fd else .invalid, package_id, true) catch null
                else
                    r.parsePackageJSON(path, if (FeatureFlags.store_file_descriptors) fd else .invalid, null, false) catch null;

                if (info.package_json) |pkg| {
                    if (pkg.browser_map.count() > 0) {
                        info.enclosing_browser_scope = result.index;
                        info.package_json_for_browser_field = pkg;
                    }

                    if (pkg.name.len > 0 or r.care_about_bin_folder)
                        info.enclosing_package_json = pkg;

                    if (pkg.dependencies.map.count() > 0 or pkg.package_manager_package_id != Install.invalid_package_id)
                        info.package_json_for_dependencies = pkg;

                    if (r.debug_logs) |*logs| {
                        logs.addNoteFmt("Resolved package.json in \"{s}\"", .{
                            path,
                        });
                    }
                }
            }
        }

        // Record if this directory has a tsconfig.json or jsconfig.json file
        if (r.opts.load_tsconfig_json) {
            var tsconfig_path: ?string = null;
            if (r.opts.tsconfig_override == null) {
                if (entries.getComptimeQuery("tsconfig.json")) |lookup| {
                    const entry = lookup.entry;
                    if (entry.kind(rfs, r.store_fd) == .file) {
                        const parts = [_]string{ path, "tsconfig.json" };

                        tsconfig_path = r.fs.absBuf(&parts, bufs(.dir_info_uncached_filename));
                    }
                }
                if (tsconfig_path == null) {
                    if (entries.getComptimeQuery("jsconfig.json")) |lookup| {
                        const entry = lookup.entry;
                        if (entry.kind(rfs, r.store_fd) == .file) {
                            const parts = [_]string{ path, "jsconfig.json" };
                            tsconfig_path = r.fs.absBuf(&parts, bufs(.dir_info_uncached_filename));
                        }
                    }
                }
            } else if (parent == null) {
                tsconfig_path = r.opts.tsconfig_override.?;
            }

            if (tsconfig_path) |tsconfigpath| {
                info.tsconfig_json = r.parseTSConfig(
                    tsconfigpath,
                    if (FeatureFlags.store_file_descriptors) fd else .zero,
                ) catch |err| brk: {
                    const pretty = tsconfigpath;
                    if (err == error.ENOENT or err == error.FileNotFound) {
                        r.log.addErrorFmt(null, logger.Loc.Empty, r.allocator, "Cannot find tsconfig file {}", .{bun.fmt.QuotedFormatter{ .text = pretty }}) catch {};
                    } else if (err != error.ParseErrorAlreadyLogged and err != error.IsDir and err != error.EISDIR) {
                        r.log.addErrorFmt(null, logger.Loc.Empty, r.allocator, "Cannot read file {}: {s}", .{ bun.fmt.QuotedFormatter{ .text = pretty }, @errorName(err) }) catch {};
                    }
                    break :brk null;
                };
                if (info.tsconfig_json) |tsconfig_json| {
                    var parent_configs = try std.BoundedArray(*TSConfigJSON, 64).init(0);
                    try parent_configs.append(tsconfig_json);
                    var current = tsconfig_json;
                    while (current.extends.len > 0) {
                        const ts_dir_name = Dirname.dirname(current.abs_path);
                        const abs_path = ResolvePath.joinAbsStringBuf(ts_dir_name, bufs(.tsconfig_path_abs), &[_]string{ ts_dir_name, current.extends }, .auto);
                        const parent_config_maybe = r.parseTSConfig(abs_path, bun.invalid_fd) catch |err| {
                            r.log.addDebugFmt(null, logger.Loc.Empty, r.allocator, "{s} loading tsconfig.json extends {}", .{
                                @errorName(err),
                                bun.fmt.QuotedFormatter{
                                    .text = abs_path,
                                },
                            }) catch {};
                            break;
                        };
                        if (parent_config_maybe) |parent_config| {
                            try parent_configs.append(parent_config);
                            current = parent_config;
                        } else {
                            break;
                        }
                    }

                    var merged_config = parent_configs.pop().?;
                    // starting from the base config (end of the list)
                    // successively apply the inheritable attributes to the next config
                    while (parent_configs.pop()) |parent_config| {
                        merged_config.emit_decorator_metadata = merged_config.emit_decorator_metadata or parent_config.emit_decorator_metadata;
                        if (parent_config.base_url.len > 0) {
                            merged_config.base_url = parent_config.base_url;
                            merged_config.base_url_for_paths = parent_config.base_url_for_paths;
                        }
                        merged_config.jsx = parent_config.mergeJSX(merged_config.jsx);
                        merged_config.jsx_flags.setUnion(parent_config.jsx_flags);

                        if (parent_config.preserve_imports_not_used_as_values) |value| {
                            merged_config.preserve_imports_not_used_as_values = value;
                        }

                        var iter = parent_config.paths.iterator();
                        while (iter.next()) |c| {
                            merged_config.paths.put(c.key_ptr.*, c.value_ptr.*) catch unreachable;
                        }
                        // todo deinit these parent configs somehow?
                    }
                    info.tsconfig_json = merged_config;
                }
                info.enclosing_tsconfig_json = info.tsconfig_json;
            }
        }
    }
};

pub const Dirname = struct {
    pub fn dirname(path: string) string {
        if (path.len == 0)
            return std.fs.path.sep_str;

        const root = brk: {
            if (Environment.isWindows) {
                const root = ResolvePath.windowsFilesystemRoot(path);
                assert(root.len > 0);

                // Preserve the trailing slash for UNC paths.
                // Going from `\\server\share\folder` should end up
                // at `\\server\share\`, not `\\server\share`
                break :brk if (root.len >= 5 and path.len > root.len) path[0 .. root.len + 1] else root;
            }
            break :brk "/";
        };

        var end_index: usize = path.len - 1;
        while (bun.path.isSepAny(path[end_index])) {
            if (end_index == 0)
                return root;
            end_index -= 1;
        }

        while (!bun.path.isSepAny(path[end_index])) {
            if (end_index == 0)
                return root;
            end_index -= 1;
        }

        if (end_index == 0 and bun.path.isSepAny(path[0]))
            return path[0..1];

        if (end_index == 0)
            return root;

        return path[0 .. end_index + 1];
    }
};

pub const RootPathPair = struct {
    base_path: string,
    package_json: *const PackageJSON,
};

pub const GlobalCache = enum {
    allow_install,
    read_only,
    auto,
    force,
    fallback,
    disable,

    pub const Map = bun.ComptimeStringMap(GlobalCache, .{
        .{ "auto", GlobalCache.auto },
        .{ "force", GlobalCache.force },
        .{ "disable", GlobalCache.disable },
        .{ "fallback", GlobalCache.fallback },
    });

    pub fn allowVersionSpecifier(this: GlobalCache) bool {
        return this == .force;
    }

    pub fn canUse(this: GlobalCache, has_a_node_modules_folder: bool) bool {
        // When there is a node_modules folder, we default to false
        // When there is NOT a node_modules folder, we default to true
        // That is the difference between these two branches.
        if (has_a_node_modules_folder) {
            return switch (this) {
                .fallback, .allow_install, .force => true,
                .read_only, .disable, .auto => false,
            };
        } else {
            return switch (this) {
                .read_only, .fallback, .allow_install, .auto, .force => true,
                .disable => false,
            };
        }
    }

    pub fn isEnabled(this: GlobalCache) bool {
        return this != .disable;
    }

    pub fn canInstall(this: GlobalCache) bool {
        return switch (this) {
            .auto, .allow_install, .force, .fallback => true,
            else => false,
        };
    }
};

comptime {
    _ = Resolver.Resolver__propForRequireMainPaths;
    @export(&JSC.toJSHostFn(Resolver.nodeModulePathsForJS), .{ .name = "Resolver__nodeModulePathsForJS" });
    @export(&Resolver.nodeModulePathsJSValue, .{ .name = "Resolver__nodeModulePathsJSValue" });
}

const assert = bun.assert;
