diff options
-rw-r--r-- | src/install/install.zig | 54 | ||||
-rw-r--r-- | src/js_ast.zig | 123 | ||||
-rw-r--r-- | test/bun.js/install/bun-install.test.ts | 484 |
3 files changed, 507 insertions, 154 deletions
diff --git a/src/install/install.zig b/src/install/install.zig index 99cb9213d..dc416005e 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -4270,17 +4270,25 @@ pub const PackageManager = struct { // 3. There is a "dependencies" (or equivalent list), and the package name exists in multiple lists ast_modifier: { // Try to use the existing spot in the dependencies list if possible - for (updates) |update, i| { + for (updates) |*update| { outer: for (dependency_lists_to_check) |list| { if (current_package_json.asProperty(list)) |query| { if (query.expr.data == .e_object) { if (query.expr.asProperty(update.name)) |value| { if (value.expr.data == .e_string) { if (update.resolved_name.isEmpty()) { - updates[i].e_string = value.expr.data.e_string; + update.e_string = value.expr.data.e_string; remaining -= 1; } else { replacing += 1; + update.e_string = (try JSAst.Expr.init( + JSAst.E.String, + JSAst.E.String{ + // we set it later + .data = "", + }, + logger.Loc.Empty, + ).clone(allocator)).data.e_string; } } break :outer; @@ -4290,13 +4298,16 @@ pub const PackageManager = struct { } } - if (remaining == 0) + if (remaining == 0 and replacing == 0) break :ast_modifier; var dependencies: []G.Property = &[_]G.Property{}; + var dependencies_obj: ?*JSAst.E.Object = null; if (current_package_json.asProperty(dependency_list)) |query| { if (query.expr.data == .e_object) { - dependencies = query.expr.data.e_object.properties.slice(); + dependencies_obj = query.expr.data.e_object; + + dependencies = dependencies_obj.?.properties.slice(); } } @@ -4304,32 +4315,25 @@ pub const PackageManager = struct { std.mem.copy(G.Property, new_dependencies, dependencies); std.mem.set(G.Property, new_dependencies[dependencies.len..], G.Property{}); - outer: for (updates) |update, j| { + outer: for (updates) |*update| { if (update.e_string != null) continue; + defer std.debug.assert(update.e_string != null); var k: usize = 0; - while (k < new_dependencies.len) : (k += 1) { - if (new_dependencies[k].key) |key| { - if (key.data.e_string.eql(string, update.name)) { - if (update.resolved_name.isEmpty()) { - // This actually is a duplicate - // like "react" appearing in both "dependencies" and "optionalDependencies" - // For this case, we'll just swap remove it - if (new_dependencies.len > 1) { - new_dependencies[k] = new_dependencies[new_dependencies.len - 1]; - new_dependencies = new_dependencies[0 .. new_dependencies.len - 1]; - } else { - new_dependencies = &[_]G.Property{}; - } - continue; + if (dependencies_obj) |obj| { + if (obj.asProperty(update.name)) |prop| { + if (prop.expr.data == .e_string) { + var str = try prop.expr.clone(allocator); + str.data.e_string.* = try str.data.e_string.clone(allocator); + update.e_string = str.data.e_string; + continue :outer; } - new_dependencies[k].key = null; } } if (new_dependencies[k].key == null) { - new_dependencies[k].key = JSAst.Expr.init( + new_dependencies[k].key = try JSAst.Expr.init( JSAst.E.String, JSAst.E.String{ .data = try allocator.dupe(u8, if (update.is_aliased or update.resolved_name.isEmpty()) @@ -4338,17 +4342,17 @@ pub const PackageManager = struct { update.resolved_name.slice(update.version_buf)), }, logger.Loc.Empty, - ); + ).clone(allocator); - new_dependencies[k].value = JSAst.Expr.init( + new_dependencies[k].value = try JSAst.Expr.init( JSAst.E.String, JSAst.E.String{ // we set it later .data = "", }, logger.Loc.Empty, - ); - updates[j].e_string = new_dependencies[k].value.?.data.e_string; + ).clone(allocator); + update.e_string = new_dependencies[k].value.?.data.e_string; continue :outer; } } diff --git a/src/js_ast.zig b/src/js_ast.zig index 350bf6561..5b575eda5 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -2228,6 +2228,13 @@ pub const Expr = struct { loc: logger.Loc, data: Data, + pub fn clone(this: Expr, allocator: std.mem.Allocator) !Expr { + return .{ + .loc = this.loc, + .data = try this.data.clone(allocator), + }; + } + pub fn wrapInArrow(this: Expr, allocator: std.mem.Allocator) !Expr { var stmts = try allocator.alloc(Stmt, 1); stmts[0] = Stmt.alloc(S.Return, S.Return{ .value = this }, this.loc); @@ -3608,6 +3615,122 @@ pub const Expr = struct { // If it ends up in JSParser or JSPrinter, it is a bug. inline_identifier: i32, + pub fn clone(this: Expr.Data, allocator: std.mem.Allocator) !Data { + return switch (this) { + .e_array => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_array))); + item.* = el.*; + return .{ .e_array = item }; + }, + .e_unary => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_unary))); + item.* = el.*; + return .{ .e_unary = item }; + }, + .e_binary => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_binary))); + item.* = el.*; + return .{ .e_binary = item }; + }, + .e_class => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_class))); + item.* = el.*; + return .{ .e_class = item }; + }, + .e_new => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_new))); + item.* = el.*; + return .{ .e_new = item }; + }, + .e_function => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_function))); + item.* = el.*; + return .{ .e_function = item }; + }, + .e_call => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_call))); + item.* = el.*; + return .{ .e_call = item }; + }, + .e_dot => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_dot))); + item.* = el.*; + return .{ .e_dot = item }; + }, + .e_index => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_index))); + item.* = el.*; + return .{ .e_index = item }; + }, + .e_arrow => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_arrow))); + item.* = el.*; + return .{ .e_arrow = item }; + }, + .e_jsx_element => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_jsx_element))); + item.* = el.*; + return .{ .e_jsx_element = item }; + }, + .e_object => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_object))); + item.* = el.*; + return .{ .e_object = item }; + }, + .e_spread => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_spread))); + item.* = el.*; + return .{ .e_spread = item }; + }, + .e_template_part => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_template_part))); + item.* = el.*; + return .{ .e_template_part = item }; + }, + .e_template => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_template))); + item.* = el.*; + return .{ .e_template = item }; + }, + .e_reg_exp => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_reg_exp))); + item.* = el.*; + return .{ .e_reg_exp = item }; + }, + .e_await => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_await))); + item.* = el.*; + return .{ .e_await = item }; + }, + .e_yield => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_yield))); + item.* = el.*; + return .{ .e_yield = item }; + }, + .e_if => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_if))); + item.* = el.*; + return .{ .e_if = item }; + }, + .e_import => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_import))); + item.* = el.*; + return .{ .e_import = item }; + }, + .e_big_int => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_big_int))); + item.* = el.*; + return .{ .e_big_int = item }; + }, + .e_string => |el| { + var item = try allocator.create(std.meta.Child(@TypeOf(this.e_string))); + item.* = el.*; + return .{ .e_string = item }; + }, + else => this, + }; + } + pub fn canBeConstValue(this: Expr.Data) bool { return switch (this) { .e_number, .e_boolean, .e_null, .e_undefined => true, diff --git a/test/bun.js/install/bun-install.test.ts b/test/bun.js/install/bun-install.test.ts index 7d127d4ed..33a662dc2 100644 --- a/test/bun.js/install/bun-install.test.ts +++ b/test/bun.js/install/bun-install.test.ts @@ -9,12 +9,7 @@ import { } from "bun:test"; import { bunExe } from "bunExe"; import { bunEnv as env } from "bunEnv"; -import { - access, - mkdir, - readlink, - writeFile, -} from "fs/promises"; +import { access, mkdir, readlink, writeFile } from "fs/promises"; import { join } from "path"; import { dummyAfterAll, @@ -28,6 +23,7 @@ import { root_url, setHandler, } from "./dummy.registry"; +import { rmSync } from "fs"; beforeAll(dummyBeforeAll); afterAll(dummyAfterAll); @@ -161,10 +157,7 @@ it("should handle empty string in dependencies", async () => { " 1 packages installed", ]); expect(await exited).toBe(0); - expect(urls).toEqual([ - `${root_url}/bar`, - `${root_url}/bar.tgz`, - ]); + expect(urls).toEqual([`${root_url}/bar`, `${root_url}/bar.tgz`]); expect(requested).toBe(2); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([ ".cache", @@ -575,10 +568,7 @@ it("should handle ^0 in dependencies", async () => { " 1 packages installed", ]); expect(await exited).toBe(0); - expect(urls).toEqual([ - `${root_url}/bar`, - `${root_url}/bar.tgz`, - ]); + expect(urls).toEqual([`${root_url}/bar`, `${root_url}/bar.tgz`]); expect(requested).toBe(2); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([ ".cache", @@ -667,10 +657,7 @@ it("should handle ^0.0 in dependencies", async () => { " 1 packages installed", ]); expect(await exited).toBe(0); - expect(urls).toEqual([ - `${root_url}/bar`, - `${root_url}/bar.tgz`, - ]); + expect(urls).toEqual([`${root_url}/bar`, `${root_url}/bar.tgz`]); expect(requested).toBe(2); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([ ".cache", @@ -798,10 +785,7 @@ it("should handle ^0.0.2 in dependencies", async () => { " 1 packages installed", ]); expect(await exited).toBe(0); - expect(urls).toEqual([ - `${root_url}/bar`, - `${root_url}/bar.tgz`, - ]); + expect(urls).toEqual([`${root_url}/bar`, `${root_url}/bar.tgz`]); expect(requested).toBe(2); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([ ".cache", @@ -851,10 +835,7 @@ it("should handle ^0.0.2-rc in dependencies", async () => { " 1 packages installed", ]); expect(await exited).toBe(0); - expect(urls).toEqual([ - `${root_url}/bar`, - `${root_url}/bar.tgz`, - ]); + expect(urls).toEqual([`${root_url}/bar`, `${root_url}/bar.tgz`]); expect(requested).toBe(2); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([ ".cache", @@ -904,10 +885,7 @@ it("should handle ^0.0.2-alpha.3+b4d in dependencies", async () => { " 1 packages installed", ]); expect(await exited).toBe(0); - expect(urls).toEqual([ - `${root_url}/bar`, - `${root_url}/bar.tgz`, - ]); + expect(urls).toEqual([`${root_url}/bar`, `${root_url}/bar.tgz`]); expect(requested).toBe(2); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([ ".cache", @@ -927,11 +905,13 @@ it("should handle ^0.0.2-alpha.3+b4d in dependencies", async () => { it("should handle dependency aliasing", async () => { const urls = []; - setHandler(dummyRegistry(urls, "0.0.3", { - bin: { - "baz-run": "index.js", - }, - })); + setHandler( + dummyRegistry(urls, "0.0.3", { + bin: { + "baz-run": "index.js", + }, + }), + ); await writeFile( join(package_dir, "package.json"), JSON.stringify({ @@ -961,25 +941,25 @@ it("should handle dependency aliasing", async () => { " 1 packages installed", ]); expect(await exited).toBe(0); - expect(urls).toEqual([ - `${root_url}/baz`, - `${root_url}/baz.tgz`, - ]); + expect(urls).toEqual([`${root_url}/baz`, `${root_url}/baz.tgz`]); expect(requested).toBe(2); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([ ".bin", ".cache", "Bar", ]); - expect(await readdirSorted(join(package_dir, "node_modules", ".bin"))).toEqual([ - "baz-run", - ]); - expect(await readlink(join(package_dir, "node_modules", ".bin", "baz-run"))).toBe(join("..", "Bar", "index.js")); - expect(await readdirSorted(join(package_dir, "node_modules", "Bar"))).toEqual([ - "index.js", - "package.json", - ]); - expect(await file(join(package_dir, "node_modules", "Bar", "package.json")).json()).toEqual({ + expect( + await readdirSorted(join(package_dir, "node_modules", ".bin")), + ).toEqual(["baz-run"]); + expect( + await readlink(join(package_dir, "node_modules", ".bin", "baz-run")), + ).toBe(join("..", "Bar", "index.js")); + expect(await readdirSorted(join(package_dir, "node_modules", "Bar"))).toEqual( + ["index.js", "package.json"], + ); + expect( + await file(join(package_dir, "node_modules", "Bar", "package.json")).json(), + ).toEqual({ name: "baz", version: "0.0.3", bin: { @@ -991,11 +971,13 @@ it("should handle dependency aliasing", async () => { it("should handle dependency aliasing (versioned)", async () => { const urls: string[] = []; - setHandler(dummyRegistry(urls, "0.0.3", { - bin: { - "baz-run": "index.js", - }, - })); + setHandler( + dummyRegistry(urls, "0.0.3", { + bin: { + "baz-run": "index.js", + }, + }), + ); await writeFile( join(package_dir, "package.json"), JSON.stringify({ @@ -1025,25 +1007,25 @@ it("should handle dependency aliasing (versioned)", async () => { " 1 packages installed", ]); expect(await exited).toBe(0); - expect(urls).toEqual([ - `${root_url}/baz`, - `${root_url}/baz.tgz`, - ]); + expect(urls).toEqual([`${root_url}/baz`, `${root_url}/baz.tgz`]); expect(requested).toBe(2); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([ ".bin", ".cache", "Bar", ]); - expect(await readdirSorted(join(package_dir, "node_modules", ".bin"))).toEqual([ - "baz-run", - ]); - expect(await readlink(join(package_dir, "node_modules", ".bin", "baz-run"))).toBe(join("..", "Bar", "index.js")); - expect(await readdirSorted(join(package_dir, "node_modules", "Bar"))).toEqual([ - "index.js", - "package.json", - ]); - expect(await file(join(package_dir, "node_modules", "Bar", "package.json")).json()).toEqual({ + expect( + await readdirSorted(join(package_dir, "node_modules", ".bin")), + ).toEqual(["baz-run"]); + expect( + await readlink(join(package_dir, "node_modules", ".bin", "baz-run")), + ).toBe(join("..", "Bar", "index.js")); + expect(await readdirSorted(join(package_dir, "node_modules", "Bar"))).toEqual( + ["index.js", "package.json"], + ); + expect( + await file(join(package_dir, "node_modules", "Bar", "package.json")).json(), + ).toEqual({ name: "baz", version: "0.0.3", bin: { @@ -1053,13 +1035,241 @@ it("should handle dependency aliasing (versioned)", async () => { await access(join(package_dir, "bun.lockb")); }); -it("should handle dependency aliasing (dist-tagged)", async () => { +it("should handle ^0.0.2-rc in dependencies", async () => { + const urls: string[] = []; + setHandler(dummyRegistry(urls, "0.0.2-rc")); + await writeFile( + join(package_dir, "package.json"), + JSON.stringify({ + name: "foo", + version: "0.0.1", + dependencies: { + bar: "^0.0.2-rc", + }, + }), + ); + const { stdout, stderr, exited } = spawn({ + cmd: [bunExe(), "install", "--config", import.meta.dir + "/basic.toml"], + cwd: package_dir, + stdout: null, + stdin: "pipe", + stderr: "pipe", + env, + }); + expect(stderr).toBeDefined(); + const err = await new Response(stderr).text(); + expect(err).toContain("Saved lockfile"); + expect(stdout).toBeDefined(); + const out = await new Response(stdout).text(); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + " + bar@0.0.2-rc", + "", + " 1 packages installed", + ]); + expect(await exited).toBe(0); + expect(urls).toEqual([`${root_url}/bar`, `${root_url}/bar.tgz`]); + expect(requested).toBe(2); + expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([ + ".cache", + "bar", + ]); + expect(await readdirSorted(join(package_dir, "node_modules", "bar"))).toEqual( + ["package.json"], + ); + expect( + await file(join(package_dir, "node_modules", "bar", "package.json")).json(), + ).toEqual({ + name: "bar", + version: "0.0.2", + }); + await access(join(package_dir, "bun.lockb")); +}); + +it("should handle ^0.0.2-alpha.3+b4d in dependencies", async () => { const urls: string[] = []; - setHandler(dummyRegistry(urls, "0.0.3", { + setHandler(dummyRegistry(urls, "0.0.2-alpha.3")); + await writeFile( + join(package_dir, "package.json"), + JSON.stringify({ + name: "foo", + version: "0.0.1", + dependencies: { + bar: "^0.0.2-alpha.3+b4d", + }, + }), + ); + const { stdout, stderr, exited } = spawn({ + cmd: [bunExe(), "install", "--config", import.meta.dir + "/basic.toml"], + cwd: package_dir, + stdout: null, + stdin: "pipe", + stderr: "pipe", + env, + }); + expect(stderr).toBeDefined(); + const err = await new Response(stderr).text(); + expect(err).toContain("Saved lockfile"); + expect(stdout).toBeDefined(); + const out = await new Response(stdout).text(); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + " + bar@0.0.2-alpha.3", + "", + " 1 packages installed", + ]); + expect(await exited).toBe(0); + expect(urls).toEqual([`${root_url}/bar`, `${root_url}/bar.tgz`]); + expect(requested).toBe(2); + expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([ + ".cache", + "bar", + ]); + expect(await readdirSorted(join(package_dir, "node_modules", "bar"))).toEqual( + ["package.json"], + ); + expect( + await file(join(package_dir, "node_modules", "bar", "package.json")).json(), + ).toEqual({ + name: "bar", + version: "0.0.2", + }); + await access(join(package_dir, "bun.lockb")); +}); + +it("should handle dependency aliasing", async () => { + const urls = []; + setHandler( + dummyRegistry(urls, "0.0.3", { + bin: { + "baz-run": "index.js", + }, + }), + ); + await writeFile( + join(package_dir, "package.json"), + JSON.stringify({ + name: "Foo", + version: "0.0.1", + dependencies: { + Bar: "npm:baz", + }, + }), + ); + const { stdout, stderr, exited } = spawn({ + cmd: [bunExe(), "install", "--config", import.meta.dir + "/basic.toml"], + cwd: package_dir, + stdout: null, + stdin: "pipe", + stderr: "pipe", + env, + }); + expect(stderr).toBeDefined(); + const err = await new Response(stderr).text(); + expect(err).toContain("Saved lockfile"); + expect(stdout).toBeDefined(); + const out = await new Response(stdout).text(); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + " + Bar@0.0.3", + "", + " 1 packages installed", + ]); + expect(await exited).toBe(0); + expect(urls).toEqual([`${root_url}/baz`, `${root_url}/baz.tgz`]); + expect(requested).toBe(2); + expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([ + ".bin", + ".cache", + "Bar", + ]); + expect( + await readdirSorted(join(package_dir, "node_modules", ".bin")), + ).toEqual(["baz-run"]); + expect( + await readlink(join(package_dir, "node_modules", ".bin", "baz-run")), + ).toBe(join("..", "Bar", "index.js")); + expect(await readdirSorted(join(package_dir, "node_modules", "Bar"))).toEqual( + ["index.js", "package.json"], + ); + expect( + await file(join(package_dir, "node_modules", "Bar", "package.json")).json(), + ).toEqual({ + name: "baz", + version: "0.0.3", bin: { "baz-run": "index.js", }, - })); + }); + await access(join(package_dir, "bun.lockb")); +}); + +it("should let you add the same package twice", async () => { + const urls: string[] = []; + setHandler(dummyRegistry(urls, "0.0.3", {})); + await writeFile( + join(package_dir, "package.json"), + JSON.stringify({ + name: "Foo", + version: "0.0.1", + dependencies: {}, + }), + ); + rmSync(`${root_url}/baz`, { recursive: true, force: true }); + for (let i = 0; i < 2; i++) { + const { stdout, stderr, exited } = spawn({ + cmd: [ + bunExe(), + "install", + "baz@0.0.3", + "--config", + import.meta.dir + "/basic.toml", + ], + cwd: package_dir, + stdout: null, + stdin: "pipe", + stderr: "pipe", + env, + }); + expect(stderr).toBeDefined(); + const err = await new Response(stderr).text(); + expect(err).toContain("Saved lockfile"); + expect(stdout).toBeDefined(); + const out = await new Response(stdout).text(); + expect(out).toContain("installed baz@0.0.3"); + if (i === 0) { + expect(out).toContain("1 packages installed"); + } else { + expect(out).not.toContain("1 packages installed"); + } + expect(await exited).toBe(0); + expect(urls).toEqual([`${root_url}/baz`, `${root_url}/baz.tgz`]); + expect(requested).toBe(2); + expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([ + ".cache", + "baz", + ]); + expect( + await file( + join(package_dir, "node_modules", "baz", "package.json"), + ).json(), + ).toEqual({ + name: "baz", + version: "0.0.3", + bin: { + "baz-run": "index.js", + }, + }); + await access(join(package_dir, "bun.lockb")); + } +}); + +it("should handle dependency aliasing (dist-tagged)", async () => { + const urls: string[] = []; + setHandler( + dummyRegistry(urls, "0.0.3", { + bin: { + "baz-run": "index.js", + }, + }), + ); await writeFile( join(package_dir, "package.json"), JSON.stringify({ @@ -1089,25 +1299,25 @@ it("should handle dependency aliasing (dist-tagged)", async () => { " 1 packages installed", ]); expect(await exited).toBe(0); - expect(urls).toEqual([ - `${root_url}/baz`, - `${root_url}/baz.tgz`, - ]); + expect(urls).toEqual([`${root_url}/baz`, `${root_url}/baz.tgz`]); expect(requested).toBe(2); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([ ".bin", ".cache", "Bar", ]); - expect(await readdirSorted(join(package_dir, "node_modules", ".bin"))).toEqual([ - "baz-run", - ]); - expect(await readlink(join(package_dir, "node_modules", ".bin", "baz-run"))).toBe(join("..", "Bar", "index.js")); - expect(await readdirSorted(join(package_dir, "node_modules", "Bar"))).toEqual([ - "index.js", - "package.json", - ]); - expect(await file(join(package_dir, "node_modules", "Bar", "package.json")).json()).toEqual({ + expect( + await readdirSorted(join(package_dir, "node_modules", ".bin")), + ).toEqual(["baz-run"]); + expect( + await readlink(join(package_dir, "node_modules", ".bin", "baz-run")), + ).toBe(join("..", "Bar", "index.js")); + expect(await readdirSorted(join(package_dir, "node_modules", "Bar"))).toEqual( + ["index.js", "package.json"], + ); + expect( + await file(join(package_dir, "node_modules", "Bar", "package.json")).json(), + ).toEqual({ name: "baz", version: "0.0.3", bin: { @@ -1119,11 +1329,13 @@ it("should handle dependency aliasing (dist-tagged)", async () => { it("should not reinstall aliased dependencies", async () => { const urls = []; - setHandler(dummyRegistry(urls, "0.0.3", { - bin: { - "baz-run": "index.js", - }, - })); + setHandler( + dummyRegistry(urls, "0.0.3", { + bin: { + "baz-run": "index.js", + }, + }), + ); await writeFile( join(package_dir, "package.json"), JSON.stringify({ @@ -1157,25 +1369,25 @@ it("should not reinstall aliased dependencies", async () => { " 1 packages installed", ]); expect(await exited1).toBe(0); - expect(urls).toEqual([ - `${root_url}/baz`, - `${root_url}/baz.tgz`, - ]); + expect(urls).toEqual([`${root_url}/baz`, `${root_url}/baz.tgz`]); expect(requested).toBe(2); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([ ".bin", ".cache", "Bar", ]); - expect(await readdirSorted(join(package_dir, "node_modules", ".bin"))).toEqual([ - "baz-run", - ]); - expect(await readlink(join(package_dir, "node_modules", ".bin", "baz-run"))).toBe(join("..", "Bar", "index.js")); - expect(await readdirSorted(join(package_dir, "node_modules", "Bar"))).toEqual([ - "index.js", - "package.json", - ]); - expect(await file(join(package_dir, "node_modules", "Bar", "package.json")).json()).toEqual({ + expect( + await readdirSorted(join(package_dir, "node_modules", ".bin")), + ).toEqual(["baz-run"]); + expect( + await readlink(join(package_dir, "node_modules", ".bin", "baz-run")), + ).toBe(join("..", "Bar", "index.js")); + expect(await readdirSorted(join(package_dir, "node_modules", "Bar"))).toEqual( + ["index.js", "package.json"], + ); + expect( + await file(join(package_dir, "node_modules", "Bar", "package.json")).json(), + ).toEqual({ name: "baz", version: "0.0.3", bin: { @@ -1214,15 +1426,18 @@ it("should not reinstall aliased dependencies", async () => { ".cache", "Bar", ]); - expect(await readdirSorted(join(package_dir, "node_modules", ".bin"))).toEqual([ - "baz-run", - ]); - expect(await readlink(join(package_dir, "node_modules", ".bin", "baz-run"))).toBe(join("..", "Bar", "index.js")); - expect(await readdirSorted(join(package_dir, "node_modules", "Bar"))).toEqual([ - "index.js", - "package.json", - ]); - expect(await file(join(package_dir, "node_modules", "Bar", "package.json")).json()).toEqual({ + expect( + await readdirSorted(join(package_dir, "node_modules", ".bin")), + ).toEqual(["baz-run"]); + expect( + await readlink(join(package_dir, "node_modules", ".bin", "baz-run")), + ).toBe(join("..", "Bar", "index.js")); + expect(await readdirSorted(join(package_dir, "node_modules", "Bar"))).toEqual( + ["index.js", "package.json"], + ); + expect( + await file(join(package_dir, "node_modules", "Bar", "package.json")).json(), + ).toEqual({ name: "baz", version: "0.0.3", bin: { @@ -1511,25 +1726,28 @@ it("should handle GitHub URL in dependencies (github:user/repo#tag)", async () = expect( await readdirSorted(join(package_dir, "node_modules", ".bin")), ).toEqual(["uglifyjs"]); - expect(await readlink(join(package_dir, "node_modules", ".bin", "uglifyjs"))).toBe(join( - "..", - "uglify", - "bin", - "uglifyjs", - )); + expect( + await readlink(join(package_dir, "node_modules", ".bin", "uglifyjs")), + ).toBe(join("..", "uglify", "bin", "uglifyjs")); expect( await readdirSorted(join(package_dir, "node_modules", ".cache")), ).toEqual(["@GH@mishoo-UglifyJS-e219a9a", "uglify"]); - expect(await readdirSorted(join(package_dir, "node_modules", ".cache", "uglify"))).toEqual([ - "mishoo-UglifyJS-e219a9a", - ]); - expect(await readlink(join( - package_dir, - "node_modules", - ".cache", - "uglify", - "mishoo-UglifyJS-e219a9a", - ))).toBe(join(package_dir, "node_modules", ".cache", "@GH@mishoo-UglifyJS-e219a9a")); + expect( + await readdirSorted(join(package_dir, "node_modules", ".cache", "uglify")), + ).toEqual(["mishoo-UglifyJS-e219a9a"]); + expect( + await readlink( + join( + package_dir, + "node_modules", + ".cache", + "uglify", + "mishoo-UglifyJS-e219a9a", + ), + ), + ).toBe( + join(package_dir, "node_modules", ".cache", "@GH@mishoo-UglifyJS-e219a9a"), + ); expect( await readdirSorted(join(package_dir, "node_modules", "uglify")), ).toEqual([ @@ -1595,8 +1813,12 @@ it("should handle GitHub URL in dependencies (https://github.com/user/repo.git)" ".cache", "uglify", ]); - expect(await readdirSorted(join(package_dir, "node_modules", ".bin"))).toEqual(["uglifyjs"]); - expect(await readdirSorted(join(package_dir, "node_modules", "uglify"))).toEqual([ + expect( + await readdirSorted(join(package_dir, "node_modules", ".bin")), + ).toEqual(["uglifyjs"]); + expect( + await readdirSorted(join(package_dir, "node_modules", "uglify")), + ).toEqual([ ".bun-tag", ".gitattributes", ".github", @@ -1658,8 +1880,12 @@ it("should handle GitHub URL in dependencies (git+https://github.com/user/repo.g ".cache", "uglify", ]); - expect(await readdirSorted(join(package_dir, "node_modules", ".bin"))).toEqual(["uglifyjs"]); - expect(await readdirSorted(join(package_dir, "node_modules", "uglify"))).toEqual([ + expect( + await readdirSorted(join(package_dir, "node_modules", ".bin")), + ).toEqual(["uglifyjs"]); + expect( + await readdirSorted(join(package_dir, "node_modules", "uglify")), + ).toEqual([ ".bun-tag", ".gitattributes", ".github", |