initial commit
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
import fs from "fs";
|
||||
import { fileURLToPath } from "url";
|
||||
console.log(fs.existsSync(fileURLToPath(import.meta.url)), fs.existsSync(import.meta.path));
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,330 @@
|
||||
import { describe } from "bun:test";
|
||||
import { itBundled } from "../expectBundled";
|
||||
|
||||
// Tests ported from:
|
||||
// https://github.com/evanw/esbuild/blob/main/internal/bundler_tests/bundler_importstar_ts_test.go
|
||||
|
||||
// For debug, all files are written to $TEMP/bun-bundle-tests/ts
|
||||
describe("bundler", () => {
|
||||
itBundled("importstar_ts/Unused", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import * as ns from './foo'
|
||||
let foo = 234
|
||||
console.log(foo)
|
||||
`,
|
||||
"/foo.ts": `export const foo = 123`,
|
||||
},
|
||||
run: { stdout: "234" },
|
||||
});
|
||||
itBundled("importstar_ts/Capture", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import * as ns from './foo'
|
||||
let foo = 234
|
||||
console.log(JSON.stringify(ns), ns.foo, foo)
|
||||
`,
|
||||
"/foo.ts": `export const foo = 123`,
|
||||
},
|
||||
run: { stdout: '{"foo":123} 123 234' },
|
||||
});
|
||||
itBundled("importstar_ts/NoCapture", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import * as ns from './foo'
|
||||
let foo = 234
|
||||
console.log(ns.foo, ns.foo, foo)
|
||||
`,
|
||||
"/foo.ts": `export const foo = 123`,
|
||||
},
|
||||
run: { stdout: "123 123 234" },
|
||||
});
|
||||
itBundled("importstar_ts/ExportImportStarUnused", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import {ns} from './bar'
|
||||
let foo = 234
|
||||
console.log(foo)
|
||||
`,
|
||||
"/foo.ts": `export const foo = 123`,
|
||||
"/bar.ts": /* ts */ `
|
||||
import * as ns from './foo'
|
||||
export {ns}
|
||||
`,
|
||||
},
|
||||
run: { stdout: "234" },
|
||||
});
|
||||
itBundled("importstar_ts/ExportImportStarNoCapture", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import {ns} from './bar'
|
||||
let foo = 234
|
||||
console.log(ns.foo, ns.foo, foo)
|
||||
`,
|
||||
"/foo.ts": `export const foo = 123`,
|
||||
"/bar.ts": /* ts */ `
|
||||
import * as ns from './foo'
|
||||
export {ns}
|
||||
`,
|
||||
},
|
||||
run: { stdout: "123 123 234" },
|
||||
});
|
||||
itBundled("importstar_ts/ExportImportStarCapture", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import {ns} from './bar'
|
||||
let foo = 234
|
||||
console.log(JSON.stringify(ns), ns.foo, foo)
|
||||
`,
|
||||
"/foo.ts": `export const foo = 123`,
|
||||
"/bar.ts": /* ts */ `
|
||||
import * as ns from './foo'
|
||||
export {ns}
|
||||
`,
|
||||
},
|
||||
run: { stdout: '{"foo":123} 123 234' },
|
||||
});
|
||||
itBundled("importstar_ts/ExportStarAsUnused", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import {ns} from './bar'
|
||||
let foo = 234
|
||||
console.log(foo)
|
||||
`,
|
||||
"/foo.ts": `export const foo = 123`,
|
||||
"/bar.ts": `export * as ns from './foo'`,
|
||||
},
|
||||
});
|
||||
itBundled("importstar_ts/ExportStarAsNoCapture", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import {ns} from './bar'
|
||||
let foo = 234
|
||||
console.log(ns.foo, ns.foo, foo)
|
||||
`,
|
||||
"/foo.ts": `export const foo = 123`,
|
||||
"/bar.ts": `export * as ns from './foo'`,
|
||||
},
|
||||
run: { stdout: "123 123 234" },
|
||||
});
|
||||
itBundled("importstar_ts/ExportStarAsCapture", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import {ns} from './bar'
|
||||
let foo = 234
|
||||
console.log(JSON.stringify(ns), ns.foo, foo)
|
||||
`,
|
||||
"/foo.ts": `export const foo = 123`,
|
||||
"/bar.ts": `export * as ns from './foo'`,
|
||||
},
|
||||
run: { stdout: '{"foo":123} 123 234' },
|
||||
});
|
||||
itBundled("importstar_ts/ExportStarUnused", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import * as ns from './bar'
|
||||
let foo = 234
|
||||
console.log(foo)
|
||||
`,
|
||||
"/foo.ts": `export const foo = 123`,
|
||||
"/bar.ts": `export * from './foo'`,
|
||||
},
|
||||
run: { stdout: "234" },
|
||||
});
|
||||
itBundled("importstar_ts/ExportStarNoCapture", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import * as ns from './bar'
|
||||
let foo = 234
|
||||
console.log(ns.foo, ns.foo, foo)
|
||||
`,
|
||||
"/foo.ts": `export const foo = 123`,
|
||||
"/bar.ts": `export * from './foo'`,
|
||||
},
|
||||
run: { stdout: "123 123 234" },
|
||||
});
|
||||
itBundled("importstar_ts/ExportStarCapture", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import * as ns from './bar'
|
||||
let foo = 234
|
||||
console.log(JSON.stringify(ns), ns.foo, foo)
|
||||
`,
|
||||
"/foo.ts": `export const foo = 123`,
|
||||
"/bar.ts": `export * from './foo'`,
|
||||
},
|
||||
run: { stdout: '{"foo":123} 123 234' },
|
||||
});
|
||||
itBundled("importstar_ts/CommonJSUnused", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import * as ns from './foo'
|
||||
let foo = 234
|
||||
console.log(foo)
|
||||
`,
|
||||
"/foo.ts": `exports.foo = 123`,
|
||||
},
|
||||
run: { stdout: "234" },
|
||||
});
|
||||
itBundled("importstar_ts/CommonJSCapture", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import * as ns from './foo'
|
||||
let foo = 234
|
||||
console.log(JSON.stringify(ns), ns.foo, foo)
|
||||
`,
|
||||
"/foo.ts": `exports.foo = 123`,
|
||||
},
|
||||
run: { stdout: '{"foo":123} 123 234' },
|
||||
});
|
||||
itBundled("importstar_ts/CommonJSNoCapture", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import * as ns from './foo'
|
||||
let foo = 234
|
||||
console.log(ns.foo, ns.foo, foo)
|
||||
`,
|
||||
"/foo.ts": `exports.foo = 123`,
|
||||
},
|
||||
run: { stdout: "123 123 234" },
|
||||
});
|
||||
itBundled("importstar_ts/TSAndCommonJS", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import * as ns from './foo'
|
||||
const ns2 = require('./foo')
|
||||
console.log(ns.foo, ns2.foo)
|
||||
`,
|
||||
"/foo.ts": `export const foo = 123`,
|
||||
},
|
||||
run: { stdout: "123 123" },
|
||||
});
|
||||
itBundled("importstar_ts/NoBundleUnused", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import * as ns from './foo'
|
||||
let foo = 234
|
||||
console.log(foo)
|
||||
`,
|
||||
},
|
||||
target: "bun",
|
||||
bundling: false,
|
||||
run: { stdout: "234" },
|
||||
});
|
||||
itBundled("importstar_ts/NoBundleCapture", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import * as ns from './foo'
|
||||
let foo = 234
|
||||
console.log(JSON.stringify(ns), ns.foo, foo)
|
||||
`,
|
||||
},
|
||||
target: "bun",
|
||||
bundling: false,
|
||||
runtimeFiles: {
|
||||
"/foo.js": `
|
||||
export const foo = 123
|
||||
`,
|
||||
},
|
||||
run: { stdout: '{"foo":123} 123 234' },
|
||||
});
|
||||
itBundled("importstar_ts/NoBundleNoCapture", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import * as ns from './foo'
|
||||
let foo = 234
|
||||
console.log(ns.foo, ns.foo, foo)
|
||||
`,
|
||||
},
|
||||
target: "bun",
|
||||
bundling: false,
|
||||
runtimeFiles: {
|
||||
"/foo.js": `
|
||||
export const foo = 123
|
||||
`,
|
||||
},
|
||||
run: { stdout: "123 123 234" },
|
||||
});
|
||||
itBundled("importstar_ts/MangleNoBundleUnused", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import * as ns from './foo'
|
||||
let foo = 234
|
||||
console.log(foo)
|
||||
`,
|
||||
},
|
||||
minifySyntax: true,
|
||||
target: "bun",
|
||||
bundling: false,
|
||||
runtimeFiles: {
|
||||
"/foo.js": `
|
||||
export const foo = 123
|
||||
`,
|
||||
},
|
||||
run: { stdout: "234" },
|
||||
});
|
||||
itBundled("importstar_ts/MangleNoBundleCapture", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import * as ns from './foo'
|
||||
let foo = 234
|
||||
console.log(JSON.stringify(ns), ns.foo, foo)
|
||||
`,
|
||||
},
|
||||
minifySyntax: true,
|
||||
bundling: false,
|
||||
runtimeFiles: {
|
||||
"/foo.js": `
|
||||
export const foo = 123
|
||||
`,
|
||||
},
|
||||
run: { stdout: '{"foo":123} 123 234' },
|
||||
});
|
||||
itBundled("importstar_ts/MangleNoBundleNoCapture", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import * as ns from './foo'
|
||||
let foo = 234
|
||||
console.log(ns.foo, ns.foo, foo)
|
||||
`,
|
||||
},
|
||||
minifySyntax: true,
|
||||
bundling: false,
|
||||
runtimeFiles: {
|
||||
"/foo.js": `
|
||||
export const foo = 123
|
||||
`,
|
||||
},
|
||||
run: { stdout: "123 123 234" },
|
||||
});
|
||||
itBundled("importstar_ts/ReExportTypeOnlyFileES6", {
|
||||
files: {
|
||||
"/entry.ts": /* ts */ `
|
||||
import * as ns from './re-export'
|
||||
console.log(ns.foo)
|
||||
`,
|
||||
"/re-export.ts": /* ts */ `
|
||||
export * from './types1'
|
||||
export * from './types2'
|
||||
export * from './types3'
|
||||
export * from './values'
|
||||
`,
|
||||
"/types1.ts": /* ts */ `
|
||||
export interface Foo {}
|
||||
export type Bar = number;
|
||||
console.log('some code')
|
||||
`,
|
||||
"/types2.ts": /* ts */ `
|
||||
import {Foo} from "./type"
|
||||
export {Foo}
|
||||
console.log('some code')
|
||||
`,
|
||||
"/types3.ts": /* ts */ `
|
||||
export {Foo} from "./type"
|
||||
console.log('some code');
|
||||
`,
|
||||
"/values.ts": `export let foo = 123`,
|
||||
"/type.ts": `export type Foo = number`,
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,902 @@
|
||||
import { describe } from "bun:test";
|
||||
import { itBundled } from "../expectBundled";
|
||||
|
||||
// Tests ported from:
|
||||
// https://github.com/evanw/esbuild/blob/main/internal/bundler_tests/bundler_loader_test.go
|
||||
|
||||
// For debug, all files are written to $TEMP/bun-bundle-tests/loader
|
||||
|
||||
describe("bundler", () => {
|
||||
itBundled("loader/JSONCommonJSAndES6", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
const x_json = require('./x.json')
|
||||
import y_json from './y.json'
|
||||
import {small, if as fi} from './z.json'
|
||||
console.log(JSON.stringify(x_json), JSON.stringify(y_json), small, fi)
|
||||
`,
|
||||
"/x.json": `{"x": true}`,
|
||||
"/y.json": `{"y1": true, "y2": false}`,
|
||||
"/z.json": /* json */ `
|
||||
{
|
||||
"big": "this is a big long line of text that should be REMOVED",
|
||||
"small": "some small text",
|
||||
"if": "test keyword imports"
|
||||
}
|
||||
`,
|
||||
},
|
||||
dce: true,
|
||||
run: {
|
||||
stdout: '{"x":true} {"y1":true,"y2":false} some small text test keyword imports',
|
||||
},
|
||||
});
|
||||
|
||||
itBundled("loader/JSONSharedWithMultipleEntriesESBuildIssue413", {
|
||||
todo: true,
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
import data from './data.json'
|
||||
import {test} from './data.json';
|
||||
import * as NSData from './data.json';
|
||||
|
||||
console.log('a:', JSON.stringify(data), data.test, test === data.test, NSData.test === data.test, NSData.default === data, NSData.default.test === data.test, JSON.stringify(NSData))
|
||||
`,
|
||||
"/b.js": /* js */ `
|
||||
import data from './data.json'
|
||||
import {test} from './data.json';
|
||||
import * as NSData from './data.json';
|
||||
console.log('b:', JSON.stringify(data), data.test, test === data.test, NSData.test === data.test, NSData.default === data, NSData.default.test === data.test, JSON.stringify(NSData))
|
||||
`,
|
||||
"/data.json": `{"test": 123}`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
format: "esm",
|
||||
run: [
|
||||
{
|
||||
file: "/out/a.js",
|
||||
stdout: 'a: {"test":123} 123 true true true true {"test":123}',
|
||||
},
|
||||
{
|
||||
file: "/out/b.js",
|
||||
stdout: 'b: {"test":123} 123 true true true true {"test":123}',
|
||||
},
|
||||
],
|
||||
});
|
||||
itBundled("loader/File", {
|
||||
todo: process.platform === "win32", // TODO
|
||||
files: {
|
||||
"/entry.js": `
|
||||
import path from 'path';
|
||||
const file = require('./test.svg');
|
||||
console.log(file);
|
||||
const contents = await Bun.file(path.join(import.meta.dir, file)).text();
|
||||
if(contents !== '<svg></svg>') throw new Error('Contents did not match');
|
||||
`,
|
||||
"/test.svg": `<svg></svg>`,
|
||||
},
|
||||
outdir: "/out",
|
||||
loader: {
|
||||
".svg": "file",
|
||||
},
|
||||
target: "bun",
|
||||
run: {
|
||||
stdout: /\.\/test-.*\.svg/,
|
||||
},
|
||||
});
|
||||
itBundled("loader/FileMultipleNoCollision", {
|
||||
todo: process.platform === "win32", // TODO
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import path from 'path';
|
||||
const file1 = require('./a/test.svg');
|
||||
console.log(file1);
|
||||
const contents = await Bun.file(path.join(import.meta.dir, file1)).text();
|
||||
if(contents !== '<svg></svg>') throw new Error('Contents did not match');
|
||||
const file2 = require('./b/test.svg');
|
||||
console.log(file2);
|
||||
const contents2 = await Bun.file(path.join(import.meta.dir, file2)).text();
|
||||
if(contents2 !== '<svg></svg>') throw new Error('Contents did not match');
|
||||
`,
|
||||
"/a/test.svg": `<svg></svg>`,
|
||||
"/b/test.svg": `<svg></svg>`,
|
||||
},
|
||||
loader: {
|
||||
".svg": "file",
|
||||
},
|
||||
target: "bun",
|
||||
outdir: "/out",
|
||||
run: {
|
||||
stdout: /\.\/test-.*\.svg\n\.\/test-.*\.svg/,
|
||||
},
|
||||
});
|
||||
itBundled("loader/FileMultipleNoCollisionAssetNames", {
|
||||
todo: process.platform === "win32", // TODO
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import path from 'path';
|
||||
const file1 = require('./a/test.svg');
|
||||
console.log(file1);
|
||||
const contents = await Bun.file(path.join(import.meta.dir, file1)).text();
|
||||
if(contents !== '<svg></svg>') throw new Error('Contents did not match');
|
||||
const file2 = require('./b/test.svg');
|
||||
console.log(file2);
|
||||
const contents2 = await Bun.file(path.join(import.meta.dir, file2)).text();
|
||||
if(contents2 !== '<svg></svg>') throw new Error('Contents did not match');
|
||||
`,
|
||||
"/a/test.svg": `<svg></svg>`,
|
||||
"/b/test.svg": `<svg></svg>`,
|
||||
},
|
||||
outdir: "/out",
|
||||
assetNaming: "assets/[name]-[hash].[ext]",
|
||||
loader: {
|
||||
".svg": "file",
|
||||
},
|
||||
target: "bun",
|
||||
run: {
|
||||
stdout: /\.\/assets\/test-.*\.svg\n\.\/assets\/test-.*\.svg/,
|
||||
},
|
||||
});
|
||||
itBundled("loader/JSXSyntaxInJSWithJSXLoader", {
|
||||
files: {
|
||||
"/entry.cjs": `console.log(<div/>)`,
|
||||
},
|
||||
loader: {
|
||||
".cjs": "jsx",
|
||||
},
|
||||
bundling: false,
|
||||
});
|
||||
// itBundled("loader/JSXPreserveCapitalLetter", {
|
||||
// // GENERATED
|
||||
// files: {
|
||||
// "/entry.jsx": /* jsx */ `
|
||||
// import { mustStartWithUpperCaseLetter as Test } from './foo'
|
||||
// console.log(<Test/>)
|
||||
// `,
|
||||
// "/foo.js": `export class mustStartWithUpperCaseLetter {}`,
|
||||
// },
|
||||
// });
|
||||
// itBundled("loader/JSXPreserveCapitalLetterMinify", {
|
||||
// files: {
|
||||
// "/entry.jsx": /* jsx */ `
|
||||
// import { mustStartWithUpperCaseLetter as XYYYY } from './foo'
|
||||
// // 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", {
|
||||
// files: {
|
||||
// "/entry.jsx": /* jsx */ `
|
||||
// x = () => {
|
||||
// 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", {
|
||||
files: {
|
||||
"/entry.js": `console.log(require('./test.custom'))`,
|
||||
"/test.custom": `#include <stdio.h>`,
|
||||
},
|
||||
loader: {
|
||||
".custom": "text",
|
||||
},
|
||||
run: {
|
||||
stdout: "#include <stdio.h>",
|
||||
},
|
||||
});
|
||||
itBundled("loader/RequireCustomExtensionBase64", {
|
||||
files: {
|
||||
"/entry.js": `console.log(require('./test.custom'))`,
|
||||
"/test.custom": `a\x00b\x80c\xFFd`,
|
||||
},
|
||||
loader: {
|
||||
".custom": "base64",
|
||||
},
|
||||
run: {
|
||||
stdout: "YQBiwoBjw79k",
|
||||
},
|
||||
});
|
||||
itBundled("loader/RequireCustomExtensionDataURL", {
|
||||
files: {
|
||||
"/entry.js": `console.log(require('./test.custom'))`,
|
||||
"/test.custom": `a\x00b\x80c\xFFd`,
|
||||
},
|
||||
loader: {
|
||||
".custom": "dataurl",
|
||||
},
|
||||
run: {
|
||||
stdout: "data:application/octet-stream,a\x00b\x80c\xFFd",
|
||||
},
|
||||
});
|
||||
itBundled("loader/RequireCustomExtensionPreferLongest", {
|
||||
files: {
|
||||
"/entry.js": `console.log(require('./test.txt'), require('./test.base64.txt'))`,
|
||||
"/test.txt": `test.txt`,
|
||||
"/test.base64.txt": `test.base64.txt`,
|
||||
},
|
||||
loader: {
|
||||
".txt": "text",
|
||||
".base64.txt": "base64",
|
||||
},
|
||||
run: {
|
||||
stdout: "test.txt dGVzdC5iYXNlNjQudHh0",
|
||||
},
|
||||
});
|
||||
itBundled("loader/AutoDetectMimeTypeFromExtension", {
|
||||
files: {
|
||||
"/entry.js": `console.log(require('./test.svg'))`,
|
||||
"/test.svg": `a\x00b\x80c\xFFd`,
|
||||
},
|
||||
loader: {
|
||||
".svg": "dataurl",
|
||||
},
|
||||
run: {
|
||||
stdout: "data:image/svg+xml,a\x00b\x80c\xFFd",
|
||||
},
|
||||
});
|
||||
itBundled("loader/JSONInvalidIdentifierES6", {
|
||||
todo: true,
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import * as ns from './test.json'
|
||||
import * as ns2 from './test2.json'
|
||||
console.log(ns['invalid-identifier'], JSON.stringify(ns2))
|
||||
`,
|
||||
"/test.json": `{"invalid-identifier": true}`,
|
||||
"/test2.json": `{"invalid-identifier": true}`,
|
||||
},
|
||||
run: {
|
||||
stdout: 'true {"invalid-identifier":true}',
|
||||
},
|
||||
});
|
||||
itBundled("loader/JSONMissingES6", {
|
||||
files: {
|
||||
"/entry.js": `import {missing} from './test.json'`,
|
||||
"/test.json": `{"present": true}`,
|
||||
},
|
||||
bundleErrors: {
|
||||
"/entry.js": [`No matching export in "test.json" for import "missing"`],
|
||||
},
|
||||
});
|
||||
itBundled("loader/TextCommonJSAndES6", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
const x_txt = require('./x.txt')
|
||||
import y_txt from './y.txt'
|
||||
console.log(x_txt, y_txt)
|
||||
`,
|
||||
"/x.txt": `x`,
|
||||
"/y.txt": `y`,
|
||||
},
|
||||
run: {
|
||||
stdout: "x y",
|
||||
},
|
||||
});
|
||||
itBundled("loader/Base64CommonJSAndES6", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
const x_b64 = require('./x.b64')
|
||||
import y_b64 from './y.b64'
|
||||
console.log(x_b64, y_b64)
|
||||
`,
|
||||
"/x.b64": `x`,
|
||||
"/y.b64": `y`,
|
||||
},
|
||||
loader: {
|
||||
".b64": "base64",
|
||||
},
|
||||
run: {
|
||||
stdout: "eA== eQ==",
|
||||
},
|
||||
});
|
||||
itBundled("loader/DataURLCommonJSAndES6", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
const x_url = require('./x.txt')
|
||||
import y_url from './y.txt'
|
||||
console.log(x_url, y_url)
|
||||
`,
|
||||
"/x.txt": `x`,
|
||||
"/y.txt": `y`,
|
||||
},
|
||||
loader: {
|
||||
".txt": "dataurl",
|
||||
},
|
||||
run: {
|
||||
stdout: "data:text/plain;charset=utf-8,x data:text/plain;charset=utf-8,y",
|
||||
},
|
||||
});
|
||||
itBundled("loader/FileCommonJSAndES6", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
const x_url = require('./x.txt')
|
||||
import y_url from './y.txt'
|
||||
console.log(x_url, y_url)
|
||||
`,
|
||||
"/x.txt": `x`,
|
||||
"/y.txt": `y`,
|
||||
},
|
||||
});
|
||||
itBundled("loader/FileRelativePathJS", {
|
||||
files: {
|
||||
"/src/entries/entry.js": /* js */ `
|
||||
import x from '../images/image.png'
|
||||
console.log(x)
|
||||
`,
|
||||
"/src/images/image.png": `x`,
|
||||
},
|
||||
root: "/src",
|
||||
outdir: "/out",
|
||||
outputPaths: ["/out/entries/entry.js"],
|
||||
loader: {
|
||||
".png": "file",
|
||||
},
|
||||
run: {
|
||||
stdout: /^..\/image-.*\.png$/,
|
||||
},
|
||||
});
|
||||
// itBundled("loader/FileRelativePathCSS", {
|
||||
// // GENERATED
|
||||
// files: {
|
||||
// "/src/entries/entry.css": /* css */ `
|
||||
// div {
|
||||
// background: url(../images/image.png);
|
||||
// }
|
||||
// `,
|
||||
// "/src/images/image.png": `x`,
|
||||
// },
|
||||
// outbase: "/src",
|
||||
// });
|
||||
return;
|
||||
itBundled("loader/FileRelativePathAssetNamesJS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/src/entries/entry.js": /* js */ `
|
||||
import x from '../images/image.png'
|
||||
console.log(x)
|
||||
`,
|
||||
"/src/images/image.png": `x`,
|
||||
},
|
||||
root: "/src",
|
||||
assetNaming: "[dir]/[name]-[hash]",
|
||||
outdir: "/out",
|
||||
outputPaths: ["/out/entries/entry.js"],
|
||||
loader: {
|
||||
".png": "file",
|
||||
},
|
||||
run: {
|
||||
stdout: /^..\/images\/image-.*\.png$/,
|
||||
},
|
||||
});
|
||||
itBundled("loader/FileExtPathAssetNamesJS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/src/entries/entry.js": /* js */ `
|
||||
import x from '../images/image.png'
|
||||
import y from '../uploads/file.txt'
|
||||
console.log(x, y)
|
||||
`,
|
||||
"/src/images/image.png": `x`,
|
||||
"/src/uploads/file.txt": `y`,
|
||||
},
|
||||
root: "/src",
|
||||
assetNaming: "[ext]/[name]-[hash]",
|
||||
});
|
||||
itBundled("loader/FileRelativePathAssetNamesCSS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/src/entries/entry.css": /* css */ `
|
||||
div {
|
||||
background: url(../images/image.png);
|
||||
}
|
||||
`,
|
||||
"/src/images/image.png": `x`,
|
||||
},
|
||||
root: "/src",
|
||||
assetNaming: "[dir]/[name]-[hash]",
|
||||
});
|
||||
itBundled("loader/FilePublicPathJS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/src/entries/entry.js": /* js */ `
|
||||
import x from '../images/image.png'
|
||||
console.log(x)
|
||||
`,
|
||||
"/src/images/image.png": `x`,
|
||||
},
|
||||
root: "/src",
|
||||
publicPath: "https://example.com",
|
||||
});
|
||||
itBundled("loader/FilePublicPathCSS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/src/entries/entry.css": /* css */ `
|
||||
div {
|
||||
background: url(../images/image.png);
|
||||
}
|
||||
`,
|
||||
"/src/images/image.png": `x`,
|
||||
},
|
||||
root: "/src",
|
||||
publicPath: "https://example.com",
|
||||
});
|
||||
itBundled("loader/FilePublicPathAssetNamesJS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/src/entries/entry.js": /* js */ `
|
||||
import x from '../images/image.png'
|
||||
console.log(x)
|
||||
`,
|
||||
"/src/images/image.png": `x`,
|
||||
},
|
||||
root: "/src",
|
||||
publicPath: "https://example.com",
|
||||
assetNaming: "[dir]/[name]-[hash]",
|
||||
});
|
||||
itBundled("loader/FilePublicPathAssetNamesCSS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/src/entries/entry.css": /* css */ `
|
||||
div {
|
||||
background: url(../images/image.png);
|
||||
}
|
||||
`,
|
||||
"/src/images/image.png": `x`,
|
||||
},
|
||||
root: "/src",
|
||||
publicPath: "https://example.com",
|
||||
assetNaming: "[dir]/[name]-[hash]",
|
||||
});
|
||||
itBundled("loader/FileOneSourceTwoDifferentOutputPathsJS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/src/entries/entry.js": `import '../shared/common.js'`,
|
||||
"/src/entries/other/entry.js": `import '../../shared/common.js'`,
|
||||
"/src/shared/common.js": /* js */ `
|
||||
import x from './common.png'
|
||||
console.log(x)
|
||||
`,
|
||||
"/src/shared/common.png": `x`,
|
||||
},
|
||||
entryPoints: ["/src/entries/entry.js", "/src/entries/other/entry.js"],
|
||||
root: "/src",
|
||||
});
|
||||
itBundled("loader/FileOneSourceTwoDifferentOutputPathsCSS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/src/entries/entry.css": `@import "../shared/common.css";`,
|
||||
"/src/entries/other/entry.css": `@import "../../shared/common.css";`,
|
||||
"/src/shared/common.css": /* css */ `
|
||||
div {
|
||||
background: url(common.png);
|
||||
}
|
||||
`,
|
||||
"/src/shared/common.png": `x`,
|
||||
},
|
||||
entryPoints: ["/src/entries/entry.css", "/src/entries/other/entry.css"],
|
||||
root: "/src",
|
||||
});
|
||||
itBundled("loader/JSONNoBundle", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/test.json": `{"test": 123, "invalid-identifier": true}`,
|
||||
},
|
||||
bundling: false,
|
||||
});
|
||||
itBundled("loader/JSONNoBundleES6", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/test.json": `{"test": 123, "invalid-identifier": true}`,
|
||||
},
|
||||
format: "esm",
|
||||
unsupportedJSFeatures: "ArbitraryModuleNamespaceNames",
|
||||
mode: "convertformat",
|
||||
});
|
||||
itBundled("loader/JSONNoBundleES6ArbitraryModuleNamespaceNames", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/test.json": `{"test": 123, "invalid-identifier": true}`,
|
||||
},
|
||||
format: "esm",
|
||||
mode: "convertformat",
|
||||
});
|
||||
itBundled("loader/JSONNoBundleCommonJS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/test.json": `{"test": 123, "invalid-identifier": true}`,
|
||||
},
|
||||
format: "cjs",
|
||||
mode: "convertformat",
|
||||
});
|
||||
itBundled("loader/JSONNoBundleIIFE", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/test.json": `{"test": 123, "invalid-identifier": true}`,
|
||||
},
|
||||
format: "iife",
|
||||
mode: "convertformat",
|
||||
});
|
||||
itBundled("loader/FileWithQueryParameter", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
// Each of these should have a separate identity (i.e. end up in the output file twice)
|
||||
import foo from './file.txt?foo'
|
||||
import bar from './file.txt?bar'
|
||||
console.log(foo, bar)
|
||||
`,
|
||||
"/file.txt": `This is some text`,
|
||||
},
|
||||
});
|
||||
itBundled("loader/FromExtensionWithQueryParameter", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import foo from './file.abc?query.xyz'
|
||||
console.log(foo)
|
||||
`,
|
||||
"/file.abc": `This should not be base64 encoded`,
|
||||
},
|
||||
});
|
||||
itBundled("loader/DataURLTextCSS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.css": /* css */ `
|
||||
@import "data:text/css,body{color:%72%65%64}";
|
||||
@import "data:text/css;base64,Ym9keXtiYWNrZ3JvdW5kOmJsdWV9";
|
||||
@import "data:text/css;charset=UTF-8,body{color:%72%65%64}";
|
||||
@import "data:text/css;charset=UTF-8;base64,Ym9keXtiYWNrZ3JvdW5kOmJsdWV9";
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("loader/DataURLTextCSSCannotImport", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.css": `@import "data:text/css,@import './other.css';";`,
|
||||
"/other.css": `div { should-not-be-imported: true }`,
|
||||
},
|
||||
/* TODO FIX expectedScanLog: `<data:text/css,@import './other.css';>: ERROR: Could not resolve "./other.css"
|
||||
`, */
|
||||
});
|
||||
itBundled("loader/DataURLTextJavaScript", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import "data:text/javascript,console.log('%31%32%33')";
|
||||
import "data:text/javascript;base64,Y29uc29sZS5sb2coMjM0KQ==";
|
||||
import "data:text/javascript;charset=UTF-8,console.log(%31%32%33)";
|
||||
import "data:text/javascript;charset=UTF-8;base64,Y29uc29sZS5sb2coMjM0KQ==";
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("loader/DataURLTextJavaScriptCannotImport", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.js": `import "data:text/javascript,import './other.js'"`,
|
||||
"/other.js": `shouldNotBeImported = true`,
|
||||
},
|
||||
/* TODO FIX expectedScanLog: `<data:text/javascript,import './other.js'>: ERROR: Could not resolve "./other.js"
|
||||
`, */
|
||||
});
|
||||
itBundled("loader/DataURLTextJavaScriptPlusCharacter", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.js": `import "data:text/javascript,console.log(1+2)";`,
|
||||
},
|
||||
});
|
||||
itBundled("loader/DataURLApplicationJSON", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import a from 'data:application/json,"%31%32%33"';
|
||||
import b from 'data:application/json;base64,eyJ3b3JrcyI6dHJ1ZX0=';
|
||||
import c from 'data:application/json;charset=UTF-8,%31%32%33';
|
||||
import d from 'data:application/json;charset=UTF-8;base64,eyJ3b3JrcyI6dHJ1ZX0=';
|
||||
console.log([
|
||||
a, b, c, d,
|
||||
])
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("loader/DataURLUnknownMIME", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import a from 'data:some/thing;what,someData%31%32%33';
|
||||
import b from 'data:other/thing;stuff;base64,c29tZURhdGEyMzQ=';
|
||||
console.log(a, b)
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("loader/DataURLExtensionBasedMIME", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.foo": /* foo */ `
|
||||
export { default as css } from "./example.css"
|
||||
export { default as eot } from "./example.eot"
|
||||
export { default as gif } from "./example.gif"
|
||||
export { default as htm } from "./example.htm"
|
||||
export { default as html } from "./example.html"
|
||||
export { default as jpeg } from "./example.jpeg"
|
||||
export { default as jpg } from "./example.jpg"
|
||||
export { default as js } from "./example.js"
|
||||
export { default as json } from "./example.json"
|
||||
export { default as mjs } from "./example.mjs"
|
||||
export { default as otf } from "./example.otf"
|
||||
export { default as pdf } from "./example.pdf"
|
||||
export { default as png } from "./example.png"
|
||||
export { default as sfnt } from "./example.sfnt"
|
||||
export { default as svg } from "./example.svg"
|
||||
export { default as ttf } from "./example.ttf"
|
||||
export { default as wasm } from "./example.wasm"
|
||||
export { default as webp } from "./example.webp"
|
||||
export { default as woff } from "./example.woff"
|
||||
export { default as woff2 } from "./example.woff2"
|
||||
export { default as xml } from "./example.xml"
|
||||
`,
|
||||
"/example.css": `css`,
|
||||
"/example.eot": `eot`,
|
||||
"/example.gif": `gif`,
|
||||
"/example.htm": `htm`,
|
||||
"/example.html": `html`,
|
||||
"/example.jpeg": `jpeg`,
|
||||
"/example.jpg": `jpg`,
|
||||
"/example.js": `js`,
|
||||
"/example.json": `json`,
|
||||
"/example.mjs": `mjs`,
|
||||
"/example.otf": `otf`,
|
||||
"/example.pdf": `pdf`,
|
||||
"/example.png": `png`,
|
||||
"/example.sfnt": `sfnt`,
|
||||
"/example.svg": `svg`,
|
||||
"/example.ttf": `ttf`,
|
||||
"/example.wasm": `wasm`,
|
||||
"/example.webp": `webp`,
|
||||
"/example.woff": `woff`,
|
||||
"/example.woff2": `woff2`,
|
||||
"/example.xml": `xml`,
|
||||
},
|
||||
});
|
||||
itBundled("loader/DataURLBase64VsPercentEncoding", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import a from './shouldUsePercent_1.txt'
|
||||
import b from './shouldUsePercent_2.txt'
|
||||
import c from './shouldUseBase64_1.txt'
|
||||
import d from './shouldUseBase64_2.txt'
|
||||
console.log(
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
)
|
||||
`,
|
||||
"/shouldUsePercent_1.txt": `\n\n\n`,
|
||||
"/shouldUsePercent_2.txt": `\n\n\n\n`,
|
||||
"/shouldUseBase64_1.txt": `\n\n\n\n\n`,
|
||||
"/shouldUseBase64_2.txt": `\n\n\n\n\n\n`,
|
||||
},
|
||||
});
|
||||
itBundled("loader/DataURLBase64InvalidUTF8", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import a from './binary.txt'
|
||||
console.log(a)
|
||||
`,
|
||||
"/binary.txt": `\xFF`,
|
||||
},
|
||||
});
|
||||
itBundled("loader/DataURLEscapePercents", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import a from './percents.txt'
|
||||
console.log(a)
|
||||
`,
|
||||
"/percents.txt": /* txt */ `
|
||||
%, %3, %33, %333
|
||||
%, %e, %ee, %eee
|
||||
%, %E, %EE, %EEE
|
||||
`,
|
||||
},
|
||||
});
|
||||
itBundled("loader/CopyWithBundleFromJS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/Users/user/project/src/entry.js": /* js */ `
|
||||
import x from "../assets/some.file"
|
||||
console.log(x)
|
||||
`,
|
||||
"/Users/user/project/assets/some.file": `stuff`,
|
||||
},
|
||||
root: "/Users/user/project",
|
||||
});
|
||||
itBundled("loader/CopyWithBundleFromCSS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/Users/user/project/src/entry.css": /* css */ `
|
||||
body {
|
||||
background: url(../assets/some.file);
|
||||
}
|
||||
`,
|
||||
"/Users/user/project/assets/some.file": `stuff`,
|
||||
},
|
||||
root: "/Users/user/project",
|
||||
});
|
||||
itBundled("loader/CopyWithBundleEntryPoint", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/Users/user/project/src/entry.js": /* js */ `
|
||||
import x from "../assets/some.file"
|
||||
console.log(x)
|
||||
`,
|
||||
"/Users/user/project/src/entry.css": /* css */ `
|
||||
body {
|
||||
background: url(../assets/some.file);
|
||||
}
|
||||
`,
|
||||
"/Users/user/project/assets/some.file": `stuff`,
|
||||
},
|
||||
entryPoints: [
|
||||
"/Users/user/project/src/entry.js",
|
||||
"/Users/user/project/src/entry.css",
|
||||
"/Users/user/project/assets/some.file",
|
||||
],
|
||||
root: "/Users/user/project",
|
||||
});
|
||||
itBundled("loader/CopyWithTransform", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/Users/user/project/src/entry.js": `console.log('entry')`,
|
||||
"/Users/user/project/assets/some.file": `stuff`,
|
||||
},
|
||||
entryPoints: ["/Users/user/project/src/entry.js", "/Users/user/project/assets/some.file"],
|
||||
root: "/Users/user/project",
|
||||
mode: "passthrough",
|
||||
});
|
||||
itBundled("loader/CopyWithFormat", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/Users/user/project/src/entry.js": `console.log('entry')`,
|
||||
"/Users/user/project/assets/some.file": `stuff`,
|
||||
},
|
||||
entryPoints: ["/Users/user/project/src/entry.js", "/Users/user/project/assets/some.file"],
|
||||
format: "iife",
|
||||
root: "/Users/user/project",
|
||||
mode: "convertformat",
|
||||
});
|
||||
itBundled("loader/JSXAutomaticNoNameCollision", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.jsx": /* jsx */ `
|
||||
import { Link } from "@remix-run/react"
|
||||
const x = <Link {...y} key={z} />
|
||||
`,
|
||||
},
|
||||
format: "cjs",
|
||||
mode: "convertformat",
|
||||
});
|
||||
itBundled("loader/AssertTypeJSONWrongLoader", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.js": `import foo from './foo.json' assert { type: 'json' }`,
|
||||
"/foo.json": `{}`,
|
||||
},
|
||||
/* TODO FIX expectedScanLog: `entry.js: ERROR: The file "foo.json" was loaded with the "js" loader
|
||||
entry.js: NOTE: This import assertion requires the loader to be "json" instead:
|
||||
NOTE: You need to either reconfigure esbuild to ensure that the loader for this file is "json" or you need to remove this import assertion.
|
||||
`, */
|
||||
});
|
||||
itBundled("loader/EmptyLoaderJS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import './a.empty'
|
||||
import * as ns from './b.empty'
|
||||
import def from './c.empty'
|
||||
import { named } from './d.empty'
|
||||
console.log(ns, def, named)
|
||||
`,
|
||||
"/a.empty": `throw 'FAIL'`,
|
||||
"/b.empty": `throw 'FAIL'`,
|
||||
"/c.empty": `throw 'FAIL'`,
|
||||
"/d.empty": `throw 'FAIL'`,
|
||||
},
|
||||
sourceMap: "external",
|
||||
metafile: true,
|
||||
/* TODO FIX expectedCompileLog: `entry.js: WARNING: Import "named" will always be undefined because the file "d.empty" has no exports
|
||||
`, */
|
||||
});
|
||||
itBundled("loader/EmptyLoaderCSS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.css": /* css */ `
|
||||
@import 'a.empty';
|
||||
a { background: url(b.empty) }
|
||||
`,
|
||||
"/a.empty": `body { color: fail }`,
|
||||
"/b.empty": `fail`,
|
||||
},
|
||||
sourceMap: "external",
|
||||
metafile: true,
|
||||
});
|
||||
itBundled("loader/ExtensionlessLoaderJS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.js": `import './what'`,
|
||||
"/what": `foo()`,
|
||||
},
|
||||
});
|
||||
itBundled("loader/ExtensionlessLoaderCSS", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/entry.css": `@import './what';`,
|
||||
"/what": `.foo { color: red }`,
|
||||
},
|
||||
});
|
||||
itBundled("loader/CopyEntryPointAdvanced", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/project/entry.js": /* js */ `
|
||||
import xyz from './xyz.copy'
|
||||
console.log(xyz)
|
||||
`,
|
||||
"/project/TEST FAILED.copy": `some stuff`,
|
||||
"/project/xyz.copy": `more stuff`,
|
||||
},
|
||||
/* TODO FIX entryPathsAdvanced: []bundler.EntryPoint{
|
||||
{
|
||||
InputPath: "/project/entry.js",
|
||||
OutputPath: "js/input/path",
|
||||
InputPathInFileNamespace: true,
|
||||
},
|
||||
{
|
||||
InputPath: "/project/TEST FAILED.copy",
|
||||
OutputPath: "copy/input/path",
|
||||
InputPathInFileNamespace: true,
|
||||
},
|
||||
}, */
|
||||
});
|
||||
itBundled("loader/CopyUseIndex", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/Users/user/project/src/index.copy": `some stuff`,
|
||||
},
|
||||
});
|
||||
itBundled("loader/CopyExplicitOutputFile", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/project/TEST FAILED.copy": `some stuff`,
|
||||
},
|
||||
outfile: "/out/this.worked",
|
||||
});
|
||||
itBundled("loader/CopyStartsWithDotAbsPath", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/project/src/.htaccess": `some stuff`,
|
||||
"/project/src/entry.js": `some.stuff()`,
|
||||
"/project/src/.ts": `foo as number`,
|
||||
},
|
||||
entryPoints: ["/project/src/.htaccess", "/project/src/entry.js", "/project/src/.ts"],
|
||||
});
|
||||
itBundled("loader/CopyStartsWithDotRelPath", {
|
||||
// GENERATED
|
||||
files: {
|
||||
"/project/src/.htaccess": `some stuff`,
|
||||
"/project/src/entry.js": `some.stuff()`,
|
||||
"/project/src/.ts": `foo as number`,
|
||||
},
|
||||
entryPoints: ["./.htaccess", "./entry.js", "./.ts"],
|
||||
/* TODO FIX absWorkingDir: "/project/src", */
|
||||
});
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,345 @@
|
||||
import { describe, expect } from "bun:test";
|
||||
import { existsSync, readFileSync } from "fs";
|
||||
import { itBundled } from "../expectBundled";
|
||||
|
||||
// Tests ported from:
|
||||
// https://github.com/evanw/esbuild/blob/main/internal/bundler_tests/bundler_default_test.go
|
||||
|
||||
describe("bundler", () => {
|
||||
itBundled("metafile/ImportWithTypeJSON", {
|
||||
files: {
|
||||
"/project/entry.js": /* js */ `
|
||||
import a from './data.json'
|
||||
import b from './data.json' assert { type: 'json' }
|
||||
import c from './data.json' with { type: 'json' }
|
||||
x = [a, b, c]
|
||||
`,
|
||||
"/project/data.json": `{"some": "data"}`,
|
||||
},
|
||||
outdir: "/out",
|
||||
metafile: "/metafile.json",
|
||||
onAfterBundle(api) {
|
||||
const metafilePath = api.join("metafile.json");
|
||||
expect(existsSync(metafilePath)).toBe(true);
|
||||
const metafile = JSON.parse(readFileSync(metafilePath, "utf-8"));
|
||||
expect(metafile.inputs).toBeDefined();
|
||||
expect(metafile.outputs).toBeDefined();
|
||||
// Should have imports with 'with' clause for JSON
|
||||
const entryInputKey = Object.keys(metafile.inputs).find(k => k.includes("entry.js"));
|
||||
expect(entryInputKey).toBeDefined();
|
||||
const entryInput = metafile.inputs[entryInputKey!];
|
||||
expect(entryInput.imports.length).toBeGreaterThan(0);
|
||||
// At least one import should have a 'with' clause
|
||||
const hasWithClause = entryInput.imports.some((imp: any) => imp.with?.type === "json");
|
||||
expect(hasWithClause).toBe(true);
|
||||
},
|
||||
});
|
||||
|
||||
itBundled("metafile/BasicStructure", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import { foo } from './foo.js';
|
||||
console.log(foo);
|
||||
`,
|
||||
"/foo.js": /* js */ `
|
||||
export const foo = 42;
|
||||
`,
|
||||
},
|
||||
outdir: "/out",
|
||||
metafile: "/metafile.json",
|
||||
onAfterBundle(api) {
|
||||
const metafilePath = api.join("metafile.json");
|
||||
expect(existsSync(metafilePath)).toBe(true);
|
||||
const metafile = JSON.parse(readFileSync(metafilePath, "utf-8"));
|
||||
// Check basic structure
|
||||
expect(metafile.inputs).toBeDefined();
|
||||
expect(metafile.outputs).toBeDefined();
|
||||
expect(Object.keys(metafile.inputs).length).toBeGreaterThanOrEqual(2);
|
||||
expect(Object.keys(metafile.outputs).length).toBeGreaterThanOrEqual(1);
|
||||
// Check input has bytes and imports
|
||||
for (const input of Object.values(metafile.inputs) as any[]) {
|
||||
expect(typeof input.bytes).toBe("number");
|
||||
expect(Array.isArray(input.imports)).toBe(true);
|
||||
}
|
||||
// Check output has bytes, inputs, imports, exports
|
||||
for (const output of Object.values(metafile.outputs) as any[]) {
|
||||
expect(typeof output.bytes).toBe("number");
|
||||
expect(typeof output.inputs).toBe("object");
|
||||
expect(Array.isArray(output.imports)).toBe(true);
|
||||
expect(Array.isArray(output.exports)).toBe(true);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
itBundled("metafile/MultipleEntryPoints", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
import { shared } from './shared.js';
|
||||
console.log('a', shared);
|
||||
`,
|
||||
"/b.js": /* js */ `
|
||||
import { shared } from './shared.js';
|
||||
console.log('b', shared);
|
||||
`,
|
||||
"/shared.js": /* js */ `
|
||||
export const shared = 'shared value';
|
||||
`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
outdir: "/out",
|
||||
metafile: "/metafile.json",
|
||||
splitting: true,
|
||||
onAfterBundle(api) {
|
||||
const metafilePath = api.join("metafile.json");
|
||||
expect(existsSync(metafilePath)).toBe(true);
|
||||
const metafile = JSON.parse(readFileSync(metafilePath, "utf-8"));
|
||||
expect(metafile.inputs).toBeDefined();
|
||||
expect(metafile.outputs).toBeDefined();
|
||||
// With splitting, we should have multiple outputs
|
||||
expect(Object.keys(metafile.outputs).length).toBeGreaterThanOrEqual(2);
|
||||
},
|
||||
});
|
||||
|
||||
itBundled("metafile/ExternalImports", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import ext1 from 'external-pkg-1';
|
||||
import ext2 from 'external-pkg-2';
|
||||
console.log(ext1, ext2);
|
||||
`,
|
||||
},
|
||||
outdir: "/out",
|
||||
metafile: "/metafile.json",
|
||||
external: ["external-pkg-1", "external-pkg-2"],
|
||||
onAfterBundle(api) {
|
||||
const metafilePath = api.join("metafile.json");
|
||||
expect(existsSync(metafilePath)).toBe(true);
|
||||
const metafile = JSON.parse(readFileSync(metafilePath, "utf-8"));
|
||||
// Find the entry file
|
||||
const entryKey = Object.keys(metafile.inputs).find(k => k.includes("entry.js"));
|
||||
expect(entryKey).toBeDefined();
|
||||
const entry = metafile.inputs[entryKey!];
|
||||
// Check that external imports are marked
|
||||
const externalImports = entry.imports.filter((imp: any) => imp.external === true);
|
||||
expect(externalImports.length).toBe(2);
|
||||
},
|
||||
});
|
||||
|
||||
itBundled("metafile/DynamicImport", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import('./dynamic.js').then(m => console.log(m));
|
||||
`,
|
||||
"/dynamic.js": /* js */ `
|
||||
export const value = 123;
|
||||
`,
|
||||
},
|
||||
outdir: "/out",
|
||||
metafile: "/metafile.json",
|
||||
splitting: true,
|
||||
onAfterBundle(api) {
|
||||
const metafilePath = api.join("metafile.json");
|
||||
expect(existsSync(metafilePath)).toBe(true);
|
||||
const metafile = JSON.parse(readFileSync(metafilePath, "utf-8"));
|
||||
expect(metafile.inputs).toBeDefined();
|
||||
expect(metafile.outputs).toBeDefined();
|
||||
// Find the entry file
|
||||
const entryKey = Object.keys(metafile.inputs).find(k => k.includes("entry.js"));
|
||||
expect(entryKey).toBeDefined();
|
||||
const entry = metafile.inputs[entryKey!];
|
||||
// Should have a dynamic import
|
||||
const dynamicImports = entry.imports.filter((imp: any) => imp.kind === "dynamic-import");
|
||||
expect(dynamicImports.length).toBe(1);
|
||||
},
|
||||
});
|
||||
|
||||
itBundled("metafile/RequireCall", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
const foo = require('./foo.js');
|
||||
console.log(foo);
|
||||
`,
|
||||
"/foo.js": /* js */ `
|
||||
module.exports = { value: 42 };
|
||||
`,
|
||||
},
|
||||
outdir: "/out",
|
||||
metafile: "/metafile.json",
|
||||
onAfterBundle(api) {
|
||||
const metafilePath = api.join("metafile.json");
|
||||
expect(existsSync(metafilePath)).toBe(true);
|
||||
const metafile = JSON.parse(readFileSync(metafilePath, "utf-8"));
|
||||
expect(metafile.inputs).toBeDefined();
|
||||
// Find the entry file
|
||||
const entryKey = Object.keys(metafile.inputs).find(k => k.includes("entry.js"));
|
||||
expect(entryKey).toBeDefined();
|
||||
const entry = metafile.inputs[entryKey!];
|
||||
// Should have a require call
|
||||
const requireImports = entry.imports.filter((imp: any) => imp.kind === "require-call");
|
||||
expect(requireImports.length).toBe(1);
|
||||
},
|
||||
});
|
||||
|
||||
itBundled("metafile/ReExports", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
export { foo } from './foo.js';
|
||||
export * from './bar.js';
|
||||
`,
|
||||
"/foo.js": /* js */ `
|
||||
export const foo = 1;
|
||||
`,
|
||||
"/bar.js": /* js */ `
|
||||
export const bar = 2;
|
||||
export const baz = 3;
|
||||
`,
|
||||
},
|
||||
outdir: "/out",
|
||||
metafile: "/metafile.json",
|
||||
onAfterBundle(api) {
|
||||
const metafilePath = api.join("metafile.json");
|
||||
expect(existsSync(metafilePath)).toBe(true);
|
||||
const metafile = JSON.parse(readFileSync(metafilePath, "utf-8"));
|
||||
expect(metafile.outputs).toBeDefined();
|
||||
// Find the output
|
||||
const outputKey = Object.keys(metafile.outputs)[0];
|
||||
const output = metafile.outputs[outputKey];
|
||||
// Should have exports
|
||||
expect(output.exports.length).toBeGreaterThanOrEqual(3); // foo, bar, baz
|
||||
},
|
||||
});
|
||||
|
||||
itBundled("metafile/NestedImports", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import { a } from './a.js';
|
||||
console.log(a);
|
||||
`,
|
||||
"/a.js": /* js */ `
|
||||
import { b } from './b.js';
|
||||
export const a = b + 1;
|
||||
`,
|
||||
"/b.js": /* js */ `
|
||||
import { c } from './c.js';
|
||||
export const b = c + 1;
|
||||
`,
|
||||
"/c.js": /* js */ `
|
||||
export const c = 1;
|
||||
`,
|
||||
},
|
||||
outdir: "/out",
|
||||
metafile: "/metafile.json",
|
||||
onAfterBundle(api) {
|
||||
const metafilePath = api.join("metafile.json");
|
||||
expect(existsSync(metafilePath)).toBe(true);
|
||||
const metafile = JSON.parse(readFileSync(metafilePath, "utf-8"));
|
||||
expect(metafile.inputs).toBeDefined();
|
||||
// Should have 4 input files
|
||||
expect(Object.keys(metafile.inputs).length).toBe(4);
|
||||
// Each file should have proper imports
|
||||
for (const [path, input] of Object.entries(metafile.inputs) as any) {
|
||||
expect(typeof input.bytes).toBe("number");
|
||||
expect(Array.isArray(input.imports)).toBe(true);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
itBundled("metafile/JSONImport", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import data from './data.json';
|
||||
console.log(data);
|
||||
`,
|
||||
"/data.json": `{"key": "value", "number": 42}`,
|
||||
},
|
||||
outdir: "/out",
|
||||
metafile: "/metafile.json",
|
||||
onAfterBundle(api) {
|
||||
const metafilePath = api.join("metafile.json");
|
||||
expect(existsSync(metafilePath)).toBe(true);
|
||||
const metafile = JSON.parse(readFileSync(metafilePath, "utf-8"));
|
||||
// Find the entry file
|
||||
const entryKey = Object.keys(metafile.inputs).find(k => k.includes("entry.js"));
|
||||
expect(entryKey).toBeDefined();
|
||||
const entry = metafile.inputs[entryKey!];
|
||||
// Should have an import to the JSON file with 'with' clause
|
||||
const jsonImport = entry.imports.find((imp: any) => imp.path.includes("data.json"));
|
||||
expect(jsonImport).toBeDefined();
|
||||
expect(jsonImport.with?.type).toBe("json");
|
||||
},
|
||||
});
|
||||
|
||||
itBundled("metafile/TextImport", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import text from './file.txt';
|
||||
console.log(text);
|
||||
`,
|
||||
"/file.txt": `Hello, World!`,
|
||||
},
|
||||
outdir: "/out",
|
||||
metafile: "/metafile.json",
|
||||
loader: {
|
||||
".txt": "text",
|
||||
},
|
||||
onAfterBundle(api) {
|
||||
const metafilePath = api.join("metafile.json");
|
||||
expect(existsSync(metafilePath)).toBe(true);
|
||||
const metafile = JSON.parse(readFileSync(metafilePath, "utf-8"));
|
||||
// Find the entry file
|
||||
const entryKey = Object.keys(metafile.inputs).find(k => k.includes("entry.js"));
|
||||
expect(entryKey).toBeDefined();
|
||||
const entry = metafile.inputs[entryKey!];
|
||||
// Should have an import to the text file with 'with' clause
|
||||
const textImport = entry.imports.find((imp: any) => imp.path.includes("file.txt"));
|
||||
expect(textImport).toBeDefined();
|
||||
expect(textImport.with?.type).toBe("text");
|
||||
},
|
||||
});
|
||||
|
||||
itBundled("metafile/EntryPoint", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
console.log('entry');
|
||||
`,
|
||||
},
|
||||
outdir: "/out",
|
||||
metafile: "/metafile.json",
|
||||
onAfterBundle(api) {
|
||||
const metafilePath = api.join("metafile.json");
|
||||
expect(existsSync(metafilePath)).toBe(true);
|
||||
const metafile = JSON.parse(readFileSync(metafilePath, "utf-8"));
|
||||
expect(metafile.outputs).toBeDefined();
|
||||
// Find an output with entryPoint
|
||||
const outputWithEntryPoint = Object.values(metafile.outputs).find((o: any) => o.entryPoint);
|
||||
expect(outputWithEntryPoint).toBeDefined();
|
||||
expect(typeof (outputWithEntryPoint as any).entryPoint).toBe("string");
|
||||
},
|
||||
});
|
||||
|
||||
itBundled("metafile/OriginalPath", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import { helper } from './lib/helper.js';
|
||||
console.log(helper);
|
||||
`,
|
||||
"/lib/helper.js": /* js */ `
|
||||
export const helper = 'helper';
|
||||
`,
|
||||
},
|
||||
outdir: "/out",
|
||||
metafile: "/metafile.json",
|
||||
onAfterBundle(api) {
|
||||
const metafilePath = api.join("metafile.json");
|
||||
expect(existsSync(metafilePath)).toBe(true);
|
||||
const metafile = JSON.parse(readFileSync(metafilePath, "utf-8"));
|
||||
// Find the entry file
|
||||
const entryKey = Object.keys(metafile.inputs).find(k => k.includes("entry.js"));
|
||||
expect(entryKey).toBeDefined();
|
||||
const entry = metafile.inputs[entryKey!];
|
||||
// Should have an import with original path
|
||||
expect(entry.imports.length).toBe(1);
|
||||
expect(entry.imports[0].original).toBe("./lib/helper.js");
|
||||
},
|
||||
});
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,664 @@
|
||||
import assert from "assert";
|
||||
import { describe, expect } from "bun:test";
|
||||
import { readdirSync } from "fs";
|
||||
import { itBundled } from "../expectBundled";
|
||||
|
||||
// Tests ported from:
|
||||
// https://github.com/evanw/esbuild/blob/main/internal/bundler_tests/bundler_splitting_test.go
|
||||
|
||||
// For debug, all files are written to $TEMP/bun-bundle-tests/splitting
|
||||
|
||||
describe("bundler", () => {
|
||||
itBundled("splitting/SharedES6IntoES6", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
import {foo} from "./shared.js"
|
||||
console.log(foo)
|
||||
`,
|
||||
"/b.js": /* js */ `
|
||||
import {foo} from "./shared.js"
|
||||
console.log(foo)
|
||||
`,
|
||||
"/shared.js": `export let foo = 123`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
run: [
|
||||
{ file: "/out/a.js", stdout: "123" },
|
||||
{ file: "/out/b.js", stdout: "123" },
|
||||
],
|
||||
assertNotPresent: {
|
||||
"/out/a.js": "123",
|
||||
"/out/b.js": "123",
|
||||
},
|
||||
});
|
||||
itBundled("splitting/SharedCommonJSIntoES6", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
const {foo} = require("./shared.js")
|
||||
console.log(foo)
|
||||
`,
|
||||
"/b.js": /* js */ `
|
||||
const {foo} = require("./shared.js")
|
||||
console.log(foo)
|
||||
`,
|
||||
"/shared.js": `exports.foo = 123`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
run: [
|
||||
{ file: "/out/a.js", stdout: "123" },
|
||||
{ file: "/out/b.js", stdout: "123" },
|
||||
],
|
||||
assertNotPresent: {
|
||||
"/out/a.js": "123",
|
||||
"/out/b.js": "123",
|
||||
},
|
||||
});
|
||||
itBundled("splitting/DynamicES6IntoES6", {
|
||||
todo: true,
|
||||
files: {
|
||||
"/entry.js": `import("./foo.js").then(({bar}) => console.log(bar))`,
|
||||
"/foo.js": `export let bar = 123`,
|
||||
},
|
||||
splitting: true,
|
||||
outdir: "/out",
|
||||
assertNotPresent: {
|
||||
"/out/entry.js": "123",
|
||||
},
|
||||
onAfterBundle(api) {
|
||||
const files = readdirSync(api.outdir);
|
||||
assert.strictEqual(
|
||||
files.length,
|
||||
2,
|
||||
"should have 2 files: entry.js and foo-[hash].js, found [" + files.join(", ") + "]",
|
||||
);
|
||||
assert(files.includes("entry.js"), "has entry.js");
|
||||
assert(!files.includes("foo.js"), "does not have foo.js");
|
||||
},
|
||||
run: {
|
||||
file: "/out/entry.js",
|
||||
stdout: "123",
|
||||
},
|
||||
});
|
||||
itBundled("splitting/DynamicCommonJSIntoES6", {
|
||||
files: {
|
||||
"/entry.js": `import("./foo.js").then(({default: {bar}}) => console.log(bar))`,
|
||||
"/foo.js": `exports.bar = 123`,
|
||||
},
|
||||
splitting: true,
|
||||
outdir: "/out",
|
||||
assertNotPresent: {
|
||||
"/out/entry.js": "123",
|
||||
},
|
||||
run: {
|
||||
file: "/out/entry.js",
|
||||
stdout: "123",
|
||||
},
|
||||
});
|
||||
itBundled("splitting/DynamicAndNotDynamicES6IntoES6", {
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import {bar as a} from "./foo.js"
|
||||
import("./foo.js").then(({bar: b}) => console.log(a, b))
|
||||
`,
|
||||
"/foo.js": `export let bar = 123`,
|
||||
},
|
||||
splitting: true,
|
||||
outdir: "/out",
|
||||
});
|
||||
itBundled("splitting/DynamicAndNotDynamicCommonJSIntoES6", {
|
||||
skipOnEsbuild: true,
|
||||
files: {
|
||||
"/entry.js": /* js */ `
|
||||
import {bar as a} from "./foo.js"
|
||||
import("./foo.js").then(({default: {bar: b}}) => console.log(a, b))
|
||||
`,
|
||||
"/foo.js": `exports.bar = 123`,
|
||||
},
|
||||
outdir: "/out",
|
||||
splitting: true,
|
||||
run: {
|
||||
file: "/out/entry.js",
|
||||
stdout: "123 123",
|
||||
},
|
||||
});
|
||||
itBundled("splitting/AssignToLocal", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
import {foo, setFoo} from "./shared.js"
|
||||
setFoo(123)
|
||||
console.log(foo)
|
||||
`,
|
||||
"/b.js": /* js */ `
|
||||
import {foo} from "./shared.js"
|
||||
console.log(foo)
|
||||
`,
|
||||
"/shared.js": /* js */ `
|
||||
export let foo = 456
|
||||
export function setFoo(value) {
|
||||
foo = value
|
||||
}
|
||||
`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
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/SideEffectsWithoutDependencies", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
import {a} from "./shared.js"
|
||||
console.log(a)
|
||||
`,
|
||||
"/b.js": /* js */ `
|
||||
import {b} from "./shared.js"
|
||||
console.log(b)
|
||||
`,
|
||||
"/shared.js": /* js */ `
|
||||
export let a = 1
|
||||
export let b = 2
|
||||
console.log('side effect')
|
||||
`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
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/NestedDirectories", {
|
||||
files: {
|
||||
"/Users/user/project/src/pages/pageA/page.js": /* js */ `
|
||||
import x from "../shared.js"
|
||||
console.log(x)
|
||||
`,
|
||||
"/Users/user/project/src/pages/pageB/page.js": /* js */ `
|
||||
import x from "../shared.js"
|
||||
console.log(-x)
|
||||
`,
|
||||
"/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,
|
||||
|
||||
run: [
|
||||
{ file: "/out/pageA/page.js", stdout: "123" },
|
||||
{ file: "/out/pageB/page.js", stdout: "-123" },
|
||||
],
|
||||
});
|
||||
itBundled("splitting/CircularReferenceESBuildIssue251", {
|
||||
todo: true,
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
export * from './b.js';
|
||||
export var p = 5;
|
||||
`,
|
||||
"/b.js": /* js */ `
|
||||
export * from './a.js';
|
||||
export var q = 6;
|
||||
|
||||
export function foo() {
|
||||
q = 7;
|
||||
}
|
||||
`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
|
||||
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/MissingLazyExport", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
import {foo} from './common.js'
|
||||
console.log(JSON.stringify(foo()))
|
||||
`,
|
||||
"/b.js": /* js */ `
|
||||
import {bar} from './common.js'
|
||||
console.log(JSON.stringify(bar()))
|
||||
`,
|
||||
"/common.js": /* js */ `
|
||||
import * as ns from './empty.js'
|
||||
export function foo() { return [ns, ns.missing] }
|
||||
export function bar() { return [ns.missing] }
|
||||
`,
|
||||
"/empty.js": /* js */ `
|
||||
// This forces the module into ES6 mode without importing or exporting anything
|
||||
import.meta
|
||||
`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
run: [
|
||||
{ file: "/out/a.js", stdout: "[{},null]" },
|
||||
{ file: "/out/b.js", stdout: "[null]" },
|
||||
],
|
||||
bundleWarnings: {
|
||||
"/common.js": [`Import "missing" will always be undefined because there is no matching export in "empty.js"`],
|
||||
},
|
||||
});
|
||||
itBundled("splitting/ReExportESBuildIssue273", {
|
||||
files: {
|
||||
"/a.js": `export const a = { value: 1 }`,
|
||||
"/b.js": `export { a } from './a'`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
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/DynamicImportESBuildIssue272", {
|
||||
files: {
|
||||
"/a.js": `import('./b')`,
|
||||
"/b.js": `export default 1; console.log('imported')`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
|
||||
run: [{ file: "/out/a.js", stdout: "imported" }],
|
||||
assertNotPresent: {
|
||||
"/out/a.js": "imported",
|
||||
},
|
||||
});
|
||||
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,
|
||||
|
||||
run: [
|
||||
{ file: "/out/entry1.js", stdout: "imported" },
|
||||
{ file: "/out/entry2.js", stdout: "imported" },
|
||||
{ file: "/both.js", stdout: "imported" },
|
||||
],
|
||||
});
|
||||
itBundled("splitting/CrossChunkAssignmentDependencies", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
import {setValue} from './shared'
|
||||
setValue(123)
|
||||
`,
|
||||
"/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;
|
||||
export function setObserver(cb) {
|
||||
observer = cb;
|
||||
}
|
||||
export function getValue() {
|
||||
return value;
|
||||
}
|
||||
export function setValue(next) {
|
||||
console.log('setValue', next)
|
||||
value = next;
|
||||
if (observer) observer();
|
||||
}
|
||||
console.log("side effects!", getValue);
|
||||
`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js", "/c.js"],
|
||||
splitting: true,
|
||||
target: "bun",
|
||||
runtimeFiles: {
|
||||
"/test.js": /* js */ `
|
||||
import './out/c.js';
|
||||
const { getValue, setObserver } = globalThis.shared;
|
||||
function observer() {
|
||||
console.log('observer', getValue());
|
||||
}
|
||||
setObserver(observer);
|
||||
await import('./out/a.js');
|
||||
await import('./out/b.js');
|
||||
`,
|
||||
},
|
||||
run: [
|
||||
{ file: "/out/a.js", stdout: "side effects! [Function: getValue]\nsetValue 123" },
|
||||
{ file: "/out/b.js", stdout: "side effects! [Function: getValue]\nb" },
|
||||
{ file: "/test.js", stdout: "side effects! [Function: getValue]\nsetValue 123\nobserver 123\nb" },
|
||||
],
|
||||
});
|
||||
itBundled("splitting/CrossChunkAssignmentDependenciesRecursive", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
import { setX } from './x'
|
||||
globalThis.a = { setX };
|
||||
`,
|
||||
"/b.js": /* js */ `
|
||||
import { setZ } from './z'
|
||||
globalThis.b = { setZ };
|
||||
`,
|
||||
"/c.js": /* js */ `
|
||||
import { setX2 } from './x'
|
||||
import { setY2 } from './y'
|
||||
import { setZ2 } from './z'
|
||||
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,
|
||||
|
||||
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/DuplicateChunkCollision", {
|
||||
files: {
|
||||
"/a.js": `import "./ab"`,
|
||||
"/b.js": `import "./ab"`,
|
||||
"/c.js": `import "./cd"`,
|
||||
"/d.js": `import "./cd"`,
|
||||
"/ab.js": `console.log(123)`,
|
||||
"/cd.js": `console.log(123)`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js", "/c.js", "/d.js"],
|
||||
splitting: true,
|
||||
minifyWhitespace: true,
|
||||
onAfterBundle(api) {
|
||||
const files = readdirSync(api.outdir);
|
||||
expect(files.length).toBe(6);
|
||||
},
|
||||
});
|
||||
itBundled("splitting/MinifyIdentifiersCrashESBuildIssue437", {
|
||||
files: {
|
||||
"/a.js": /* js */ `
|
||||
import {foo} from "./shared"
|
||||
console.log(foo)
|
||||
`,
|
||||
"/b.js": /* js */ `
|
||||
import {foo} from "./shared"
|
||||
console.log(foo)
|
||||
`,
|
||||
"/c.js": `import "./shared"`,
|
||||
"/shared.js": `export function foo(bar) {}`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js", "/c.js"],
|
||||
splitting: true,
|
||||
minifyIdentifiers: true,
|
||||
run: [
|
||||
{ file: "/out/a.js", stdout: "[Function: f]" },
|
||||
{ file: "/out/b.js", stdout: "[Function: f]" },
|
||||
],
|
||||
});
|
||||
itBundled("splitting/HybridESMAndCJSESBuildIssue617", {
|
||||
files: {
|
||||
"/a.js": `export let foo = 123`,
|
||||
"/b.js": `export let bar = require('./a')`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
splitting: true,
|
||||
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/PublicPathEntryName", {
|
||||
files: {
|
||||
"/a.js": `import("./b")`,
|
||||
"/b.js": `console.log('b')`,
|
||||
},
|
||||
outdir: "/out",
|
||||
splitting: true,
|
||||
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/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')`,
|
||||
},
|
||||
outdir: "/out",
|
||||
splitting: true,
|
||||
chunkNaming: "[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/",
|
||||
);
|
||||
},
|
||||
});
|
||||
const EdgeCaseESBuildIssue2793WithSplitting = itBundled("splitting/EdgeCaseESBuildIssue2793WithSplitting", {
|
||||
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"
|
||||
`,
|
||||
},
|
||||
outdir: "/out",
|
||||
entryPoints: ["/src/index.js"],
|
||||
splitting: true,
|
||||
target: "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", {
|
||||
...EdgeCaseESBuildIssue2793WithSplitting.options,
|
||||
splitting: false,
|
||||
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",
|
||||
},
|
||||
});
|
||||
// Test that CJS modules with dynamic imports to other CJS entry points work correctly
|
||||
// when code splitting causes the dynamically imported module to be in a separate chunk.
|
||||
// The dynamic import should properly unwrap the default export using __toESM.
|
||||
// Regression test for: dynamic import of CJS chunk returns { default: { __esModule, ... } }
|
||||
// and needs .then((m)=>__toESM(m.default)) to unwrap correctly.
|
||||
// Note: __esModule is required because bun optimizes simple CJS to ESM otherwise.
|
||||
itBundled("splitting/CJSDynamicImportOfCJSChunk", {
|
||||
files: {
|
||||
"/main.js": /* js */ `
|
||||
import("./impl.js").then(mod => console.log(mod.foo()));
|
||||
`,
|
||||
"/impl.js": /* js */ `
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.foo = () => "success";
|
||||
`,
|
||||
},
|
||||
entryPoints: ["/main.js", "/impl.js"],
|
||||
splitting: true,
|
||||
outdir: "/out",
|
||||
run: {
|
||||
file: "/out/main.js",
|
||||
stdout: "success",
|
||||
},
|
||||
});
|
||||
// https://github.com/oven-sh/bun/issues/32395
|
||||
for (const format of ["cjs", "iife"] as const) {
|
||||
for (const backend of ["cli", "api"] as const) {
|
||||
itBundled(`splitting/ErrorWithNonEsmFormat_${format}_${backend}`, {
|
||||
files: {
|
||||
"/shared.js": /* js */ `
|
||||
export function sharedFn() { return "shared"; }
|
||||
export const sharedConst = 42;
|
||||
`,
|
||||
"/a.js": /* js */ `
|
||||
import { sharedFn, sharedConst } from "./shared";
|
||||
export const a = sharedFn() + sharedConst;
|
||||
`,
|
||||
"/b.js": /* js */ `
|
||||
import { sharedFn, sharedConst } from "./shared";
|
||||
export const b = sharedFn() + sharedConst;
|
||||
`,
|
||||
},
|
||||
entryPoints: ["/a.js", "/b.js"],
|
||||
outdir: "/out",
|
||||
splitting: true,
|
||||
format,
|
||||
backend,
|
||||
bundleErrors: {
|
||||
"<bun>": ['Code splitting is currently only supported when format is set to "esm"'],
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user