diff options
author | 2023-06-28 11:20:59 +0300 | |
---|---|---|
committer | 2023-06-28 01:20:59 -0700 | |
commit | 0de5bb22af427dcad57731d7063f8678b13265e2 (patch) | |
tree | 3ae79b038bb9146e24d8d4ed1daa1ebcb3da1b7e | |
parent | f670c0fc1866352b846f092e4f0741b51f59ec1a (diff) | |
download | bun-0de5bb22af427dcad57731d7063f8678b13265e2.tar.gz bun-0de5bb22af427dcad57731d7063f8678b13265e2.tar.zst bun-0de5bb22af427dcad57731d7063f8678b13265e2.zip |
[install] workaround run-time module loading issue (#3432)
-rw-r--r-- | src/bun.js/module_loader.zig | 6 | ||||
-rw-r--r-- | src/install/install.zig | 40 | ||||
-rw-r--r-- | src/resolver/resolver.zig | 27 | ||||
-rw-r--r-- | test/cli/install/bun-run.test.ts | 96 | ||||
-rw-r--r-- | test/cli/install/bunx.test.ts | 80 |
5 files changed, 143 insertions, 106 deletions
diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig index b25bb4b10..6fd4fef99 100644 --- a/src/bun.js/module_loader.zig +++ b/src/bun.js/module_loader.zig @@ -271,14 +271,8 @@ pub const ModuleLoader = struct { pub fn onPoll(this: *Queue) void { debug("onPoll", .{}); - var pm = this.vm().packageManager(); - this.runTasks(); - _ = pm.scheduleTasks(); - this.runTasks(); - this.pollModules(); - _ = pm.flushDependencyQueue(); } pub fn runTasks(this: *Queue) void { diff --git a/src/install/install.zig b/src/install/install.zig index 9465c4897..87f931291 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -1718,9 +1718,8 @@ pub const PackageManager = struct { } pub fn wake(this: *PackageManager) void { - if (this.onWake.context != null) { - this.onWake.getHandler()(this.onWake.context.?, this); - return; + if (this.onWake.context) |ctx| { + this.onWake.getHandler()(ctx, this); } _ = this.wait_count.fetchAdd(1, .Monotonic); @@ -1791,12 +1790,37 @@ pub const PackageManager = struct { return .{ .failure = err }; }; - const resolution_id = this.lockfile.buffers.resolutions.items[index]; + const resolution_id = switch (this.lockfile.buffers.resolutions.items[index]) { + invalid_package_id => brk: { + this.drainDependencyList(); + + switch (this.options.log_level) { + inline else => |log_level| { + if (log_level.showProgress()) this.startProgressBarIfNone(); + while (this.pending_tasks > 0) : (this.sleep()) { + this.runTasks( + void, + {}, + .{ + .onExtract = {}, + .onResolve = {}, + .onPackageManifestError = {}, + .onPackageDownloadError = {}, + }, + log_level, + ) catch |err| { + return .{ .failure = err }; + }; + } + }, + } - // check if we managed to synchronously resolve the dependency - if (resolution_id == invalid_package_id) return .{ .pending = index }; + break :brk this.lockfile.buffers.resolutions.items[index]; + }, + // we managed to synchronously resolve the dependency + else => |pkg_id| pkg_id, + }; - this.drainDependencyList(); return .{ .resolution = .{ .resolution = this.lockfile.packages.items(.resolution)[resolution_id], @@ -5310,6 +5334,8 @@ pub const PackageManager = struct { manager.progress.supports_ansi_escape_codes = Output.enable_ansi_colors_stderr; manager.root_progress_node = manager.progress.start("", 0); manager.root_download_node = manager.root_progress_node.start(ProgressStrings.download(), 0); + } else { + manager.options.log_level = .default_no_progress; } if (!manager.options.enable.cache) { diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index 40b106f3a..d9f4dc887 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -534,20 +534,19 @@ pub const Resolver = struct { 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; - - return this.package_manager.?; + 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 { diff --git a/test/cli/install/bun-run.test.ts b/test/cli/install/bun-run.test.ts new file mode 100644 index 000000000..fecbfc3d5 --- /dev/null +++ b/test/cli/install/bun-run.test.ts @@ -0,0 +1,96 @@ +import { file, spawn } from "bun"; +import { afterEach, beforeEach, expect, it } from "bun:test"; +import { bunExe, bunEnv as env } from "harness"; +import { mkdtemp, realpath, rm, writeFile } from "fs/promises"; +import { tmpdir } from "os"; +import { join } from "path"; +import { readdirSorted } from "./dummy.registry"; + +let run_dir: string; + +beforeEach(async () => { + run_dir = await realpath(await mkdtemp(join(tmpdir(), "bun-run.test"))); +}); +afterEach(async () => { + await rm(run_dir, { force: true, recursive: true }); +}); + +it("should download dependency to run local file", async () => { + await writeFile( + join(run_dir, "test.js"), + ` + const { minify } = require("uglify-js@3.17.4"); + + console.log(minify("print(6 * 7)").code); + `, + ); + const { stdout, stderr, exited } = spawn({ + cmd: [bunExe(), "test.js"], + cwd: run_dir, + stdout: null, + stdin: "pipe", + stderr: "pipe", + env: { + ...env, + BUN_INSTALL_CACHE_DIR: join(run_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(run_dir)).toEqual([".cache", "test.js"]); +}); + +it("should download dependencies to run local file", async () => { + await writeFile( + join(run_dir, "test.js"), + ` + import { file } from "bun"; + import decompress from "decompress@4.2.1"; + + const buffer = await file("${join(import.meta.dir, "baz-0.0.3.tgz")}").arrayBuffer(); + for (const entry of await decompress(Buffer.from(buffer))) { + console.log(\`\${entry.type}: \${entry.path}\`); + } + `, + ); + const { stdout, stderr, exited } = spawn({ + cmd: [bunExe(), "test.js"], + cwd: run_dir, + stdout: null, + stdin: "pipe", + stderr: "pipe", + env: { + ...env, + BUN_INSTALL_CACHE_DIR: join(run_dir, ".cache"), + }, + }); + expect(stderr).toBeDefined(); + const err = await new Response(stderr).text(); + expect(err).toBe(""); + expect(await readdirSorted(run_dir)).toEqual([".cache", "test.js"]); + expect(await readdirSorted(join(run_dir, ".cache"))).toContain("decompress"); + expect(await readdirSorted(join(run_dir, ".cache", "decompress"))).toEqual(["4.2.1"]); + expect(await readdirSorted(join(run_dir, ".cache", "decompress", "4.2.1"))).toEqual([ + "index.js", + "license", + "package.json", + "readme.md", + ]); + expect(await file(join(run_dir, ".cache", "decompress", "4.2.1", "index.js")).text()).toContain( + "\nmodule.exports = ", + ); + expect(stdout).toBeDefined(); + const out = await new Response(stdout).text(); + expect(out.split(/\r?\n/)).toEqual([ + "directory: package/", + "file: package/index.js", + "file: package/package.json", + "", + ]); + expect(await exited).toBe(0); +}); diff --git a/test/cli/install/bunx.test.ts b/test/cli/install/bunx.test.ts index 3605f5b6b..70d7aac29 100644 --- a/test/cli/install/bunx.test.ts +++ b/test/cli/install/bunx.test.ts @@ -1,4 +1,4 @@ -import { file, spawn } from "bun"; +import { spawn } from "bun"; import { afterEach, beforeEach, expect, it } from "bun:test"; import { bunExe, bunEnv as env } from "harness"; import { mkdtemp, realpath, rm, writeFile } from "fs/promises"; @@ -109,84 +109,6 @@ it("should work for @scoped packages", async () => { expect(await cached.exited).toBe(0); }); -it("should download dependency to run local file", async () => { - await writeFile( - join(x_dir, "test.js"), - ` -const { minify } = require("uglify-js@3.17.4"); - -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"]); -}); - -it("should download dependencies to run local file", async () => { - await writeFile( - join(x_dir, "test.js"), - ` -import { file } from "bun"; -import decompress from "decompress@4.2.1"; - -const buffer = await file("${join(import.meta.dir, "baz-0.0.3.tgz")}").arrayBuffer(); -for (const entry of await decompress(Buffer.from(buffer))) { - console.log(\`\${entry.type}: \${entry.path}\`); -} -`, - ); - 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(await readdirSorted(x_dir)).toEqual([".cache", "test.js"]); - expect(await readdirSorted(join(x_dir, ".cache"))).toContain("decompress"); - expect(await readdirSorted(join(x_dir, ".cache", "decompress"))).toEqual(["4.2.1"]); - expect(await readdirSorted(join(x_dir, ".cache", "decompress", "4.2.1"))).toEqual([ - "index.js", - "license", - "package.json", - "readme.md", - ]); - expect(await file(join(x_dir, ".cache", "decompress", "4.2.1", "index.js")).text()).toContain("\nmodule.exports = "); - expect(stdout).toBeDefined(); - const out = await new Response(stdout).text(); - expect(out.split(/\r?\n/)).toEqual([ - "directory: package/", - "file: package/index.js", - "file: package/package.json", - "", - ]); - expect(await exited).toBe(0); -}); - it("should execute from current working directory", async () => { await writeFile( join(x_dir, "test.js"), |