diff options
author | 2023-07-11 19:14:34 -0700 | |
---|---|---|
committer | 2023-07-11 19:14:34 -0700 | |
commit | cbb88672f217a90db1aa1eb29cd92d5d9035b22b (patch) | |
tree | 43a00501f3cde495967e116f0b660777051551f8 /src/resolver | |
parent | 1f900cff453700b19bca2acadfe26da4468c1282 (diff) | |
parent | 34b0e7a2bbd8bf8097341cdb0075d0908283e834 (diff) | |
download | bun-jarred/esm-conditions.tar.gz bun-jarred/esm-conditions.tar.zst bun-jarred/esm-conditions.zip |
Merge branch 'main' into jarred/esm-conditionsjarred/esm-conditions
Diffstat (limited to 'src/resolver')
-rw-r--r-- | src/resolver/package_json.zig | 18 | ||||
-rw-r--r-- | src/resolver/resolve_path.zig | 4 | ||||
-rw-r--r-- | src/resolver/resolver.zig | 190 | ||||
-rw-r--r-- | src/resolver/tsconfig_json.zig | 2 |
4 files changed, 154 insertions, 60 deletions
diff --git a/src/resolver/package_json.zig b/src/resolver/package_json.zig index effe3297c..81dcbf3a6 100644 --- a/src/resolver/package_json.zig +++ b/src/resolver/package_json.zig @@ -59,7 +59,7 @@ pub const PackageJSON = struct { pub fn generateHash(package_json: *PackageJSON) void { var hashy: [1024]u8 = undefined; - std.mem.set(u8, &hashy, 0); + @memset(&hashy, 0); var used: usize = 0; bun.copy(u8, &hashy, package_json.name); used = package_json.name.len; @@ -390,7 +390,7 @@ pub const PackageJSON = struct { var count: usize = 0; const items = array.items.slice(); for (items) |item| { - count += @boolToInt(item.data == .e_string and item.data.e_string.data.len > 0); + count += @intFromBool(item.data == .e_string and item.data.e_string.data.len > 0); } switch (count) { 0 => {}, @@ -888,10 +888,10 @@ pub const PackageJSON = struct { const dependency_groups = comptime brk: { var out_groups: [ - @as(usize, @boolToInt(features.dependencies)) + - @as(usize, @boolToInt(features.dev_dependencies)) + - @as(usize, @boolToInt(features.optional_dependencies)) + - @as(usize, @boolToInt(features.peer_dependencies)) + @as(usize, @intFromBool(features.dependencies)) + + @as(usize, @intFromBool(features.dev_dependencies)) + + @as(usize, @intFromBool(features.optional_dependencies)) + + @as(usize, @intFromBool(features.peer_dependencies)) ]DependencyGroup = undefined; var out_group_i: usize = 0; if (features.dependencies) { @@ -989,7 +989,7 @@ pub const PackageJSON = struct { const key = prop.key.?.asString(allocator) orelse continue; const value = prop.value.?.asString(allocator) orelse continue; - count += @as(usize, @boolToInt(key.len > 0 and value.len > 0)); + count += @as(usize, @intFromBool(key.len > 0 and value.len > 0)); } if (count == 0) break :read_scripts; @@ -1022,7 +1022,7 @@ pub const PackageJSON = struct { } pub fn hashModule(this: *const PackageJSON, module: string) u32 { - var hasher = std.hash.Wyhash.init(0); + var hasher = bun.Wyhash.init(0); hasher.update(std.mem.asBytes(&this.hash)); hasher.update(module); @@ -1148,7 +1148,7 @@ pub const ExportsMap = struct { // PATTERN_KEY_COMPARE which orders in descending order of specificity. const GlobLengthSorter: type = strings.NewGlobLengthSorter(Entry.Data.Map.MapEntry, "key"); var sorter = GlobLengthSorter{}; - std.sort.sort(Entry.Data.Map.MapEntry, expansion_keys, sorter, GlobLengthSorter.lessThan); + std.sort.block(Entry.Data.Map.MapEntry, expansion_keys, sorter, GlobLengthSorter.lessThan); return Entry{ .data = .{ diff --git a/src/resolver/resolve_path.zig b/src/resolver/resolve_path.zig index c5ffdc626..e63318887 100644 --- a/src/resolver/resolve_path.zig +++ b/src/resolver/resolve_path.zig @@ -376,7 +376,7 @@ pub fn relativeToCommonPath( var out_slice: []u8 = buf[0..0]; if (normalized_from.len > 0) { - var i: usize = @intCast(usize, @boolToInt(normalized_from[0] == separator)) + 1 + last_common_separator; + var i: usize = @intCast(usize, @intFromBool(normalized_from[0] == separator)) + 1 + last_common_separator; while (i <= normalized_from.len) : (i += 1) { if (i == normalized_from.len or (normalized_from[i] == separator and i + 1 < normalized_from.len)) { @@ -549,7 +549,7 @@ pub fn normalizeStringGeneric(path: []const u8, buf: []u8, comptime allow_above_ const from = r; while (r < n and !isSeparator(path[r])) : (r += 1) {} const count = r - from; - @memcpy(buf[buf_i..].ptr, path[from..].ptr, count); + @memcpy(buf[buf_i..][0..count], path[from..][0..count]); buf_i += count; } diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index 8a6a2bc5e..409df85af 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -27,7 +27,6 @@ const CacheSet = cache.Set; const DataURL = @import("./data_url.zig").DataURL; pub const DirInfo = @import("./dir_info.zig"); const HTTPWatcher = if (Environment.isTest or Environment.isWasm) void else @import("../http.zig").Watcher; -const Wyhash = std.hash.Wyhash; const ResolvePath = @import("./resolve_path.zig"); const NodeFallbackModules = @import("../node_fallbacks.zig"); const Mutex = @import("../lock.zig").Lock; @@ -95,6 +94,7 @@ const bufs = struct { threadlocal var remap_path_trailing_slash: [bun.MAX_PATH_BYTES]u8 = undefined; threadlocal var path_in_global_disk_cache: [bun.MAX_PATH_BYTES]u8 = undefined; threadlocal var abs_to_rel: [bun.MAX_PATH_BYTES]u8 = undefined; + threadlocal var node_modules_paths_buf: [bun.MAX_PATH_BYTES]u8 = undefined; pub inline fn bufs(comptime field: std.meta.DeclEnum(@This())) *@TypeOf(@field(@This(), @tagName(field))) { return &@field(@This(), @tagName(field)); @@ -283,10 +283,10 @@ pub const Result = struct { if (strings.lastIndexOf(module, node_module_root)) |end_| { var end: usize = end_ + node_module_root.len; - return @truncate(u32, std.hash.Wyhash.hash(0, module[end..])); + return @truncate(u32, bun.hash(module[end..])); } - return @truncate(u32, std.hash.Wyhash.hash(0, this.path_pair.primary.text)); + return @truncate(u32, bun.hash(this.path_pair.primary.text)); } }; @@ -533,21 +533,24 @@ pub const Resolver = struct { // all parent directories dir_cache: *DirInfo.HashMap, - pub fn getPackageManager(this: *Resolver) *PackageManager { - if (this.package_manager != null) { - return this.package_manager.?; - } - bun.HTTPThead.init() catch unreachable; - this.package_manager = PackageManager.initWithRuntime( - this.log, - this.opts.install, - this.allocator, - .{}, - this.env_loader.?, - ) catch @panic("Failed to initialize package manager"); - this.package_manager.?.onWake = this.onWakePackageManager; + /// This is set to false for the runtime. The runtime should choose "main" + /// over "module" in package.json + prefer_module_field: bool = true, - return this.package_manager.?; + pub fn getPackageManager(this: *Resolver) *PackageManager { + return this.package_manager orelse brk: { + bun.HTTPThead.init() catch unreachable; + const pm = PackageManager.initWithRuntime( + this.log, + this.opts.install, + this.allocator, + .{}, + this.env_loader.?, + ) catch @panic("Failed to initialize package manager"); + pm.onWake = this.onWakePackageManager; + this.package_manager = pm; + break :brk pm; + }; } pub inline fn usePackageManager(self: *const ThisResolver) bool { @@ -609,7 +612,7 @@ pub const Resolver = struct { 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 (@enumToInt(r.log.level) <= @enumToInt(logger.Log.Level.verbose)) { + } 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()); } } @@ -1253,19 +1256,13 @@ pub const Resolver = struct { if (check_package) { if (r.opts.polyfill_node_globals) { - var import_path_without_node_prefix = import_path; - const had_node_prefix = import_path_without_node_prefix.len > "node:".len and - strings.eqlComptime(import_path_without_node_prefix[0.."node:".len], "node:"); - - import_path_without_node_prefix = if (had_node_prefix) - import_path_without_node_prefix["node:".len..] - else - import_path_without_node_prefix; + 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 = @intToPtr(*PackageJSON, @ptrToInt(fallback_module.package_json)); + result.package_json = @ptrFromInt(*PackageJSON, @intFromPtr(fallback_module.package_json)); result.is_from_node_modules = true; return .{ .success = result }; // "node:* @@ -1275,7 +1272,7 @@ pub const Resolver = struct { } else if (had_node_prefix or (strings.hasPrefixComptime(import_path_without_node_prefix, "fs") and (import_path_without_node_prefix.len == 2 or - import_path_without_node_prefix[3] == '/'))) + import_path_without_node_prefix[2] == '/'))) { result.path_pair.primary.namespace = "node"; result.path_pair.primary.text = import_path_without_node_prefix; @@ -1695,8 +1692,9 @@ pub const Resolver = struct { // If the source directory doesn't have a node_modules directory, we can // check the global cache directory for a package.json file. var manager = r.getPackageManager(); - var dependency_version: Dependency.Version = .{}; - var dependency_behavior = @intToEnum(Dependency.Behavior, Dependency.Behavior.normal); + var dependency_version = Dependency.Version{}; + var dependency_behavior = @enumFromInt(Dependency.Behavior, Dependency.Behavior.normal); + var string_buf = esm.version; // const initial_pending_tasks = manager.pending_tasks; var resolved_package_id: Install.PackageID = brk: { @@ -1704,7 +1702,6 @@ pub const Resolver = struct { // and try to look up the dependency from there if (dir_info.package_json_for_dependencies) |package_json| { var dependencies_list: []const Dependency = &[_]Dependency{}; - var string_buf: []const u8 = ""; const resolve_from_lockfile = package_json.package_manager_package_id != Install.invalid_package_id; if (resolve_from_lockfile) { @@ -1720,24 +1717,21 @@ pub const Resolver = struct { } for (dependencies_list, 0..) |dependency, dependency_id| { - const dep_name = dependency.name.slice(string_buf); - if (dep_name.len == esm.name.len) { - if (!strings.eqlLong(dep_name, esm.name, false)) { - continue; - } - - dependency_version = dependency.version; - dependency_behavior = dependency.behavior; + if (!strings.eqlLong(dependency.name.slice(string_buf), esm.name, true)) { + continue; + } - if (resolve_from_lockfile) { - const resolutions = &manager.lockfile.packages.items(.resolutions)[package_json.package_manager_package_id]; + dependency_version = dependency.version; + dependency_behavior = dependency.behavior; - // found it! - break :brk resolutions.get(manager.lockfile.buffers.resolutions.items)[dependency_id]; - } + if (resolve_from_lockfile) { + const resolutions = &manager.lockfile.packages.items(.resolutions)[package_json.package_manager_package_id]; - break; + // found it! + break :brk resolutions.get(manager.lockfile.buffers.resolutions.items)[dependency_id]; } + + break; } } @@ -1767,6 +1761,7 @@ pub const Resolver = struct { 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), @@ -1792,6 +1787,7 @@ pub const Resolver = struct { dependency_behavior, &resolved_package_id, dependency_version, + string_buf, )) { .resolution => |res| break :brk res, .pending => |pending| return .{ .pending = pending }, @@ -2070,6 +2066,7 @@ pub const Resolver = struct { 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 }); @@ -2132,7 +2129,7 @@ pub const Resolver = struct { // All packages are enqueued to the root // because we download all the npm package dependencies - switch (pm.enqueueDependencyToRoot(esm.name, esm.version, &version, behavior)) { + switch (pm.enqueueDependencyToRoot(esm.name, &version, version_buf, behavior)) { .resolution => |result| { input_package_id_.* = result.package_id; return .{ .resolution = result.resolution }; @@ -2629,7 +2626,7 @@ pub const Resolver = struct { // Directories must always end in a trailing slash or else various bugs can occur. // This covers "what happens when the trailing" - end += @intCast(usize, @boolToInt(safe_path.len > end and end > 0 and safe_path[end - 1] != std.fs.path.sep and safe_path[end] == std.fs.path.sep)); + end += @intCast(usize, @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]; }; @@ -3108,6 +3105,93 @@ pub const Resolver = struct { }; } + pub export fn Resolver__nodeModulePathsForJS(globalThis: *bun.JSC.JSGlobalObject, callframe: *bun.JSC.CallFrame) callconv(.C) bun.JSC.JSValue { + bun.JSC.markBinding(@src()); + const argument: bun.JSC.JSValue = callframe.argument(0); + + if (argument.isEmpty() or !argument.isString()) { + globalThis.throwInvalidArgumentType("nodeModulePaths", "path", "string"); + return .zero; + } + + const in_str = argument.toBunString(globalThis); + var r = &globalThis.bunVM().bundler.resolver; + return nodeModulePathsJSValue(r, in_str, globalThis); + } + + pub export fn Resolver__propForRequireMainPaths(globalThis: *bun.JSC.JSGlobalObject) callconv(.C) bun.JSC.JSValue { + bun.JSC.markBinding(@src()); + + const in_str = bun.String.create("."); + var r = &globalThis.bunVM().bundler.resolver; + return nodeModulePathsJSValue(r, in_str, globalThis); + } + + pub fn nodeModulePathsJSValue( + r: *ThisResolver, + in_str: bun.String, + globalObject: *bun.JSC.JSGlobalObject, + ) bun.JSC.JSValue { + var list = std.ArrayList(bun.String).init(bun.default_allocator); + defer list.deinit(); + + const sliced = in_str.toUTF8(bun.default_allocator); + defer sliced.deinit(); + + const str = brk: { + if (std.fs.path.isAbsolute(sliced.slice())) break :brk sliced.slice(); + var dir_path_buf = bufs(.node_modules_paths_buf); + break :brk r.fs.joinBuf(&[_]string{ r.fs.top_level_dir, sliced.slice() }, dir_path_buf); + }; + var arena = std.heap.ArenaAllocator.init(bun.default_allocator); + defer arena.deinit(); + var stack_fallback_allocator = std.heap.stackFallback(1024, arena.allocator()); + + if (r.readDirInfo(strings.withoutTrailingSlash(str)) catch null) |result| { + var dir_info = result; + + while (true) { + const path_without_trailing_slash = strings.withoutTrailingSlash(dir_info.abs_path); + const path_parts = brk: { + if (path_without_trailing_slash.len == 1 and path_without_trailing_slash[0] == '/') { + break :brk [2]string{ "", "/node_modules" }; + } + + break :brk [2]string{ path_without_trailing_slash, "/node_modules" }; + }; + list.append( + bun.String.create( + bun.strings.concat(stack_fallback_allocator.get(), &path_parts) catch unreachable, + ), + ) catch unreachable; + dir_info = (r.readDirInfo(std.fs.path.dirname(path_without_trailing_slash) orelse break) catch null) orelse break; + } + } else { + // does not exist + const full_path = std.fs.path.resolve(r.allocator, &[1][]const u8{str}) catch unreachable; + var path = full_path; + while (true) { + const path_without_trailing_slash = strings.withoutTrailingSlash(path); + + list.append( + bun.String.create( + bun.strings.concat( + stack_fallback_allocator.get(), + &[_]string{ + path_without_trailing_slash, + "/node_modules", + }, + ) catch unreachable, + ), + ) catch unreachable; + + path = path[0 .. strings.lastIndexOfChar(path, '/') orelse break]; + } + } + + return bun.String.toJSArray(globalObject, list.items); + } + pub fn loadAsIndex(r: *ThisResolver, dir_info: *DirInfo, extension_order: []const string) ?MatchResult { var rfs = &r.fs.fs; // Try the "index" file with extensions @@ -3322,7 +3406,10 @@ pub const Resolver = struct { // 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. - if (kind != ast.ImportKind.require) { + // + // 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.key_path.text }); @@ -3893,3 +3980,10 @@ pub const GlobalCache = enum { }; } }; + +comptime { + if (!bun.JSC.is_bindgen) { + _ = Resolver.Resolver__nodeModulePathsForJS; + _ = Resolver.Resolver__propForRequireMainPaths; + } +} diff --git a/src/resolver/tsconfig_json.zig b/src/resolver/tsconfig_json.zig index 4f04c39ca..2ec402fd2 100644 --- a/src/resolver/tsconfig_json.zig +++ b/src/resolver/tsconfig_json.zig @@ -344,7 +344,7 @@ pub const TSConfigJSON = struct { // foo == 1 // foo.bar.baz == 3 // foo.bar.baz.bun == 4 - const parts_count = std.mem.count(u8, text, ".") + @as(usize, @boolToInt(text[text.len - 1] != '.')); + const parts_count = std.mem.count(u8, text, ".") + @as(usize, @intFromBool(text[text.len - 1] != '.')); var parts = std.ArrayList(string).initCapacity(allocator, parts_count) catch unreachable; if (parts_count == 1) { |