diff options
author | 2023-02-12 06:40:18 +0200 | |
---|---|---|
committer | 2023-02-11 20:40:18 -0800 | |
commit | 30e82c5df42fab71a238cd9b7d268cbb6510bd7a (patch) | |
tree | 8f3c9212696545af28c6eba4a43a35599522cadf | |
parent | 9eba1e0e3fbd9ba80f7cac4a74c860e35335d86e (diff) | |
download | bun-30e82c5df42fab71a238cd9b7d268cbb6510bd7a.tar.gz bun-30e82c5df42fab71a238cd9b7d268cbb6510bd7a.tar.zst bun-30e82c5df42fab71a238cd9b7d268cbb6510bd7a.zip |
fix segfault during non-install script execution (#2045)
-rw-r--r-- | src/bun.js/module_loader.zig | 50 | ||||
-rw-r--r-- | src/install/dependency.zig | 12 | ||||
-rw-r--r-- | src/install/extract_tarball.zig | 9 | ||||
-rw-r--r-- | src/install/install.zig | 217 | ||||
-rw-r--r-- | src/install/lockfile.zig | 2 | ||||
-rw-r--r-- | src/resolver/package_json.zig | 2 | ||||
-rw-r--r-- | src/resolver/resolver.zig | 1 | ||||
-rw-r--r-- | test/bun.js/install/bunx.test.ts | 33 |
8 files changed, 107 insertions, 219 deletions
diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig index dd4e258e6..0583a36ad 100644 --- a/src/bun.js/module_loader.zig +++ b/src/bun.js/module_loader.zig @@ -212,7 +212,7 @@ pub const ModuleLoader = struct { const DeferredDependencyError = struct { dependency: Dependency, - root_dependency_id: Install.PackageID, + root_dependency_id: Install.DependencyID, err: anyerror, }; @@ -228,7 +228,7 @@ pub const ModuleLoader = struct { _ = this.vm().packageManager().scheduleNetworkTasks(); } - pub fn onDependencyError(ctx: *anyopaque, dependency: Dependency, root_dependency_id: Install.PackageID, err: anyerror) void { + pub fn onDependencyError(ctx: *anyopaque, dependency: Dependency, root_dependency_id: Install.DependencyID, err: anyerror) void { var this = bun.cast(*Queue, ctx); debug("onDependencyError: {s}", .{this.vm().packageManager().lockfile.str(&dependency.name)}); @@ -236,7 +236,7 @@ pub const ModuleLoader = struct { var i: usize = 0; outer: for (modules) |module_| { var module = module_; - var root_dependency_ids = module.parse_result.pending_imports.items(.root_dependency_id); + const root_dependency_ids = module.parse_result.pending_imports.items(.root_dependency_id); for (root_dependency_ids) |dep, dep_i| { if (dep != root_dependency_id) continue; module.resolveError( @@ -289,7 +289,7 @@ pub const ModuleLoader = struct { *Queue, this, .{ - .onExtract = onExtract, + .onExtract = {}, .onResolve = onResolve, .onPackageManifestError = onPackageManifestError, .onPackageDownloadError = onPackageDownloadError, @@ -302,7 +302,7 @@ pub const ModuleLoader = struct { *Queue, this, .{ - .onExtract = onExtract, + .onExtract = {}, .onResolve = onResolve, .onPackageManifestError = onPackageManifestError, .onPackageDownloadError = onPackageDownloadError, @@ -369,16 +369,18 @@ pub const ModuleLoader = struct { ) void { debug("onPackageDownloadError: {s}", .{name}); + const resolution_ids = this.vm().packageManager().lockfile.buffers.resolutions.items; var modules: []AsyncModule = this.map.items; var i: usize = 0; outer: for (modules) |module_| { var module = module_; - var root_dependency_ids = module.parse_result.pending_imports.items(.root_dependency_id); - for (root_dependency_ids) |dep, dep_i| { - if (this.vm().packageManager().dynamicRootDependencies().items[dep].resolution_id != package_id) continue; + const record_ids = module.parse_result.pending_imports.items(.import_record_id); + const root_dependency_ids = module.parse_result.pending_imports.items(.root_dependency_id); + for (root_dependency_ids) |dependency_id, import_id| { + if (resolution_ids[dependency_id] != package_id) continue; module.downloadError( this.vm(), - module.parse_result.pending_imports.items(.import_record_id)[dep_i], + record_ids[import_id], .{ .name = name, .resolution = resolution, @@ -395,27 +397,6 @@ pub const ModuleLoader = struct { this.map.items.len = i; } - pub fn onExtract(this: *Queue, package_id: Install.PackageID, _: Install.ExtractData, comptime _: PackageManager.Options.LogLevel) void { - if (comptime Environment.allow_assert) { - const lockfile = this.vm().packageManager().lockfile; - debug("onExtract: {s} ({d})", .{ - lockfile.str(&lockfile.packages.get(package_id).name), - package_id, - }); - } - this.onPackageID(package_id); - } - - pub fn onPackageID(this: *Queue, package_id: Install.PackageID) void { - var values = this.map.items; - for (values) |value| { - var package_ids = value.parse_result.pending_imports.items(.resolution_id); - - _ = package_id; - _ = package_ids; - } - } - pub fn pollModules(this: *Queue) void { var pm = this.vm().packageManager(); if (pm.pending_tasks > 0) return; @@ -426,16 +407,15 @@ pub const ModuleLoader = struct { for (modules) |mod| { var module = mod; var tags = module.parse_result.pending_imports.items(.tag); - var root_dependency_ids = module.parse_result.pending_imports.items(.root_dependency_id); + const root_dependency_ids = module.parse_result.pending_imports.items(.root_dependency_id); // var esms = module.parse_result.pending_imports.items(.esm); // var versions = module.parse_result.pending_imports.items(.dependency); var done_count: usize = 0; for (tags) |tag, tag_i| { const root_id = root_dependency_ids[tag_i]; - if (root_id == Install.invalid_package_id) continue; - const root_items = pm.dynamicRootDependencies().items; - if (root_items.len <= root_id) continue; - const package_id = root_items[root_id].resolution_id; + const resolution_ids = pm.lockfile.buffers.resolutions.items; + if (root_id >= resolution_ids.len) continue; + const package_id = resolution_ids[root_id]; switch (tag) { .resolve => { diff --git a/src/install/dependency.zig b/src/install/dependency.zig index 2cc3d4177..973a8b997 100644 --- a/src/install/dependency.zig +++ b/src/install/dependency.zig @@ -15,12 +15,6 @@ const string = @import("../string_types.zig").string; const strings = @import("../string_immutable.zig"); const Dependency = @This(); -pub const Pair = struct { - resolution_id: Install.PackageID = Install.invalid_package_id, - dependency: Dependency = .{}, - failed: ?anyerror = null, -}; - pub const URI = union(Tag) { local: String, remote: String, @@ -44,8 +38,8 @@ pub const URI = union(Tag) { }; name_hash: PackageNameHash = 0, -name: String = String{}, -version: Dependency.Version = Dependency.Version{}, +name: String = .{}, +version: Dependency.Version = .{}, /// This is how the dependency is specified in the package.json file. /// This allows us to track whether a package originated in any permutation of: @@ -55,7 +49,7 @@ version: Dependency.Version = Dependency.Version{}, /// - `peerDependencies` /// Technically, having the same package name specified under multiple fields is invalid /// But we don't want to allocate extra arrays for them. So we use a bitfield instead. -behavior: Behavior = Behavior.uninitialized, +behavior: Behavior = .uninitialized, /// Sorting order for dependencies is: /// 1. [`dependencies`, `devDependencies`, `optionalDependencies`, `peerDependencies`] diff --git a/src/install/extract_tarball.zig b/src/install/extract_tarball.zig index 7ba085297..7563655e1 100644 --- a/src/install/extract_tarball.zig +++ b/src/install/extract_tarball.zig @@ -24,11 +24,11 @@ cache_dir: std.fs.Dir, temp_dir: std.fs.Dir, dependency_id: DependencyID, skip_verify: bool = false, -integrity: Integrity = Integrity{}, +integrity: Integrity = .{}, url: string = "", package_manager: *PackageManager, -pub inline fn run(this: ExtractTarball, task_id: u64, bytes: []const u8) !Install.ExtractData { +pub inline fn run(this: ExtractTarball, bytes: []const u8) !Install.ExtractData { if (!this.skip_verify and this.integrity.tag.isSupported()) { if (!this.integrity.verify(bytes)) { Output.prettyErrorln("<r><red>Integrity check failed<r> for tarball: {s}", .{this.name.slice()}); @@ -36,7 +36,7 @@ pub inline fn run(this: ExtractTarball, task_id: u64, bytes: []const u8) !Instal return error.IntegrityCheckFailed; } } - return this.extract(bytes, task_id); + return this.extract(bytes); } pub fn buildURL( @@ -149,7 +149,7 @@ threadlocal var final_path_buf: [bun.MAX_PATH_BYTES]u8 = undefined; threadlocal var folder_name_buf: [bun.MAX_PATH_BYTES]u8 = undefined; threadlocal var json_path_buf: [bun.MAX_PATH_BYTES]u8 = undefined; -fn extract(this: *const ExtractTarball, tgz_bytes: []const u8, task_id: u64) !Install.ExtractData { +fn extract(this: *const ExtractTarball, tgz_bytes: []const u8) !Install.ExtractData { var tmpdir = this.temp_dir; var tmpname_buf: [256]u8 = undefined; const name = this.name.slice(); @@ -401,6 +401,5 @@ fn extract(this: *const ExtractTarball, tgz_bytes: []const u8, task_id: u64) !In .json_path = ret_json_path, .json_buf = json_buf, .json_len = json_len, - .task_id = task_id, }; } diff --git a/src/install/install.zig b/src/install/install.zig index a411d2098..3034b82f8 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -567,7 +567,6 @@ const Task = struct { }, .extract => { const result = this.request.extract.tarball.run( - this.id, this.request.extract.network.response_buffer.toOwnedSliceLeaky(), ) catch |err| { if (comptime Environment.isDebug) { @@ -633,7 +632,6 @@ pub const ExtractData = struct { json_path: string = "", json_buf: []u8 = "", json_len: usize = 0, - task_id: u64 = 0, }; const PackageInstall = struct { @@ -1410,19 +1408,15 @@ pub const Resolution = @import("./resolution.zig").Resolution; const Progress = std.Progress; const TaggedPointer = @import("../tagged_pointer.zig"); const TaskCallbackContext = union(Tag) { - dependency: PackageID, - request_id: PackageID, - root_dependency: PackageID, + dependency: DependencyID, + root_dependency: DependencyID, root_request_id: PackageID, - node_modules_folder: u32, // Really, this is a file descriptor - root_node_modules_folder: u32, // Really, this is a file descriptor + node_modules_folder: std.os.fd_t, pub const Tag = enum { dependency, - request_id, node_modules_folder, root_dependency, root_request_id, - root_node_modules_folder, }; }; @@ -1474,11 +1468,6 @@ pub const PackageManager = struct { root_package_json_file: std.fs.File, root_dependency_list: Lockfile.DependencySlice = .{}, - /// Used to make "dependencies" optional in the main package - /// Depended on packages have to explicitly list their dependencies - dynamic_root_dependencies: ?std.ArrayList(Dependency.Pair) = null, - // remote_dependencies: RemoteDependency.List = .{}, - thread_pool: ThreadPool, manifests: PackageManifestMap = PackageManifestMap{}, @@ -1530,24 +1519,18 @@ pub const PackageManager = struct { } pub inline fn getonDependencyError(t: @This()) *const fn (ctx: *anyopaque, Dependency, DependencyID, anyerror) void { - return bun.cast(*const fn (ctx: *anyopaque, Dependency, PackageID, anyerror) void, t.handler); + return bun.cast(*const fn (ctx: *anyopaque, Dependency, DependencyID, anyerror) void, t.handler); } }; pub fn failRootResolution(this: *PackageManager, dependency: *const Dependency, dependency_id: DependencyID, err: anyerror) void { - if (this.dynamic_root_dependencies) |*dynamic| { - dynamic.items[dependency_id].failed = err; - if (this.onWake.context) |ctx| { - this.onWake.getonDependencyError()( - ctx, - dependency.*, - dependency_id, - err, - ); - } - } else { - // this means a bug - bun.unreachablePanic("assignRootResolution: dependency_id: {d} out of bounds", .{dependency_id}); + if (this.onWake.context) |ctx| { + this.onWake.getonDependencyError()( + ctx, + dependency.*, + dependency_id, + err, + ); } } @@ -1572,6 +1555,7 @@ pub const PackageManager = struct { not_found: void, failure: anyerror, }; + pub fn enqueueDependencyToRoot( this: *PackageManager, name: []const u8, @@ -1580,23 +1564,21 @@ pub const PackageManager = struct { behavior: Dependency.Behavior, is_main: bool, ) DependencyToEnqueue { - var root_deps = this.dynamicRootDependencies(); - const existing: []const Dependency.Pair = root_deps.items; - var str_buf = this.lockfile.buffers.string_bytes.items; - for (existing) |pair, i| { - if (strings.eqlLong(this.lockfile.str(&pair.dependency.name), name, true)) { - if (pair.dependency.version.eql(version, str_buf, version_buf)) { - if (pair.resolution_id != invalid_package_id) { - return .{ - .resolution = .{ - .resolution = this.lockfile.packages.items(.resolution)[pair.resolution_id], - .package_id = pair.resolution_id, - }, - }; - } - return .{ .pending = @truncate(DependencyID, i) }; - } - } + const str_buf = this.lockfile.buffers.string_bytes.items; + for (this.lockfile.buffers.dependencies.items) |dependency, dependency_id| { + if (!strings.eqlLong(dependency.name.slice(str_buf), name, true)) continue; + if (!dependency.version.eql(version, str_buf, version_buf)) continue; + return switch (this.lockfile.buffers.resolutions.items[dependency_id]) { + invalid_package_id => .{ + .pending = @truncate(DependencyID, dependency_id), + }, + else => |resolution_id| .{ + .resolution = .{ + .resolution = this.lockfile.packages.items(.resolution)[resolution_id], + .package_id = resolution_id, + }, + }, + }; } var builder = this.lockfile.stringBuilder(); @@ -1612,10 +1594,10 @@ pub const PackageManager = struct { const cloned_dependency = dependency.cloneWithDifferentBuffers(name, version_buf, @TypeOf(&builder), &builder) catch unreachable; builder.clamp(); - const index = @truncate(DependencyID, root_deps.items.len); - root_deps.append(.{ - .dependency = cloned_dependency, - }) catch unreachable; + const index = @truncate(DependencyID, this.lockfile.buffers.dependencies.items.len); + this.lockfile.buffers.dependencies.append(this.allocator, cloned_dependency) catch unreachable; + this.lockfile.buffers.resolutions.append(this.allocator, invalid_package_id) catch unreachable; + if (Environment.allow_assert) std.debug.assert(this.lockfile.buffers.dependencies.items.len == this.lockfile.buffers.resolutions.items.len); if (is_main) { this.enqueueDependencyWithMainAndSuccessFn( index, @@ -1625,7 +1607,6 @@ pub const PackageManager = struct { assignRootResolution, failRootResolution, ) catch |err| { - root_deps.items.len = index; return .{ .failure = err }; }; } else { @@ -1637,30 +1618,22 @@ pub const PackageManager = struct { assignRootResolution, failRootResolution, ) catch |err| { - root_deps.items.len = index; return .{ .failure = err }; }; } - if (root_deps.items[index].failed) |fail| { - root_deps.items.len = index; - return .{ .failure = fail }; - } - - const resolution_id = root_deps.items[index].resolution_id; + const resolution_id = this.lockfile.buffers.resolutions.items[index]; // check if we managed to synchronously resolve the dependency - if (resolution_id != invalid_package_id) { - this.drainDependencyList(); - return .{ - .resolution = .{ - .resolution = this.lockfile.packages.items(.resolution)[resolution_id], - .package_id = resolution_id, - }, - }; - } + if (resolution_id == invalid_package_id) return .{ .pending = index }; - return .{ .pending = index }; + this.drainDependencyList(); + return .{ + .resolution = .{ + .resolution = this.lockfile.packages.items(.resolution)[resolution_id], + .package_id = resolution_id, + }, + }; } pub fn globalLinkDir(this: *PackageManager) !std.fs.IterableDir { @@ -2323,21 +2296,11 @@ pub const PackageManager = struct { fn assignRootResolution(this: *PackageManager, dependency_id: DependencyID, package_id: PackageID) void { if (comptime Environment.allow_assert) { + std.debug.assert(dependency_id < this.lockfile.buffers.resolutions.items.len); std.debug.assert(package_id < this.lockfile.packages.len); + std.debug.assert(this.lockfile.buffers.resolutions.items[dependency_id] == invalid_package_id); } - if (this.dynamic_root_dependencies) |*dynamic| { - if (comptime Environment.allow_assert) { - std.debug.assert(dependency_id < dynamic.items.len); - std.debug.assert(dynamic.items[dependency_id].resolution_id == invalid_package_id); - } - dynamic.items[dependency_id].resolution_id = package_id; - } else { - if (comptime Environment.allow_assert) { - std.debug.assert(dependency_id < this.lockfile.buffers.resolutions.items.len); - std.debug.assert(this.lockfile.buffers.resolutions.items[dependency_id] == invalid_package_id); - } - this.lockfile.buffers.resolutions.items[dependency_id] = package_id; - } + this.lockfile.buffers.resolutions.items[dependency_id] = package_id; } fn getOrPutResolvedPackage( @@ -2483,23 +2446,6 @@ pub const PackageManager = struct { return &task.threadpool_task; } - pub fn dynamicRootDependencies(this: *PackageManager) *std.ArrayList(Dependency.Pair) { - if (this.dynamic_root_dependencies == null) { - const root_deps = this.lockfile.rootPackage().?.dependencies.get(this.lockfile.buffers.dependencies.items); - - this.dynamic_root_dependencies = std.ArrayList(Dependency.Pair).initCapacity(this.allocator, root_deps.len) catch unreachable; - this.dynamic_root_dependencies.?.items.len = root_deps.len; - for (root_deps) |dep, i| { - this.dynamic_root_dependencies.?.items[i] = .{ - .dependency = dep, - .resolution_id = invalid_package_id, - }; - } - } - - return &this.dynamic_root_dependencies.?; - } - pub fn writeYarnLock(this: *PackageManager) !void { var printer = Lockfile.Printer{ .lockfile = this.lockfile, @@ -2544,10 +2490,6 @@ pub const PackageManager = struct { } pub fn isRootDependency(this: *const PackageManager, id: DependencyID) bool { - if (this.dynamic_root_dependencies != null) { - return false; - } - return this.root_dependency_list.contains(id); } @@ -3007,9 +2949,8 @@ pub const PackageManager = struct { }, .root_dependency => |dependency_id| { - const pair = this.dynamicRootDependencies().items[dependency_id]; - const dependency = pair.dependency; - const resolution = pair.resolution_id; + const dependency = this.lockfile.buffers.dependencies.items[dependency_id]; + const resolution = this.lockfile.buffers.resolutions.items[dependency_id]; try this.enqueueDependencyWithMainAndSuccessFn( dependency_id, @@ -3021,8 +2962,8 @@ pub const PackageManager = struct { ); if (any_root) |ptr| { - const new_resolution_id = this.dynamicRootDependencies().items[dependency_id].resolution_id; - if (new_resolution_id != pair.resolution_id) { + const new_resolution_id = this.lockfile.buffers.resolutions.items[dependency_id]; + if (new_resolution_id != resolution) { ptr.* = true; } } @@ -3182,15 +3123,6 @@ pub const PackageManager = struct { const err = task.http.err orelse error.HTTPError; if (@TypeOf(callbacks.onPackageManifestError) != void) { - if (manager.dynamic_root_dependencies) |*root_deps| { - var deps: []Dependency.Pair = root_deps.items; - for (deps) |*dep| { - if (strings.eqlLong(manager.lockfile.str(&dep.dependency.name), name.slice(), true)) { - dep.failed = dep.failed orelse err; - } - } - } - callbacks.onPackageManifestError( extract_ctx, name.slice(), @@ -3226,15 +3158,6 @@ pub const PackageManager = struct { else => error.PackageManifestHTTP5xx, }; - if (manager.dynamic_root_dependencies) |*root_deps| { - var deps: []Dependency.Pair = root_deps.items; - for (deps) |*dep| { - if (strings.eql(manager.lockfile.str(&dep.dependency.name), name.slice())) { - dep.failed = dep.failed orelse err; - } - } - } - callbacks.onPackageManifestError( extract_ctx, name.slice(), @@ -3363,13 +3286,6 @@ pub const PackageManager = struct { const package_id = manager.lockfile.buffers.resolutions.items[extract.dependency_id]; if (@TypeOf(callbacks.onPackageDownloadError) != void) { - if (manager.dynamic_root_dependencies) |*root_deps| { - for (root_deps.items) |*dep| { - if (dep.resolution_id == package_id) { - dep.failed = err; - } - } - } callbacks.onPackageDownloadError( extract_ctx, package_id, @@ -3409,14 +3325,6 @@ pub const PackageManager = struct { }; const package_id = manager.lockfile.buffers.resolutions.items[extract.dependency_id]; - if (manager.dynamic_root_dependencies) |*root_deps| { - for (root_deps.items) |*dep| { - if (dep.resolution_id == package_id) { - dep.failed = err; - } - } - } - callbacks.onPackageDownloadError( extract_ctx, package_id, @@ -3486,15 +3394,6 @@ pub const PackageManager = struct { const err = task.err orelse error.Failed; if (@TypeOf(callbacks.onPackageManifestError) != void) { - if (manager.dynamic_root_dependencies) |*root_deps| { - var deps: []Dependency.Pair = root_deps.items; - for (deps) |*dep| { - if (strings.eql(manager.lockfile.str(&dep.dependency.name), name.slice())) { - dep.failed = dep.failed orelse err; - } - } - } - callbacks.onPackageManifestError( extract_ctx, name.slice(), @@ -3544,15 +3443,6 @@ pub const PackageManager = struct { if (task.status == .fail) { const err = task.err orelse error.TarballFailedToExtract; if (@TypeOf(callbacks.onPackageDownloadError) != void) { - if (manager.dynamic_root_dependencies) |*root_deps| { - var deps: []Dependency.Pair = root_deps.items; - for (deps) |*dep| { - if (dep.resolution_id == package_id) { - dep.failed = dep.failed orelse err; - } - } - } - callbacks.onPackageDownloadError( extract_ctx, package_id, @@ -3613,7 +3503,7 @@ pub const PackageManager = struct { needs_flush = true; }, .root_dependency => |id| { - manager.dynamicRootDependencies().items[id].dependency.version.value.github.package_name = name; + manager.lockfile.buffers.dependencies.items[id].version.value.github.package_name = name; try manager.processDependencyListItem(dep, &any_root); needs_flush = true; }, @@ -5871,8 +5761,7 @@ pub const PackageManager = struct { const prev_node_modules_folder = this.node_modules_folder; defer this.node_modules_folder = prev_node_modules_folder; for (callbacks.items) |cb| { - const node_modules_folder = cb.node_modules_folder; - this.node_modules_folder = .{ .dir = .{ .fd = @intCast(bun.FileDescriptor, node_modules_folder) } }; + this.node_modules_folder = .{ .dir = .{ .fd = cb.node_modules_folder } }; this.installPackageWithNameAndResolution(dependency_id, package_id, log_level, name, resolution); } } @@ -6086,9 +5975,7 @@ pub const PackageManager = struct { dependency_id, package_id, &resolution.value.github, - .{ - .node_modules_folder = @intCast(u32, this.node_modules_folder.dir.fd), - }, + .{ .node_modules_folder = this.node_modules_folder.dir.fd }, ); }, .npm => { @@ -6099,9 +5986,7 @@ pub const PackageManager = struct { package_id, resolution.value.npm.version, resolution.value.npm.url.slice(buf), - .{ - .node_modules_folder = @intCast(u32, this.node_modules_folder.dir.fd), - }, + .{ .node_modules_folder = this.node_modules_folder.dir.fd }, ); }, else => { diff --git a/src/install/lockfile.zig b/src/install/lockfile.zig index e96a7be80..cb4326699 100644 --- a/src/install/lockfile.zig +++ b/src/install/lockfile.zig @@ -2701,7 +2701,7 @@ pub const Package = extern struct { try lockfile.buffers.resolutions.ensureUnusedCapacity(lockfile.allocator, total_dependencies_count); const total_len = lockfile.buffers.dependencies.items.len + total_dependencies_count; - std.debug.assert(lockfile.buffers.dependencies.items.len == lockfile.buffers.resolutions.items.len); + if (Environment.allow_assert) std.debug.assert(lockfile.buffers.dependencies.items.len == lockfile.buffers.resolutions.items.len); const off = lockfile.buffers.dependencies.items.len; var package_dependencies = lockfile.buffers.dependencies.items.ptr[off..total_len]; diff --git a/src/resolver/package_json.zig b/src/resolver/package_json.zig index ec7c94816..fb0c91b86 100644 --- a/src/resolver/package_json.zig +++ b/src/resolver/package_json.zig @@ -1277,7 +1277,7 @@ pub const ESModule = struct { return .{ .name = this.name, .subpath = this.subpath, - .version = ">=0.0.0", + .version = "latest", }; } diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index b2be261d5..3331e8b06 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -1979,7 +1979,6 @@ pub const Resolver = struct { .pending = .{ .esm = cloned, .dependency = version, - .resolution_id = Install.invalid_package_id, .root_dependency_id = id, .string_buf = builder.allocatedSlice(), .tag = .resolve, diff --git a/test/bun.js/install/bunx.test.ts b/test/bun.js/install/bunx.test.ts index b754ca0c6..08ec3fc50 100644 --- a/test/bun.js/install/bunx.test.ts +++ b/test/bun.js/install/bunx.test.ts @@ -3,9 +3,10 @@ import { afterEach, beforeEach, expect, it } from "bun:test"; import { bunExe } from "bunExe"; import { bunEnv as env } from "bunEnv"; import { realpathSync } from "fs"; -import { mkdtemp, rm } from "fs/promises"; +import { mkdtemp, rm, writeFile } from "fs/promises"; import { tmpdir } from "os"; import { join } from "path"; +import { readdirSorted } from "./dummy.registry"; let x_dir; @@ -51,3 +52,33 @@ it("should install and run specified version", async () => { expect(out.split(/\r?\n/)).toEqual(["uglify-js 3.14.1", ""]); expect(await exited).toBe(0); }); + +it("should download dependencies to run local file", async () => { + await writeFile( + join(x_dir, "test.js"), + ` +import { minify } from "uglify-js"; + +console.log(minify("print(6 * 7)").code); +`, + ); + const { stdout, stderr, exited } = spawn({ + cmd: [bunExe(), "test.js"], + cwd: x_dir, + stdout: null, + stdin: "pipe", + stderr: "pipe", + env: { + ...env, + BUN_INSTALL_CACHE_DIR: join(x_dir, ".cache"), + }, + }); + expect(stderr).toBeDefined(); + const err = await new Response(stderr).text(); + expect(err).toBe(""); + expect(stdout).toBeDefined(); + const out = await new Response(stdout).text(); + expect(out.split(/\r?\n/)).toEqual(["print(42);", ""]); + expect(await exited).toBe(0); + expect(await readdirSorted(x_dir)).toEqual([".cache", "test.js"]); +}); |