aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--bench/install/README.md26
-rwxr-xr-xpackages/bun-lambda/runtime.ts6
-rw-r--r--src/bun.js/api/bun.zig2
-rw-r--r--src/bun.js/bindings/JSBuffer.cpp1
-rw-r--r--src/bun.js/javascript.zig2
-rw-r--r--src/bundler.zig6
-rw-r--r--src/cli/run_command.zig4
-rw-r--r--src/env_loader.zig89
-rw-r--r--src/install/install.zig2
-rw-r--r--src/install/lockfile.zig2
-rw-r--r--src/io/io_darwin.zig6
-rw-r--r--src/resolver/resolve_path.zig4
-rw-r--r--test/cli/run/env.test.ts43
-rw-r--r--test/js/bun/io/bun-write.test.js9
-rw-r--r--test/js/node/buffer.test.js13
-rw-r--r--test/js/node/path/path.test.js13
17 files changed, 182 insertions, 48 deletions
diff --git a/Makefile b/Makefile
index 49d6535a7..b3fe2d6bf 100644
--- a/Makefile
+++ b/Makefile
@@ -1880,7 +1880,7 @@ PACKAGE_MAP = --pkg-begin async_io $(BUN_DIR)/src/io/io_darwin.zig --pkg-begin b
.PHONY: base64
base64:
- cd $(BUN_DEPS_DIR)/base64 && make clean && cmake $(CMAKE_FLAGS) . && make
+ cd $(BUN_DEPS_DIR)/base64 && make clean && rm -rf CMakeCache.txt CMakeFiles && cmake $(CMAKE_FLAGS) . && make
cp $(BUN_DEPS_DIR)/base64/libbase64.a $(BUN_DEPS_OUT_DIR)/libbase64.a
.PHONY: cold-jsc-start
diff --git a/bench/install/README.md b/bench/install/README.md
index e9b617995..42739a1aa 100644
--- a/bench/install/README.md
+++ b/bench/install/README.md
@@ -1,11 +1,33 @@
# `install` benchmark
-Requires [`hyperfine`](https://github.com/sharkdp/hyperfine)
+Requires [`hyperfine`](https://github.com/sharkdp/hyperfine). The goal of this benchmark is to compare installation performance of Bun with other package managers _when caches are hot_.
-```
+### With lockfile, online mode
+
+To run the benchmark with the standard "install" command for each package manager:
+
+```sh
$ hyperfine --prepare 'rm -rf node_modules' --warmup 1 --runs 3 'bun install' 'pnpm install' 'yarn' 'npm install'
```
+### With lockfile, offline mode
+
+Even though all packages are cached, some tools may hit the npm API during the version resolution step. (This is not the same as re-downloading a package.) To entirely avoid network calls, the other package managers require `--prefer-offline/--offline` flag. To run the benchmark using "offline" mode:
+
+```sh
+$ hyperfine --prepare 'rm -rf node_modules' --runs 1 'bun install' 'pnpm install --prefer-offline' 'yarn --offline' 'npm install --prefer-offline'
+```
+
+### Without lockfile, offline mode
+
+To run the benchmark with offline mode but without lockfiles:
+
+```sh
+$ hyperfine --prepare 'rm -rf node_modules' --warmup 1 'rm bun.lockb && bun install' 'rm pnpm-lock.yaml && pnpm install --prefer-offline' 'rm yarn.lock && yarn --offline' 'rm package-lock.json && npm install --prefer-offline'
+```
+
+##
+
To check that the app is working as expected:
```
diff --git a/packages/bun-lambda/runtime.ts b/packages/bun-lambda/runtime.ts
index 4b38b6dfa..b4e08944d 100755
--- a/packages/bun-lambda/runtime.ts
+++ b/packages/bun-lambda/runtime.ts
@@ -22,11 +22,11 @@ function log(level: string, ...args: any[]): void {
if (!args.length) {
return;
}
- const message = Bun.inspect(...args).replace(/\n/g, "\r");
+ const messages = args.map(arg => Bun.inspect(arg).replace(/\n/g, "\r"));
if (requestId === undefined) {
- logger(level, message);
+ logger(level, ...messages);
} else {
- logger(level, `RequestId: ${requestId}`, message);
+ logger(level, `RequestId: ${requestId}`, ...messages);
}
}
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig
index 36e52821f..966c82d38 100644
--- a/src/bun.js/api/bun.zig
+++ b/src/bun.js/api/bun.zig
@@ -4431,7 +4431,7 @@ pub const EnvironmentVariables = struct {
var vm = globalObject.bunVM();
var sliced = name.toSlice(vm.allocator);
defer sliced.deinit();
- const value = vm.bundler.env.map.map.get(sliced.slice()) orelse return null;
+ const value = vm.bundler.env.map.get(sliced.slice()) orelse return null;
return ZigString.initUTF8(value);
}
};
diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp
index ad901b0e4..9227e47b3 100644
--- a/src/bun.js/bindings/JSBuffer.cpp
+++ b/src/bun.js/bindings/JSBuffer.cpp
@@ -351,6 +351,7 @@ static EncodedJSValue constructFromEncoding(JSGlobalObject* lexicalGlobalObject,
case WebCore::BufferEncodingType::utf8:
case WebCore::BufferEncodingType::base64:
case WebCore::BufferEncodingType::base64url:
+ case WebCore::BufferEncodingType::hex:
case WebCore::BufferEncodingType::ascii:
case WebCore::BufferEncodingType::latin1: {
result = Bun__encoding__constructFromUTF16(lexicalGlobalObject, view.characters16(), view.length(), static_cast<uint8_t>(encoding));
diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig
index 0d73c31c5..752fcb3a4 100644
--- a/src/bun.js/javascript.zig
+++ b/src/bun.js/javascript.zig
@@ -670,7 +670,7 @@ pub const VirtualMachine = struct {
}
if (map.map.fetchSwapRemove("BUN_INTERNAL_IPC_FD")) |kv| {
- if (std.fmt.parseInt(i32, kv.value, 10) catch null) |fd| {
+ if (std.fmt.parseInt(i32, kv.value.value, 10) catch null) |fd| {
this.initIPCInstance(fd);
} else {
Output.printErrorln("Failed to parse BUN_INTERNAL_IPC_FD", .{});
diff --git a/src/bundler.zig b/src/bundler.zig
index 66443d165..76fbc02ee 100644
--- a/src/bundler.zig
+++ b/src/bundler.zig
@@ -472,11 +472,11 @@ pub const Bundler = struct {
}
if (!has_production_env and this.options.isTest()) {
- try this.env.load(&this.fs.fs, dir, .@"test");
+ try this.env.load(dir, .@"test");
} else if (this.options.production) {
- try this.env.load(&this.fs.fs, dir, .production);
+ try this.env.load(dir, .production);
} else {
- try this.env.load(&this.fs.fs, dir, .development);
+ try this.env.load(dir, .development);
}
},
.disable => {
diff --git a/src/cli/run_command.zig b/src/cli/run_command.zig
index f637bfe6c..dcb5312b1 100644
--- a/src/cli/run_command.zig
+++ b/src/cli/run_command.zig
@@ -525,9 +525,9 @@ pub const RunCommand = struct {
if (root_dir_info.getEntries(0)) |dir| {
// Run .env again if it exists in a parent dir
if (this_bundler.options.production) {
- this_bundler.env.load(&this_bundler.fs.fs, dir, .production) catch {};
+ this_bundler.env.load(dir, .production) catch {};
} else {
- this_bundler.env.load(&this_bundler.fs.fs, dir, .development) catch {};
+ this_bundler.env.load(dir, .development) catch {};
}
}
}
diff --git a/src/env_loader.zig b/src/env_loader.zig
index 7c2c38a99..7f0be98a7 100644
--- a/src/env_loader.zig
+++ b/src/env_loader.zig
@@ -231,7 +231,7 @@ pub const Loader = struct {
if (behavior == .prefix) {
while (iter.next()) |entry| {
- const value: string = entry.value_ptr.*;
+ const value: string = entry.value_ptr.value;
if (strings.startsWith(entry.key_ptr.*, prefix)) {
const key_str = std.fmt.allocPrint(key_allocator, "process.env.{s}", .{entry.key_ptr.*}) catch unreachable;
@@ -282,12 +282,12 @@ pub const Loader = struct {
}
} else {
while (iter.next()) |entry| {
- const value: string = if (entry.value_ptr.*.len == 0) empty_string_value else entry.value_ptr.*;
+ const value: string = if (entry.value_ptr.value.len == 0) empty_string_value else entry.value_ptr.value;
const key = std.fmt.allocPrint(key_allocator, "process.env.{s}", .{entry.key_ptr.*}) catch unreachable;
e_strings[0] = js_ast.E.String{
- .data = if (entry.value_ptr.*.len > 0)
- @as([*]u8, @ptrFromInt(@intFromPtr(entry.value_ptr.*.ptr)))[0..value.len]
+ .data = if (entry.value_ptr.value.len > 0)
+ @as([*]u8, @ptrFromInt(@intFromPtr(entry.value_ptr.value.ptr)))[0..value.len]
else
&[_]u8{},
};
@@ -370,7 +370,6 @@ pub const Loader = struct {
// .env goes last
pub fn load(
this: *Loader,
- fs: *Fs.FileSystem.RealFS,
dir: *Fs.FileSystem.DirEntry,
comptime suffix: enum { development, production, @"test" },
) !void {
@@ -380,19 +379,19 @@ pub const Loader = struct {
switch (comptime suffix) {
.development => {
if (dir.hasComptimeQuery(".env.development.local")) {
- try this.loadEnvFile(fs, dir_handle, ".env.development.local", false);
+ try this.loadEnvFile(dir_handle, ".env.development.local", false, true);
Analytics.Features.dotenv = true;
}
},
.production => {
if (dir.hasComptimeQuery(".env.production.local")) {
- try this.loadEnvFile(fs, dir_handle, ".env.production.local", false);
+ try this.loadEnvFile(dir_handle, ".env.production.local", false, true);
Analytics.Features.dotenv = true;
}
},
.@"test" => {
if (dir.hasComptimeQuery(".env.test.local")) {
- try this.loadEnvFile(fs, dir_handle, ".env.test.local", false);
+ try this.loadEnvFile(dir_handle, ".env.test.local", false, true);
Analytics.Features.dotenv = true;
}
},
@@ -400,7 +399,7 @@ pub const Loader = struct {
if (comptime suffix != .@"test") {
if (dir.hasComptimeQuery(".env.local")) {
- try this.loadEnvFile(fs, dir_handle, ".env.local", false);
+ try this.loadEnvFile(dir_handle, ".env.local", false, false);
Analytics.Features.dotenv = true;
}
}
@@ -408,26 +407,26 @@ pub const Loader = struct {
switch (comptime suffix) {
.development => {
if (dir.hasComptimeQuery(".env.development")) {
- try this.loadEnvFile(fs, dir_handle, ".env.development", false);
+ try this.loadEnvFile(dir_handle, ".env.development", false, true);
Analytics.Features.dotenv = true;
}
},
.production => {
if (dir.hasComptimeQuery(".env.production")) {
- try this.loadEnvFile(fs, dir_handle, ".env.production", false);
+ try this.loadEnvFile(dir_handle, ".env.production", false, true);
Analytics.Features.dotenv = true;
}
},
.@"test" => {
if (dir.hasComptimeQuery(".env.test")) {
- try this.loadEnvFile(fs, dir_handle, ".env.test", false);
+ try this.loadEnvFile(dir_handle, ".env.test", false, true);
Analytics.Features.dotenv = true;
}
},
}
if (dir.hasComptimeQuery(".env")) {
- try this.loadEnvFile(fs, dir_handle, ".env", false);
+ try this.loadEnvFile(dir_handle, ".env", false, false);
Analytics.Features.dotenv = true;
}
@@ -487,8 +486,13 @@ pub const Loader = struct {
Output.flush();
}
- pub fn loadEnvFile(this: *Loader, fs: *Fs.FileSystem.RealFS, dir: std.fs.Dir, comptime base: string, comptime override: bool) !void {
- _ = fs;
+ pub fn loadEnvFile(
+ this: *Loader,
+ dir: std.fs.Dir,
+ comptime base: string,
+ comptime override: bool,
+ comptime conditional: bool,
+ ) !void {
if (@field(this, base) != null) {
return;
}
@@ -565,6 +569,7 @@ pub const Loader = struct {
this.map,
override,
false,
+ conditional,
);
@field(this, base) = source;
@@ -789,6 +794,7 @@ const Parser = struct {
map: *Map,
comptime override: bool,
comptime is_process: bool,
+ comptime conditional: bool,
) void {
var count = map.map.count();
while (this.pos < this.src.len) {
@@ -804,19 +810,25 @@ const Parser = struct {
// https://github.com/oven-sh/bun/issues/1262
if (comptime !override) continue;
} else {
- allocator.free(entry.value_ptr.*);
+ allocator.free(entry.value_ptr.value);
}
}
- entry.value_ptr.* = allocator.dupe(u8, value) catch unreachable;
+ entry.value_ptr.* = .{
+ .value = allocator.dupe(u8, value) catch unreachable,
+ .conditional = conditional,
+ };
}
if (comptime !is_process) {
var it = map.iter();
while (it.next()) |entry| {
if (count > 0) {
count -= 1;
- } else if (expandValue(map, entry.value_ptr.*)) |value| {
- allocator.free(entry.value_ptr.*);
- entry.value_ptr.* = allocator.dupe(u8, value) catch unreachable;
+ } else if (expandValue(map, entry.value_ptr.value)) |value| {
+ allocator.free(entry.value_ptr.value);
+ entry.value_ptr.* = .{
+ .value = allocator.dupe(u8, value) catch unreachable,
+ .conditional = conditional,
+ };
}
}
}
@@ -828,14 +840,19 @@ const Parser = struct {
map: *Map,
comptime override: bool,
comptime is_process: bool,
+ comptime conditional: bool,
) void {
var parser = Parser{ .src = source.contents };
- parser._parse(allocator, map, override, is_process);
+ parser._parse(allocator, map, override, is_process, conditional);
}
};
pub const Map = struct {
- const HashTable = bun.StringArrayHashMap(string);
+ const HashTableValue = struct {
+ value: string,
+ conditional: bool,
+ };
+ const HashTable = bun.StringArrayHashMap(HashTableValue);
map: HashTable,
@@ -848,10 +865,10 @@ pub const Map = struct {
var it = env_map.iterator();
var i: usize = 0;
while (it.next()) |pair| : (i += 1) {
- const env_buf = try arena.allocSentinel(u8, pair.key_ptr.len + pair.value_ptr.len + 1, 0);
+ const env_buf = try arena.allocSentinel(u8, pair.key_ptr.len + pair.value_ptr.value.len + 1, 0);
bun.copy(u8, env_buf, pair.key_ptr.*);
env_buf[pair.key_ptr.len] = '=';
- bun.copy(u8, env_buf[pair.key_ptr.len + 1 ..], pair.value_ptr.*);
+ bun.copy(u8, env_buf[pair.key_ptr.len + 1 ..], pair.value_ptr.value);
envp_buf[i] = env_buf.ptr;
}
std.debug.assert(i == envp_count);
@@ -864,7 +881,10 @@ pub const Map = struct {
var iter_ = this.map.iterator();
while (iter_.next()) |entry| {
- try env_map.putMove(bun.constStrToU8(entry.key_ptr.*), bun.constStrToU8(entry.value_ptr.*));
+ // Allow var from .env.development or .env.production to be loaded again. Also don't clone empty vars.
+ if (!entry.value_ptr.conditional and entry.value_ptr.value.len > 0) {
+ try env_map.putMove(bun.constStrToU8(entry.key_ptr.*), bun.constStrToU8(entry.value_ptr.value));
+ }
}
return env_map;
@@ -879,7 +899,10 @@ pub const Map = struct {
}
pub inline fn put(this: *Map, key: string, value: string) !void {
- try this.map.put(key, value);
+ try this.map.put(key, .{
+ .value = value,
+ .conditional = false,
+ });
}
pub fn jsonStringify(self: *const @This(), writer: anytype) !void {
@@ -907,22 +930,28 @@ pub const Map = struct {
this: *const Map,
key: string,
) ?string {
- return this.map.get(key);
+ return if (this.map.get(key)) |entry| entry.value else null;
}
pub fn get_(
this: *const Map,
key: string,
) ?string {
- return this.map.get(key);
+ return if (this.map.get(key)) |entry| entry.value else null;
}
pub inline fn putDefault(this: *Map, key: string, value: string) !void {
- _ = try this.map.getOrPutValue(key, value);
+ _ = try this.map.getOrPutValue(key, .{
+ .value = value,
+ .conditional = false,
+ });
}
pub inline fn getOrPut(this: *Map, key: string, value: string) !void {
- _ = try this.map.getOrPutValue(key, value);
+ _ = try this.map.getOrPutValue(key, .{
+ .value = value,
+ .conditional = false,
+ });
}
};
diff --git a/src/install/install.zig b/src/install/install.zig
index e8b95b820..bf6422cc7 100644
--- a/src/install/install.zig
+++ b/src/install/install.zig
@@ -5243,7 +5243,7 @@ pub const PackageManager = struct {
};
env.loadProcess();
- try env.load(&fs.fs, entries_option.entries, .production);
+ try env.load(entries_option.entries, .production);
if (env.map.get("BUN_INSTALL_VERBOSE") != null) {
PackageManager.verbose_install = true;
diff --git a/src/install/lockfile.zig b/src/install/lockfile.zig
index 0b5e0d7bc..a9bee2d27 100644
--- a/src/install/lockfile.zig
+++ b/src/install/lockfile.zig
@@ -983,7 +983,7 @@ pub const Printer = struct {
};
env_loader.loadProcess();
- try env_loader.load(&fs.fs, entries_option.entries, .production);
+ try env_loader.load(entries_option.entries, .production);
var log = logger.Log.init(allocator);
try options.load(
allocator,
diff --git a/src/io/io_darwin.zig b/src/io/io_darwin.zig
index 226a4d284..cb2d15afb 100644
--- a/src/io/io_darwin.zig
+++ b/src/io/io_darwin.zig
@@ -1350,6 +1350,12 @@ pub fn read(
struct {
fn doOperation(op: anytype) ReadError!usize {
while (true) {
+ if (op.positional) {
+ const rc = os.system.lseek(op.fd, @intCast(op.offset), 0);
+ if (rc == -1) {
+ return error.Unseekable;
+ }
+ }
const rc = os.system.read(
op.fd,
op.buf,
diff --git a/src/resolver/resolve_path.zig b/src/resolver/resolve_path.zig
index 4800d7d90..f74211709 100644
--- a/src/resolver/resolve_path.zig
+++ b/src/resolver/resolve_path.zig
@@ -471,7 +471,7 @@ pub fn relativePlatform(from: []const u8, to: []const u8, comptime platform: Pla
Fs.FileSystem.instance.top_level_dir,
&relative_from_buf,
&[_][]const u8{
- normalizeStringBuf(from, relative_from_buf[1..], false, platform, true),
+ normalizeStringBuf(from, relative_from_buf[1..], true, platform, true),
},
platform,
);
@@ -484,7 +484,7 @@ pub fn relativePlatform(from: []const u8, to: []const u8, comptime platform: Pla
Fs.FileSystem.instance.top_level_dir,
&relative_to_buf,
&[_][]const u8{
- normalizeStringBuf(to, relative_to_buf[1..], false, platform, true),
+ normalizeStringBuf(to, relative_to_buf[1..], true, platform, true),
},
platform,
);
diff --git a/test/cli/run/env.test.ts b/test/cli/run/env.test.ts
index 159793e27..3ed300477 100644
--- a/test/cli/run/env.test.ts
+++ b/test/cli/run/env.test.ts
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test";
-import { bunRun, bunTest, tempDirWithFiles, bunExe, bunEnv } from "harness";
+import { bunRun, bunRunAsScript, bunTest, tempDirWithFiles, bunExe, bunEnv } from "harness";
import path from "path";
function bunRunWithoutTrim(file: string, env?: Record<string, string>) {
@@ -255,6 +255,47 @@ test(".env process variables no comments", () => {
expect(stdout).toBe('test#1 "test#2"');
});
+describe("package scripts load from .env.production and .env.development", () => {
+ test("NODE_ENV=production", () => {
+ const dir = tempDirWithFiles("dotenv-package-script-prod", {
+ "index.ts": "console.log(process.env.TEST);",
+ "package.json": `
+ {
+ "name": "foo",
+ "version": "2.0",
+ "scripts": {
+ "test": "NODE_ENV=production ${bunExe()} run index.ts",
+ }
+ }
+ `,
+ ".env.production": "TEST=prod",
+ ".env.development": "TEST=dev",
+ });
+
+ const { stdout } = bunRunAsScript(dir, "test");
+ expect(stdout).toBe("prod");
+ });
+ test("NODE_ENV=development", () => {
+ const dir = tempDirWithFiles("dotenv-package-script-prod", {
+ "index.ts": "console.log(process.env.TEST);",
+ "package.json": `
+ {
+ "name": "foo",
+ "version": "2.0",
+ "scripts": {
+ "test": "NODE_ENV=development ${bunExe()} run index.ts",
+ }
+ }
+ `,
+ ".env.production": "TEST=prod",
+ ".env.development": "TEST=dev",
+ });
+
+ const { stdout } = bunRunAsScript(dir, "test");
+ expect(stdout).toBe("dev");
+ });
+});
+
test(".env escaped dollar sign", () => {
const dir = tempDirWithFiles("dotenv-dollar", {
".env": "FOO=foo\nBAR=\\$FOO",
diff --git a/test/js/bun/io/bun-write.test.js b/test/js/bun/io/bun-write.test.js
index b67df9405..f435d2ceb 100644
--- a/test/js/bun/io/bun-write.test.js
+++ b/test/js/bun/io/bun-write.test.js
@@ -291,6 +291,15 @@ it.skip("Bun.write('output.html', HTMLRewriter.transform(Bun.file)))", async don
done();
});
+it("offset should work #4963", async () => {
+ const filename = tmpdir() + "/bun.test.offset.txt";
+ await Bun.write(filename, "contents");
+ const file = Bun.file(filename);
+ const slice = file.slice(2, file.size);
+ const contents = await slice.text();
+ expect(contents).toBe("ntents");
+});
+
it("#2674", async () => {
const file = path.join(import.meta.dir, "big-stdout.js");
diff --git a/test/js/node/buffer.test.js b/test/js/node/buffer.test.js
index 7c3d16536..afc9cdee8 100644
--- a/test/js/node/buffer.test.js
+++ b/test/js/node/buffer.test.js
@@ -2572,3 +2572,16 @@ it("construct buffer from UTF16, issue #3914", () => {
const buf = Buffer.from(str, "latin1");
expect(buf).toStrictEqual(raw);
});
+
+it("construct buffer from hex, issue #4919", () => {
+ const data = "测试63e9f6c4b04fa8c80f3fb0ee";
+
+ const slice1 = data.substring(0, 2);
+ const slice2 = data.substring(2);
+
+ const buf1 = Buffer.from(slice1, "hex");
+ const buf2 = Buffer.from(slice2, "hex");
+
+ expect(buf1).toStrictEqual(Buffer.from([]));
+ expect(buf2).toStrictEqual(Buffer.from([0x63, 0xe9, 0xf6, 0xc4, 0xb0, 0x4f, 0xa8, 0xc8, 0x0f, 0x3f, 0xb0, 0xee]));
+});
diff --git a/test/js/node/path/path.test.js b/test/js/node/path/path.test.js
index 3c8a04d72..5865d6182 100644
--- a/test/js/node/path/path.test.js
+++ b/test/js/node/path/path.test.js
@@ -415,6 +415,9 @@ it("path.join", () => {
it("path.relative", () => {
const failures = [];
+ const cwd = process.cwd();
+ const cwdParent = path.dirname(cwd);
+ const parentIsRoot = cwdParent == "/";
const relativeTests = [
// [
@@ -477,6 +480,16 @@ it("path.relative", () => {
["/webp4ck-hot-middleware", "/webpack/buildin/module.js", "../webpack/buildin/module.js"],
["/webpack-hot-middleware", "/webp4ck/buildin/module.js", "../webp4ck/buildin/module.js"],
["/var/webpack-hot-middleware", "/var/webpack/buildin/module.js", "../webpack/buildin/module.js"],
+ ["/app/node_modules/pkg", "../static", `../../..${parentIsRoot ? "" : cwdParent}/static`],
+ ["/app/node_modules/pkg", "../../static", `../../..${parentIsRoot ? "" : path.dirname(cwdParent)}/static`],
+ ["/app", "../static", `..${parentIsRoot ? "" : cwdParent}/static`],
+ ["/app", "../".repeat(64) + "static", "../static"],
+ [".", "../static", cwd == "/" ? "static" : "../static"],
+ ["/", "../static", parentIsRoot ? "static" : `${cwdParent}/static`.slice(1)],
+ ["../", "../", ""],
+ ["../", "../../", parentIsRoot ? "" : ".."],
+ ["../../", "../", parentIsRoot ? "" : path.basename(cwdParent)],
+ ["../../", "../../", ""],
],
],
];