aboutsummaryrefslogtreecommitdiff
path: root/src/resolver/resolver.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/resolver/resolver.zig')
-rw-r--r--src/resolver/resolver.zig191
1 files changed, 121 insertions, 70 deletions
diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig
index 93cdec82e..6496ce118 100644
--- a/src/resolver/resolver.zig
+++ b/src/resolver/resolver.zig
@@ -1007,7 +1007,7 @@ pub const Resolver = struct {
if (remapped.len == 0) {
// "browser": {"module": false}
// does the module exist in the filesystem?
- if (r.loadNodeModules(import_path, kind, source_dir_info)) |node_module| {
+ if (r.loadNodeModules(import_path, kind, source_dir_info, false)) |node_module| {
var pair = node_module.path_pair;
pair.primary.is_disabled = true;
if (pair.secondary != null) {
@@ -1183,7 +1183,13 @@ pub const Resolver = struct {
threadlocal var esm_subpath_buf: [512]u8 = undefined;
threadlocal var esm_absolute_package_path: [bun.MAX_PATH_BYTES]u8 = undefined;
threadlocal var esm_absolute_package_path_joined: [bun.MAX_PATH_BYTES]u8 = undefined;
- pub fn loadNodeModules(r: *ThisResolver, import_path: string, kind: ast.ImportKind, _dir_info: *DirInfo) ?MatchResult {
+ pub fn loadNodeModules(
+ r: *ThisResolver,
+ import_path: string,
+ kind: ast.ImportKind,
+ _dir_info: *DirInfo,
+ forbid_imports: bool,
+ ) ?MatchResult {
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 }) catch {};
@@ -1221,6 +1227,44 @@ pub const Resolver = struct {
const esm_ = ESModule.Package.parse(import_path, &esm_subpath_buf);
+ if (import_path[0] == '#' and !forbid_imports) {
+ if (esm_ != null) {
+ if (dir_info.package_json) |package_json| {
+ load_from_imports_map: {
+ const imports_map = package_json.imports orelse break :load_from_imports_map;
+
+ 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}) catch {};
+ }
+ return null;
+ }
+
+ 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,
+ };
+
+ const esm_resolution = esmodule.resolveImports(import_path, imports_map.root);
+
+ if (esm_resolution.status == .PackageResolve)
+ return r.loadNodeModules(
+ esm_resolution.path,
+ kind,
+ dir_info,
+ true,
+ );
+
+ return r.handleESMResolution(esm_resolution, dir_info.abs_path, kind, package_json);
+ }
+ }
+ }
+ }
+
// Then check for the package in any enclosing "node_modules" directories
while (true) {
// Skip directories that are themselves called "node_modules", since we
@@ -1259,73 +1303,10 @@ pub const Resolver = struct {
// 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.
- var esm_resolution = esmodule.resolve("/", esm.subpath, exports_map.root);
-
- if ((esm_resolution.status == .Inexact or esm_resolution.status == .Exact) and
- esm_resolution.path.len > 0 and esm_resolution.path[0] == '/')
- {
- const abs_esm_path: string = brk: {
- var parts = [_]string{
- abs_package_path,
- esm_resolution.path[1..],
- };
- break :brk r.fs.absBuf(&parts, &esm_absolute_package_path_joined);
- };
-
- switch (esm_resolution.status) {
- .Exact => {
- 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() orelse {
- esm_resolution.status = .ModuleNotFound;
- return null;
- };
- const entry_query = entries.get(std.fs.path.basename(abs_esm_path)) orelse {
- esm_resolution.status = .ModuleNotFound;
- return null;
- };
-
- if (entry_query.entry.kind(&r.fs.fs) == .dir) {
- esm_resolution.status = .UnsupportedDirectoryImport;
- 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();
- };
-
- 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,
- };
- },
- .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| {
- res.is_node_module = true;
- res.package_json = res.package_json orelse package_json;
- return res.*;
- }
- esm_resolution.status = .ModuleNotFound;
- return null;
- },
- else => unreachable,
- }
+ const esm_resolution = esmodule.resolve("/", esm.subpath, exports_map.root);
+
+ if (r.handleESMResolution(esm_resolution, abs_package_path, kind, package_json)) |res| {
+ return res;
}
}
}
@@ -1347,9 +1328,79 @@ pub const Resolver = struct {
return null;
}
+ fn handleESMResolution(r: *ThisResolver, esm_resolution_: ESModule.Resolution, abs_package_path: string, kind: ast.ImportKind, package_json: *PackageJSON) ?MatchResult {
+ var esm_resolution = esm_resolution_;
+ if (!((esm_resolution.status == .Inexact or esm_resolution.status == .Exact) and
+ esm_resolution.path.len > 0 and esm_resolution.path[0] == '/'))
+ return null;
+
+ const abs_esm_path: string = brk: {
+ var parts = [_]string{
+ abs_package_path,
+ esm_resolution.path[1..],
+ };
+ break :brk r.fs.absBuf(&parts, &esm_absolute_package_path_joined);
+ };
+
+ switch (esm_resolution.status) {
+ .Exact => {
+ 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() orelse {
+ esm_resolution.status = .ModuleNotFound;
+ return null;
+ };
+ const entry_query = entries.get(std.fs.path.basename(abs_esm_path)) orelse {
+ esm_resolution.status = .ModuleNotFound;
+ return null;
+ };
+
+ if (entry_query.entry.kind(&r.fs.fs) == .dir) {
+ esm_resolution.status = .UnsupportedDirectoryImport;
+ 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();
+ };
+
+ 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,
+ };
+ },
+ .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| {
+ res.is_node_module = true;
+ res.package_json = res.package_json orelse package_json;
+ return res.*;
+ }
+ esm_resolution.status = .ModuleNotFound;
+ return null;
+ },
+ else => unreachable,
+ }
+ }
+
pub fn resolveWithoutRemapping(r: *ThisResolver, source_dir_info: *DirInfo, import_path: string, kind: ast.ImportKind) ?MatchResult {
if (isPackagePath(import_path)) {
- return r.loadNodeModules(import_path, kind, source_dir_info);
+ return r.loadNodeModules(import_path, kind, source_dir_info, false);
} else {
const paths = [_]string{ source_dir_info.abs_path, import_path };
var resolved = r.fs.absBuf(&paths, &resolve_without_remapping_buf);