mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
Continue bundler tests (#2691)
* start refine + skipping some packagejson tests * some more tests * stuff * tests for minify branch * pkgjson * add minify/MergeAdjacentVars * add test for #2699 * more tests! * more tests * finish splitting tests * all but 2 import star tests are good * test
This commit is contained in:
284
test/bundler/bundler_browser.test.ts
Normal file
284
test/bundler/bundler_browser.test.ts
Normal file
@@ -0,0 +1,284 @@
|
||||
import assert from "assert";
|
||||
import dedent from "dedent";
|
||||
import { bundlerTest, expectBundled, itBundled, testForFile } from "./expectBundled";
|
||||
var { describe, test, expect } = testForFile(import.meta.path);
|
||||
|
||||
describe("bundler", () => {
|
||||
const nodePolyfillList = {
|
||||
"assert": "polyfill",
|
||||
"buffer": "polyfill",
|
||||
"child_process": "no-op",
|
||||
"cluster": "no-op",
|
||||
"console": "polyfill",
|
||||
"constants": "polyfill",
|
||||
"crypto": "polyfill",
|
||||
"dgram": "no-op",
|
||||
"dns": "no-op",
|
||||
"domain": "polyfill",
|
||||
"events": "polyfill",
|
||||
"fs": "no-op",
|
||||
"http": "polyfill",
|
||||
"https": "polyfill",
|
||||
"module": "no-op",
|
||||
"net": "polyfill",
|
||||
"os": "polyfill",
|
||||
"path": "polyfill",
|
||||
"perf_hooks": "no-op",
|
||||
"process": "polyfill",
|
||||
"punycode": "polyfill",
|
||||
"querystring": "polyfill",
|
||||
"readline": "no-op",
|
||||
"repl": "no-op",
|
||||
"stream": "polyfill",
|
||||
"string_decoder": "polyfill",
|
||||
"sys": "polyfill",
|
||||
"timers": "polyfill",
|
||||
"tls": "no-op",
|
||||
"tty": "polyfill",
|
||||
"url": "polyfill",
|
||||
"util": "polyfill",
|
||||
"v8": "no-op",
|
||||
"vm": "no-op",
|
||||
"zlib": "polyfill",
|
||||
};
|
||||
itBundled("browser/NodeFS", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import * as fs from "node:fs";
|
||||
import * as fs2 from "fs";
|
||||
import { readFileSync } from "fs";
|
||||
console.log(typeof fs);
|
||||
console.log(typeof fs2);
|
||||
console.log(typeof readFileSync);
|
||||
`,
|
||||
},
|
||||
platform: "browser",
|
||||
run: {
|
||||
stdout: "function\nfunction\nundefined",
|
||||
},
|
||||
});
|
||||
// TODO: use nodePolyfillList to generate the code in here.
|
||||
const NodePolyfills = itBundled("browser/NodePolyfills", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import * as assert from "node:assert";
|
||||
import * as buffer from "node:buffer";
|
||||
import * as child_process from "node:child_process";
|
||||
import * as cluster from "node:cluster";
|
||||
import * as console2 from "node:console";
|
||||
import * as constants from "node:constants";
|
||||
import * as crypto from "node:crypto";
|
||||
import * as dgram from "node:dgram";
|
||||
import * as dns from "node:dns";
|
||||
import * as domain from "node:domain";
|
||||
import * as events from "node:events";
|
||||
import * as fs from "node:fs";
|
||||
import * as http from "node:http";
|
||||
import * as https from "node:https";
|
||||
import * as module2 from "node:module";
|
||||
import * as net from "node:net";
|
||||
import * as os from "node:os";
|
||||
import * as path from "node:path";
|
||||
import * as perf_hooks from "node:perf_hooks";
|
||||
import * as process from "node:process";
|
||||
import * as punycode from "node:punycode";
|
||||
import * as querystring from "node:querystring";
|
||||
import * as readline from "node:readline";
|
||||
import * as repl from "node:repl";
|
||||
import * as stream from "node:stream";
|
||||
import * as string_decoder from "node:string_decoder";
|
||||
import * as sys from "node:sys";
|
||||
import * as timers from "node:timers";
|
||||
import * as tls from "node:tls";
|
||||
import * as tty from "node:tty";
|
||||
import * as url from "node:url";
|
||||
import * as util from "node:util";
|
||||
import * as v8 from "node:v8";
|
||||
import * as vm from "node:vm";
|
||||
import * as zlib from "node:zlib";
|
||||
function scan(obj) {
|
||||
if (typeof obj === 'function') obj = obj()
|
||||
return Object.keys(obj).length === 0 ? 'no-op' : 'polyfill'
|
||||
}
|
||||
console.log('assert :', scan(assert))
|
||||
console.log('buffer :', scan(buffer))
|
||||
console.log('child_process :', scan(child_process))
|
||||
console.log('cluster :', scan(cluster))
|
||||
console.log('console :', console2 === console ? 'equal' : 'polyfill')
|
||||
console.log('constants :', scan(constants))
|
||||
console.log('crypto :', scan(crypto))
|
||||
console.log('dgram :', scan(dgram))
|
||||
console.log('dns :', scan(dns))
|
||||
console.log('domain :', scan(domain))
|
||||
console.log('events :', scan(events))
|
||||
console.log('fs :', scan(fs))
|
||||
console.log('http :', scan(http))
|
||||
console.log('https :', scan(https))
|
||||
console.log('module :', scan(module2))
|
||||
console.log('net :', scan(net))
|
||||
console.log('os :', scan(os))
|
||||
console.log('path :', scan(path))
|
||||
console.log('perf_hooks :', scan(perf_hooks))
|
||||
console.log('process :', scan(process))
|
||||
console.log('punycode :', scan(punycode))
|
||||
console.log('querystring :', scan(querystring))
|
||||
console.log('readline :', scan(readline))
|
||||
console.log('repl :', scan(repl))
|
||||
console.log('stream :', scan(stream))
|
||||
console.log('string_decoder :', scan(string_decoder))
|
||||
console.log('sys :', scan(sys))
|
||||
console.log('timers :', scan(timers))
|
||||
console.log('tls :', scan(tls))
|
||||
console.log('tty :', scan(tty))
|
||||
console.log('url :', scan(url))
|
||||
console.log('util :', scan(util))
|
||||
console.log('v8 :', scan(v8))
|
||||
console.log('vm :', scan(vm))
|
||||
console.log('zlib :', scan(zlib))
|
||||
`,
|
||||
},
|
||||
platform: "browser",
|
||||
onAfterBundle(api) {
|
||||
assert(!api.readFile("/out.js").includes("\0"), "bundle should not contain null bytes");
|
||||
const file = api.readFile("/out.js");
|
||||
const imports = new Bun.Transpiler().scanImports(file);
|
||||
expect(imports).toStrictEqual([]);
|
||||
},
|
||||
run: {
|
||||
stdout: `
|
||||
assert : polyfill
|
||||
buffer : polyfill
|
||||
child_process : no-op
|
||||
cluster : no-op
|
||||
console : polyfill
|
||||
constants : polyfill
|
||||
crypto : polyfill
|
||||
dgram : no-op
|
||||
dns : no-op
|
||||
domain : polyfill
|
||||
events : polyfill
|
||||
fs : no-op
|
||||
http : polyfill
|
||||
https : polyfill
|
||||
module : no-op
|
||||
net : polyfill
|
||||
os : polyfill
|
||||
path : polyfill
|
||||
perf_hooks : no-op
|
||||
process : polyfill
|
||||
punycode : polyfill
|
||||
querystring : polyfill
|
||||
readline : no-op
|
||||
repl : no-op
|
||||
stream : polyfill
|
||||
string_decoder : polyfill
|
||||
sys : polyfill
|
||||
timers : polyfill
|
||||
tls : no-op
|
||||
tty : polyfill
|
||||
url : polyfill
|
||||
util : polyfill
|
||||
v8 : no-op
|
||||
vm : no-op
|
||||
zlib : polyfill
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("browser/NodePolyfillExternal", {
|
||||
skipOnEsbuild: true,
|
||||
files: {
|
||||
"/entry.js": NodePolyfills.options.files["/entry.js"],
|
||||
},
|
||||
platform: "browser",
|
||||
external: Object.keys(nodePolyfillList),
|
||||
onAfterBundle(api) {
|
||||
const file = api.readFile("/out.js");
|
||||
const imports = new Bun.Transpiler().scanImports(file);
|
||||
expect(imports).toStrictEqual(
|
||||
Object.keys(nodePolyfillList).map(x => ({
|
||||
kind: "import-statement",
|
||||
path: "node:" + x,
|
||||
})),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// unsure: do we want polyfills or no-op stuff like node:* has
|
||||
// right now all error except bun:wrap which errors at resolve time, but is included if external
|
||||
const bunModules: Record<string, "no-op" | "polyfill" | "error"> = {
|
||||
"bun": "error",
|
||||
"bun:ffi": "error",
|
||||
"bun:dns": "error",
|
||||
"bun:test": "error",
|
||||
"bun:sqlite": "error",
|
||||
"bun:wrap": "error",
|
||||
"bun:internal": "error",
|
||||
"bun:jsc": "error",
|
||||
};
|
||||
|
||||
const nonErroringBunModules = Object.entries(bunModules)
|
||||
.filter(x => x[1] !== "error")
|
||||
.map(x => x[0]);
|
||||
|
||||
// segfaults the test runner
|
||||
itBundled.skip("browser/BunPolyfill", {
|
||||
skipOnEsbuild: true,
|
||||
files: {
|
||||
"/entry.js": `
|
||||
${nonErroringBunModules.map((x, i) => `import * as bun_${i} from "${x}";`).join("\n")}
|
||||
function scan(obj) {
|
||||
if (typeof obj === 'function') obj = obj()
|
||||
return Object.keys(obj).length === 0 ? 'no-op' : 'polyfill'
|
||||
}
|
||||
${nonErroringBunModules.map((x, i) => `console.log("${x.padEnd(12, " ")}:", scan(bun_${i}));`).join("\n")}
|
||||
`,
|
||||
},
|
||||
platform: "browser",
|
||||
onAfterBundle(api) {
|
||||
assert(!api.readFile("/out.js").includes("\0"), "bundle should not contain null bytes");
|
||||
const file = api.readFile("/out.js");
|
||||
const imports = new Bun.Transpiler().scanImports(file);
|
||||
expect(imports).toStrictEqual([]);
|
||||
},
|
||||
run: {
|
||||
stdout: nonErroringBunModules.map(x => `${x.padEnd(12, " ")}: ${bunModules[x]}`).join("\n"),
|
||||
},
|
||||
});
|
||||
|
||||
const ImportBunError = itBundled("browser/ImportBunError", {
|
||||
skipOnEsbuild: true,
|
||||
files: {
|
||||
"/entry.js": `
|
||||
${Object.keys(bunModules)
|
||||
.map((x, i) => `import * as bun_${i} from "${x}";`)
|
||||
.join("\n")}
|
||||
${Object.keys(bunModules)
|
||||
.map((x, i) => `console.log("${x.padEnd(12, " ")}:", !!bun_${i});`)
|
||||
.join("\n")}
|
||||
`,
|
||||
},
|
||||
platform: "browser",
|
||||
bundleErrors: {
|
||||
"/entry.js": Object.keys(bunModules)
|
||||
.filter(x => bunModules[x] === "error")
|
||||
.map(x => `Could not resolve: "${x}". Maybe you need to "bun install"?`),
|
||||
},
|
||||
});
|
||||
|
||||
itBundled("browser/BunPolyfillExternal", {
|
||||
skipOnEsbuild: true,
|
||||
files: ImportBunError.options.files,
|
||||
platform: "browser",
|
||||
external: Object.keys(bunModules),
|
||||
onAfterBundle(api) {
|
||||
const file = api.readFile("/out.js");
|
||||
const imports = new Bun.Transpiler().scanImports(file);
|
||||
expect(imports).toStrictEqual(
|
||||
Object.keys(bunModules).map(x => ({
|
||||
kind: "import-statement",
|
||||
path: x,
|
||||
})),
|
||||
);
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -16,14 +16,155 @@ describe("bundler", () => {
|
||||
}
|
||||
`,
|
||||
},
|
||||
minifySyntax: true,
|
||||
platform: "bun",
|
||||
// TODO: better assertion
|
||||
onAfterBundle(api) {
|
||||
assert(!api.readFile("/out.js").includes("__commonJS"), "should not include the commonJS helper");
|
||||
},
|
||||
cjs2esm: true,
|
||||
run: {
|
||||
stdout: "foo",
|
||||
},
|
||||
});
|
||||
itBundled("cjs2esm/ExportsFunction", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import { foo } from 'lib';
|
||||
console.log(foo());
|
||||
`,
|
||||
"/node_modules/lib/index.js": /* js */ `
|
||||
exports.foo = function() {
|
||||
return 'foo';
|
||||
}
|
||||
`,
|
||||
},
|
||||
cjs2esm: true,
|
||||
run: {
|
||||
stdout: "foo",
|
||||
},
|
||||
});
|
||||
itBundled("cjs2esm/ModuleExportsFunctionTreeShaking", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import { foo } from 'lib';
|
||||
console.log(foo());
|
||||
`,
|
||||
"/node_modules/lib/index.js": /* js */ `
|
||||
module.exports.foo = function() {
|
||||
return 'foo';
|
||||
}
|
||||
module.exports.bar = function() {
|
||||
return 'remove_me';
|
||||
}
|
||||
`,
|
||||
},
|
||||
cjs2esm: true,
|
||||
dce: true,
|
||||
treeShaking: true,
|
||||
run: {
|
||||
stdout: "foo",
|
||||
},
|
||||
});
|
||||
itBundled("cjs2esm/ModuleExportsEqualsRequire", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import { foo } from 'lib';
|
||||
console.log(foo);
|
||||
`,
|
||||
"/node_modules/lib/index.js": /* js */ `
|
||||
// bundler should see through this
|
||||
module.exports = require('./library.js')
|
||||
`,
|
||||
"/node_modules/lib/library.js": /* js */ `
|
||||
module.exports.foo = 'bar';
|
||||
`,
|
||||
},
|
||||
cjs2esm: true,
|
||||
run: {
|
||||
stdout: "bar",
|
||||
},
|
||||
});
|
||||
itBundled("cjs2esm/ModuleExportsBasedOnNodeEnvProduction", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import { foo } from 'lib';
|
||||
console.log(foo);
|
||||
`,
|
||||
"/node_modules/lib/index.js": /* js */ `
|
||||
// bundler should see through this
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
module.exports = require('./library.prod.js')
|
||||
} else {
|
||||
module.exports = require('./library.dev.js')
|
||||
}
|
||||
`,
|
||||
"/node_modules/lib/library.prod.js": /* js */ `
|
||||
module.exports.foo = 'production';
|
||||
`,
|
||||
"/node_modules/lib/library.dev.js": /* js */ `
|
||||
module.exports.foo = 'FAILED';
|
||||
`,
|
||||
},
|
||||
cjs2esm: true,
|
||||
dce: true,
|
||||
env: {
|
||||
NODE_ENV: "production",
|
||||
},
|
||||
run: {
|
||||
stdout: "production",
|
||||
},
|
||||
});
|
||||
itBundled("cjs2esm/ModuleExportsBasedOnNodeEnvDevelopment", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import { foo } from 'lib';
|
||||
console.log(foo);
|
||||
`,
|
||||
"/node_modules/lib/index.js": /* js */ `
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
module.exports = require('./library.prod.js')
|
||||
} else {
|
||||
module.exports = require('./library.dev.js')
|
||||
}
|
||||
`,
|
||||
"/node_modules/lib/library.prod.js": /* js */ `
|
||||
module.exports.foo = 'FAILED';
|
||||
`,
|
||||
"/node_modules/lib/library.dev.js": /* js */ `
|
||||
module.exports.foo = 'development';
|
||||
`,
|
||||
},
|
||||
cjs2esm: true,
|
||||
dce: true,
|
||||
env: {
|
||||
NODE_ENV: "development",
|
||||
},
|
||||
run: {
|
||||
stdout: "development",
|
||||
},
|
||||
});
|
||||
itBundled("cjs2esm/ModuleExportsEqualsRuntimeCondition", {
|
||||
notImplemented: true,
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import { foo } from 'lib';
|
||||
console.log(foo);
|
||||
`,
|
||||
"/node_modules/lib/index.js": /* js */ `
|
||||
if (globalThis.USE_PROD) {
|
||||
module.exports = require('./library.prod.js')
|
||||
} else {
|
||||
module.exports = require('./library.dev.js')
|
||||
}
|
||||
`,
|
||||
// these should have the cjs transform
|
||||
"/node_modules/lib/library.prod.js": /* js */ `
|
||||
module.exports.foo = 'production';
|
||||
`,
|
||||
"/node_modules/lib/library.dev.js": /* js */ `
|
||||
module.exports.foo = 'development';
|
||||
`,
|
||||
},
|
||||
cjs2esm: {
|
||||
exclude: ["/node_modules/lib/index.js"],
|
||||
},
|
||||
run: {
|
||||
stdout: "development",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,6 +9,18 @@ describe("bundler", () => {
|
||||
"/entry.js": "",
|
||||
},
|
||||
});
|
||||
itBundled("edgecase/EmptyCommonJSModule", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import * as module from './module.cjs';
|
||||
console.log(typeof module)
|
||||
`,
|
||||
"/module.cjs": /* js */ ``,
|
||||
},
|
||||
run: {
|
||||
stdout: "object",
|
||||
},
|
||||
});
|
||||
itBundled("edgecase/ImportStarFunction", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
@@ -83,4 +95,77 @@ describe("bundler", () => {
|
||||
},
|
||||
capture: ['"Hello\0"'],
|
||||
});
|
||||
// https://github.com/oven-sh/bun/issues/2699
|
||||
itBundled("edgecase/ImportNamedFromExportStarCJS", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import { foo } from './foo';
|
||||
console.log(foo);
|
||||
`,
|
||||
"/foo.js": /* js */ `
|
||||
export * from './bar.cjs';
|
||||
`,
|
||||
"/bar.cjs": /* js */ `
|
||||
module.exports = { foo: 'bar' };
|
||||
`,
|
||||
},
|
||||
run: {
|
||||
stdout: "bar",
|
||||
},
|
||||
});
|
||||
itBundled("edgecase/NodeEnvDefaultUnset", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
capture(process.env.NODE_ENV);
|
||||
capture(process.env.NODE_ENV === 'production');
|
||||
capture(process.env.NODE_ENV === 'development');
|
||||
`,
|
||||
},
|
||||
platform: "browser",
|
||||
capture: ['"development"', "false", "true"],
|
||||
env: {
|
||||
// undefined will ensure this variable is not passed to the bundler
|
||||
NODE_ENV: undefined,
|
||||
},
|
||||
});
|
||||
itBundled("edgecase/NodeEnvDefaultDevelopment", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
capture(process.env.NODE_ENV);
|
||||
capture(process.env.NODE_ENV === 'production');
|
||||
capture(process.env.NODE_ENV === 'development');
|
||||
`,
|
||||
},
|
||||
platform: "browser",
|
||||
capture: ['"development"', "false", "true"],
|
||||
env: {
|
||||
NODE_ENV: "development",
|
||||
},
|
||||
});
|
||||
itBundled("edgecase/NodeEnvDefaultProduction", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
capture(process.env.NODE_ENV);
|
||||
capture(process.env.NODE_ENV === 'production');
|
||||
capture(process.env.NODE_ENV === 'development');
|
||||
`,
|
||||
},
|
||||
platform: "browser",
|
||||
capture: ['"production"', "true", "false"],
|
||||
env: {
|
||||
NODE_ENV: "production",
|
||||
},
|
||||
});
|
||||
itBundled("edgecase/ProcessEnvArbitrary", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
capture(process.env.ARBITRARY);
|
||||
`,
|
||||
},
|
||||
platform: "browser",
|
||||
capture: ["process.env.ARBITRARY"],
|
||||
env: {
|
||||
ARBITRARY: "secret environment stuff!",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { describe } from "bun:test";
|
||||
import { itBundled } from "./expectBundled";
|
||||
import assert from "assert";
|
||||
import dedent from "dedent";
|
||||
import { bundlerTest, expectBundled, itBundled, testForFile } from "./expectBundled";
|
||||
var { describe, test, expect } = testForFile(import.meta.path);
|
||||
|
||||
describe("bundler", () => {
|
||||
itBundled("minify/TemplateStringFolding", {
|
||||
@@ -49,7 +51,77 @@ describe("bundler", () => {
|
||||
"!1",
|
||||
"!1",
|
||||
],
|
||||
minifySyntax: true,
|
||||
platform: "bun",
|
||||
minifySyntax: true,
|
||||
});
|
||||
itBundled("minify/FunctionExpressionRemoveName", {
|
||||
notImplemented: true,
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
capture(function remove() {});
|
||||
capture(function() {});
|
||||
capture(function rename_me() { rename_me() });
|
||||
`,
|
||||
},
|
||||
// capture is pretty stupid and will stop at first )
|
||||
capture: ["function(", "function(", "function e("],
|
||||
minifySyntax: true,
|
||||
minifyIdentifiers: true,
|
||||
platform: "bun",
|
||||
});
|
||||
itBundled("minify/PrivateIdentifiersNameCollision", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
class C {
|
||||
${new Array(500)
|
||||
.fill(null)
|
||||
.map((_, i) => `#identifier${i} = 123;`)
|
||||
.join("\n")}
|
||||
a = 456;
|
||||
|
||||
getAllValues() {
|
||||
return [
|
||||
${new Array(500)
|
||||
.fill(null)
|
||||
.map((_, i) => `this.#identifier${i}`)
|
||||
.join(",")}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
const values = new C().getAllValues();
|
||||
for (const value of values) {
|
||||
if(value !== 123) { throw new Error("Expected 123!"); }
|
||||
}
|
||||
|
||||
console.log("a = " + new C().a);
|
||||
`,
|
||||
},
|
||||
minifyIdentifiers: true,
|
||||
run: { stdout: "a = 456" },
|
||||
});
|
||||
itBundled("minify/MergeAdjacentVars", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
var a = 1;
|
||||
var b = 2;
|
||||
var c = 3;
|
||||
|
||||
// some code to prevent inlining
|
||||
a = 4;
|
||||
console.log(a, b, c)
|
||||
b = 5;
|
||||
console.log(a, b, c)
|
||||
c = 6;
|
||||
console.log(a, b, c)
|
||||
`,
|
||||
},
|
||||
minifySyntax: true,
|
||||
run: { stdout: "4 2 3\n4 5 3\n4 5 6" },
|
||||
onAfterBundle(api) {
|
||||
const code = api.readFile("/out.js");
|
||||
assert([...code.matchAll(/var /g)].length === 1, "expected only 1 variable declaration statement");
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -279,7 +279,6 @@ describe("bundler", () => {
|
||||
function nested() { return import('./c') },
|
||||
]
|
||||
|
||||
import { deepEqual } from 'node:assert'
|
||||
deepEqual(a, 1, 'a');
|
||||
deepEqual(a2, 4, 'a2');
|
||||
deepEqual(c3, 2, 'c3');
|
||||
@@ -305,7 +304,9 @@ describe("bundler", () => {
|
||||
export const a2 = 4;
|
||||
`,
|
||||
"/test.js": String.raw/* js */ `
|
||||
import './out.js';
|
||||
import { deepEqual } from 'node:assert';
|
||||
globalThis.deepEqual = deepEqual;
|
||||
await import ('./out.js');
|
||||
if (!globalThis.aWasImported) {
|
||||
throw new Error('"import \'./a\'" was tree-shaken when it should not have been.')
|
||||
}
|
||||
@@ -314,10 +315,11 @@ describe("bundler", () => {
|
||||
}
|
||||
`,
|
||||
},
|
||||
mode: "transform",
|
||||
// mode: "transform",
|
||||
run: {
|
||||
file: "/test.js",
|
||||
},
|
||||
external: ["node:assert", "./a", "./b", "./c"],
|
||||
} as const;
|
||||
itBundled("default/ImportFormsWithNoBundle", {
|
||||
...importFormsConfig,
|
||||
@@ -1859,7 +1861,7 @@ describe("bundler", () => {
|
||||
});
|
||||
itBundled("default/ArgumentsSpecialCaseNoBundle", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
"/entry.cjs": /* js */ `
|
||||
(async() => {
|
||||
var arguments = 'var';
|
||||
|
||||
@@ -1902,7 +1904,7 @@ describe("bundler", () => {
|
||||
// assertions:
|
||||
// we need this helper function to get "Arguments" objects, though this only applies for tests using v8
|
||||
const argumentsFor = new Function('return arguments;');
|
||||
const assert = require('assert');
|
||||
const assert = (0, require)('assert');
|
||||
assert.deepEqual(f1(), [argumentsFor(), argumentsFor()], 'f1()');
|
||||
assert.deepEqual(f1(1), [1, argumentsFor(1)], 'f1(1)');
|
||||
assert.deepEqual(f2(), [argumentsFor(), argumentsFor()], 'f2()');
|
||||
@@ -1949,42 +1951,58 @@ describe("bundler", () => {
|
||||
assert.deepEqual(a19(1), [1, 'var'], 'a19(1)');
|
||||
assert.deepEqual(await a20(), ['var', 'var'], 'a20()');
|
||||
assert.deepEqual(await a20(1), [1, 'var'], 'a20(1)');
|
||||
})();
|
||||
})(1,3,5);
|
||||
`,
|
||||
},
|
||||
format: "cjs",
|
||||
format: "esm",
|
||||
outfile: "/out.js",
|
||||
minifyIdentifiers: true,
|
||||
mode: "transform",
|
||||
// mode: "transform",
|
||||
});
|
||||
itBundled("default/WithStatementTaintingNoBundle", {
|
||||
// TODO: MANUAL CHECK: make sure the snapshot we use works.
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
(() => {
|
||||
let local = 1
|
||||
let outer = 2
|
||||
let outerDead = 3
|
||||
with ({}) {
|
||||
console.log(local, outer, outerDead)
|
||||
with ({ outer: 100, local: 150, hoisted: 200, extra: 500 }) {
|
||||
console.log(outer, outerDead, hoisted, extra)
|
||||
var hoisted = 4
|
||||
let local = 5
|
||||
hoisted++
|
||||
local++
|
||||
console.log(local, outer, outerDead, hoisted, extra)
|
||||
if (1) outer++
|
||||
if (0) outerDead++
|
||||
console.log(local, outer, outerDead, hoisted, extra)
|
||||
}
|
||||
console.log(local, outer, outerDead, hoisted)
|
||||
if (1) {
|
||||
hoisted++
|
||||
local++
|
||||
outer++
|
||||
outerDead++
|
||||
}
|
||||
console.log(local, outer, outerDead, hoisted)
|
||||
})()
|
||||
`,
|
||||
},
|
||||
format: "iife",
|
||||
minifyIdentifiers: true,
|
||||
mode: "transform",
|
||||
run: {
|
||||
runtime: "node",
|
||||
stdout: `
|
||||
1 2 3
|
||||
100 3 200 500
|
||||
6 100 3 5 500
|
||||
6 101 3 5 500
|
||||
1 2 3 undefined
|
||||
2 3 4 NaN
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("default/DirectEvalTaintingNoBundle", {
|
||||
files: {
|
||||
@@ -2279,6 +2297,7 @@ describe("bundler", () => {
|
||||
},
|
||||
});
|
||||
itBundled("default/AutoExternalNode", {
|
||||
skipOnEsbuild: true,
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
// These URLs should be external automatically
|
||||
@@ -2287,9 +2306,12 @@ describe("bundler", () => {
|
||||
|
||||
// This should be external and should be tree-shaken because it's side-effect free
|
||||
import "node:path";
|
||||
import "bun";
|
||||
import "bun:sqlite";
|
||||
|
||||
// This should be external too, but shouldn't be tree-shaken because it could be a run-time error
|
||||
import "node:what-is-this";
|
||||
import "bun:what-is-this";
|
||||
`,
|
||||
},
|
||||
platform: "node",
|
||||
@@ -2368,18 +2390,22 @@ describe("bundler", () => {
|
||||
get #bar() {}
|
||||
set #bar(x) {}
|
||||
}
|
||||
|
||||
cool(Foo)
|
||||
cool(Bar)
|
||||
`,
|
||||
},
|
||||
minifyIdentifiers: true,
|
||||
mode: "transform",
|
||||
onAfterBundle(api) {
|
||||
const text = api.readFile("/out.js");
|
||||
assert(text.includes("doNotRenameMe"), "bundler should not have renamed `doNotRenameMe`");
|
||||
assert(!text.includes("#foo"), "bundler should have renamed `#foo`");
|
||||
assert(text.includes("#"), "bundler keeps private variables private `#`");
|
||||
},
|
||||
});
|
||||
// These labels should all share the same minified names
|
||||
itBundled("default/MinifySiblingLabelsNoBundle", {
|
||||
notImplemented: true,
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
foo: {
|
||||
@@ -2403,48 +2429,68 @@ describe("bundler", () => {
|
||||
`,
|
||||
},
|
||||
minifyIdentifiers: true,
|
||||
mode: "transform",
|
||||
onAfterBundle(api) {
|
||||
const text = api.readFile("/out.js");
|
||||
const labels = [...text.matchAll(/([a-z0-9]+):/gi)].map(x => x[1]);
|
||||
expect(labels).toStrictEqual([labels[0], labels[1], labels[0], labels[1], labels[0], labels[1]]);
|
||||
},
|
||||
});
|
||||
// This is such a fun file. it crashes prettier and some other parsers.
|
||||
const crazyNestedLabelFile = dedent`
|
||||
L001:{L002:{L003:{L004:{L005:{L006:{L007:{L008:{L009:{L010:{L011:{L012:{L013:{L014:{L015:{L016:{console.log('a')
|
||||
L017:{L018:{L019:{L020:{L021:{L022:{L023:{L024:{L025:{L026:{L027:{L028:{L029:{L030:{L031:{L032:{console.log('a')
|
||||
L033:{L034:{L035:{L036:{L037:{L038:{L039:{L040:{L041:{L042:{L043:{L044:{L045:{L046:{L047:{L048:{console.log('a')
|
||||
L049:{L050:{L051:{L052:{L053:{L054:{L055:{L056:{L057:{L058:{L059:{L060:{L061:{L062:{L063:{L064:{console.log('a')
|
||||
L065:{L066:{L067:{L068:{L069:{L070:{L071:{L072:{L073:{L074:{L075:{L076:{L077:{L078:{L079:{L080:{console.log('a')
|
||||
L081:{L082:{L083:{L084:{L085:{L086:{L087:{L088:{L089:{L090:{L091:{L092:{L093:{L094:{L095:{L096:{console.log('a')
|
||||
L097:{L098:{L099:{L100:{L101:{L102:{L103:{L104:{L105:{L106:{L107:{L108:{L109:{L110:{L111:{L112:{console.log('a')
|
||||
L113:{L114:{L115:{L116:{L117:{L118:{L119:{L120:{L121:{L122:{L123:{L124:{L125:{L126:{L127:{L128:{console.log('a')
|
||||
L129:{L130:{L131:{L132:{L133:{L134:{L135:{L136:{L137:{L138:{L139:{L140:{L141:{L142:{L143:{L144:{console.log('a')
|
||||
L145:{L146:{L147:{L148:{L149:{L150:{L151:{L152:{L153:{L154:{L155:{L156:{L157:{L158:{L159:{L160:{console.log('a')
|
||||
L161:{L162:{L163:{L164:{L165:{L166:{L167:{L168:{L169:{L170:{L171:{L172:{L173:{L174:{L175:{L176:{console.log('a')
|
||||
L177:{L178:{L179:{L180:{L181:{L182:{L183:{L184:{L185:{L186:{L187:{L188:{L189:{L190:{L191:{L192:{console.log('a')
|
||||
L193:{L194:{L195:{L196:{L197:{L198:{L199:{L200:{L201:{L202:{L203:{L204:{L205:{L206:{L207:{L208:{console.log('a')
|
||||
L209:{L210:{L211:{L212:{L213:{L214:{L215:{L216:{L217:{L218:{L219:{L220:{L221:{L222:{L223:{L224:{console.log('a')
|
||||
L225:{L226:{L227:{L228:{L229:{L230:{L231:{L232:{L233:{L234:{L235:{L236:{L237:{L238:{L239:{L240:{console.log('a')
|
||||
L241:{L242:{L243:{L244:{L245:{L246:{L247:{L248:{L249:{L250:{L251:{L252:{L253:{L254:{L255:{L256:{console.log('a')
|
||||
L257:{L258:{L259:{L260:{L261:{L262:{L263:{L264:{L265:{L266:{L267:{L268:{L269:{L270:{L271:{L272:{console.log('a')
|
||||
L273:{L274:{L275:{L276:{L277:{L278:{L279:{L280:{L281:{L282:{L283:{L284:{L285:{L286:{L287:{L288:{console.log('a')
|
||||
L289:{L290:{L291:{L292:{L293:{L294:{L295:{L296:{L297:{L298:{L299:{L300:{L301:{L302:{L303:{L304:{console.log('a')
|
||||
L305:{L306:{L307:{L308:{L309:{L310:{L311:{L312:{L313:{L314:{L315:{L316:{L317:{L318:{L319:{L320:{console.log('a')
|
||||
L321:{L322:{L323:{L324:{L325:{L326:{L327:{L328:{L329:{L330:{L331:{L332:{L333:{}}}}}}}}}}}}}}}}}}console.log('a')
|
||||
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}console.log('a')
|
||||
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}console.log('a')
|
||||
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}console.log('a')
|
||||
}}}}}}}}}}}}}}}}}}}}}}}}}}}
|
||||
`;
|
||||
itBundled("default/NestedLabelsBundle", {
|
||||
files: {
|
||||
"/entry.js": crazyNestedLabelFile,
|
||||
},
|
||||
});
|
||||
itBundled("default/NestedLabelsNoBundle", {
|
||||
files: {
|
||||
"/entry.js": crazyNestedLabelFile,
|
||||
},
|
||||
mode: "transform",
|
||||
});
|
||||
itBundled("default/MinifyNestedLabelsNoBundle", {
|
||||
files: {
|
||||
"/entry.js": dedent`
|
||||
L001:{L002:{L003:{L004:{L005:{L006:{L007:{L008:{L009:{L010:{L011:{L012:{L013:{L014:{L015:{L016:{console.log('a')
|
||||
L017:{L018:{L019:{L020:{L021:{L022:{L023:{L024:{L025:{L026:{L027:{L028:{L029:{L030:{L031:{L032:{console.log('a')
|
||||
L033:{L034:{L035:{L036:{L037:{L038:{L039:{L040:{L041:{L042:{L043:{L044:{L045:{L046:{L047:{L048:{console.log('a')
|
||||
L049:{L050:{L051:{L052:{L053:{L054:{L055:{L056:{L057:{L058:{L059:{L060:{L061:{L062:{L063:{L064:{console.log('a')
|
||||
L065:{L066:{L067:{L068:{L069:{L070:{L071:{L072:{L073:{L074:{L075:{L076:{L077:{L078:{L079:{L080:{console.log('a')
|
||||
L081:{L082:{L083:{L084:{L085:{L086:{L087:{L088:{L089:{L090:{L091:{L092:{L093:{L094:{L095:{L096:{console.log('a')
|
||||
L097:{L098:{L099:{L100:{L101:{L102:{L103:{L104:{L105:{L106:{L107:{L108:{L109:{L110:{L111:{L112:{console.log('a')
|
||||
L113:{L114:{L115:{L116:{L117:{L118:{L119:{L120:{L121:{L122:{L123:{L124:{L125:{L126:{L127:{L128:{console.log('a')
|
||||
L129:{L130:{L131:{L132:{L133:{L134:{L135:{L136:{L137:{L138:{L139:{L140:{L141:{L142:{L143:{L144:{console.log('a')
|
||||
L145:{L146:{L147:{L148:{L149:{L150:{L151:{L152:{L153:{L154:{L155:{L156:{L157:{L158:{L159:{L160:{console.log('a')
|
||||
L161:{L162:{L163:{L164:{L165:{L166:{L167:{L168:{L169:{L170:{L171:{L172:{L173:{L174:{L175:{L176:{console.log('a')
|
||||
L177:{L178:{L179:{L180:{L181:{L182:{L183:{L184:{L185:{L186:{L187:{L188:{L189:{L190:{L191:{L192:{console.log('a')
|
||||
L193:{L194:{L195:{L196:{L197:{L198:{L199:{L200:{L201:{L202:{L203:{L204:{L205:{L206:{L207:{L208:{console.log('a')
|
||||
L209:{L210:{L211:{L212:{L213:{L214:{L215:{L216:{L217:{L218:{L219:{L220:{L221:{L222:{L223:{L224:{console.log('a')
|
||||
L225:{L226:{L227:{L228:{L229:{L230:{L231:{L232:{L233:{L234:{L235:{L236:{L237:{L238:{L239:{L240:{console.log('a')
|
||||
L241:{L242:{L243:{L244:{L245:{L246:{L247:{L248:{L249:{L250:{L251:{L252:{L253:{L254:{L255:{L256:{console.log('a')
|
||||
L257:{L258:{L259:{L260:{L261:{L262:{L263:{L264:{L265:{L266:{L267:{L268:{L269:{L270:{L271:{L272:{console.log('a')
|
||||
L273:{L274:{L275:{L276:{L277:{L278:{L279:{L280:{L281:{L282:{L283:{L284:{L285:{L286:{L287:{L288:{console.log('a')
|
||||
L289:{L290:{L291:{L292:{L293:{L294:{L295:{L296:{L297:{L298:{L299:{L300:{L301:{L302:{L303:{L304:{console.log('a')
|
||||
L305:{L306:{L307:{L308:{L309:{L310:{L311:{L312:{L313:{L314:{L315:{L316:{L317:{L318:{L319:{L320:{console.log('a')
|
||||
L321:{L322:{L323:{L324:{L325:{L326:{L327:{L328:{L329:{L330:{L331:{L332:{L333:{}}}}}}}}}}}}}}}}}}console.log('a')
|
||||
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}console.log('a')
|
||||
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}console.log('a')
|
||||
}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}console.log('a')
|
||||
}}}}}}}}}}}}}}}}}}}}}}}}}}}
|
||||
`,
|
||||
"/entry.js": crazyNestedLabelFile,
|
||||
},
|
||||
minifyWhitespace: true,
|
||||
minifyIdentifiers: true,
|
||||
minifySyntax: true,
|
||||
mode: "transform",
|
||||
});
|
||||
itBundled("default/MinifyNestedLabelsBundle", {
|
||||
files: {
|
||||
"/entry.js": crazyNestedLabelFile,
|
||||
},
|
||||
minifyWhitespace: true,
|
||||
minifyIdentifiers: true,
|
||||
minifySyntax: true,
|
||||
});
|
||||
itBundled("default/ExportsAndModuleFormatCommonJS", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
@@ -4474,8 +4520,14 @@ describe("bundler", () => {
|
||||
}
|
||||
const a = capture(api.readFile("/out/a.js"));
|
||||
const b = capture(api.readFile("/out/b.js"));
|
||||
expect(a).toEqual(b);
|
||||
expect(a).not.toEqual(["one", "two", "three", "four"]);
|
||||
expect(b).not.toEqual(["one", "two", "three", "four"]);
|
||||
try {
|
||||
expect(a).toEqual(b);
|
||||
} catch (error) {
|
||||
console.error("Comments should not affect minified names!");
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
});
|
||||
itBundled("default/ImportRelativeAsPackage", {
|
||||
|
||||
@@ -32,6 +32,10 @@ describe("bundler", () => {
|
||||
"/foo.js": `export const foo = 123`,
|
||||
},
|
||||
run: {
|
||||
// esbuild:
|
||||
// stdout: '{"default":{"foo":123},"foo":123} 123 234',
|
||||
|
||||
// bun:
|
||||
stdout: '{"foo":123} 123 234',
|
||||
},
|
||||
});
|
||||
@@ -209,7 +213,7 @@ describe("bundler", () => {
|
||||
"/foo.js": `exports.foo = 123`,
|
||||
},
|
||||
run: {
|
||||
stdout: '{"default":{"foo":123},"foo":123} 123 234',
|
||||
stdout: '{"foo":123} 123 234',
|
||||
},
|
||||
});
|
||||
itBundled("importstar/ImportStarCommonJSNoCapture", {
|
||||
@@ -247,6 +251,7 @@ describe("bundler", () => {
|
||||
runtimeFiles: {
|
||||
"/foo.js": `console.log('foo')`,
|
||||
},
|
||||
external: ["./foo"],
|
||||
run: {
|
||||
stdout: "foo\n234",
|
||||
},
|
||||
@@ -263,6 +268,7 @@ describe("bundler", () => {
|
||||
runtimeFiles: {
|
||||
"/foo.js": `export const foo = 123`,
|
||||
},
|
||||
external: ["./foo"],
|
||||
run: {
|
||||
stdout: '{"foo":123} 123 234',
|
||||
},
|
||||
@@ -275,6 +281,7 @@ describe("bundler", () => {
|
||||
console.log(ns.foo, ns.foo, foo)
|
||||
`,
|
||||
},
|
||||
external: ["./foo"],
|
||||
mode: "transform",
|
||||
runtimeFiles: {
|
||||
"/foo.js": `export const foo = 123`,
|
||||
@@ -292,6 +299,7 @@ describe("bundler", () => {
|
||||
`,
|
||||
},
|
||||
minifySyntax: true,
|
||||
external: ["./foo"],
|
||||
mode: "transform",
|
||||
runtimeFiles: {
|
||||
"/foo.js": `console.log('foo')`,
|
||||
@@ -310,6 +318,7 @@ describe("bundler", () => {
|
||||
},
|
||||
minifySyntax: true,
|
||||
mode: "transform",
|
||||
external: ["./foo"],
|
||||
runtimeFiles: {
|
||||
"/foo.js": `export const foo = 123`,
|
||||
},
|
||||
@@ -327,6 +336,7 @@ describe("bundler", () => {
|
||||
},
|
||||
minifySyntax: true,
|
||||
mode: "transform",
|
||||
external: ["./foo"],
|
||||
runtimeFiles: {
|
||||
"/foo.js": `export const foo = 123`,
|
||||
},
|
||||
@@ -355,7 +365,7 @@ describe("bundler", () => {
|
||||
},
|
||||
dce: true,
|
||||
run: {
|
||||
stdout: '{"x":1,"z":4}',
|
||||
stdout: '{"z":4,"x":1}',
|
||||
},
|
||||
});
|
||||
itBundled("importstar/ImportExportStarAmbiguousError", {
|
||||
@@ -847,6 +857,9 @@ describe("bundler", () => {
|
||||
run: {
|
||||
stdout: '{"x":123} undefined',
|
||||
},
|
||||
bundleWarnings: {
|
||||
"/entry.js": [`Import "foo" will always be undefined because there is no matching export in "foo.js"`],
|
||||
},
|
||||
});
|
||||
itBundled("importstar/ExportOtherCommonJS", {
|
||||
files: {
|
||||
@@ -897,6 +910,9 @@ describe("bundler", () => {
|
||||
run: {
|
||||
stdout: "undefined",
|
||||
},
|
||||
bundleWarnings: {
|
||||
"/entry.js": [`Import "foo" will always be undefined because there is no matching export in "foo.js"`],
|
||||
},
|
||||
});
|
||||
itBundled("importstar/NamespaceImportMissingCommonJS", {
|
||||
files: {
|
||||
@@ -959,7 +975,7 @@ describe("bundler", () => {
|
||||
"/bar.js": `export const x = 123`,
|
||||
},
|
||||
bundleErrors: {
|
||||
"/foo.js": ['ERROR: No matching export in "bar.js" for import "foo"'],
|
||||
"/foo.js": [`No matching export in "bar.js" for import "foo"`],
|
||||
},
|
||||
});
|
||||
itBundled("importstar/NamespaceImportReExportUnusedMissingES6", {
|
||||
@@ -972,7 +988,7 @@ describe("bundler", () => {
|
||||
"/bar.js": `export const x = 123`,
|
||||
},
|
||||
bundleErrors: {
|
||||
"/foo.js": ['ERROR: No matching export in "bar.js" for import "foo"'],
|
||||
"/foo.js": [`No matching export in "bar.js" for import "foo"`],
|
||||
},
|
||||
});
|
||||
itBundled("importstar/NamespaceImportReExportStarMissingES6", {
|
||||
@@ -1208,7 +1224,7 @@ describe("bundler", () => {
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("importstar/ImportDefaultNamespaceComboNoDefault", {
|
||||
const ImportDefaultNamespaceComboNoDefault = itBundled("importstar/ImportDefaultNamespaceComboNoDefault1", {
|
||||
files: {
|
||||
"/entry-default-ns-prop.js": `import def, * as ns from './foo'; console.log(def, ns, ns.default)`,
|
||||
"/entry-default-ns.js": `import def, * as ns from './foo'; console.log(def, ns)`,
|
||||
@@ -1217,20 +1233,40 @@ describe("bundler", () => {
|
||||
"/entry-prop.js": `import * as ns from './foo'; console.log(ns.default)`,
|
||||
"/foo.js": `export let foo = 123`,
|
||||
},
|
||||
entryPoints: [
|
||||
"/entry-default-ns-prop.js",
|
||||
"/entry-default-ns.js",
|
||||
"/entry-default-prop.js",
|
||||
"/entry-default.js",
|
||||
"/entry-prop.js",
|
||||
],
|
||||
entryPoints: ["/entry-default-ns-prop.js"],
|
||||
bundleErrors: {
|
||||
"/entry-default-ns-prop.js": ['No matching export in "foo.js" for import "default"'],
|
||||
},
|
||||
});
|
||||
itBundled("importstar/ImportDefaultNamespaceComboNoDefault2", {
|
||||
...ImportDefaultNamespaceComboNoDefault.options,
|
||||
entryPoints: ["/entry-default-ns.js"],
|
||||
bundleErrors: {
|
||||
"/entry-default-ns.js": ['No matching export in "foo.js" for import "default"'],
|
||||
},
|
||||
});
|
||||
itBundled("importstar/ImportDefaultNamespaceComboNoDefault3", {
|
||||
...ImportDefaultNamespaceComboNoDefault.options,
|
||||
entryPoints: ["/entry-default-prop.js"],
|
||||
bundleErrors: {
|
||||
"/entry-default-prop.js": ['No matching export in "foo.js" for import "default"'],
|
||||
},
|
||||
});
|
||||
itBundled("importstar/ImportDefaultNamespaceComboNoDefault4", {
|
||||
...ImportDefaultNamespaceComboNoDefault.options,
|
||||
entryPoints: ["/entry-default.js"],
|
||||
bundleErrors: {
|
||||
"/entry-default.js": ['No matching export in "foo.js" for import "default"'],
|
||||
},
|
||||
});
|
||||
itBundled("importstar/ImportDefaultNamespaceComboNoDefault5", {
|
||||
...ImportDefaultNamespaceComboNoDefault.options,
|
||||
entryPoints: ["/entry-prop.js"],
|
||||
bundleErrors: undefined,
|
||||
bundleWarnings: {
|
||||
"/entry-prop.js": [`Import "default" will always be undefined because there is no matching export in "foo.js"`],
|
||||
},
|
||||
});
|
||||
itBundled("importstar/ImportNamespaceUndefinedPropertyEmptyFile", {
|
||||
files: {
|
||||
"/entry-nope.js": /* js */ `
|
||||
@@ -1260,9 +1296,9 @@ describe("bundler", () => {
|
||||
entryPoints: ["/entry-nope.js", "/entry-default.js"],
|
||||
bundleWarnings: {
|
||||
"/entry-nope.js": [
|
||||
'Import "nope" will always be undefined because the file "empty.js" has no exports',
|
||||
'Import "nope" will always be undefined because the file "empty.mjs" has no exports',
|
||||
'Import "nope" will always be undefined because the file "empty.cjs" has no exports',
|
||||
`Import "nope" will always be undefined because there is no matching export in "empty.js"`,
|
||||
`Import "nope" will always be undefined because there is no matching export in "empty.mjs"`,
|
||||
`Import "nope" will always be undefined because there is no matching export in "empty.cjs"`,
|
||||
],
|
||||
},
|
||||
run: [
|
||||
@@ -1314,6 +1350,21 @@ describe("bundler", () => {
|
||||
stdout: `js\ncjs\n{} undefined {}`,
|
||||
},
|
||||
],
|
||||
bundleWarnings: {
|
||||
"/foo/no-side-effects.js": [
|
||||
`Import "nope" will always be undefined because the file "foo/no-side-effects.js" has no exports`,
|
||||
],
|
||||
"/foo/no-side-effects.mjs": [
|
||||
`Import "nope" will always be undefined because the file "foo/no-side-effects.mjs" has no exports`,
|
||||
],
|
||||
"/foo/no-side-effects.cjs": [
|
||||
`Import "nope" will always be undefined because the file "foo/no-side-effects.cjs" has no exports`,
|
||||
],
|
||||
"/entry-default.js": [
|
||||
`Import "default" will always be undefined because there is no matching export in "foo/no-side-effects.js"`,
|
||||
`Import "default" will always be undefined because there is no matching export in "foo/no-side-effects.mjs"`,
|
||||
],
|
||||
},
|
||||
});
|
||||
itBundled("importstar/ReExportStarEntryPointAndInnerFile", {
|
||||
files: {
|
||||
|
||||
@@ -102,26 +102,28 @@ describe("bundler", () => {
|
||||
},
|
||||
});
|
||||
itBundled("loader/JSXPreserveCapitalLetterMinify", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.jsx": /* jsx */ `
|
||||
import { mustStartWithUpperCaseLetter as XYYYY } from './foo'
|
||||
console.log(<XYYYY tag-must-start-with-capital-letter />)
|
||||
// This should be named "Y" due to frequency analysis
|
||||
console.log(<XYYYY YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY />)
|
||||
`,
|
||||
"/foo.js": `export class mustStartWithUpperCaseLetter {}`,
|
||||
},
|
||||
external: ["react"],
|
||||
minifyIdentifiers: true,
|
||||
});
|
||||
itBundled("loader/JSXPreserveCapitalLetterMinifyNested", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.jsx": /* jsx */ `
|
||||
x = () => {
|
||||
class XYYYYY {} // This should be named "Y" due to frequency analysis
|
||||
return <XYYYYY tag-must-start-with-capital-letter />
|
||||
class RENAME_ME {} // This should be named "Y" due to frequency analysis
|
||||
capture(RENAME_ME)
|
||||
return <RENAME_ME YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY />
|
||||
}
|
||||
`,
|
||||
},
|
||||
external: ["react"],
|
||||
minifyIdentifiers: true,
|
||||
});
|
||||
itBundled("loader/RequireCustomExtensionString", {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,6 @@
|
||||
import { RUN_UNCHECKED_TESTS, itBundled, testForFile } from "../expectBundled";
|
||||
import assert from "assert";
|
||||
import { readdirSync } from "fs";
|
||||
import { itBundled, testForFile } from "../expectBundled";
|
||||
var { describe, test, expect } = testForFile(import.meta.path);
|
||||
|
||||
// Tests ported from:
|
||||
@@ -7,7 +9,7 @@ var { describe, test, expect } = testForFile(import.meta.path);
|
||||
// For debug, all files are written to $TEMP/bun-bundle-tests/splitting
|
||||
|
||||
describe("bundler", () => {
|
||||
itBundled("splitting/SplittingSharedES6IntoES6", {
|
||||
itBundled("splitting/SharedES6IntoES6", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
import {foo} from "./shared.js"
|
||||
@@ -21,7 +23,6 @@ describe("bundler", () => {
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
run: [
|
||||
{ file: "/out/a.js", stdout: "123" },
|
||||
{ file: "/out/b.js", stdout: "123" },
|
||||
@@ -31,9 +32,7 @@ describe("bundler", () => {
|
||||
"/out/b.js": "123",
|
||||
},
|
||||
});
|
||||
if (!RUN_UNCHECKED_TESTS) return;
|
||||
itBundled("splitting/SplittingSharedCommonJSIntoES6", {
|
||||
// GENERATED
|
||||
itBundled("splitting/SharedCommonJSIntoES6", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
const {foo} = require("./shared.js")
|
||||
@@ -47,28 +46,46 @@ describe("bundler", () => {
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
run: [
|
||||
{ file: "/out/a.js", stdout: "123" },
|
||||
{ file: "/out/b.js", stdout: "123" },
|
||||
],
|
||||
assertNotPresent: {
|
||||
"/out/a.js": "123",
|
||||
"/out/b.js": "123",
|
||||
},
|
||||
});
|
||||
itBundled("splitting/SplittingDynamicES6IntoES6", {
|
||||
// GENERATED
|
||||
itBundled("splitting/DynamicES6IntoES6", {
|
||||
files: {
|
||||
"/entry.js": `import("./foo.js").then(({bar}) => console.log(bar))`,
|
||||
"/foo.js": `export let bar = 123`,
|
||||
},
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
outdir: "/out",
|
||||
assertNotPresent: {
|
||||
"/out/entry.js": "123",
|
||||
},
|
||||
run: {
|
||||
file: "/out/entry.js",
|
||||
stdout: "123",
|
||||
},
|
||||
});
|
||||
itBundled("splitting/SplittingDynamicCommonJSIntoES6", {
|
||||
// GENERATED
|
||||
itBundled("splitting/DynamicCommonJSIntoES6", {
|
||||
files: {
|
||||
"/entry.js": `import("./foo.js").then(({default: {bar}}) => console.log(bar))`,
|
||||
"/foo.js": `exports.bar = 123`,
|
||||
},
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
outdir: "/out",
|
||||
assertNotPresent: {
|
||||
"/out/entry.js": "123",
|
||||
},
|
||||
run: {
|
||||
file: "/out/entry.js",
|
||||
stdout: "123",
|
||||
},
|
||||
});
|
||||
itBundled("splitting/SplittingDynamicAndNotDynamicES6IntoES6", {
|
||||
// GENERATED
|
||||
itBundled("splitting/DynamicAndNotDynamicES6IntoES6", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import {bar as a} from "./foo.js"
|
||||
@@ -77,10 +94,10 @@ describe("bundler", () => {
|
||||
"/foo.js": `export let bar = 123`,
|
||||
},
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
outdir: "/out",
|
||||
});
|
||||
itBundled("splitting/SplittingDynamicAndNotDynamicCommonJSIntoES6", {
|
||||
// GENERATED
|
||||
itBundled("splitting/DynamicAndNotDynamicCommonJSIntoES6", {
|
||||
skipOnEsbuild: true,
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import {bar as a} from "./foo.js"
|
||||
@@ -88,11 +105,14 @@ describe("bundler", () => {
|
||||
`,
|
||||
"/foo.js": `exports.bar = 123`,
|
||||
},
|
||||
outdir: "/out",
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
run: {
|
||||
file: "/out/entry.js",
|
||||
stdout: "123 123",
|
||||
},
|
||||
});
|
||||
itBundled("splitting/SplittingAssignToLocal", {
|
||||
// GENERATED
|
||||
itBundled("splitting/AssignToLocal", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
import {foo, setFoo} from "./shared.js"
|
||||
@@ -104,7 +124,7 @@ describe("bundler", () => {
|
||||
console.log(foo)
|
||||
`,
|
||||
"/shared.js": /* js */ `
|
||||
export let foo
|
||||
export let foo = 456
|
||||
export function setFoo(value) {
|
||||
foo = value
|
||||
}
|
||||
@@ -112,10 +132,24 @@ describe("bundler", () => {
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
runtimeFiles: {
|
||||
"/test1.js": /* js */ `
|
||||
await import('./out/a.js')
|
||||
await import('./out/b.js')
|
||||
`,
|
||||
"/test2.js": /* js */ `
|
||||
await import('./out/b.js')
|
||||
await import('./out/a.js')
|
||||
`,
|
||||
},
|
||||
run: [
|
||||
{ file: "/out/a.js", stdout: "123" },
|
||||
{ file: "/out/b.js", stdout: "456" },
|
||||
{ file: "/test1.js", stdout: "123\n123" },
|
||||
{ file: "/test2.js", stdout: "456\n123" },
|
||||
],
|
||||
});
|
||||
itBundled("splitting/SplittingSideEffectsWithoutDependencies", {
|
||||
// GENERATED
|
||||
itBundled("splitting/SideEffectsWithoutDependencies", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
import {a} from "./shared.js"
|
||||
@@ -133,10 +167,24 @@ describe("bundler", () => {
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
runtimeFiles: {
|
||||
"/test1.js": /* js */ `
|
||||
await import('./out/a.js')
|
||||
await import('./out/b.js')
|
||||
`,
|
||||
"/test2.js": /* js */ `
|
||||
await import('./out/b.js')
|
||||
await import('./out/a.js')
|
||||
`,
|
||||
},
|
||||
run: [
|
||||
{ file: "/out/a.js", stdout: "side effect\n1" },
|
||||
{ file: "/out/b.js", stdout: "side effect\n2" },
|
||||
{ file: "/test1.js", stdout: "side effect\n1\n2" },
|
||||
{ file: "/test2.js", stdout: "side effect\n2\n1" },
|
||||
],
|
||||
});
|
||||
itBundled("splitting/SplittingNestedDirectories", {
|
||||
// GENERATED
|
||||
itBundled("splitting/NestedDirectories", {
|
||||
files: {
|
||||
"/Users/user/project/src/pages/pageA/page.js": /* js */ `
|
||||
import x from "../shared.js"
|
||||
@@ -149,11 +197,15 @@ describe("bundler", () => {
|
||||
"/Users/user/project/src/pages/shared.js": `export default 123`,
|
||||
},
|
||||
entryPoints: ["/Users/user/project/src/pages/pageA/page.js", "/Users/user/project/src/pages/pageB/page.js"],
|
||||
outputPaths: ["/out/pageA/page.js", "/out/pageB/page.js"],
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
|
||||
run: [
|
||||
{ file: "/out/pageA/page.js", stdout: "123" },
|
||||
{ file: "/out/pageB/page.js", stdout: "-123" },
|
||||
],
|
||||
});
|
||||
itBundled("splitting/SplittingCircularReferenceESBuildIssue251", {
|
||||
// GENERATED
|
||||
itBundled("splitting/CircularReferenceESBuildIssue251", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
export * from './b.js';
|
||||
@@ -162,22 +214,37 @@ describe("bundler", () => {
|
||||
"/b.js": /* js */ `
|
||||
export * from './a.js';
|
||||
export var q = 6;
|
||||
|
||||
export function foo() {
|
||||
q = 7;
|
||||
}
|
||||
`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
|
||||
runtimeFiles: {
|
||||
"/test.js": /* js */ `
|
||||
import { p, q, foo } from './out/a.js';
|
||||
console.log(p, q)
|
||||
import { p as p2, q as q2, foo as foo2 } from './out/b.js';
|
||||
console.log(p2, q2)
|
||||
console.log(foo === foo2)
|
||||
foo();
|
||||
console.log(q, q2)
|
||||
`,
|
||||
},
|
||||
run: [{ file: "/test.js", stdout: "5 6\n5 6\ntrue\n7 7" }],
|
||||
});
|
||||
itBundled("splitting/SplittingMissingLazyExport", {
|
||||
// GENERATED
|
||||
itBundled("splitting/MissingLazyExport", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
import {foo} from './common.js'
|
||||
console.log(foo())
|
||||
console.log(JSON.stringify(foo()))
|
||||
`,
|
||||
"/b.js": /* js */ `
|
||||
import {bar} from './common.js'
|
||||
console.log(bar())
|
||||
console.log(JSON.stringify(bar()))
|
||||
`,
|
||||
"/common.js": /* js */ `
|
||||
import * as ns from './empty.js'
|
||||
@@ -191,49 +258,75 @@ describe("bundler", () => {
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
/* TODO FIX expectedCompileLog: `common.js: WARNING: Import "missing" will always be undefined because the file "empty.js" has no exports
|
||||
`, */
|
||||
run: [
|
||||
{ file: "/out/a.js", stdout: "[{},null]" },
|
||||
{ file: "/out/b.js", stdout: "[null]" },
|
||||
],
|
||||
bundleWarnings: {
|
||||
"/empty.js": [`Import "missing" will always be undefined because the file "empty.js" has no exports`],
|
||||
},
|
||||
});
|
||||
itBundled("splitting/SplittingReExportESBuildIssue273", {
|
||||
// GENERATED
|
||||
itBundled("splitting/ReExportESBuildIssue273", {
|
||||
files: {
|
||||
"/a.js": `export const a = 1`,
|
||||
"/a.js": `export const a = { value: 1 }`,
|
||||
"/b.js": `export { a } from './a'`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
runtimeFiles: {
|
||||
"/test.js": /* js */ `
|
||||
import { a } from './out/a.js';
|
||||
import { a as a2 } from './out/b.js';
|
||||
console.log(a === a2, a.value, a2.value)
|
||||
`,
|
||||
},
|
||||
run: [{ file: "/test.js", stdout: "true 1 1" }],
|
||||
});
|
||||
itBundled("splitting/SplittingDynamicImportESBuildIssue272", {
|
||||
// GENERATED
|
||||
itBundled("splitting/DynamicImportESBuildIssue272", {
|
||||
files: {
|
||||
"/a.js": `import('./b')`,
|
||||
"/b.js": `export default 1`,
|
||||
"/b.js": `export default 1; console.log('imported')`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
|
||||
run: [{ file: "/out/a.js", stdout: "imported" }],
|
||||
assertNotPresent: {
|
||||
"/out/a.js": "imported",
|
||||
},
|
||||
});
|
||||
itBundled("splitting/SplittingDynamicImportOutsideSourceTreeESBuildIssue264", {
|
||||
// GENERATED
|
||||
itBundled("splitting/DynamicImportOutsideSourceTreeESBuildIssue264", {
|
||||
files: {
|
||||
"/Users/user/project/src/entry1.js": `import('package')`,
|
||||
"/Users/user/project/src/entry2.js": `import('package')`,
|
||||
"/Users/user/project/node_modules/package/index.js": `console.log('imported')`,
|
||||
},
|
||||
runtimeFiles: {
|
||||
"/both.js": /* js */ `
|
||||
import('./out/entry1.js');
|
||||
import('./out/entry2.js');
|
||||
`,
|
||||
},
|
||||
entryPoints: ["/Users/user/project/src/entry1.js", "/Users/user/project/src/entry2.js"],
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
|
||||
run: [
|
||||
{ file: "/out/entry1.js", stdout: "imported" },
|
||||
{ file: "/out/entry2.js", stdout: "imported" },
|
||||
{ file: "/both.js", stdout: "imported" },
|
||||
],
|
||||
});
|
||||
itBundled("splitting/SplittingCrossChunkAssignmentDependencies", {
|
||||
// GENERATED
|
||||
itBundled("splitting/CrossChunkAssignmentDependencies", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
import {setValue} from './shared'
|
||||
setValue(123)
|
||||
`,
|
||||
"/b.js": `import './shared'`,
|
||||
"/b.js": `import './shared'; console.log('b')`,
|
||||
"/c.js": /* js */ `
|
||||
import * as shared from './shared'
|
||||
globalThis.shared = shared;
|
||||
`,
|
||||
"/shared.js": /* js */ `
|
||||
var observer;
|
||||
var value;
|
||||
@@ -244,59 +337,136 @@ describe("bundler", () => {
|
||||
return value;
|
||||
}
|
||||
export function setValue(next) {
|
||||
console.log('setValue', next)
|
||||
value = next;
|
||||
if (observer) observer();
|
||||
}
|
||||
sideEffects(getValue);
|
||||
console.log("side effects!", getValue);
|
||||
`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
entryPoints: ["/a.js", "/b.js", "/c.js"],
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
runtimeFiles: {
|
||||
"/test.js": /* js */ `
|
||||
import './out/c.js';
|
||||
const { getValue, setObserver } = globalThis.shared;
|
||||
function observer() {
|
||||
console.log('observer', getValue());
|
||||
}
|
||||
setObserver(observer);
|
||||
import('./out/a.js');
|
||||
import('./out/b.js');
|
||||
`,
|
||||
},
|
||||
run: [
|
||||
{ file: "/out/a.js", stdout: "side effects! [Function]\nsetValue 123" },
|
||||
{ file: "/out/b.js", stdout: "side effects! [Function]\nb" },
|
||||
{ file: "/test.js", stdout: "side effects! [Function]\nsetValue 123\nobserver 123\nb" },
|
||||
],
|
||||
});
|
||||
itBundled("splitting/SplittingCrossChunkAssignmentDependenciesRecursive", {
|
||||
// GENERATED
|
||||
itBundled("splitting/CrossChunkAssignmentDependenciesRecursive", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
import { setX } from './x'
|
||||
setX()
|
||||
globalThis.a = { setX };
|
||||
`,
|
||||
"/b.js": /* js */ `
|
||||
import { setZ } from './z'
|
||||
setZ()
|
||||
globalThis.b = { setZ };
|
||||
`,
|
||||
"/c.js": /* js */ `
|
||||
import { setX2 } from './x'
|
||||
import { setY2 } from './y'
|
||||
import { setZ2 } from './z'
|
||||
setX2();
|
||||
setY2();
|
||||
setZ2();
|
||||
globalThis.c = { setX2, setY2, setZ2 };
|
||||
`,
|
||||
"/x.js": /* js */ `
|
||||
let _x
|
||||
export function setX(v) { _x = v }
|
||||
export function setX2(v) { _x = v }
|
||||
globalThis.x = { setX, setX2 };
|
||||
`,
|
||||
"/y.js": /* js */ `
|
||||
import { setX } from './x'
|
||||
let _y
|
||||
export function setY(v) { _y = v }
|
||||
export function setY2(v) { setX(v); _y = v }
|
||||
globalThis.y = { setY, setY2 };
|
||||
`,
|
||||
"/z.js": /* js */ `
|
||||
import { setY } from './y'
|
||||
let _z
|
||||
export function setZ(v) { _z = v }
|
||||
export function setZ2(v) { setY(v); _z = v }
|
||||
globalThis.z = { setZ, setZ2, setY };
|
||||
`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js", "/c.js"],
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
|
||||
runtimeFiles: {
|
||||
"/test_all.js": /* js */ `
|
||||
import './out/a.js';
|
||||
import './out/b.js';
|
||||
import './out/c.js';
|
||||
try {
|
||||
a; b; c; x; y; z; // throw if not defined
|
||||
} catch (error) {
|
||||
throw new Error('chunks were not emitted right.')
|
||||
}
|
||||
import assert from 'assert';
|
||||
assert(a.setX === x.setX, 'a.setX');
|
||||
assert(b.setZ === z.setZ, 'b.setZ');
|
||||
assert(c.setX2 === x.setX2, 'c.setX2');
|
||||
assert(c.setY2 === y.setY2, 'c.setY2');
|
||||
assert(c.setZ2 === z.setZ2, 'c.setZ2');
|
||||
assert(z.setY === y.setY, 'z.setY');
|
||||
`,
|
||||
"/test_a_only.js": /* js */ `
|
||||
import './out/a.js';
|
||||
try {
|
||||
a; x; // throw if not defined
|
||||
} catch (error) {
|
||||
throw new Error('chunks were not emitted right.')
|
||||
}
|
||||
import assert from 'assert';
|
||||
assert(a.setX === x.setX, 'a.setX');
|
||||
assert(globalThis.b === undefined, 'b should not be loaded');
|
||||
assert(globalThis.c === undefined, 'c should not be loaded');
|
||||
assert(globalThis.y === undefined, 'y should not be loaded');
|
||||
assert(globalThis.z === undefined, 'z should not be loaded');
|
||||
`,
|
||||
"/test_b_only.js": /* js */ `
|
||||
import './out/b.js';
|
||||
try {
|
||||
b; x; y; z; // throw if not defined
|
||||
} catch (error) {
|
||||
throw new Error('chunks were not emitted right.')
|
||||
}
|
||||
import assert from 'assert';
|
||||
assert(globalThis.a === undefined, 'a should not be loaded');
|
||||
assert(globalThis.c === undefined, 'c should not be loaded');
|
||||
`,
|
||||
"/test_c_only.js": /* js */ `
|
||||
import './out/c.js';
|
||||
try {
|
||||
c; x; y; z; // throw if not defined
|
||||
} catch (error) {
|
||||
throw new Error('chunks were not emitted right.')
|
||||
}
|
||||
import assert from 'assert';
|
||||
assert(globalThis.a === undefined, 'a should not be loaded');
|
||||
assert(globalThis.b === undefined, 'b should not be loaded');
|
||||
`,
|
||||
},
|
||||
run: [
|
||||
{ file: "/test_all.js" },
|
||||
{ file: "/test_a_only.js" },
|
||||
{ file: "/test_b_only.js" },
|
||||
{ file: "/test_c_only.js" },
|
||||
],
|
||||
});
|
||||
itBundled("splitting/SplittingDuplicateChunkCollision", {
|
||||
// GENERATED
|
||||
itBundled("splitting/DuplicateChunkCollision", {
|
||||
files: {
|
||||
"/a.js": `import "./ab"`,
|
||||
"/b.js": `import "./ab"`,
|
||||
@@ -308,10 +478,12 @@ describe("bundler", () => {
|
||||
entryPoints: ["/a.js", "/b.js", "/c.js", "/d.js"],
|
||||
splitting: true,
|
||||
minifyWhitespace: true,
|
||||
format: "esm",
|
||||
onAfterBundle(api) {
|
||||
const files = readdirSync(api.outdir);
|
||||
expect(files.length).toBe(6);
|
||||
},
|
||||
});
|
||||
itBundled("splitting/SplittingMinifyIdentifiersCrashESBuildIssue437", {
|
||||
// GENERATED
|
||||
itBundled("splitting/MinifyIdentifiersCrashESBuildIssue437", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
import {foo} from "./shared"
|
||||
@@ -327,39 +499,65 @@ describe("bundler", () => {
|
||||
entryPoints: ["/a.js", "/b.js", "/c.js"],
|
||||
splitting: true,
|
||||
minifyIdentifiers: true,
|
||||
format: "esm",
|
||||
run: [
|
||||
{ file: "/out/a.js", stdout: "[Function]" },
|
||||
{ file: "/out/b.js", stdout: "[Function]" },
|
||||
],
|
||||
});
|
||||
itBundled("splitting/SplittingHybridESMAndCJSESBuildIssue617", {
|
||||
// GENERATED
|
||||
itBundled("splitting/HybridESMAndCJSESBuildIssue617", {
|
||||
files: {
|
||||
"/a.js": `export let foo`,
|
||||
"/a.js": `export let foo = 123`,
|
||||
"/b.js": `export let bar = require('./a')`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
assertNotPresent: {
|
||||
"/out/b.js": `123`,
|
||||
},
|
||||
runtimeFiles: {
|
||||
"/test.js": /* js */ `
|
||||
import { foo } from './out/a.js'
|
||||
import { bar } from './out/b.js'
|
||||
console.log(JSON.stringify({ foo, bar }))
|
||||
`,
|
||||
},
|
||||
run: {
|
||||
file: "/test.js",
|
||||
stdout: '{"foo":123,"bar":{"foo":123}}',
|
||||
},
|
||||
});
|
||||
itBundled("splitting/SplittingPublicPathEntryName", {
|
||||
// GENERATED
|
||||
itBundled("splitting/PublicPathEntryName", {
|
||||
files: {
|
||||
"/a.js": `import("./b")`,
|
||||
"/b.js": `console.log('b')`,
|
||||
},
|
||||
outdir: "/out",
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
publicPath: "/www",
|
||||
onAfterBundle(api) {
|
||||
const t = new Bun.Transpiler();
|
||||
const imports = t.scanImports(api.readFile("/out/a.js"));
|
||||
expect(imports.length).toBe(1);
|
||||
expect(imports[0].kind).toBe("dynamic-import");
|
||||
assert(imports[0].path.startsWith("/www/"), `Expected path to start with "/www/" but got "${imports[0].path}"`);
|
||||
},
|
||||
});
|
||||
itBundled("splitting/SplittingChunkPathDirPlaceholderImplicitOutbase", {
|
||||
// GENERATED
|
||||
itBundled("splitting/ChunkPathDirPlaceholderImplicitOutbase", {
|
||||
files: {
|
||||
"/project/entry.js": `console.log(import('./output-path/should-contain/this-text/file'))`,
|
||||
"/project/output-path/should-contain/this-text/file.js": `console.log('file.js')`,
|
||||
},
|
||||
format: "esm",
|
||||
outdir: "/out",
|
||||
splitting: true,
|
||||
chunkNames: "[dir]/[name]-[hash].[ext]",
|
||||
onAfterBundle(api) {
|
||||
assert(
|
||||
readdirSync(api.outdir + "/output-path/should-contain/this-text").length === 1,
|
||||
"Expected one file in out/output-path/should-contain/this-text/",
|
||||
);
|
||||
},
|
||||
});
|
||||
itBundled("splitting/EdgeCaseESBuildIssue2793WithSplitting", {
|
||||
// GENERATED
|
||||
const EdgeCaseESBuildIssue2793WithSplitting = itBundled("splitting/EdgeCaseESBuildIssue2793WithSplitting", {
|
||||
files: {
|
||||
"/src/a.js": `export const A = 42;`,
|
||||
"/src/b.js": `export const B = async () => (await import(".")).A`,
|
||||
@@ -370,21 +568,31 @@ describe("bundler", () => {
|
||||
},
|
||||
outdir: "/out",
|
||||
entryPoints: ["/src/index.js"],
|
||||
format: "esm",
|
||||
splitting: true,
|
||||
platform: "browser",
|
||||
runtimeFiles: {
|
||||
"/test.js": /* js */ `
|
||||
import { A, B } from './out/index.js'
|
||||
console.log(A, B() instanceof Promise, await B())
|
||||
`,
|
||||
},
|
||||
run: {
|
||||
file: "/test.js",
|
||||
stdout: "42 true 42",
|
||||
},
|
||||
});
|
||||
itBundled("splitting/EdgeCaseESBuildIssue2793WithoutSplitting", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/src/a.js": `export const A = 42;`,
|
||||
"/src/b.js": `export const B = async () => (await import(".")).A`,
|
||||
"/src/index.js": /* js */ `
|
||||
export * from "./a"
|
||||
export * from "./b"
|
||||
...EdgeCaseESBuildIssue2793WithSplitting.options,
|
||||
splitting: false,
|
||||
runtimeFiles: {
|
||||
"/test.js": /* js */ `
|
||||
import { A, B } from './out/index.js'
|
||||
console.log(A, B() instanceof Promise, await B())
|
||||
`,
|
||||
},
|
||||
entryPoints: ["/src/index.js"],
|
||||
format: "esm",
|
||||
outdir: "/out",
|
||||
run: {
|
||||
file: "/test.js",
|
||||
stdout: "42 true 42",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,10 +5,10 @@ var { describe, test, expect } = testForFile(import.meta.path);
|
||||
// Tests ported from:
|
||||
// https://github.com/evanw/esbuild/blob/main/internal/bundler_tests/bundler_ts_test.go
|
||||
|
||||
// For debug, all files are written to $TEMP/bun-bundle-tests/ts
|
||||
// For debug, all files are written to $TEMP/bun-bundle-tests/
|
||||
|
||||
describe("bundler", () => {
|
||||
itBundled("ts/TSDeclareConst", {
|
||||
itBundled("ts/DeclareConst", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
declare const require: any
|
||||
@@ -27,7 +27,7 @@ describe("bundler", () => {
|
||||
assert(!api.readFile("/out.js").includes("const foo"), 'does not include "const foo"');
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSDeclareLet", {
|
||||
itBundled("ts/DeclareLet", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
declare let require: any
|
||||
@@ -45,7 +45,7 @@ describe("bundler", () => {
|
||||
assert(!api.readFile("/out.js").includes("module"), 'does not include "module"');
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSDeclareVar", {
|
||||
itBundled("ts/DeclareVar", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
declare var require: any
|
||||
@@ -63,7 +63,7 @@ describe("bundler", () => {
|
||||
assert(!api.readFile("/out.js").includes("module"), 'does not include "module"');
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSDeclareClass", {
|
||||
itBundled("ts/DeclareClass", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
declare class require {}
|
||||
@@ -82,7 +82,7 @@ describe("bundler", () => {
|
||||
assert(!api.readFile("/out.js").includes("class"), 'does not include "class"');
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSDeclareClassFields", {
|
||||
itBundled("ts/DeclareClassFields", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import './setup'
|
||||
@@ -101,15 +101,15 @@ describe("bundler", () => {
|
||||
`,
|
||||
"/define-false/index.ts": /* ts */ `
|
||||
class Foo {
|
||||
a
|
||||
declare b
|
||||
[(() => null, c)]
|
||||
declare [(() => null, d)]
|
||||
a = 1
|
||||
declare b: number
|
||||
[(() => null, c)] = 3
|
||||
declare [(() => null, d)]: number
|
||||
|
||||
static A
|
||||
static declare B
|
||||
static [(() => null, C)]
|
||||
static declare [(() => null, D)]
|
||||
static A = 5
|
||||
static declare B: number
|
||||
static [(() => null, C)] = 7
|
||||
static declare [(() => null, D)]: number
|
||||
}
|
||||
const props = x => JSON.stringify({ ...Object.getOwnPropertyDescriptors(x), length: undefined, prototype: undefined })
|
||||
console.log('Foo ', props(Foo))
|
||||
@@ -141,14 +141,14 @@ describe("bundler", () => {
|
||||
},
|
||||
run: {
|
||||
stdout: `
|
||||
Foo {"name":{"value":"Foo","writable":false,"enumerable":false,"configurable":true}}
|
||||
new Foo {}
|
||||
Foo {"name":{"value":"Foo","writable":false,"enumerable":false,"configurable":true},"A":{"value":5,"writable":true,"enumerable":true,"configurable":true},"global.C":{"value":7,"writable":true,"enumerable":true,"configurable":true}}
|
||||
new Foo {"a":{"value":1,"writable":true,"enumerable":true,"configurable":true},"global.c":{"value":3,"writable":true,"enumerable":true,"configurable":true}}
|
||||
Bar {"name":{"value":"Bar","writable":false,"enumerable":false,"configurable":true},"A":{"writable":true,"enumerable":true,"configurable":true},"global.C":{"writable":true,"enumerable":true,"configurable":true}}
|
||||
new Bar {"a":{"writable":true,"enumerable":true,"configurable":true},"global.c":{"writable":true,"enumerable":true,"configurable":true}}
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSDeclareFunction", {
|
||||
itBundled("ts/DeclareFunction", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
declare function require(): void
|
||||
@@ -167,7 +167,7 @@ describe("bundler", () => {
|
||||
assert(!api.readFile("/out.js").includes("function"), 'does not include "function"');
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSDeclareNamespace", {
|
||||
itBundled("ts/DeclareNamespace", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
declare namespace require {}
|
||||
@@ -186,7 +186,7 @@ describe("bundler", () => {
|
||||
assert(!api.readFile("/out.js").includes("namespace"), 'does not include "namespace"');
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSDeclareEnum", {
|
||||
itBundled("ts/DeclareEnum", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
declare enum require {}
|
||||
@@ -205,7 +205,7 @@ describe("bundler", () => {
|
||||
assert(!api.readFile("/out.js").includes("enum"), 'does not include "enum"');
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSDeclareConstEnum", {
|
||||
itBundled("ts/DeclareConstEnum", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
declare const enum require {}
|
||||
@@ -225,7 +225,10 @@ describe("bundler", () => {
|
||||
assert(!api.readFile("/out.js").includes("const"), 'does not include "const"');
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSConstEnumComments", {
|
||||
itBundled("ts/ConstEnumComments", {
|
||||
// When it comes time to implement this inlining, we may decide we do NOT
|
||||
// want to insert helper comments.
|
||||
notImplemented: true,
|
||||
files: {
|
||||
"/bar.ts": /* ts */ `
|
||||
export const enum Foo {
|
||||
@@ -268,7 +271,7 @@ describe("bundler", () => {
|
||||
stdout: `{"should have comments":[1,1],"should not have comments":[2,2]}`,
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSImportEmptyNamespace", {
|
||||
itBundled("ts/ImportEmptyNamespace", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import {REMOVE} from './ns.ts'
|
||||
@@ -280,7 +283,7 @@ describe("bundler", () => {
|
||||
dce: true,
|
||||
run: true,
|
||||
});
|
||||
itBundled("ts/TSImportMissingES6", {
|
||||
itBundled("ts/ImportMissingES6", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import fn, {x as a, y as b} from './foo'
|
||||
@@ -290,24 +293,25 @@ describe("bundler", () => {
|
||||
},
|
||||
bundleErrors: {
|
||||
"/entry.ts": [
|
||||
`No matching export "default" in "foo.js" for import "default"`,
|
||||
`No matching export "y" in "foo.js" for import "y"`,
|
||||
`No matching export in "foo.js" for import "default"`,
|
||||
`No matching export in "foo.js" for import "y"`,
|
||||
],
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSImportMissingUnusedES6", {
|
||||
itBundled("ts/ImportMissingUnusedES6", {
|
||||
files: {
|
||||
"/entry.ts": `import fn, {x as a, y as b} from './foo'`,
|
||||
"/foo.js": `export const x = 123`,
|
||||
},
|
||||
// goal for this test is there is no error. we dont really care about the output
|
||||
});
|
||||
itBundled("ts/TSExportMissingES6", {
|
||||
itBundled("ts/ExportMissingES6", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import * as ns from './foo'
|
||||
console.log(JSON.stringify(ns))
|
||||
`,
|
||||
// the reason this doesnt error in TS is because `nope` can be a type
|
||||
"/foo.ts": `export {nope} from './bar'`,
|
||||
"/bar.js": `export const yep = 123`,
|
||||
},
|
||||
@@ -315,7 +319,7 @@ describe("bundler", () => {
|
||||
stdout: `{}`,
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSImportMissingFile", {
|
||||
itBundled("ts/ImportMissingFile", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import {Something} from './doesNotExist.ts'
|
||||
@@ -326,7 +330,7 @@ describe("bundler", () => {
|
||||
"/entry.ts": [`Could not resolve: "./doesNotExist.ts"`],
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSImportTypeOnlyFile", {
|
||||
itBundled("ts/ImportTypeOnlyFile", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import {SomeType1} from './doesNotExist1.ts'
|
||||
@@ -340,7 +344,7 @@ describe("bundler", () => {
|
||||
stdout: "2",
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSExportEquals", {
|
||||
itBundled("ts/ExportEquals", {
|
||||
files: {
|
||||
"/a.ts": /* ts */ `
|
||||
import b from './b.ts'
|
||||
@@ -355,7 +359,7 @@ describe("bundler", () => {
|
||||
stdout: `[123,null]`,
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSExportNamespace", {
|
||||
itBundled("ts/ExportNamespace", {
|
||||
files: {
|
||||
"/a.ts": /* ts */ `
|
||||
import {Foo} from './b.ts'
|
||||
@@ -377,33 +381,34 @@ describe("bundler", () => {
|
||||
stdout: `{}\n1\n2`,
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSMinifyEnum", {
|
||||
itBundled("ts/MinifyEnum", {
|
||||
notImplemented: true,
|
||||
files: {
|
||||
"/a.ts": `enum Foo { A, B, C = Foo }\ncapture(Foo)`,
|
||||
"/b.ts": `export enum Foo { X, Y, Z = Foo }`,
|
||||
// "/b.ts": `export enum Foo { X, Y, Z = Foo }`,
|
||||
},
|
||||
entryPoints: ["/a.ts", "/b.ts"],
|
||||
entryPoints: ["/a.ts"],
|
||||
minifySyntax: true,
|
||||
minifyWhitespace: true,
|
||||
minifyIdentifiers: true,
|
||||
mode: "transform",
|
||||
onAfterBundle(api) {
|
||||
const a = api.readFile("/out/a.js");
|
||||
api.writeFile("/out/a.edited.js", a.replace(/capture\((.*?)\)/, `export const Foo = $1`));
|
||||
const b = api.readFile("/out/b.js");
|
||||
const a = api.readFile("/out.js");
|
||||
api.writeFile("/out.edited.js", a.replace(/capture\((.*?)\)/, `export const Foo = $1`));
|
||||
// const b = api.readFile("/out/b.js");
|
||||
|
||||
// make sure the minification trick "enum[enum.K=V]=K" is used, but `enum`
|
||||
assert(a.match(/\b[a-zA-Z$]\[[a-zA-Z$]\.A=0]=["']A["']/), "should be using enum minification trick (1)");
|
||||
assert(a.match(/\b[a-zA-Z$]\[[a-zA-Z$]\.B=1]=["']B["']/), "should be using enum minification trick (2)");
|
||||
assert(a.match(/\b[a-zA-Z$]\[[a-zA-Z$]\.C=[a-zA-Z$]]=["']C["']/), "should be using enum minification trick (3)");
|
||||
assert(b.match(/\b[a-zA-Z$]\[[a-zA-Z$]\.X=0]=["']X["']/), "should be using enum minification trick (4)");
|
||||
assert(b.match(/\b[a-zA-Z$]\[[a-zA-Z$]\.Y=1]=["']Y["']/), "should be using enum minification trick (5)");
|
||||
assert(b.match(/\b[a-zA-Z$]\[[a-zA-Z$]\.Z=[a-zA-Z$]]=["']Z["']/), "should be using enum minification trick (6)");
|
||||
// assert(b.match(/\b[a-zA-Z$]\[[a-zA-Z$]\.X=0]=["']X["']/), "should be using enum minification trick (4)");
|
||||
// assert(b.match(/\b[a-zA-Z$]\[[a-zA-Z$]\.Y=1]=["']Y["']/), "should be using enum minification trick (5)");
|
||||
// assert(b.match(/\b[a-zA-Z$]\[[a-zA-Z$]\.Z=[a-zA-Z$]]=["']Z["']/), "should be using enum minification trick (6)");
|
||||
},
|
||||
runtimeFiles: {
|
||||
"/test.js": /* js */ `
|
||||
import {Foo as FooA} from './out/a.edited.js'
|
||||
import {Foo as FooB} from './out/b.js'
|
||||
// import {Foo as FooB} from './out/b.js'
|
||||
import assert from 'assert';
|
||||
assert.strictEqual(FooA.A, 0, 'a.ts Foo.A')
|
||||
assert.strictEqual(FooA.B, 1, 'a.ts Foo.B')
|
||||
@@ -411,6 +416,37 @@ describe("bundler", () => {
|
||||
assert.strictEqual(FooA[0], 'A', 'a.ts Foo[0]')
|
||||
assert.strictEqual(FooA[1], 'B', 'a.ts Foo[1]')
|
||||
assert.strictEqual(FooA[FooA], 'C', 'a.ts Foo[Foo]')
|
||||
// assert.strictEqual(FooB.X, 0, 'b.ts Foo.X')
|
||||
// assert.strictEqual(FooB.Y, 1, 'b.ts Foo.Y')
|
||||
// assert.strictEqual(FooB.Z, FooB, 'b.ts Foo.Z')
|
||||
// assert.strictEqual(FooB[0], 'X', 'b.ts Foo[0]')
|
||||
// assert.strictEqual(FooB[1], 'Y', 'b.ts Foo[1]')
|
||||
// assert.strictEqual(FooB[FooB], 'Z', 'b.ts Foo[Foo]')
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("ts/MinifyEnumExported", {
|
||||
notImplemented: true,
|
||||
files: {
|
||||
"/b.ts": `export enum Foo { X, Y, Z = Foo }`,
|
||||
},
|
||||
entryPoints: ["/b.ts"],
|
||||
minifySyntax: true,
|
||||
minifyWhitespace: true,
|
||||
minifyIdentifiers: true,
|
||||
mode: "transform",
|
||||
onAfterBundle(api) {
|
||||
const b = api.readFile("/out.js");
|
||||
|
||||
// make sure the minification trick "enum[enum.K=V]=K" is used, but `enum`
|
||||
assert(b.match(/\b[a-zA-Z$]\[[a-zA-Z$]\.X=0]=["']X["']/), "should be using enum minification trick (4)");
|
||||
assert(b.match(/\b[a-zA-Z$]\[[a-zA-Z$]\.Y=1]=["']Y["']/), "should be using enum minification trick (5)");
|
||||
assert(b.match(/\b[a-zA-Z$]\[[a-zA-Z$]\.Z=[a-zA-Z$]]=["']Z["']/), "should be using enum minification trick (6)");
|
||||
},
|
||||
runtimeFiles: {
|
||||
"/test.js": /* js */ `
|
||||
import {Foo as FooB} from './out.js'
|
||||
import assert from 'assert';
|
||||
assert.strictEqual(FooB.X, 0, 'b.ts Foo.X')
|
||||
assert.strictEqual(FooB.Y, 1, 'b.ts Foo.Y')
|
||||
assert.strictEqual(FooB.Z, FooB, 'b.ts Foo.Z')
|
||||
@@ -420,7 +456,7 @@ describe("bundler", () => {
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSMinifyNestedEnum", {
|
||||
itBundled("ts/MinifyNestedEnum", {
|
||||
files: {
|
||||
"/a.ts": `function foo(arg) { enum Foo { A, B, C = Foo, D = arg } return Foo }\ncapture(foo)`,
|
||||
"/b.ts": `export function foo(arg) { enum Foo { X, Y, Z = Foo, W = arg } return Foo }`,
|
||||
@@ -429,7 +465,6 @@ describe("bundler", () => {
|
||||
minifySyntax: true,
|
||||
minifyWhitespace: true,
|
||||
minifyIdentifiers: true,
|
||||
mode: "transform",
|
||||
onAfterBundle(api) {
|
||||
const a = api.readFile("/out/a.js");
|
||||
api.writeFile("/out/a.edited.js", a.replace(/capture\((.*?)\)/, `export const Foo = $1`));
|
||||
@@ -461,7 +496,7 @@ describe("bundler", () => {
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSMinifyNestedEnumNoLogicalAssignment", {
|
||||
itBundled("ts/MinifyNestedEnumNoLogicalAssignment", {
|
||||
files: {
|
||||
"/a.ts": `function foo(arg) { enum Foo { A, B, C = Foo, D = arg } return Foo }\ncapture(foo)`,
|
||||
"/b.ts": `export function foo(arg) { enum Foo { X, Y, Z = Foo, W = arg } return Foo }`,
|
||||
@@ -481,7 +516,7 @@ describe("bundler", () => {
|
||||
assert(!b.includes("||="), "b should not use logical assignment");
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSMinifyNestedEnumNoArrow", {
|
||||
itBundled("ts/MinifyNestedEnumNoArrow", {
|
||||
files: {
|
||||
"/a.ts": `function foo() { enum Foo { A, B, C = Foo } return Foo }`,
|
||||
"/b.ts": `export function foo() { enum Foo { X, Y, Z = Foo } return Foo }`,
|
||||
@@ -502,7 +537,7 @@ describe("bundler", () => {
|
||||
assert(!b.includes("=>"), "b should not use arrow");
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSMinifyNamespace", {
|
||||
itBundled("ts/MinifyNamespace", {
|
||||
files: {
|
||||
"/a.ts": /* ts */ `
|
||||
namespace Foo {
|
||||
@@ -524,7 +559,6 @@ describe("bundler", () => {
|
||||
minifySyntax: true,
|
||||
minifyWhitespace: true,
|
||||
minifyIdentifiers: true,
|
||||
mode: "transform",
|
||||
onAfterBundle(api) {
|
||||
api.writeFile("/out/a.edited.js", api.readFile("/out/a.js").replace(/capture\((.*?)\)/, `export const Foo = $1`));
|
||||
},
|
||||
@@ -540,7 +574,7 @@ describe("bundler", () => {
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSMinifyNamespaceNoLogicalAssignment", {
|
||||
itBundled("ts/MinifyNamespaceNoLogicalAssignment", {
|
||||
files: {
|
||||
"/a.ts": /* ts */ `
|
||||
namespace Foo {
|
||||
@@ -573,7 +607,7 @@ describe("bundler", () => {
|
||||
assert(!b.includes("||="), "b should not use logical assignment");
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSMinifyNamespaceNoArrow", {
|
||||
itBundled("ts/MinifyNamespaceNoArrow", {
|
||||
files: {
|
||||
"/a.ts": /* ts */ `
|
||||
namespace Foo {
|
||||
@@ -606,7 +640,7 @@ describe("bundler", () => {
|
||||
assert(!b.includes("=>"), "b should not use arrow");
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSMinifyDerivedClass", {
|
||||
itBundled("ts/MinifyDerivedClass", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
class Foo extends Bar {
|
||||
@@ -648,7 +682,7 @@ describe("bundler", () => {
|
||||
stdout: "super\n1 2 3",
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSImportVsLocalCollisionAllTypes", {
|
||||
itBundled("ts/ImportVsLocalCollisionAllTypes", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import {a, b, c, d, e} from './other.ts'
|
||||
@@ -665,7 +699,7 @@ describe("bundler", () => {
|
||||
stdout: '[null,0,null,5,{"prop":2}]',
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSImportVsLocalCollisionMixed", {
|
||||
itBundled("ts/ImportVsLocalCollisionMixed", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import {a, b, c, d, e, real} from './other.ts'
|
||||
@@ -682,7 +716,8 @@ describe("bundler", () => {
|
||||
stdout: '[null,0,null,5,{"prop":2},123]',
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSImportEqualsEliminationTest", {
|
||||
itBundled("ts/ImportEqualsEliminationTest", {
|
||||
notImplemented: true,
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import a = foo.a
|
||||
@@ -713,7 +748,7 @@ describe("bundler", () => {
|
||||
stdout: "123",
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSImportEqualsTreeShakingFalse", {
|
||||
itBundled("ts/ImportEqualsTreeShakingFalse", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import { foo } from 'pkg'
|
||||
@@ -725,8 +760,9 @@ describe("bundler", () => {
|
||||
treeShaking: false,
|
||||
dce: true,
|
||||
mode: "transform",
|
||||
external: ["pkg"],
|
||||
});
|
||||
itBundled("ts/TSImportEqualsTreeShakingTrue", {
|
||||
itBundled("ts/ImportEqualsTreeShakingTrue", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import { foo } from 'pkg'
|
||||
@@ -737,9 +773,11 @@ describe("bundler", () => {
|
||||
},
|
||||
dce: true,
|
||||
treeShaking: true,
|
||||
external: ["pkg"],
|
||||
mode: "transform",
|
||||
});
|
||||
itBundled("ts/TSImportEqualsBundle", {
|
||||
itBundled("ts/ImportEqualsBundle", {
|
||||
notImplemented: true,
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import { foo } from 'pkg'
|
||||
@@ -749,9 +787,10 @@ describe("bundler", () => {
|
||||
`,
|
||||
},
|
||||
dce: true,
|
||||
treeShaking: true,
|
||||
external: ["pkg"],
|
||||
});
|
||||
itBundled("ts/TSMinifiedBundleES6", {
|
||||
itBundled("ts/MinifiedBundleES6", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import {foo} from './a'
|
||||
@@ -770,7 +809,7 @@ describe("bundler", () => {
|
||||
stdout: "123",
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSMinifiedBundleCommonJS", {
|
||||
itBundled("ts/MinifiedBundleCommonJS", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
const {foo} = require('./a')
|
||||
@@ -1004,7 +1043,7 @@ describe("bundler", () => {
|
||||
]);
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSExportDefaultTypeESBuildIssue316", {
|
||||
itBundled("ts/ExportDefaultTypeESBuildIssue316", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import dc_def, { bar as dc } from './keep/declare-class'
|
||||
@@ -1139,7 +1178,7 @@ describe("bundler", () => {
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSImplicitExtensions", {
|
||||
itBundled("ts/ImplicitExtensions", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import './pick-js.js'
|
||||
@@ -1166,7 +1205,7 @@ describe("bundler", () => {
|
||||
stdout: "correct\n".repeat(6),
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSImplicitExtensionsMissing", {
|
||||
itBundled("ts/ImplicitExtensionsMissing", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import './mjs.mjs'
|
||||
@@ -1499,7 +1538,7 @@ describe("bundler", () => {
|
||||
file: "/test.js",
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSComputedClassFieldUseDefineFalse", {
|
||||
itBundled("ts/ComputedClassFieldUseDefineFalse", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
class Foo {
|
||||
@@ -1546,7 +1585,7 @@ describe("bundler", () => {
|
||||
file: "/test.js",
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSComputedClassFieldUseDefineTrue", {
|
||||
itBundled("ts/ComputedClassFieldUseDefineTrue", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
class Foo {
|
||||
@@ -1593,7 +1632,7 @@ describe("bundler", () => {
|
||||
file: "/test.js",
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSComputedClassFieldUseDefineTrueLower", {
|
||||
itBundled("ts/ComputedClassFieldUseDefineTrueLower", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
class Foo {
|
||||
@@ -1641,7 +1680,7 @@ describe("bundler", () => {
|
||||
},
|
||||
unsupportedJSFeatures: ["class-field"],
|
||||
});
|
||||
itBundled("ts/TSAbstractClassFieldUseAssign", {
|
||||
itBundled("ts/AbstractClassFieldUseAssign", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
const keepThis = Symbol('keepThis')
|
||||
@@ -1659,7 +1698,7 @@ describe("bundler", () => {
|
||||
dce: true,
|
||||
useDefineForClassFields: false,
|
||||
});
|
||||
itBundled("ts/TSAbstractClassFieldUseDefine", {
|
||||
itBundled("ts/AbstractClassFieldUseDefine", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
const keepThisToo = Symbol('keepThisToo')
|
||||
@@ -1677,7 +1716,7 @@ describe("bundler", () => {
|
||||
mode: "transform",
|
||||
useDefineForClassFields: true,
|
||||
});
|
||||
itBundled("ts/TSImportMTS", {
|
||||
itBundled("ts/ImportMTS", {
|
||||
files: {
|
||||
"/entry.ts": `import './imported.mjs'`,
|
||||
"/imported.mts": `console.log('works')`,
|
||||
@@ -1686,7 +1725,7 @@ describe("bundler", () => {
|
||||
stdout: "works",
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSImportCTS", {
|
||||
itBundled("ts/ImportCTS", {
|
||||
files: {
|
||||
"/entry.ts": `require('./required.cjs')`,
|
||||
"/required.cjs": `console.log('works')`,
|
||||
@@ -1695,7 +1734,7 @@ describe("bundler", () => {
|
||||
stdout: "works",
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSSideEffectsFalseWarningTypeDeclarations", {
|
||||
itBundled("ts/SideEffectsFalseWarningTypeDeclarations", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import "some-js"
|
||||
@@ -1719,7 +1758,7 @@ describe("bundler", () => {
|
||||
expect(api.readFile("/out.js").trim()).toBe("");
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSSiblingNamespace", {
|
||||
itBundled("ts/SiblingNamespace", {
|
||||
files: {
|
||||
"/let.ts": /* ts */ `
|
||||
export namespace x { export let y = 123 }
|
||||
@@ -1760,8 +1799,7 @@ describe("bundler", () => {
|
||||
`,
|
||||
},
|
||||
});
|
||||
if (!RUN_UNCHECKED_TESTS) return;
|
||||
itBundled("ts/TSSiblingEnum", {
|
||||
itBundled("ts/SiblingEnum", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/number.ts": /* ts */ `
|
||||
@@ -1837,7 +1875,7 @@ describe("bundler", () => {
|
||||
],
|
||||
mode: "passthrough",
|
||||
});
|
||||
itBundled("ts/TSEnumTreeShaking", {
|
||||
itBundled("ts/EnumTreeShaking", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/simple-member.ts": /* ts */ `
|
||||
@@ -1888,7 +1926,7 @@ describe("bundler", () => {
|
||||
"/namespace-after.ts",
|
||||
],
|
||||
});
|
||||
itBundled("ts/TSEnumJSX", {
|
||||
itBundled("ts/EnumJSX", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/element.tsx": /* tsx */ `
|
||||
@@ -1911,14 +1949,14 @@ describe("bundler", () => {
|
||||
entryPoints: ["/element.tsx", "/fragment.tsx", "/nested-element.tsx", "/nested-fragment.tsx"],
|
||||
mode: "passthrough",
|
||||
});
|
||||
itBundled("ts/TSEnumDefine", {
|
||||
itBundled("ts/EnumDefine", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.ts": `enum a { b = 123, c = d }`,
|
||||
},
|
||||
mode: "passthrough",
|
||||
});
|
||||
itBundled("ts/TSEnumSameModuleInliningAccess", {
|
||||
itBundled("ts/EnumSameModuleInliningAccess", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
@@ -1937,7 +1975,7 @@ describe("bundler", () => {
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSEnumCrossModuleInliningAccess", {
|
||||
itBundled("ts/EnumCrossModuleInliningAccess", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
@@ -1959,7 +1997,7 @@ describe("bundler", () => {
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSEnumCrossModuleInliningDefinitions", {
|
||||
itBundled("ts/EnumCrossModuleInliningDefinitions", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
@@ -1981,7 +2019,7 @@ describe("bundler", () => {
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSEnumCrossModuleInliningReExport", {
|
||||
itBundled("ts/EnumCrossModuleInliningReExport", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
@@ -2003,7 +2041,7 @@ describe("bundler", () => {
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSEnumCrossModuleTreeShaking", {
|
||||
itBundled("ts/EnumCrossModuleTreeShaking", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
@@ -2048,7 +2086,7 @@ describe("bundler", () => {
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSEnumExportClause", {
|
||||
itBundled("ts/EnumExportClause", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
@@ -2075,7 +2113,7 @@ describe("bundler", () => {
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("ts/TSThisIsUndefinedWarning", {
|
||||
itBundled("ts/ThisIsUndefinedWarning", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/warning1.ts": `export var foo = this`,
|
||||
@@ -2093,7 +2131,7 @@ describe("bundler", () => {
|
||||
warning3.ts: NOTE: This file is considered to be an ECMAScript module because of the "export" keyword here:
|
||||
`, */
|
||||
});
|
||||
itBundled("ts/TSCommonJSVariableInESMTypeModule", {
|
||||
itBundled("ts/CommonJSVariableInESMTypeModule", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.ts": `module.exports = null`,
|
||||
@@ -2182,7 +2220,7 @@ describe("bundler", () => {
|
||||
},
|
||||
entryPoints: ["/supported.ts", "/not-supported.ts"],
|
||||
});
|
||||
itBundled("ts/TSEnumUseBeforeDeclare", {
|
||||
itBundled("ts/EnumUseBeforeDeclare", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
|
||||
@@ -30,9 +30,11 @@ const ESBUILD = process.env.BUN_BUNDLER_TEST_USE_ESBUILD;
|
||||
const DEBUG = process.env.BUN_BUNDLER_TEST_DEBUG;
|
||||
/** Set this to the id of a bundle test to run just that test */
|
||||
const FILTER = process.env.BUN_BUNDLER_TEST_FILTER;
|
||||
/** Set this to hide skips */
|
||||
const HIDE_SKIP = process.env.BUN_BUNDLER_TEST_HIDE_SKIP;
|
||||
/** Path to the bun. TODO: Once bundler is merged, we should remove the `bun-debug` fallback. */
|
||||
const BUN_EXE = (process.env.BUN_EXE && Bun.which(process.env.BUN_EXE)) ?? Bun.which("bun-debug") ?? bunExe();
|
||||
export const RUN_UNCHECKED_TESTS = true;
|
||||
export const RUN_UNCHECKED_TESTS = false;
|
||||
|
||||
const outBaseTemplate = path.join(tmpdir(), "bun-build-tests", `${ESBUILD ? "esbuild" : "bun"}-`);
|
||||
if (!existsSync(path.dirname(outBaseTemplate))) mkdirSync(path.dirname(outBaseTemplate), { recursive: true });
|
||||
@@ -73,6 +75,8 @@ export interface BundlerTestInput {
|
||||
define?: Record<string, string | number>;
|
||||
/** Default is "[name].[ext]" */
|
||||
entryNames?: string;
|
||||
/** Default is "[name]-[hash].[ext]" */
|
||||
chunkNames?: string;
|
||||
extensionOrder?: string[];
|
||||
/** Replaces "{{root}}" with the file root */
|
||||
external?: string[];
|
||||
@@ -114,6 +118,10 @@ export interface BundlerTestInput {
|
||||
useDefineForClassFields?: boolean;
|
||||
sourceMap?: boolean | "inline" | "external";
|
||||
|
||||
// pass subprocess.env
|
||||
env?: Record<string, any>;
|
||||
nodePaths?: string[];
|
||||
|
||||
// assertion options
|
||||
|
||||
/**
|
||||
@@ -137,6 +145,13 @@ export interface BundlerTestInput {
|
||||
* Checks source code for REMOVE, FAIL, DROP, which will fail the test.
|
||||
*/
|
||||
dce?: boolean;
|
||||
/**
|
||||
* Shorthand for testing CJS->ESM cases.
|
||||
* Checks source code for the commonjs helper.
|
||||
*
|
||||
* Set to true means all cjs files should be converted. You can pass `exclude` to expect them to stay commonjs.
|
||||
*/
|
||||
cjs2esm?: boolean | { exclude: string[] };
|
||||
/**
|
||||
* Override the number of keep markers, which is auto detected by default.
|
||||
* Does nothing if dce is false.
|
||||
@@ -233,12 +248,14 @@ export function expectBundled(
|
||||
bundleErrors,
|
||||
bundleWarnings,
|
||||
capture,
|
||||
chunkNames,
|
||||
dce,
|
||||
dceKeepMarkerCount,
|
||||
define,
|
||||
entryNames,
|
||||
entryPoints,
|
||||
entryPointsRaw,
|
||||
env,
|
||||
external,
|
||||
files,
|
||||
format,
|
||||
@@ -261,6 +278,7 @@ export function expectBundled(
|
||||
outfile,
|
||||
outputPaths,
|
||||
platform,
|
||||
publicPath,
|
||||
run,
|
||||
runtimeFiles,
|
||||
skipOnEsbuild,
|
||||
@@ -273,10 +291,6 @@ export function expectBundled(
|
||||
...unknownProps
|
||||
} = opts;
|
||||
|
||||
if (!ESBUILD && platform === "neutral") {
|
||||
platform = "browser";
|
||||
}
|
||||
|
||||
// TODO: Remove this check once all options have been implemented
|
||||
if (Object.keys(unknownProps).length > 0) {
|
||||
throw new Error("expectBundled recieved unexpected options: " + Object.keys(unknownProps).join(", "));
|
||||
@@ -337,6 +351,12 @@ export function expectBundled(
|
||||
if (!ESBUILD && inject) {
|
||||
throw new Error("inject not implemented in bun build");
|
||||
}
|
||||
if (!ESBUILD && publicPath) {
|
||||
throw new Error("publicPath not implemented in bun build");
|
||||
}
|
||||
if (!ESBUILD && chunkNames) {
|
||||
throw new Error("chunkNames is not implemented in bun build");
|
||||
}
|
||||
if (ESBUILD && skipOnEsbuild) {
|
||||
return testRef(id, opts);
|
||||
}
|
||||
@@ -362,8 +382,13 @@ export function expectBundled(
|
||||
: entryPaths.map(file => path.join(outdir!, path.basename(file)))
|
||||
).map(x => x.replace(/\.ts$/, ".js"));
|
||||
|
||||
if (mode === "transform" && !outfile) {
|
||||
throw new Error("transform mode requires one single outfile");
|
||||
}
|
||||
|
||||
if (outdir) {
|
||||
entryNames ??= "[name].[ext]";
|
||||
chunkNames ??= "[name]-[hash].[ext]";
|
||||
}
|
||||
|
||||
// Option validation
|
||||
@@ -410,7 +435,7 @@ export function expectBundled(
|
||||
"build",
|
||||
...entryPaths,
|
||||
...(entryPointsRaw ?? []),
|
||||
outfile ? `--outfile=${outfile}` : `--outdir=${outdir}`,
|
||||
mode === "bundle" ? [outfile ? `--outfile=${outfile}` : `--outdir=${outdir}`] : [],
|
||||
define && Object.entries(define).map(([k, v]) => ["--define", `${k}=${v}`]),
|
||||
`--platform=${platform}`,
|
||||
external && external.map(x => ["--external", x]),
|
||||
@@ -426,6 +451,7 @@ export function expectBundled(
|
||||
// metafile && `--metafile=${metafile}`,
|
||||
// sourceMap && `--sourcemap${sourceMap !== true ? `=${sourceMap}` : ""}`,
|
||||
entryNames && entryNames !== "[name].[ext]" && [`--entry-names`, entryNames],
|
||||
// chunkNames && chunkNames !== "[name]-[hash].[ext]" && [`--chunk-names`, chunkNames],
|
||||
// `--format=${format}`,
|
||||
// legalComments && `--legal-comments=${legalComments}`,
|
||||
splitting && `--splitting`,
|
||||
@@ -434,6 +460,7 @@ export function expectBundled(
|
||||
// keepNames && `--keep-names`,
|
||||
// mainFields && `--main-fields=${mainFields}`,
|
||||
// loader && Object.entries(loader).map(([k, v]) => ["--loader", `${k}=${v}`]),
|
||||
// publicPath && `--public-path=${publicPath}`,
|
||||
mode === "transform" && "--transform",
|
||||
]
|
||||
: [
|
||||
@@ -454,6 +481,7 @@ export function expectBundled(
|
||||
jsx.fragment && `--jsx-fragment=${jsx.fragment}`,
|
||||
jsx.development && `--jsx-dev`,
|
||||
entryNames && entryNames !== "[name].[ext]" && `--entry-names=${entryNames.replace(/\.\[ext]$/, "")}`,
|
||||
chunkNames && chunkNames !== "[name]-[hash].[ext]" && `--chunk-names=${chunkNames.replace(/\.\[ext]$/, "")}`,
|
||||
metafile && `--metafile=${metafile}`,
|
||||
sourceMap && `--sourcemap${sourceMap !== true ? `=${sourceMap}` : ""}`,
|
||||
banner && `--banner:js=${banner}`,
|
||||
@@ -464,6 +492,7 @@ export function expectBundled(
|
||||
keepNames && `--keep-names`,
|
||||
mainFields && `--main-fields=${mainFields.join(",")}`,
|
||||
loader && Object.entries(loader).map(([k, v]) => `--loader:${k}=${v}`),
|
||||
publicPath && `--public-path=${publicPath}`,
|
||||
[...(unsupportedJSFeatures ?? []), ...(unsupportedCSSFeatures ?? [])].map(x => `--supported:${x}=false`),
|
||||
...entryPaths,
|
||||
...(entryPointsRaw ?? []),
|
||||
@@ -508,11 +537,19 @@ export function expectBundled(
|
||||
);
|
||||
}
|
||||
|
||||
const bundlerEnv = { ...bunEnv, ...env };
|
||||
// remove undefined keys instead of passing "undefined"
|
||||
for (const key in bundlerEnv) {
|
||||
if (bundlerEnv[key] === undefined) {
|
||||
delete bundlerEnv[key];
|
||||
}
|
||||
}
|
||||
|
||||
const { stdout, stderr, success } = Bun.spawnSync({
|
||||
cmd,
|
||||
cwd: root,
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
env: bunEnv,
|
||||
env: bundlerEnv,
|
||||
});
|
||||
|
||||
// Check for errors
|
||||
@@ -607,6 +644,11 @@ export function expectBundled(
|
||||
throw new Error("Errors were expected while bundling:\n" + expectedErrors.map(formatError).join("\n"));
|
||||
}
|
||||
|
||||
if (mode === "transform" && !ESBUILD) {
|
||||
mkdirSync(path.dirname(outfile!), { recursive: true });
|
||||
Bun.write(outfile!, stdout);
|
||||
}
|
||||
|
||||
// Check for warnings
|
||||
let warningReference: Record<string, { file: string; error: string; line?: string; col?: string }[]> = {};
|
||||
if (!ESBUILD) {
|
||||
@@ -967,7 +1009,7 @@ export function itBundled(id: string, opts: BundlerTestInput): BundlerTestRef {
|
||||
try {
|
||||
expectBundled(id, opts, true);
|
||||
} catch (error) {
|
||||
it.skip(id, () => {});
|
||||
if (!HIDE_SKIP) it.skip(id, () => {});
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
@@ -981,7 +1023,7 @@ export function itBundled(id: string, opts: BundlerTestInput): BundlerTestRef {
|
||||
);
|
||||
});
|
||||
} catch (error: any) {
|
||||
it.skip(id, () => {});
|
||||
if (!HIDE_SKIP) it.skip(id, () => {});
|
||||
}
|
||||
} else {
|
||||
it(id, () => expectBundled(id, opts));
|
||||
@@ -989,8 +1031,11 @@ export function itBundled(id: string, opts: BundlerTestInput): BundlerTestRef {
|
||||
return ref;
|
||||
}
|
||||
itBundled.skip = (id: string, opts: BundlerTestInput) => {
|
||||
if (FILTER && id !== FILTER) {
|
||||
return testRef(id, opts);
|
||||
}
|
||||
const { it } = testForFile(callerSourceOrigin());
|
||||
it.skip(id, () => expectBundled(id, opts));
|
||||
if (!HIDE_SKIP) it.skip(id, () => expectBundled(id, opts));
|
||||
return testRef(id, opts);
|
||||
};
|
||||
|
||||
@@ -1003,8 +1048,11 @@ export function bundlerTest(id: string, cb: () => void) {
|
||||
it(id, cb);
|
||||
}
|
||||
bundlerTest.skip = (id: string, cb: any) => {
|
||||
if (FILTER && id !== FILTER) {
|
||||
return;
|
||||
}
|
||||
const { it } = testForFile(callerSourceOrigin());
|
||||
it.skip(id, cb);
|
||||
if (!HIDE_SKIP) it.skip(id, cb);
|
||||
};
|
||||
|
||||
function formatError(err: { file: string; error: string; line?: string; col?: string }) {
|
||||
|
||||
Reference in New Issue
Block a user