Compare commits

...

8 Commits

Author SHA1 Message Date
Jarred Sumner
394701e3dc Update bundle_v2.zig 2024-11-30 07:15:20 -08:00
Jarred Sumner
73efb97de9 Ensure we always drain the dependency list 2024-11-30 06:42:17 -08:00
Jarred Sumner
7d76db8752 Split these into separate functions 2024-11-30 05:05:31 -08:00
Jarred Sumner
2d7b163b3c Update PipeReader.zig 2024-11-30 05:04:08 -08:00
Jarred Sumner
def017a4b4 Fix auto install 2024-11-30 04:09:33 -08:00
Jarred Sumner
25c321031c More 2024-11-30 01:28:03 -08:00
Jarred Sumner
6904d7d526 Introduce bun build --install ./path-to-file.ts 2024-11-30 00:18:52 -08:00
Jarred Sumner
daefcd310d Configure auto install 2024-11-30 00:18:24 -08:00
16 changed files with 1023 additions and 504 deletions

View File

@@ -47,14 +47,7 @@ pub fn buildCommand(ctx: bun.CLI.Command.Context) !void {
vm.argv = ctx.passthrough;
vm.arena = &arena;
vm.allocator = arena.allocator();
b.options.install = ctx.install;
b.resolver.opts.install = ctx.install;
b.resolver.opts.global_cache = ctx.debug.global_cache;
b.resolver.opts.prefer_offline_install = (ctx.debug.offline_mode_setting orelse .online) == .offline;
b.resolver.opts.prefer_latest_install = (ctx.debug.offline_mode_setting orelse .online) == .latest;
b.options.global_cache = b.resolver.opts.global_cache;
b.options.prefer_offline_install = b.resolver.opts.prefer_offline_install;
b.options.prefer_latest_install = b.resolver.opts.prefer_latest_install;
b.configureAutoInstall(ctx.install, &ctx.debug);
b.resolver.env_loader = b.env;
b.options.minify_identifiers = ctx.bundler_options.minify_identifiers;
b.options.minify_whitespace = ctx.bundler_options.minify_whitespace;

View File

@@ -2126,6 +2126,24 @@ pub const EventLoopHandle = union(enum) {
js: *JSC.EventLoop,
mini: *MiniEventLoop,
pub fn tick(
this: EventLoopHandle,
context: anytype,
comptime isDone: *const fn (@TypeOf(context)) bool,
) void {
switch (this) {
.js => |js_loop| {
while (!isDone(context)) {
js_loop.tick();
js_loop.autoTick();
}
},
.mini => |mini| {
mini.tick(context, @ptrCast(isDone));
},
}
}
pub fn globalObject(this: EventLoopHandle) ?*JSC.JSGlobalObject {
return switch (this) {
.js => this.js.global,
@@ -2266,6 +2284,28 @@ pub const EventLoopHandle = union(enum) {
.mini => this.mini.env.?,
};
}
pub fn wakeup(this: EventLoopHandle) void {
switch (this) {
.js => this.js.wakeup(),
.mini => this.mini.loop.wakeup(),
}
}
pub fn tickOnce(
this: EventLoopHandle,
context: anytype,
) void {
switch (this) {
.js => |js_loop| {
js_loop.tick();
js_loop.autoTickActive();
},
.mini => |mini| {
mini.tickWithoutIdle(context);
},
}
}
};
pub const EventLoopTask = union {

View File

@@ -812,7 +812,7 @@ pub const ModuleLoader = struct {
this.vm().packageManager().drainDependencyList();
}
pub fn onDependencyError(ctx: *anyopaque, dependency: Dependency, root_dependency_id: Install.DependencyID, err: anyerror) void {
pub fn onDependencyError(ctx: *anyopaque, dependency: *const 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)});
@@ -1016,7 +1016,7 @@ pub const ModuleLoader = struct {
continue;
}
const package = pm.lockfile.packages.get(package_id);
const package = &pm.lockfile.packages.get(package_id);
bun.assert(package.resolution.tag != .root);
var name_and_version_hash: ?u64 = null;

View File

@@ -77,14 +77,7 @@ pub const Run = struct {
vm.arena = &run.arena;
vm.allocator = arena.allocator();
b.options.install = ctx.install;
b.resolver.opts.install = ctx.install;
b.resolver.opts.global_cache = ctx.debug.global_cache;
b.resolver.opts.prefer_offline_install = (ctx.debug.offline_mode_setting orelse .online) == .offline;
b.resolver.opts.prefer_latest_install = (ctx.debug.offline_mode_setting orelse .online) == .latest;
b.options.global_cache = b.resolver.opts.global_cache;
b.options.prefer_offline_install = b.resolver.opts.prefer_offline_install;
b.options.prefer_latest_install = b.resolver.opts.prefer_latest_install;
b.configureAutoInstall(ctx.install, &ctx.debug);
b.resolver.env_loader = b.env;
b.options.minify_identifiers = ctx.bundler_options.minify_identifiers;
@@ -222,14 +215,7 @@ pub const Run = struct {
}
}
b.options.install = ctx.install;
b.resolver.opts.install = ctx.install;
b.resolver.opts.global_cache = ctx.debug.global_cache;
b.resolver.opts.prefer_offline_install = (ctx.debug.offline_mode_setting orelse .online) == .offline;
b.resolver.opts.prefer_latest_install = (ctx.debug.offline_mode_setting orelse .online) == .latest;
b.options.global_cache = b.resolver.opts.global_cache;
b.options.prefer_offline_install = b.resolver.opts.prefer_offline_install;
b.options.prefer_latest_install = b.resolver.opts.prefer_latest_install;
b.configureAutoInstall(ctx.install, &ctx.debug);
b.resolver.env_loader = b.env;
b.options.minify_identifiers = ctx.bundler_options.minify_identifiers;

View File

@@ -395,6 +395,17 @@ pub const Bundler = struct {
this.resolver.allocator = allocator;
}
pub fn configureAutoInstall(this: *Bundler, install: ?*Api.BunInstall, debug: *const DebugOptions) void {
this.options.install = install;
this.resolver.opts.install = install;
this.resolver.opts.global_cache = debug.global_cache;
this.resolver.opts.prefer_offline_install = (debug.offline_mode_setting orelse .online) == .offline;
this.resolver.opts.prefer_latest_install = (debug.offline_mode_setting orelse .online) == .latest;
this.options.global_cache = this.resolver.opts.global_cache;
this.options.prefer_offline_install = this.resolver.opts.prefer_offline_install;
this.options.prefer_latest_install = this.resolver.opts.prefer_latest_install;
}
fn _resolveEntryPoint(bundler: *Bundler, entry_point: string) !_resolver.Result {
return bundler.resolver.resolveWithFramework(bundler.fs.top_level_dir, entry_point, .entry_point) catch |err| {
// Relative entry points that were not resolved to a node_modules package are

File diff suppressed because it is too large Load Diff

View File

@@ -284,6 +284,9 @@ pub const Arguments = struct {
clap.parseParam("--minify-identifiers Minify identifiers") catch unreachable,
clap.parseParam("--experimental-css Enabled experimental CSS bundling") catch unreachable,
clap.parseParam("--experimental-css-chunking Chunk CSS files together to reduce duplicated CSS loaded in a browser. Only has an affect when multiple entrypoints import CSS") catch unreachable,
clap.parseParam("--no-install Disable auto install in the Bun runtime") catch unreachable,
clap.parseParam("--auto-install <STR>? Configure auto-install behavior. One of \"auto\" (auto-installs when no node_modules), \"fallback\" (missing packages only), \"force\" (always), \"disable\" (default, no auto-installs).") catch unreachable,
clap.parseParam("-i Auto-install dependencies during execution. Equivalent to --install=fallback.") catch unreachable,
clap.parseParam("--dump-environment-variables") catch unreachable,
clap.parseParam("--conditions <STR>... Pass custom conditions to resolve") catch unreachable,
clap.parseParam("--app (EXPERIMENTAL) Build a web app for production using Bun Bake.") catch unreachable,
@@ -291,6 +294,7 @@ pub const Arguments = struct {
} ++ if (FeatureFlags.bake_debugging_features) [_]ParamType{
clap.parseParam("--debug-dump-server-files When --app is set, dump all server files to disk even when building statically") catch unreachable,
} else .{};
pub const build_params = build_only_params ++ transpiler_params_ ++ base_params_;
// TODO: update test completions
@@ -784,7 +788,7 @@ pub const Arguments = struct {
ctx.bundler_options.ignore_dce_annotations = args.flag("--ignore-dce-annotations");
if (cmd == .BuildCommand) {
if (comptime cmd == .BuildCommand) {
ctx.bundler_options.transform_only = args.flag("--no-bundle");
ctx.bundler_options.bytecode = args.flag("--bytecode");
@@ -829,6 +833,23 @@ pub const Arguments = struct {
ctx.bundler_options.emit_dce_annotations = args.flag("--emit-dce-annotations") or
!ctx.bundler_options.minify_whitespace;
if (args.flag("-i")) {
ctx.debug.global_cache = .fallback;
} else if (args.option("--auto-install")) |enum_value| {
// -i=auto --auto-install=force, --auto-install=disable
if (options.GlobalCache.Map.get(enum_value)) |result| {
ctx.debug.global_cache = result;
// -i, --auto-install
} else if (enum_value.len == 0) {
ctx.debug.global_cache = options.GlobalCache.force;
} else {
Output.errGeneric("Invalid value for --auto-install: \"{s}\". Must be either \"auto\", \"fallback\", \"force\", or \"disable\"\n", .{enum_value});
Global.exit(1);
}
} else {
ctx.debug.global_cache = .disable;
}
if (args.options("--external").len > 0) {
var externals = try allocator.alloc([]const u8, args.options("--external").len);
for (args.options("--external"), 0..) |external, i| {

View File

@@ -271,6 +271,8 @@ pub const BuildCommand = struct {
var minify_duration: u64 = 0;
var input_code_length: u64 = 0;
this_bundler.configureAutoInstall(ctx.install, &ctx.debug);
const output_files: []options.OutputFile = brk: {
if (ctx.bundler_options.transform_only) {
this_bundler.options.import_path_format = .relative;

View File

@@ -2730,7 +2730,7 @@ pub const PackageManager = struct {
// name hash from alias package name -> aliased package dependency version info
known_npm_aliases: NpmAliasMap = .{},
event_loop: JSC.AnyEventLoop,
event_loop: JSC.EventLoopHandle,
// During `installPackages` we learn exactly what dependencies from --trust
// actually have scripts to run, and we add them to this list
@@ -3082,8 +3082,8 @@ pub const PackageManager = struct {
return bun.cast(*const fn (ctx: *anyopaque, pm: *PackageManager) void, t.handler);
}
pub inline fn getonDependencyError(t: @This()) *const fn (ctx: *anyopaque, Dependency, DependencyID, anyerror) void {
return bun.cast(*const fn (ctx: *anyopaque, Dependency, DependencyID, anyerror) void, t.handler);
pub inline fn getonDependencyError(t: @This()) *const fn (ctx: *anyopaque, *const Dependency, DependencyID, anyerror) void {
return bun.cast(*const fn (ctx: *anyopaque, *const Dependency, DependencyID, anyerror) void, t.handler);
}
};
@@ -3091,7 +3091,7 @@ pub const PackageManager = struct {
if (this.onWake.context) |ctx| {
this.onWake.getonDependencyError()(
ctx,
dependency.*,
dependency,
dependency_id,
err,
);
@@ -3139,12 +3139,12 @@ pub const PackageManager = struct {
version_buf: []const u8,
behavior: Dependency.Behavior,
) DependencyToEnqueue {
const dep_id = @as(DependencyID, @truncate(brk: {
const dep_id: u32, const is_newly_added = brk: {
const str_buf = this.lockfile.buffers.string_bytes.items;
for (this.lockfile.buffers.dependencies.items, 0..) |dep, id| {
if (!strings.eqlLong(dep.name.slice(str_buf), name, true)) continue;
if (!dep.version.eql(version, str_buf, version_buf)) continue;
break :brk id;
break :brk .{ @truncate(id), true };
}
var builder = this.lockfile.stringBuilder();
@@ -3164,100 +3164,50 @@ pub const PackageManager = struct {
this.lockfile.buffers.dependencies.append(this.allocator, dep) catch unreachable;
this.lockfile.buffers.resolutions.append(this.allocator, invalid_package_id) catch unreachable;
if (comptime Environment.allow_assert) bun.assert(this.lockfile.buffers.dependencies.items.len == this.lockfile.buffers.resolutions.items.len);
break :brk index;
}));
break :brk .{ @truncate(index), false };
};
_ = is_newly_added; // autofix
if (this.lockfile.buffers.resolutions.items[dep_id] == invalid_package_id) {
const initial_pending_task_count = this.pendingTaskCount();
_ = initial_pending_task_count; // autofix
var resolution_id = this.lockfile.buffers.resolutions.items[dep_id];
if (resolution_id == invalid_package_id) {
this.enqueueDependencyWithMainAndSuccessFn(
dep_id,
&this.lockfile.buffers.dependencies.items[dep_id],
invalid_package_id,
resolution_id,
false,
assignRootResolution,
failRootResolution,
) catch |err| {
return .{ .failure = err };
};
// We might immediately resolve it.
resolution_id = this.lockfile.buffers.resolutions.items[dep_id];
}
const resolution_id = switch (this.lockfile.buffers.resolutions.items[dep_id]) {
invalid_package_id => brk: {
this.drainDependencyList();
this.drainDependencyList();
switch (this.options.log_level) {
inline else => |log_levela| {
const Closure = struct {
// https://github.com/ziglang/zig/issues/19586
pub fn issue_19586_workaround(comptime log_level: Options.LogLevel) type {
return struct {
err: ?anyerror = null,
manager: *PackageManager,
pub fn isDone(closure: *@This()) bool {
const manager = closure.manager;
if (manager.pendingTaskCount() > 0) {
manager.runTasks(
void,
{},
.{
.onExtract = {},
.onResolve = {},
.onPackageManifestError = {},
.onPackageDownloadError = {},
},
false,
log_level,
) catch |err| {
closure.err = err;
return true;
};
if (PackageManager.verbose_install and manager.pendingTaskCount() > 0) {
if (PackageManager.hasEnoughTimePassedBetweenWaitingMessages()) Output.prettyErrorln("<d>[PackageManager]<r> waiting for {d} tasks\n", .{closure.manager.pendingTaskCount()});
}
}
return manager.pendingTaskCount() == 0;
}
};
}
}.issue_19586_workaround(log_levela);
if (comptime log_levela.showProgress()) {
this.startProgressBarIfNone();
}
var closure = Closure{ .manager = this };
this.sleepUntil(&closure, &Closure.isDone);
if (comptime log_levela.showProgress()) {
this.endProgressBar();
Output.flush();
}
if (closure.err) |err| {
return .{ .failure = err };
}
},
}
break :brk this.lockfile.buffers.resolutions.items[dep_id];
},
// we managed to synchronously resolve the dependency
else => |pkg_id| pkg_id,
};
if (resolution_id == invalid_package_id) {
return .{
.not_found = {},
};
var out_name_and_version_hash: ?u64 = null;
var out_patchfile_hash: ?u64 = null;
if (resolution_id != invalid_package_id) {
switch (this.determinePreinstallStateAndPossiblyDownloadPackageIntoCache(&this.lockfile.packages.get(resolution_id), dep_id, this.lockfile, &out_name_and_version_hash, &out_patchfile_hash)) {
.extract, .extracting => {
return .{ .pending = dep_id };
},
else => {
return .{
.resolution = .{
.resolution = this.lockfile.packages.items(.resolution)[resolution_id],
.package_id = resolution_id,
},
};
},
}
}
return .{
.resolution = .{
.resolution = this.lockfile.packages.items(.resolution)[resolution_id],
.package_id = resolution_id,
},
};
return .{ .pending = dep_id };
}
pub fn globalLinkDir(this: *PackageManager) !std.fs.Dir {
@@ -3336,7 +3286,7 @@ pub const PackageManager = struct {
pub fn determinePreinstallState(
manager: *PackageManager,
this: Package,
this: *const Package,
lockfile: *Lockfile,
out_name_and_version_hash: *?u64,
out_patchfile_hash: *?u64,
@@ -3421,6 +3371,94 @@ pub const PackageManager = struct {
}
}
pub fn determinePreinstallStateAndPossiblyDownloadPackageIntoCache(
manager: *PackageManager,
this: *const Package,
dependency_id: DependencyID,
lockfile: *Lockfile,
out_name_and_version_hash: *?u64,
out_patchfile_hash: *?u64,
) PreinstallState {
switch (manager.getPreinstallState(this.meta.id)) {
.unknown => switch (manager.determinePreinstallState(this, lockfile, out_name_and_version_hash, out_patchfile_hash)) {
.extract => {
if (this.resolution.tag.canEnqueueInstallTask()) {
switch (this.resolution.tag) {
.git => {
manager.enqueueGitForCheckout(
dependency_id,
"",
&this.resolution,
.{ .root_dependency = dependency_id },
out_name_and_version_hash.*,
);
},
.github => {
const url = manager.allocGitHubURL(&this.resolution.value.github);
defer manager.allocator.free(url);
manager.enqueueTarballForDownload(
dependency_id,
this.meta.id,
url,
.{ .root_dependency = dependency_id },
out_name_and_version_hash.*,
);
},
.local_tarball => {
manager.enqueueTarballForReading(
dependency_id,
"",
&this.resolution,
.{ .root_dependency = dependency_id },
);
},
.remote_tarball => {
manager.enqueueTarballForDownload(
dependency_id,
this.meta.id,
manager.lockfile.str(&this.resolution.value.remote_tarball),
.{ .root_dependency = dependency_id },
out_name_and_version_hash.*,
);
},
.npm => {
if (comptime Environment.isDebug) {
// Very old versions of Bun didn't store the tarball url when it didn't seem necessary
// This caused bugs. We can't assert on it because they could come from old lockfiles
if (this.resolution.value.npm.url.isEmpty()) {
Output.debugWarn("package {s}@{} missing tarball_url", .{ manager.lockfile.str(&this.name), this.resolution.fmt(manager.lockfile.buffers.string_bytes.items, .posix) });
}
}
manager.enqueuePackageForDownload(
manager.lockfile.str(&this.name),
dependency_id,
this.meta.id,
this.resolution.value.npm.version,
manager.lockfile.str(&this.resolution.value.npm.url),
.{ .root_dependency = dependency_id },
out_name_and_version_hash.*,
);
},
else => {
if (comptime Environment.allow_assert) {
@panic("unreachable, handled above");
}
},
}
manager.setPreinstallState(this.meta.id, lockfile, .extracting);
return .extracting;
}
return .extract;
},
else => |val| return val,
},
else => |val| return val,
}
}
pub fn scopeForPackageName(this: *const PackageManager, name: string) *const Npm.Registry.Scope {
if (name.len == 0 or name[0] != '@') return &this.options.scope;
return this.options.registries.getPtr(
@@ -3975,6 +4013,7 @@ pub const PackageManager = struct {
return this.pathForCachedNPMPath(buf, package_name, npm.version);
},
else => return "",
}
}
@@ -4262,7 +4301,7 @@ pub const PackageManager = struct {
var patchfile_hash: ?u64 = null;
return switch (this.determinePreinstallState(
package,
&package,
this.lockfile,
&name_and_version_hash,
&patchfile_hash,
@@ -4571,33 +4610,14 @@ pub const PackageManager = struct {
switch (version.tag) {
.npm, .dist_tag => {
resolve_from_workspace: {
if (version.tag == .npm) {
const workspace_path = if (this.lockfile.workspace_paths.count() > 0) this.lockfile.workspace_paths.get(name_hash) else null;
const workspace_version = this.lockfile.workspace_versions.get(name_hash);
const buf = this.lockfile.buffers.string_bytes.items;
if ((workspace_version != null and version.value.npm.version.satisfies(workspace_version.?, buf, buf)) or
// https://github.com/oven-sh/bun/pull/10899#issuecomment-2099609419
// if the workspace doesn't have a version, it can still be used if
// dependency version is wildcard
(workspace_path != null and version.value.npm.version.@"is *"()))
{
const root_package = this.lockfile.rootPackage() orelse break :resolve_from_workspace;
const root_dependencies = root_package.dependencies.get(this.lockfile.buffers.dependencies.items);
const root_resolutions = root_package.resolutions.get(this.lockfile.buffers.resolutions.items);
for (root_dependencies, root_resolutions) |root_dep, workspace_package_id| {
if (workspace_package_id != invalid_package_id and root_dep.version.tag == .workspace and root_dep.name_hash == name_hash) {
// make sure verifyResolutions sees this resolution as a valid package id
successFn(this, dependency_id, workspace_package_id);
return .{
.package = this.lockfile.packages.get(workspace_package_id),
.is_first_time = false,
};
}
}
}
if (version.tag == .npm) {
if (this.lockfile.resolveWorkspaceFromNpmVersion(name_hash, &version)) |workspace_package_id| {
// make sure verifyResolutions sees this resolution as a valid package id
successFn(this, dependency_id, workspace_package_id);
return .{
.package = this.lockfile.packages.get(workspace_package_id),
.is_first_time = false,
};
}
}
@@ -4614,26 +4634,14 @@ pub const PackageManager = struct {
.npm => manifest.findBestVersion(version.value.npm.version, this.lockfile.buffers.string_bytes.items),
else => unreachable,
} orelse {
resolve_workspace_from_dist_tag: {
// choose a workspace for a dist_tag only if a version was not found
if (version.tag == .dist_tag) {
const workspace_path = if (this.lockfile.workspace_paths.count() > 0) this.lockfile.workspace_paths.get(name_hash) else null;
if (workspace_path != null) {
const root_package = this.lockfile.rootPackage() orelse break :resolve_workspace_from_dist_tag;
const root_dependencies = root_package.dependencies.get(this.lockfile.buffers.dependencies.items);
const root_resolutions = root_package.resolutions.get(this.lockfile.buffers.resolutions.items);
for (root_dependencies, root_resolutions) |root_dep, workspace_package_id| {
if (workspace_package_id != invalid_package_id and root_dep.version.tag == .workspace and root_dep.name_hash == name_hash) {
// make sure verifyResolutions sees this resolution as a valid package id
successFn(this, dependency_id, workspace_package_id);
return .{
.package = this.lockfile.packages.get(workspace_package_id),
.is_first_time = false,
};
}
}
}
// choose a workspace for a dist_tag only if a version was not found
if (version.tag == .dist_tag) {
if (this.lockfile.resolveWorkspaceFromNpmDistTag(name_hash)) |workspace_package_id| {
return .{
.package = this.lockfile.packages.get(workspace_package_id),
.is_first_time = false,
};
}
}
@@ -6208,6 +6216,24 @@ pub const PackageManager = struct {
var timestamp_this_tick: ?u32 = null;
defer {
manager.drainDependencyList();
if (comptime log_level.showProgress()) {
manager.startProgressBarIfNone();
if (@hasField(@TypeOf(callbacks), "progress_bar") and callbacks.progress_bar == true) {
const completed_items = manager.total_tasks - manager.pendingTaskCount();
if (completed_items != manager.downloads_node.?.unprotected_completed_items or has_updated_this_run) {
manager.downloads_node.?.setCompletedItems(completed_items);
manager.downloads_node.?.setEstimatedTotalItems(manager.total_tasks);
}
}
manager.downloads_node.?.activate();
manager.progress.maybeRefresh();
}
}
var patch_tasks_batch = manager.patch_task_queue.popBatch();
var patch_tasks_iter = patch_tasks_batch.iterator();
while (patch_tasks_iter.next()) |ptask| {
@@ -6259,6 +6285,7 @@ pub const PackageManager = struct {
const name = manifest_req.name;
if (comptime log_level.showProgress()) {
if (!has_updated_this_run) {
manager.startProgressBarIfNone();
manager.setNodeName(manager.downloads_node.?, name.slice(), ProgressStrings.download_emoji, true);
has_updated_this_run = true;
}
@@ -6606,6 +6633,7 @@ pub const PackageManager = struct {
if (comptime log_level.showProgress()) {
if (!has_updated_this_run) {
manager.startProgressBarIfNone();
manager.setNodeName(manager.downloads_node.?, extract.name.slice(), ProgressStrings.extract_emoji, true);
has_updated_this_run = true;
}
@@ -6673,6 +6701,7 @@ pub const PackageManager = struct {
if (comptime log_level.showProgress()) {
if (!has_updated_this_run) {
manager.startProgressBarIfNone();
manager.setNodeName(manager.downloads_node.?, manifest.name(), ProgressStrings.download_emoji, true);
has_updated_this_run = true;
}
@@ -6800,6 +6829,7 @@ pub const PackageManager = struct {
if (comptime log_level.showProgress()) {
if (!has_updated_this_run) {
manager.startProgressBarIfNone();
manager.setNodeName(manager.downloads_node.?, alias, ProgressStrings.extract_emoji, true);
has_updated_this_run = true;
}
@@ -6845,6 +6875,7 @@ pub const PackageManager = struct {
if (comptime log_level.showProgress()) {
if (!has_updated_this_run) {
manager.startProgressBarIfNone();
manager.setNodeName(manager.downloads_node.?, name, ProgressStrings.download_emoji, true);
has_updated_this_run = true;
}
@@ -6924,6 +6955,7 @@ pub const PackageManager = struct {
if (comptime log_level.showProgress()) {
if (!has_updated_this_run) {
manager.startProgressBarIfNone();
manager.setNodeName(manager.downloads_node.?, alias.slice(), ProgressStrings.download_emoji, true);
has_updated_this_run = true;
}
@@ -6931,20 +6963,6 @@ pub const PackageManager = struct {
},
}
}
manager.drainDependencyList();
if (comptime log_level.showProgress()) {
if (@hasField(@TypeOf(callbacks), "progress_bar") and callbacks.progress_bar == true) {
const completed_items = manager.total_tasks - manager.pendingTaskCount();
if (completed_items != manager.downloads_node.?.unprotected_completed_items or has_updated_this_run) {
manager.downloads_node.?.setCompletedItems(completed_items);
manager.downloads_node.?.setEstimatedTotalItems(manager.total_tasks);
}
}
manager.downloads_node.?.activate();
manager.progress.maybeRefresh();
}
}
pub const Options = struct {
@@ -8736,16 +8754,16 @@ pub const PackageManager = struct {
.root_package_json_file = root_package_json_file,
// .progress
.event_loop = .{
.mini = JSC.MiniEventLoop.init(bun.default_allocator),
.mini = bun.create(bun.default_allocator, JSC.MiniEventLoop, JSC.MiniEventLoop.init(bun.default_allocator)),
},
.original_package_json_path = original_package_json_path,
.workspace_package_json_cache = workspace_package_json_cache,
.workspace_name_hash = workspace_name_hash,
.subcommand = subcommand,
};
manager.event_loop.loop().internal_loop_data.setParentEventLoop(bun.JSC.EventLoopHandle.init(&manager.event_loop));
manager.event_loop.loop().internal_loop_data.setParentEventLoop(manager.event_loop);
manager.lockfile = try ctx.allocator.create(Lockfile);
JSC.MiniEventLoop.global = &manager.event_loop.mini;
JSC.MiniEventLoop.global = manager.event_loop.mini;
if (!manager.options.enable.cache) {
manager.options.enable.manifest_cache = false;
manager.options.enable.manifest_cache_control = false;
@@ -8840,7 +8858,10 @@ pub const PackageManager = struct {
cli: CommandLineArguments,
env: *DotEnv.Loader,
) *PackageManager {
init_with_runtime_once.call(.{
init_with_event_loop_once.call(.{
.{
.js = JSC.VirtualMachine.get().eventLoop(),
},
log,
bun_install,
allocator,
@@ -8850,9 +8871,22 @@ pub const PackageManager = struct {
return PackageManager.get();
}
var init_with_runtime_once = bun.once(initWithRuntimeOnce);
var init_with_event_loop_once = bun.once(initWithEventLoopOnce);
pub fn initWithRuntimeOnce(
pub fn initWithEventLoop(
loop: JSC.EventLoopHandle,
log: *logger.Log,
bun_install: ?*Api.BunInstall,
allocator: std.mem.Allocator,
cli: CommandLineArguments,
env: *DotEnv.Loader,
) *PackageManager {
init_with_event_loop_once.call(.{ loop, log, bun_install, allocator, cli, env });
return PackageManager.get();
}
fn initWithEventLoopOnce(
loop: JSC.EventLoopHandle,
log: *logger.Log,
bun_install: ?*Api.BunInstall,
allocator: std.mem.Allocator,
@@ -8898,9 +8932,7 @@ pub const PackageManager = struct {
}),
.lockfile = undefined,
.root_package_json_file = undefined,
.event_loop = .{
.js = JSC.VirtualMachine.get().eventLoop(),
},
.event_loop = loop,
.original_package_json_path = original_package_json_path[0..original_package_json_path.len :0],
.subcommand = .install,
};
@@ -11770,7 +11802,7 @@ pub const PackageManager = struct {
Global.crash();
};
const paths = bun.patch.gitDiffPreprocessPaths(bun.default_allocator, old_folder, new_folder, false);
const opts = bun.patch.spawnOpts(paths[0], paths[1], cwd, git, &manager.event_loop);
const opts = bun.patch.spawnOpts(paths[0], paths[1], cwd, git, manager.event_loop);
var spawn_result = switch (bun.spawnSync(&opts) catch |e| {
Output.prettyError(

View File

@@ -48,8 +48,8 @@ pub const LifecycleScriptSubprocess = struct {
return this.manager.event_loop.loop();
}
pub fn eventLoop(this: *const LifecycleScriptSubprocess) *JSC.AnyEventLoop {
return &this.manager.event_loop;
pub fn eventLoop(this: *const LifecycleScriptSubprocess) JSC.EventLoopHandle {
return this.manager.event_loop;
}
pub fn scriptName(this: *const LifecycleScriptSubprocess) []const u8 {
@@ -187,7 +187,7 @@ pub const LifecycleScriptSubprocess = struct {
.windows = if (Environment.isWindows)
.{
.loop = JSC.EventLoopHandle.init(&manager.event_loop),
.loop = this.eventLoop(),
}
else {},
@@ -233,7 +233,7 @@ pub const LifecycleScriptSubprocess = struct {
}
}
const event_loop = &this.manager.event_loop;
const event_loop = this.manager.event_loop;
var process = spawned.toProcess(
event_loop,
false,

View File

@@ -1073,6 +1073,45 @@ pub fn cleanWithLogger(
return new;
}
pub fn resolveWorkspaceFromNpmVersion(this: *const Lockfile, name_hash: PackageNameHash, version: *const Dependency.Version) ?PackageID {
const workspace_path = if (this.workspace_paths.count() > 0) this.workspace_paths.get(name_hash) else null;
const workspace_version = this.workspace_versions.get(name_hash);
const buf = this.buffers.string_bytes.items;
if ((workspace_version != null and version.value.npm.version.satisfies(workspace_version.?, buf, buf)) or
// https://github.com/oven-sh/bun/pull/10899#issuecomment-2099609419
// if the workspace doesn't have a version, it can still be used if
// dependency version is wildcard
(workspace_path != null and version.value.npm.version.@"is *"()))
{
const root_package = this.rootPackage() orelse return null;
const root_dependencies = root_package.dependencies.get(this.buffers.dependencies.items);
const root_resolutions = root_package.resolutions.get(this.buffers.resolutions.items);
for (root_dependencies, root_resolutions) |root_dep, workspace_package_id| {
if (workspace_package_id != invalid_package_id and root_dep.version.tag == .workspace and root_dep.name_hash == name_hash) {
return workspace_package_id;
}
}
}
return null;
}
pub fn resolveWorkspaceFromNpmDistTag(this: *const Lockfile, name_hash: PackageNameHash) ?PackageID {
const workspace_path = if (this.workspace_paths.count() > 0) this.workspace_paths.get(name_hash) else null;
if (workspace_path != null) {
const root_package = this.rootPackage() orelse return null;
const root_dependencies = root_package.dependencies.get(this.buffers.dependencies.items);
const root_resolutions = root_package.resolutions.get(this.buffers.resolutions.items);
for (root_dependencies, root_resolutions) |root_dep, workspace_package_id| {
if (workspace_package_id != invalid_package_id and root_dep.version.tag == .workspace and root_dep.name_hash == name_hash) {
return workspace_package_id;
}
}
}
return null;
}
pub const MetaHashFormatter = struct {
meta_hash: *const MetaHash,

View File

@@ -204,7 +204,7 @@ pub const PatchTask = struct {
var out_name_and_version_hash: ?u64 = null;
var out_patchfile_hash: ?u64 = null;
manager.setPreinstallState(pkg.meta.id, manager.lockfile, .unknown);
switch (manager.determinePreinstallState(pkg, manager.lockfile, &out_name_and_version_hash, &out_patchfile_hash)) {
switch (manager.determinePreinstallState(&pkg, manager.lockfile, &out_name_and_version_hash, &out_patchfile_hash)) {
.done => {
// patched pkg in folder path, should now be handled by PackageInstall.install()
debug("pkg: {s} done", .{pkg.name.slice(manager.lockfile.buffers.string_bytes.items)});

View File

@@ -342,7 +342,10 @@ pub const Resolution = extern struct {
}
pub fn canEnqueueInstallTask(this: Tag) bool {
return this == .npm or this == .local_tarball or this == .remote_tarball or this == .git or this == .github;
return switch (this) {
.npm, .local_tarball, .remote_tarball, .git, .github, .gitlab => true,
else => false,
};
}
};
};

View File

@@ -626,16 +626,21 @@ const BufferedReaderVTable = struct {
}
}.loop_fn;
const eventLoop_fn = &struct {
pub fn eventLoop_fn(this: *anyopaque) JSC.EventLoopHandle {
return JSC.EventLoopHandle.init(Type.eventLoop(@alignCast(@ptrCast(this))));
const event_loop_fn = &struct {
pub fn event_loop_fn(this: *anyopaque) JSC.EventLoopHandle {
const result = Type.eventLoop(@alignCast(@ptrCast(this)));
if (@TypeOf(result) == JSC.EventLoopHandle) {
return result;
}
return JSC.EventLoopHandle.init(result);
}
}.eventLoop_fn;
}.event_loop_fn;
return comptime &BufferedReaderVTable.Fn{
.onReadChunk = if (@hasDecl(Type, "onReadChunk")) @ptrCast(&Type.onReadChunk) else null,
.onReaderDone = @ptrCast(&Type.onReaderDone),
.onReaderError = @ptrCast(&Type.onReaderError),
.eventLoop = eventLoop_fn,
.eventLoop = event_loop_fn,
.loop = loop_fn,
};
}

View File

@@ -1238,7 +1238,7 @@ pub fn spawnOpts(
new_folder: []const u8,
cwd: [:0]const u8,
git: [:0]const u8,
loop: *JSC.AnyEventLoop,
loop: JSC.EventLoopHandle,
) bun.spawn.sync.Options {
const argv: []const []const u8 = brk: {
const ARGV = &[_][:0]const u8{
@@ -1287,10 +1287,7 @@ pub fn spawnOpts(
.cwd = cwd,
.envp = envp,
.argv = argv,
.windows = if (bun.Environment.isWindows) .{ .loop = switch (loop.*) {
.js => |x| .{ .js = x },
.mini => |*x| .{ .mini = x },
} } else {},
.windows = if (bun.Environment.isWindows) .{ .loop = loop } else {},
};
}

View File

@@ -399,7 +399,10 @@ pub const PendingResolution = struct {
string_buf: []u8 = "",
tag: Tag,
pub const List = std.MultiArrayList(PendingResolution);
/// Only used for auto-install in bun.bundle_v2
user_data: *anyopaque = undefined,
pub const List = bun.MultiArrayList(PendingResolution);
pub fn deinitListItems(list_: List, allocator: std.mem.Allocator) void {
var list = list_;
@@ -416,6 +419,7 @@ pub const PendingResolution = struct {
pub fn deinit(this: *PendingResolution, allocator: std.mem.Allocator) void {
this.dependency.deinit();
this.parse_tasks.deinit(allocator);
allocator.free(this.string_buf);
}
@@ -934,6 +938,30 @@ pub const Resolver = struct {
return r.resolve(source_dir, import_path, kind);
}
pub fn resolveWithFrameworkAndAutoInstall(r: *ThisResolver, source_dir: string, import_path: string, kind: ast.ImportKind) Result.Union {
if (r.opts.framework) |f| {
if (f.built_in_modules.get(import_path)) |mod| {
switch (mod) {
.code => {
return .{
.success = .{
.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.resolveAndAutoInstall(r.fs.top_level_dir, path, .entry_point, r.opts.global_cache),
}
return .{};
}
}
return r.resolveAndAutoInstall(source_dir, import_path, kind, r.opts.global_cache);
}
const ModuleTypeMap = bun.ComptimeStringMap(options.ModuleType, .{
.{ ".mjs", options.ModuleType.esm },
.{ ".mts", options.ModuleType.esm },