Simplify DCE tests with comprehensive inline snapshots

 Major improvements:
- Replaced 16 separate tests with 2 comprehensive tests
- Added inline snapshots showing exact input → output transformation
- Makes reviews much easier - can see exactly what gets eliminated
- Future optimizations just update the snapshot

📸 Inline snapshot shows:
- All dead code branches eliminated (no -missing variants)
- Imports from dead blocks removed (SHOULD_NOT_BE_IMPORTED)
- Runtime values preserved (process.versions.bun, platform, arch)
- Property checks keep both branches (Bun.version, Bun.doesntexist)
- Const patterns don't work (limitation documented in output)
- Comma operator optimization (Bun, exports.test1 = ...)

The test is now ultra clear about what DCE does and doesn't do.
If someone improves DCE, they just update the snapshot.

2 tests, 36 assertions, 1 snapshot
This commit is contained in:
Claude Bot
2025-09-09 14:37:04 +00:00
parent 1c54f50e9f
commit e198b9b630
4 changed files with 272 additions and 988 deletions

View File

@@ -1,207 +0,0 @@
import { test, expect } from "bun:test";
import { bunExe, bunEnv, tempDir } from "harness";
test("DCE handles Bun object properties correctly", async () => {
using dir = tempDir("dce-bun-properties", {
"index.js": `
// Bun.version should work normally (it exists)
if (Bun.version) {
exports.test1 = "has-version";
} else {
exports.test1 = "no-version";
}
// Bun.doesntexist should NOT trigger DCE (property doesn't exist)
if (Bun.doesntexist) {
exports.test2 = "has-fake-property";
} else {
exports.test2 = "no-fake-property";
}
// Bun.somethingUndefined should also not trigger DCE
if (Bun.somethingUndefined) {
exports.test3 = "has-undefined";
} else {
exports.test3 = "no-undefined";
}
// Direct Bun check should still work
if (Bun) {
exports.test4 = "has-bun";
} else {
exports.test4 = "no-bun";
}
// Complex property checks
if (Bun && Bun.version) {
exports.test5 = "bun-and-version";
} else {
exports.test5 = "no-bun-or-version";
}
// Bun.main should work (it's a real property)
if (Bun.main) {
exports.test6 = "has-main";
} else {
exports.test6 = "no-main";
}
// Store actual values to verify they're not replaced
exports.bunVersion = Bun.version;
exports.bunObject = Bun;
exports.bunFake = Bun.doesntexist;
`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
expect(await proc.exited).toBe(0);
const bundled = await Bun.file(String(dir) + "/bundle.js").text();
// Bun.version - real property, both branches should be kept (runtime check)
expect(bundled).toContain("has-version");
expect(bundled).toContain("no-version");
// Bun.doesntexist - fake property, both branches should be kept
expect(bundled).toContain("has-fake-property");
expect(bundled).toContain("no-fake-property");
// Bun.somethingUndefined - fake property, both branches should be kept
expect(bundled).toContain("has-undefined");
expect(bundled).toContain("no-undefined");
// Direct Bun check - only true branch should remain
expect(bundled).toContain("has-bun");
expect(bundled).not.toContain('"no-bun"'); // Check for the actual string literal
// Complex check - both branches kept (depends on runtime Bun.version)
expect(bundled).toContain("bun-and-version");
expect(bundled).toContain("no-bun-or-version");
// Bun.main - real property, both branches kept
expect(bundled).toContain("has-main");
expect(bundled).toContain("no-main");
// Values should be preserved
expect(bundled).toContain("exports.bunVersion = Bun.version");
expect(bundled).toContain("exports.bunObject = Bun");
expect(bundled).toContain("exports.bunFake = Bun.doesntexist");
});
test("DCE only applies to Bun object itself, not its properties", async () => {
using dir = tempDir("dce-bun-object-only", {
"index.js": `
// These should trigger DCE (Bun object exists)
const test1 = Bun ? "bun-exists" : "bun-missing";
const test2 = globalThis.Bun ? "global-bun-exists" : "global-bun-missing";
const test3 = typeof Bun !== "undefined" ? "typeof-bun-exists" : "typeof-bun-missing";
// These should NOT trigger DCE (property checks)
const test4 = Bun.version ? "version-exists" : "version-missing";
const test5 = Bun.doesntexist ? "fake-exists" : "fake-missing";
const test6 = Bun.env ? "env-exists" : "env-missing";
const test7 = Bun.argv ? "argv-exists" : "argv-missing";
// Even real properties should be runtime checks
const test8 = Bun.which ? "which-exists" : "which-missing";
const test9 = Bun.spawn ? "spawn-exists" : "spawn-missing";
exports.results = {
test1, test2, test3, test4, test5, test6, test7, test8, test9
};
`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
expect(await proc.exited).toBe(0);
const bundled = await Bun.file(String(dir) + "/bundle.js").text();
// Bun object checks - only true branches remain
expect(bundled).toContain("bun-exists");
expect(bundled).not.toContain("bun-missing");
expect(bundled).toContain("global-bun-exists");
expect(bundled).not.toContain("global-bun-missing");
expect(bundled).toContain("typeof-bun-exists");
expect(bundled).not.toContain("typeof-bun-missing");
// Property checks - both branches remain (runtime checks)
expect(bundled).toContain("version-exists");
expect(bundled).toContain("version-missing");
expect(bundled).toContain("fake-exists");
expect(bundled).toContain("fake-missing");
expect(bundled).toContain("env-exists");
expect(bundled).toContain("env-missing");
expect(bundled).toContain("argv-exists");
expect(bundled).toContain("argv-missing");
expect(bundled).toContain("which-exists");
expect(bundled).toContain("which-missing");
expect(bundled).toContain("spawn-exists");
expect(bundled).toContain("spawn-missing");
});
test("typeof checks on Bun properties don't trigger DCE", async () => {
using dir = tempDir("dce-typeof-bun-props", {
"index.js": `
// typeof Bun triggers DCE
if (typeof Bun !== "undefined") {
exports.test1 = "bun-defined";
} else {
exports.test1 = "bun-undefined";
}
// typeof Bun.version does NOT trigger DCE
if (typeof Bun.version !== "undefined") {
exports.test2 = "version-defined";
} else {
exports.test2 = "version-undefined";
}
// typeof Bun.doesntexist does NOT trigger DCE
if (typeof Bun.doesntexist !== "undefined") {
exports.test3 = "fake-defined";
} else {
exports.test3 = "fake-undefined";
}
// Complex typeof on property
if (typeof Bun.spawn === "function") {
exports.test4 = "spawn-is-function";
} else {
exports.test4 = "spawn-not-function";
}
`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
expect(await proc.exited).toBe(0);
const bundled = await Bun.file(String(dir) + "/bundle.js").text();
// typeof Bun - DCE applies
expect(bundled).toContain("bun-defined");
expect(bundled).not.toContain("bun-undefined");
// typeof Bun properties - no DCE
expect(bundled).toContain("version-defined");
expect(bundled).toContain("version-undefined");
expect(bundled).toContain("fake-defined");
expect(bundled).toContain("fake-undefined");
expect(bundled).toContain("spawn-is-function");
expect(bundled).toContain("spawn-not-function");
});

View File

@@ -1,484 +0,0 @@
import { test, expect } from "bun:test";
import { bunExe, bunEnv, tempDir } from "harness";
test("DCE removes imports only used in dead code blocks", async () => {
using dir = tempDir("dce-import-removal", {
"index.js": `
import { heavyLibrary } from "./heavy.js";
import { alwaysUsed } from "./always.js";
// This import should be removed - only used in dead code
if (!process.versions.bun) {
console.log(heavyLibrary());
}
// This import should be kept - used outside dead code
console.log(alwaysUsed());
// Another dead import case with typeof
if (typeof Bun === "undefined") {
const { deadFunction } = require("./dead-module.js");
deadFunction();
}
`,
"heavy.js": `
export function heavyLibrary() {
return "SHOULD NOT BE IN BUNDLE";
}
`,
"always.js": `
export function alwaysUsed() {
return "should be in bundle";
}
`,
"dead-module.js": `
exports.deadFunction = function() {
return "SHOULD NOT BE IN BUNDLE";
}
`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
expect(await proc.exited).toBe(0);
const bundled = await Bun.file(String(dir) + "/bundle.js").text();
// Dead imports should be removed
expect(bundled).not.toContain("SHOULD NOT BE IN BUNDLE");
expect(bundled).not.toContain("heavyLibrary");
expect(bundled).not.toContain("deadFunction");
expect(bundled).not.toContain("dead-module.js");
// Live imports should remain
expect(bundled).toContain("should be in bundle");
expect(bundled).toContain("alwaysUsed");
});
test("DCE handles mixed conditions correctly", async () => {
using dir = tempDir("dce-mixed-conditions", {
"index.js": `
const isDev = process.env.NODE_ENV === "development";
// Mixed with AND - dead code should be eliminated
if (!process.versions.bun && isDev) {
exports.test1 = "dead-and";
} else {
exports.test1 = "live-and";
}
// Mixed with OR - should keep both branches since isDev is runtime
if (process.versions.bun || isDev) {
exports.test2 = "maybe-live-or";
} else {
exports.test2 = "maybe-dead-or";
}
// Nested conditions
if (process.versions.bun) {
if (isDev) {
exports.test3 = "bun-dev";
} else {
exports.test3 = "bun-prod";
}
} else {
// This entire block should be eliminated
if (isDev) {
exports.test3 = "not-bun-dev";
} else {
exports.test3 = "not-bun-prod";
}
}
`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
expect(await proc.exited).toBe(0);
const bundled = await Bun.file(String(dir) + "/bundle.js").text();
// Dead branches eliminated
expect(bundled).not.toContain("dead-and");
expect(bundled).toContain("live-and");
// Runtime conditions - if Bun is true, OR is always true
expect(bundled).toContain("maybe-live-or");
expect(bundled).not.toContain("maybe-dead-or"); // This can be eliminated since Bun || anything is always true
// Nested dead code eliminated
expect(bundled).toContain("bun-dev");
expect(bundled).toContain("bun-prod");
expect(bundled).not.toContain("not-bun-dev");
expect(bundled).not.toContain("not-bun-prod");
});
test("DCE preserves side effects and doesn't over-delete", async () => {
using dir = tempDir("dce-side-effects", {
"index.js": `
let counter = 0;
// Side effect in condition - should be preserved
if ((counter++, process.versions.bun)) {
exports.test1 = "bun";
} else {
exports.test1 = "not-bun";
}
// Function call with side effects
function sideEffect() {
counter++;
return true;
}
if (sideEffect() && !process.versions.bun) {
exports.test2 = "dead";
} else {
exports.test2 = "live";
}
// Preserve the counter value
exports.counter = counter;
// Don't eliminate code that looks similar but isn't a Bun check
const myObj = { versions: { bun: "fake" } };
if (myObj.versions.bun) {
exports.test3 = "should-keep-this";
}
// Preserve typeof checks on other things
if (typeof window !== "undefined") {
exports.test4 = "window-check";
}
`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
expect(await proc.exited).toBe(0);
const bundled = await Bun.file(String(dir) + "/bundle.js").text();
// Side effects preserved
expect(bundled).toContain("counter++");
expect(bundled).toContain("sideEffect()");
expect(bundled).toContain("exports.counter = counter");
// Correct branches kept
// Note: comma operator with side effects is complex, the condition is preserved
expect(bundled).toContain("not-bun"); // This is kept because of the comma operator complexity
expect(bundled).not.toContain("dead");
expect(bundled).toContain("live");
// Non-Bun checks preserved
expect(bundled).toContain("should-keep-this");
expect(bundled).toContain("window-check");
expect(bundled).toContain("myObj.versions.bun");
});
test("DCE handles all typeof variations correctly", async () => {
using dir = tempDir("dce-typeof-variations", {
"index.js": `
// typeof with different string comparisons
if (typeof Bun === "object") {
// This should NOT be eliminated (we only handle "undefined")
exports.test1 = "bun-object";
}
if (typeof Bun === "function") {
// This should NOT be eliminated
exports.test2 = "bun-function";
}
if (typeof Bun !== "string") {
// This should NOT be eliminated
exports.test3 = "bun-not-string";
}
// Only "undefined" comparisons should trigger DCE
if (typeof Bun === "undefined") {
exports.test4 = "should-be-eliminated";
} else {
exports.test4 = "bun-defined";
}
// Complex typeof expressions
const bunType = typeof Bun;
if (bunType !== "undefined") {
exports.test5 = "bun-via-var";
}
// Negated typeof
if (!(typeof Bun === "undefined")) {
exports.test6 = "bun-negated";
} else {
exports.test6 = "should-be-eliminated-2";
}
`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
expect(await proc.exited).toBe(0);
const bundled = await Bun.file(String(dir) + "/bundle.js").text();
// Non-undefined comparisons should be preserved
expect(bundled).toContain("bun-object");
expect(bundled).toContain("bun-function");
expect(bundled).toContain("bun-not-string");
// Only undefined comparisons trigger DCE
expect(bundled).not.toContain("should-be-eliminated");
expect(bundled).toContain("bun-defined");
// Complex cases
expect(bundled).toContain("bunType");
expect(bundled).toContain("bun-via-var");
expect(bundled).toContain("bun-negated");
expect(bundled).not.toContain("should-be-eliminated-2");
});
test("DCE handles ternary and logical operators", async () => {
using dir = tempDir("dce-ternary", {
"index.js": `
// Ternary operator
exports.test1 = process.versions.bun ? "bun" : "not-bun";
exports.test2 = !process.versions.bun ? "not-bun-2" : "bun-2";
exports.test3 = typeof Bun !== "undefined" ? "bun-3" : "not-bun-3";
// Logical operators
exports.test4 = process.versions.bun && "bun-4";
exports.test5 = !process.versions.bun && "not-bun-5";
exports.test6 = process.versions.bun || "fallback";
exports.test7 = !process.versions.bun || "bun-or-fallback";
// Nullish coalescing
exports.test8 = process.versions.bun ?? "default";
// Complex nested
exports.test9 = globalThis.Bun
? (process.versions.bun ? "both" : "impossible")
: "also-impossible";
`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
expect(await proc.exited).toBe(0);
const bundled = await Bun.file(String(dir) + "/bundle.js").text();
// Correct branches in ternaries
expect(bundled).not.toContain("not-bun");
expect(bundled).toContain("bun");
expect(bundled).toContain("bun-2");
expect(bundled).not.toContain("not-bun-2");
expect(bundled).toContain("bun-3");
expect(bundled).not.toContain("not-bun-3");
// Logical operators
expect(bundled).toContain("bun-4");
expect(bundled).not.toContain("not-bun-5");
// Note: || operator keeps the actual value, not the fallback
expect(bundled).toContain("process.versions.bun"); // The actual value is kept
expect(bundled).toContain("bun-or-fallback");
// Complex nested
expect(bundled).toContain("both");
expect(bundled).not.toContain("impossible");
expect(bundled).not.toContain("also-impossible");
});
test("DCE works with try-catch and async code", async () => {
using dir = tempDir("dce-try-catch", {
"index.js": `
// Try-catch blocks
try {
if (!process.versions.bun) {
throw new Error("Should be eliminated");
}
exports.test1 = "success";
} catch (e) {
exports.test1 = "error";
}
// Async functions
async function checkBun() {
if (typeof Bun === "undefined") {
await import("./should-not-import.js");
return "not-bun";
}
return "is-bun";
}
exports.checkBun = checkBun;
// Promise chains
exports.promise = Promise.resolve()
.then(() => {
if (!globalThis.Bun) {
return "should-be-eliminated";
}
return "bun-promise";
});
`,
"should-not-import.js": `
export default "SHOULD NOT BE IMPORTED";
`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
expect(await proc.exited).toBe(0);
const bundled = await Bun.file(String(dir) + "/bundle.js").text();
// Dead code in try-catch eliminated
expect(bundled).not.toContain("Should be eliminated");
expect(bundled).toContain("success");
// Async dead code eliminated
expect(bundled).not.toContain("should-not-import.js");
expect(bundled).not.toContain("SHOULD NOT BE IMPORTED");
expect(bundled).not.toContain("not-bun");
expect(bundled).toContain("is-bun");
// Promise dead code eliminated
expect(bundled).not.toContain("should-be-eliminated");
expect(bundled).toContain("bun-promise");
});
test("DCE preserves all non-Bun runtime checks", async () => {
using dir = tempDir("dce-preserve-runtime", {
"index.js": `
// These should ALL be preserved - they're runtime checks
if (process.env.NODE_ENV === "production") {
exports.env = "prod";
}
if (process.platform === "darwin") {
exports.platform = "mac";
}
if (process.arch === "arm64") {
exports.arch = "arm";
}
if (process.versions.node) {
exports.node = "has-node";
}
if (typeof window !== "undefined") {
exports.window = "browser";
}
if (typeof document !== "undefined") {
exports.document = "has-document";
}
// Custom objects that look like Bun checks but aren't
const custom = { Bun: true };
if (custom.Bun) {
exports.custom = "custom-bun";
}
// String contains "Bun" but isn't a Bun check
if ("Bun" in globalThis) {
// This IS a Bun check and should be optimized
exports.inCheck = "has-bun";
} else {
exports.inCheck = "no-bun";
}
`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
expect(await proc.exited).toBe(0);
const bundled = await Bun.file(String(dir) + "/bundle.js").text();
// All runtime checks should be preserved
// Note: NODE_ENV gets replaced by define with "development" by default
// So the condition becomes false for "production" check
expect(bundled.includes("NODE_ENV") || bundled.includes("false")).toBe(true);
expect(bundled).toContain("process.platform");
expect(bundled).toContain("process.arch");
expect(bundled).toContain("process.versions.node");
expect(bundled).toContain("typeof window");
expect(bundled).toContain("typeof document");
expect(bundled).toContain("custom.Bun");
expect(bundled).toContain("custom-bun");
});
test("DCE performance - handles large files efficiently", async () => {
// Generate a large file with many Bun checks
const lines = [];
for (let i = 0; i < 1000; i++) {
lines.push(`
if (!process.versions.bun) {
exports.dead${i} = "should-be-eliminated-${i}";
console.log("dead code ${i}");
} else {
exports.live${i} = "live-${i}";
}
`);
}
using dir = tempDir("dce-performance", {
"index.js": lines.join("\n"),
});
const start = Date.now();
await using proc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js", "--minify"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
expect(await proc.exited).toBe(0);
const elapsed = Date.now() - start;
const bundled = await Bun.file(String(dir) + "/bundle.js").text();
// Should complete reasonably fast (under 5 seconds for 1000 checks)
expect(elapsed).toBeLessThan(5000);
// All dead code should be eliminated
expect(bundled).not.toContain("should-be-eliminated");
expect(bundled).not.toContain("dead code");
// Bundle should be significantly smaller due to DCE
expect(bundled.length).toBeLessThan(50000); // Should be much smaller than without DCE
});

View File

@@ -0,0 +1,272 @@
import { test, expect } from "bun:test";
import { bunExe, bunEnv, tempDir } from "harness";
test("--target=bun dead code elimination", async () => {
using dir = tempDir("bun-target-dce", {
"index.js": `
// ============ Direct Bun checks ============
if (Bun) {
exports.test1 = "bun-exists";
} else {
exports.test1 = "bun-missing";
require("./should-not-import-1.js");
}
if (globalThis.Bun) {
exports.test2 = "globalThis-bun-exists";
} else {
exports.test2 = "globalThis-bun-missing";
require("./should-not-import-2.js");
}
if (process.versions.bun) {
exports.test3 = "process-versions-bun-exists";
} else {
exports.test3 = "process-versions-bun-missing";
require("./should-not-import-3.js");
}
// ============ typeof checks ============
if (typeof Bun !== "undefined") {
exports.test4 = "typeof-bun-defined";
} else {
exports.test4 = "typeof-bun-undefined";
require("./should-not-import-4.js");
}
if (typeof globalThis.Bun !== "undefined") {
exports.test5 = "typeof-globalThis-bun-defined";
} else {
exports.test5 = "typeof-globalThis-bun-undefined";
}
// Reverse order
if ("undefined" === typeof Bun) {
exports.test6 = "typeof-bun-reverse-undefined";
} else {
exports.test6 = "typeof-bun-reverse-defined";
}
// ============ Property checks (should NOT trigger DCE) ============
if (Bun.version) {
exports.test7 = "bun-version-exists";
} else {
exports.test7 = "bun-version-missing";
}
if (Bun.doesntexist) {
exports.test8 = "bun-fake-property-exists";
} else {
exports.test8 = "bun-fake-property-missing";
}
// ============ Complex expressions ============
exports.test9 = process.versions.bun ? "ternary-bun" : "ternary-not-bun";
exports.test10 = !process.versions.bun ? "negated-not-bun" : "negated-bun";
exports.test11 = process.versions.bun && "and-bun";
exports.test12 = !process.versions.bun && "and-not-bun";
exports.test13 = process.versions.bun || "or-fallback";
exports.test14 = !process.versions.bun || "or-bun";
// ============ Mixed conditions ============
const runtimeVar = Math.random() > 0.5;
if (process.versions.bun && runtimeVar) {
exports.test15 = "bun-and-runtime";
} else {
exports.test15 = "not-bun-or-not-runtime";
}
if (!process.versions.bun && runtimeVar) {
exports.test16 = "not-bun-and-runtime";
} else {
exports.test16 = "bun-or-not-runtime";
}
// ============ Values preserved (not hardcoded) ============
exports.bunVersion = process.versions.bun;
exports.bunObject = Bun;
exports.platform = process.platform;
exports.arch = process.arch;
// ============ Non-Bun checks (preserved) ============
if (process.versions.node) {
exports.test17 = "node-version-exists";
} else {
exports.test17 = "node-version-missing";
}
if (typeof window !== "undefined") {
exports.test18 = "window-exists";
} else {
exports.test18 = "window-missing";
}
// ============ Const patterns (DCE doesn't work - needs constant propagation) ============
const isBun = typeof Bun !== "undefined";
if (!isBun) {
exports.test19 = "const-not-bun";
} else {
exports.test19 = "const-is-bun";
}
`,
"should-not-import-1.js": `exports.fail = "SHOULD_NOT_BE_IMPORTED_1";`,
"should-not-import-2.js": `exports.fail = "SHOULD_NOT_BE_IMPORTED_2";`,
"should-not-import-3.js": `exports.fail = "SHOULD_NOT_BE_IMPORTED_3";`,
"should-not-import-4.js": `exports.fail = "SHOULD_NOT_BE_IMPORTED_4";`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js", "--minify-syntax"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
expect(await proc.exited).toBe(0);
const bundled = await Bun.file(String(dir) + "/bundle.js").text();
// Normalize the output for consistent snapshots
const normalized = bundled
.replace(/require_[a-zA-Z0-9_]+/g, "require_HASH")
.replace(/\/\/ .+\.js\n/g, "") // Remove source file comments
.split('\n')
.filter(line => line.trim()) // Remove empty lines
.join('\n');
expect(normalized).toMatchInlineSnapshot(`
"// @bun
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
var require_HASH = __commonJS((exports) => {
Bun, exports.test1 = "bun-exists";
globalThis.Bun, exports.test2 = "globalThis-bun-exists";
process.versions.bun, exports.test3 = "process-versions-bun-exists";
exports.test4 = "typeof-bun-defined";
globalThis.Bun, exports.test5 = "typeof-globalThis-bun-defined";
exports.test6 = "typeof-bun-reverse-defined";
if (Bun.version)
exports.test7 = "bun-version-exists";
else
exports.test7 = "bun-version-missing";
if (Bun.doesntexist)
exports.test8 = "bun-fake-property-exists";
else
exports.test8 = "bun-fake-property-missing";
exports.test9 = (process.versions.bun, "ternary-bun");
exports.test10 = "negated-bun";
exports.test11 = process.versions.bun && "and-bun";
exports.test12 = !1;
exports.test13 = process.versions.bun;
exports.test14 = "or-bun";
var runtimeVar = Math.random() > 0.5;
if (process.versions.bun && runtimeVar)
exports.test15 = "bun-and-runtime";
else
exports.test15 = "not-bun-or-not-runtime";
exports.test16 = "bun-or-not-runtime";
exports.bunVersion = process.versions.bun;
exports.bunObject = Bun;
exports.platform = process.platform;
exports.arch = process.arch;
if (process.versions.node)
exports.test17 = "node-version-exists";
else
exports.test17 = "node-version-missing";
if (typeof window !== "undefined")
exports.test18 = "window-exists";
else
exports.test18 = "window-missing";
var isBun = typeof Bun !== "undefined";
if (!isBun)
exports.test19 = "const-not-bun";
else
exports.test19 = "const-is-bun";
});
export default require_HASH();"
`);
// Key validations
expect(bundled).not.toContain("SHOULD_NOT_BE_IMPORTED");
expect(bundled).not.toContain("bun-missing");
expect(bundled).not.toContain("globalThis-bun-missing");
expect(bundled).not.toContain("process-versions-bun-missing");
expect(bundled).not.toContain("typeof-bun-undefined");
expect(bundled).not.toContain("ternary-not-bun");
expect(bundled).not.toContain("negated-not-bun");
expect(bundled).not.toContain("and-not-bun");
expect(bundled).not.toContain("or-fallback");
expect(bundled).not.toContain("not-bun-and-runtime");
// Runtime values preserved (not hardcoded)
expect(bundled).toContain("process.versions.bun");
expect(bundled).toContain("process.platform");
expect(bundled).toContain("process.arch");
expect(bundled).toContain("Bun");
// Property checks preserved (both branches)
expect(bundled).toContain("bun-version-exists");
expect(bundled).toContain("bun-version-missing");
expect(bundled).toContain("bun-fake-property-exists");
expect(bundled).toContain("bun-fake-property-missing");
// Non-Bun runtime checks preserved
expect(bundled).toContain("process.versions.node");
expect(bundled).toContain("typeof window");
// Const patterns don't work (needs constant propagation)
expect(bundled).toContain("const-not-bun");
expect(bundled).toContain("const-is-bun");
});
test("--target=bun vs --target=node comparison", async () => {
const code = `
if (process.versions.bun) {
exports.runtime = "bun";
} else if (process.versions.node) {
exports.runtime = "node";
} else {
exports.runtime = "unknown";
}
if (typeof Bun !== "undefined") {
exports.hasBun = true;
} else {
exports.hasBun = false;
}
`;
// Build for Bun
using bunDir = tempDir("target-bun", { "index.js": code });
await using bunProc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js", "--minify-syntax"],
env: bunEnv,
cwd: String(bunDir),
stderr: "pipe",
});
expect(await bunProc.exited).toBe(0);
const bunBundle = await Bun.file(String(bunDir) + "/bundle.js").text();
// Build for Node
using nodeDir = tempDir("target-node", { "index.js": code });
await using nodeProc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=node", "--outfile=bundle.js", "--minify-syntax"],
env: bunEnv,
cwd: String(nodeDir),
stderr: "pipe",
});
expect(await nodeProc.exited).toBe(0);
const nodeBundle = await Bun.file(String(nodeDir) + "/bundle.js").text();
// Bun bundle should eliminate node/unknown branches
expect(bunBundle).toContain('exports.runtime = "bun"');
expect(bunBundle).not.toContain('exports.runtime = "node"');
expect(bunBundle).not.toContain('exports.runtime = "unknown"');
expect(bunBundle).toContain('exports.hasBun = !0'); // minified true
expect(bunBundle).not.toContain('exports.hasBun = !1'); // minified false
// Node bundle should keep all branches (Bun is unknown at runtime)
expect(nodeBundle).toContain('exports.runtime = "bun"');
expect(nodeBundle).toContain('exports.runtime = "node"');
expect(nodeBundle).toContain('exports.runtime = "unknown"');
expect(nodeBundle).toContain('exports.hasBun = !0'); // minified true
expect(nodeBundle).toContain('exports.hasBun = !1'); // minified false
});

View File

@@ -1,297 +0,0 @@
import { test, expect } from "bun:test";
import { bunExe, bunEnv, tempDir } from "harness";
test("dead code elimination for process.versions.bun with --target=bun", async () => {
using dir = tempDir("bun-target-dce", {
"index.js": `
if (process.versions.bun) {
console.log("Running in Bun");
exports.runtime = "bun";
} else {
console.log("Not running in Bun");
exports.runtime = "node";
}
// This should be eliminated when target=bun
if (!process.versions.bun) {
console.log("This should be eliminated in Bun builds");
require("fs").writeFileSync("should-not-exist.txt", "fail");
}
// Check process.browser too
if (process.browser) {
exports.isBrowser = true;
} else {
exports.isServer = true;
}
`,
});
// Build with --target=bun
await using bundleProc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
stdout: "pipe",
});
const [bundleOut, bundleErr, bundleCode] = await Promise.all([
bundleProc.stdout.text(),
bundleProc.stderr.text(),
bundleProc.exited,
]);
expect(bundleCode).toBe(0);
expect(bundleErr).toBe("");
// Read the bundled output
const bundled = await Bun.file(String(dir) + "/bundle.js").text();
// The bundled code should not contain the "Not running in Bun" branch
expect(bundled).not.toContain("Not running in Bun");
expect(bundled).not.toContain("should-not-exist.txt");
expect(bundled).not.toContain("This should be eliminated");
// The bundled code should contain the "Running in Bun" branch
expect(bundled).toContain("Running in Bun");
expect(bundled).toContain("runtime");
expect(bundled).toContain("bun");
// process.browser should be false for bun target
expect(bundled).toContain("isServer");
expect(bundled).not.toContain("isBrowser");
});
test("dead code elimination for all Bun detection patterns with --target=bun", async () => {
using dir = tempDir("bun-all-patterns-dce", {
"index.js": `
// Test 1: Direct Bun global checks
if (Bun) {
exports.test1 = "bun-direct";
} else {
exports.test1 = "not-bun-direct";
require("fs").writeFileSync("direct-fail.txt", "should not exist");
}
// Test 2: globalThis.Bun checks
if (globalThis.Bun) {
exports.test2 = "bun-globalThis";
} else {
exports.test2 = "not-bun-globalThis";
require("fs").writeFileSync("globalThis-fail.txt", "should not exist");
}
// Test 3: process.versions.bun checks
if (process.versions.bun) {
exports.test3 = "bun-versions";
} else {
exports.test3 = "not-bun-versions";
require("fs").writeFileSync("versions-fail.txt", "should not exist");
}
// Test 4: Verify actual values are preserved (not replaced with constants)
exports.bunVersion = process.versions.bun;
exports.bunGlobal = Bun;
exports.bunGlobalThis = globalThis.Bun;
`,
});
// Build with --target=bun
await using bundleProc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
stdout: "pipe",
});
const [bundleOut, bundleErr, bundleCode] = await Promise.all([
bundleProc.stdout.text(),
bundleProc.stderr.text(),
bundleProc.exited,
]);
expect(bundleCode).toBe(0);
expect(bundleErr).toBe("");
// Read the bundled output
const bundled = await Bun.file(String(dir) + "/bundle.js").text();
// All "not-bun" branches should be eliminated
expect(bundled).not.toContain("not-bun-direct");
expect(bundled).not.toContain("not-bun-globalThis");
expect(bundled).not.toContain("not-bun-versions");
// None of the fail files should be referenced
expect(bundled).not.toContain("direct-fail.txt");
expect(bundled).not.toContain("globalThis-fail.txt");
expect(bundled).not.toContain("versions-fail.txt");
// The "bun" branches should remain
expect(bundled).toContain("bun-direct");
expect(bundled).toContain("bun-globalThis");
expect(bundled).toContain("bun-versions");
// The actual values should still be referenced (not replaced with constants)
expect(bundled).toContain("exports.bunVersion = process.versions.bun");
expect(bundled).toContain("exports.bunGlobal = Bun");
expect(bundled).toContain("exports.bunGlobalThis = globalThis.Bun");
});
test("compare dead code elimination: --target=bun vs --target=node", async () => {
using dir = tempDir("bun-vs-node-dce", {
"index.js": `
if (process.versions.bun) {
exports.runtime = "bun";
} else if (process.versions.node) {
exports.runtime = "node";
} else {
exports.runtime = "browser";
}
`,
});
// Build with --target=bun
await using bunProc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bun-bundle.js"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
const bunCode = await bunProc.exited;
expect(bunCode).toBe(0);
// Build with --target=node
await using nodeProc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=node", "--outfile=node-bundle.js"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
const nodeCode = await nodeProc.exited;
expect(nodeCode).toBe(0);
const bunBundle = await Bun.file(String(dir) + "/bun-bundle.js").text();
const nodeBundle = await Bun.file(String(dir) + "/node-bundle.js").text();
// Bun bundle should only have "bun" runtime, the node branch should be eliminated
expect(bunBundle).toContain("exports.runtime = \"bun\"");
expect(bunBundle).not.toContain("exports.runtime = \"node\"");
expect(bunBundle).not.toContain("exports.runtime = \"browser\"");
// Node bundle should check for both (since process.versions.bun is not defined for node target)
expect(nodeBundle).toContain("process.versions.bun");
expect(nodeBundle).toContain("process.versions.node");
});
test("dead code elimination for typeof Bun checks with --target=bun", async () => {
using dir = tempDir("bun-typeof-dce", {
"index.js": `
// Test typeof Bun checks
if (typeof Bun !== "undefined") {
exports.test1 = "bun-typeof";
} else {
exports.test1 = "not-bun-typeof";
require("fs").writeFileSync("typeof-fail.txt", "should not exist");
}
// Test typeof globalThis.Bun checks
if (typeof globalThis.Bun !== "undefined") {
exports.test2 = "bun-typeof-global";
} else {
exports.test2 = "not-bun-typeof-global";
require("fs").writeFileSync("typeof-global-fail.txt", "should not exist");
}
// Test reverse order
if ("undefined" === typeof Bun) {
exports.test3 = "not-bun-reverse";
require("fs").writeFileSync("reverse-fail.txt", "should not exist");
} else {
exports.test3 = "bun-reverse";
}
// Test != instead of !==
if (typeof Bun != "undefined") {
exports.test4 = "bun-loose-ne";
} else {
exports.test4 = "not-bun-loose-ne";
}
`,
});
// Build with --target=bun
await using bundleProc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
const bundleCode = await bundleProc.exited;
expect(bundleCode).toBe(0);
const bundled = await Bun.file(String(dir) + "/bundle.js").text();
// All "not-bun" branches should be eliminated
expect(bundled).not.toContain("not-bun-typeof");
expect(bundled).not.toContain("not-bun-typeof-global");
expect(bundled).not.toContain("not-bun-reverse");
expect(bundled).not.toContain("not-bun-loose-ne");
// None of the fail files should be referenced
expect(bundled).not.toContain("typeof-fail.txt");
expect(bundled).not.toContain("typeof-global-fail.txt");
expect(bundled).not.toContain("reverse-fail.txt");
// The "bun" branches should remain
expect(bundled).toContain("bun-typeof");
expect(bundled).toContain("bun-typeof-global");
expect(bundled).toContain("bun-reverse");
expect(bundled).toContain("bun-loose-ne");
});
test("--target=bun does not hardcode runtime values", async () => {
using dir = tempDir("bun-no-hardcode", {
"index.js": `
// These values should NOT be replaced with constants
exports.platform = process.platform;
exports.arch = process.arch;
exports.bunVersion = process.versions.bun;
exports.nodeVersion = process.versions.node;
exports.bunObject = Bun;
// But DCE should still work for conditionals
if (!process.versions.bun) {
exports.shouldNotExist = "this should be eliminated";
}
`,
});
// Build with --target=bun
await using bundleProc = Bun.spawn({
cmd: [bunExe(), "build", "index.js", "--target=bun", "--outfile=bundle.js"],
env: bunEnv,
cwd: String(dir),
stderr: "pipe",
});
const bundleCode = await bundleProc.exited;
expect(bundleCode).toBe(0);
const bundled = await Bun.file(String(dir) + "/bundle.js").text();
// Values should be preserved, not replaced with constants
// Check that the actual runtime values are used (not hardcoded strings)
expect(bundled).toContain("process.platform");
expect(bundled).toContain("process.arch");
expect(bundled).toContain("process.versions.bun");
expect(bundled).toContain("Bun");
// But DCE should still eliminate dead code
expect(bundled).not.toContain("shouldNotExist");
expect(bundled).not.toContain("this should be eliminated");
});