fix: embed .txt files in Bun.embeddedFiles with --compile

When passing .txt files as entry points to `bun build --compile`,
they were not appearing in `Bun.embeddedFiles`. This was because
the `.text` loader didn't set `unique_key_for_additional_file` and
`shouldCopyForBundling()` returned false for it.

This fix:
1. Adds `.text`, `.base64`, and `.dataurl` loaders to
   `shouldCopyForBundling()` so these files are tracked as
   additional files during bundling
2. Updates the `.text` loader to set `unique_key_for_additional_file`
   so the file content is properly embedded

The imported value still returns the inline text content (not a URL)
to maintain backwards compatibility with `import x from './file.txt'`.

Fixes #26617

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Claude Bot
2026-01-31 01:48:55 +00:00
parent 71ce550cfa
commit a467c81b27
3 changed files with 47 additions and 0 deletions

View File

@@ -372,6 +372,30 @@ fn getAST(
return JSAst.init((try js_parser.newLazyExportAST(allocator, transpiler.options.define, opts, &temp_log, root, source, "")).?);
},
.text => {
// Set unique_key_for_additional_file so the file appears in Bun.embeddedFiles
// when passed as an entry point in --compile mode. The exported value is still
// the inline text content (not a URL) for import compatibility.
const content_hash = ContentHasher.run(source.contents);
const unique_key: []const u8 = if (transpiler.options.dev_server != null)
try std.fmt.allocPrint(
allocator,
bun.bake.DevServer.asset_prefix ++ "/{s}{s}",
.{
&std.fmt.bytesToHex(std.mem.asBytes(&content_hash), .lower),
std.fs.path.extension(source.path.text),
},
)
else
try std.fmt.allocPrint(
allocator,
"{f}A{d:0>8}",
.{ bun.fmt.hexIntLower(unique_key_prefix), source.index.get() },
);
unique_key_for_additional_file.* = .{
.key = unique_key,
.content_hash = content_hash,
};
// Export the inline text content (not the URL) for import compatibility
const root = Expr.init(E.String, E.String{
.data = source.contents,
}, Logger.Loc{ .start = 0 });

View File

@@ -681,6 +681,9 @@ pub const Loader = enum(u8) {
pub fn shouldCopyForBundling(this: Loader) bool {
return switch (this) {
.file,
.text,
.base64,
.dataurl,
.napi,
.sqlite,
.sqlite_embedded,

View File

@@ -935,4 +935,24 @@ const server = serve({
const result = await Bun.$`./app`.cwd(dir).env(bunEnv).nothrow();
expect(result.stdout.toString().trim()).toBe("IT WORKS");
});
// https://github.com/oven-sh/bun/issues/26617
// .txt files passed as entry points should appear in Bun.embeddedFiles
test("txt files are embedded in Bun.embeddedFiles with --compile", async () => {
const dir = tempDirWithFiles("compile-txt-embed", {
"app.ts": `
const files = Bun.embeddedFiles;
const txtFile = files.find(f => f.name.endsWith(".txt"));
if (!txtFile) throw new Error("txt file not in embeddedFiles: " + JSON.stringify(files.map(f => f.name)));
console.log(await txtFile.text());
`,
"data.txt": "hello from txt",
});
await Bun.$`${bunExe()} build --compile app.ts data.txt --outfile app`.cwd(dir).env(bunEnv).throws(true);
const result = await Bun.$`./app`.cwd(dir).env(bunEnv).nothrow();
expect(result.stdout.toString().trim()).toBe("hello from txt");
expect(result.exitCode).toBe(0);
});
});