Skip to content

Conversation

robobun
Copy link
Collaborator

@robobun robobun commented Sep 4, 2025

Summary

  • Automatically removes the "Original Filename" field from Windows single-file executables
  • Prevents compiled executables from incorrectly showing "bun.exe" as their original filename
  • Adds comprehensive tests to verify the field is properly removed

Problem

When creating single-file executables on Windows, the "Original Filename" metadata field was showing "bun.exe" regardless of the actual executable name. This was confusing for users and incorrect from a metadata perspective.

Solution

Modified rescle__setWindowsMetadata() in src/bun.js/bindings/windows/rescle-binding.cpp to automatically clear the OriginalFilename field by setting it to an empty string whenever Windows metadata is updated during executable creation.

Test Plan

  • Added tests in test/bundler/compile-windows-metadata.test.ts to verify:
    • Original Filename field is empty in basic compilation
    • Original Filename field remains empty even when all other metadata is set
  • Verified cross-platform compilation with bun run zig:check-all - all platforms compile successfully

The tests will run on Windows CI to verify the behavior is correct.

🤖 Generated with Claude Code

When creating single-file executables on Windows, the 'Original Filename'
field was showing 'bun.exe' regardless of the actual executable name.
This change automatically removes this field by setting it to an empty
string in the rescle metadata update process.

The fix modifies rescle__setWindowsMetadata() to automatically clear
the OriginalFilename field when updating Windows executable metadata.

Tests added to verify the field is properly removed in all scenarios.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@robobun
Copy link
Collaborator Author

robobun commented Sep 4, 2025

Updated 7:37 PM PT - Sep 3rd, 2025

@autofix-ci[bot], your commit bdca2b9 has some failures in Build #24977


🧪   To try this PR locally:

bunx bun-pr 22389

That installs a local version of the PR into your bun-22389 executable, so you can run:

bun-22389 --bun

@github-actions github-actions bot added the claude label Sep 4, 2025
Copy link
Contributor

coderabbitai bot commented Sep 4, 2025

Walkthrough

Clears the Windows VersionInfo OriginalFilename by setting RU_VS_ORIGINAL_FILENAME to an empty string in the metadata binding, returning -13 on failure, before committing. Adds tests that build Windows executables and assert VersionInfo.OriginalFilename is empty for minimal and full metadata; the test block is duplicated. No public signatures changed.

Changes

Cohort / File(s) Summary of Changes
Windows metadata binding update
src/bun.js/bindings/windows/rescle-binding.cpp
In rescle__setWindowsMetadata, sets RU_VS_ORIGINAL_FILENAME to an empty string and returns -13 on failure; commit behavior and return codes remain unchanged. No exported/public signatures altered.
Tests for Original Filename removal
test/bundler/compile-windows-metadata.test.ts
Adds two duplicated "Original Filename removal" suites, each with two tests that build Windows executables (minimal and full metadata) and assert VersionInfo.OriginalFilename is empty. No exported/public declarations changed.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1ee0d9a and bdca2b9.

📒 Files selected for processing (1)
  • test/bundler/compile-windows-metadata.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/bundler/compile-windows-metadata.test.ts
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/remove-original-filename-metadata

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
test/bundler/compile-windows-metadata.test.ts (4)

352-395: Harden the assertion to avoid false positives and sanity-check metadata read.

getMetadata() returns "" on PowerShell errors, which could mask failures. Also assert ProductName to ensure the VersionInfo read worked, and prefer length-check for clarity.

-      const originalFilename = getMetadata("OriginalFilename");
-      expect(originalFilename).toBe("");
-      expect(originalFilename).not.toBe("bun.exe");
+      // Sanity check that we're actually reading VersionInfo
+      expect(getMetadata("ProductName")).toBe("Test Application");
+
+      const originalFilename = getMetadata("OriginalFilename");
+      expect(originalFilename).toHaveLength(0);
+      expect(originalFilename).not.toBe("bun.exe");

396-452: Mirror the stronger checks in the full-metadata case.

Same rationale as above.

-      // But Original Filename should still be empty
-      const originalFilename = getMetadata("OriginalFilename");
-      expect(originalFilename).toBe("");
-      expect(originalFilename).not.toBe("bun.exe");
+      // But Original Filename should still be empty
+      expect(getMetadata("ProductName")).toBe("Complete App");
+      const originalFilename = getMetadata("OriginalFilename");
+      expect(originalFilename).toHaveLength(0);
+      expect(originalFilename).not.toBe("bun.exe");

352-452: DRY the PowerShell accessor.

getMetadata is duplicated; consider extracting a single helper at top-level for reuse in this file.

Example helper (place near cleanup()):

function getVersionInfoField(outfile: string, field: string): string {
  try {
    return execSync(`powershell -Command "(Get-ItemProperty '${outfile}').VersionInfo.${field}"`, { encoding: "utf8" }).trim();
  } catch {
    return "";
  }
}

Then replace local getMetadata calls with getVersionInfoField(outfile, "...").


396-452: Add API-path coverage for OriginalFilename.

We verify CLI; also add a Bun.build() test asserting OriginalFilename is empty to cover the API code path.

Example:

test("Original Filename empty via Bun.build()", async () => {
  const dir = tempDirWithFiles("windows-original-api", { "app.js": `console.log("api");` });
  const result = await Bun.build({
    entrypoints: [join(dir, "app.js")],
    outdir: dir,
    compile: { target: "bun-windows-x64", outfile: "api-original.exe", windows: { title: "API OFN" } },
  });
  expect(result.success).toBe(true);
  const outfile = result.outputs[0].path;
  await using _cleanup = cleanup(outfile);
  const get = (f: string) => execSync(`powershell -Command "(Get-ItemProperty '${outfile}').VersionInfo.${f}"`, { encoding: "utf8" }).trim();
  expect(get("ProductName")).toBe("API OFN");
  expect(get("OriginalFilename")).toHaveLength(0);
  expect(get("OriginalFilename").toLowerCase()).not.toBe("bun.exe");
});
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 60ab798 and 1ee0d9a.

📒 Files selected for processing (2)
  • src/bun.js/bindings/windows/rescle-binding.cpp (1 hunks)
  • test/bundler/compile-windows-metadata.test.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{cpp,h}

📄 CodeRabbit inference engine (.cursor/rules/javascriptcore-class.mdc)

**/*.{cpp,h}: When exposing a JS class with public Constructor and Prototype, define three C++ types: class Foo : public JSC::DestructibleObject (if it has C++ fields), class FooPrototype : public JSC::JSNonFinalObject, and class FooConstructor : public JSC::InternalFunction
If the class has C++ data members, inherit from JSC::DestructibleObject and provide proper destruction; if it has no C++ fields (only JS properties), avoid a class and use JSC::constructEmptyObject(vm, structure) with putDirectOffset
Prefer placing the subspaceFor implementation in the .cpp file rather than the header when possible

Files:

  • src/bun.js/bindings/windows/rescle-binding.cpp
**/*.cpp

📄 CodeRabbit inference engine (.cursor/rules/javascriptcore-class.mdc)

**/*.cpp: Include "root.h" at the top of C++ binding files to satisfy lints
Define prototype properties using a const HashTableValue array and declare accessors/functions with JSC_DECLARE_* macros
Prototype classes should subclass JSC::JSNonFinalObject, provide create/createStructure, DECLARE_INFO, finishCreation that reifies static properties, and set mayBePrototype on the Structure
Custom getters should use JSC_DEFINE_CUSTOM_GETTER, jsDynamicCast to validate this, and throwThisTypeError on mismatch
Custom setters should use JSC_DEFINE_CUSTOM_SETTER, validate this via jsDynamicCast, and store via WriteBarrier/set semantics
Prototype functions should use JSC_DEFINE_HOST_FUNCTION, validate this with jsDynamicCast, and return encoded JSValue
Constructors should subclass JSC::InternalFunction, return internalFunctionSpace in subspaceFor, set the prototype property as non-configurable/non-writable, and provide create/createStructure
Provide a setup function that builds the Prototype, Constructor, and Structure, and assigns them to the LazyClassStructure initializer
Use the cached Structure via globalObject->m_.get(globalObject) when constructing instances
Expose constructors to Zig via an extern "C" function that returns the constructor from the LazyClassStructure
Provide an extern "C" Bun____toJS function that creates an instance using the cached Structure and returns an EncodedJSValue

Files:

  • src/bun.js/bindings/windows/rescle-binding.cpp
src/bun.js/bindings/**/*.cpp

📄 CodeRabbit inference engine (CLAUDE.md)

src/bun.js/bindings/**/*.cpp: When implementing a JS class with a public constructor in C++ bindings, create Foo, FooPrototype, and FooConstructor classes
Define JS-visible properties using HashTableValue arrays
Add iso subspaces for classes with C++ fields
Cache class structures in ZigGlobalObject for bindings

Files:

  • src/bun.js/bindings/windows/rescle-binding.cpp
**/*.{cpp,hpp,h,cc,cxx}

📄 CodeRabbit inference engine (CLAUDE.md)

Run clang-format to format C/C++ files (bun run clang-format)

Files:

  • src/bun.js/bindings/windows/rescle-binding.cpp
test/**

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

Place all tests under the test/ directory

Files:

  • test/bundler/compile-windows-metadata.test.ts
test/bundler/**/*

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

Place bundler/transpiler/CSS/bun build tests under test/bundler/

Files:

  • test/bundler/compile-windows-metadata.test.ts
test/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

test/**/*.{js,ts}: Write tests in JavaScript or TypeScript using Bun’s Jest-style APIs (test, describe, expect) and run with bun test
Prefer data-driven tests (e.g., test.each) to reduce boilerplate
Use shared utilities from test/harness.ts where applicable

Files:

  • test/bundler/compile-windows-metadata.test.ts
test/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

test/**/*.test.{ts,tsx}: Tests must be named with the suffix .test.ts or .test.tsx and live under the test/ directory
In tests, always use port: 0 and never hardcode ports or use custom random-port utilities
Prefer snapshot tests using normalizeBunSnapshot(...) over direct string equality on stdout/stderr
Do not write tests that assert absence of 'panic', 'uncaught exception', or similar strings in output
Avoid shelling out to tools like find or grep in tests; use Bun.Glob and built-in utilities

Files:

  • test/bundler/compile-windows-metadata.test.ts
test/bundler/**

📄 CodeRabbit inference engine (CLAUDE.md)

Place bundler and transpiler tests under test/bundler/

Files:

  • test/bundler/compile-windows-metadata.test.ts
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

Run Prettier to format JS/TS files (bun run prettier)

Files:

  • test/bundler/compile-windows-metadata.test.ts
test/**/*.test.ts

📄 CodeRabbit inference engine (test/CLAUDE.md)

test/**/*.test.ts: Name test files *.test.ts and use bun:test
Do not write flaky tests: never wait for arbitrary time; wait for conditions instead
Never hardcode port numbers in tests; use port: 0 to get a random port
When spawning Bun in tests, use bunExe() and bunEnv from harness
Prefer async/await in tests; for a single callback, use Promise.withResolvers()
Do not set explicit test timeouts; rely on Bun’s built-in timeouts
Use tempDir/tempDirWithFiles from harness for temporary files and directories in tests
For large/repetitive strings in tests, prefer Buffer.alloc(count, fill).toString() over "A".repeat(count)
Import common test utilities from harness (e.g., bunExe, bunEnv, tempDirWithFiles, tmpdirSync, platform checks, GC helpers)
In error tests, assert non-zero exit codes for failing processes and use toThrow for synchronous errors
Use describe blocks for grouping, describe.each for parameterized tests, snapshots with toMatchSnapshot, and lifecycle hooks (beforeAll, beforeEach, afterEach); track resources for cleanup in afterEach
Use using/await using with Bun resources (e.g., Bun.listen/connect/spawn/serve) to ensure cleanup in tests

Files:

  • test/bundler/compile-windows-metadata.test.ts
🧠 Learnings (1)
📚 Learning: 2025-08-30T00:09:39.100Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/dev-server-tests.mdc:0-0
Timestamp: 2025-08-30T00:09:39.100Z
Learning: Applies to test/bake/dev/bundle.test.ts : bundle.test.ts should contain DevServer-specific bundling tests

Applied to files:

  • test/bundler/compile-windows-metadata.test.ts
🧬 Code graph analysis (1)
test/bundler/compile-windows-metadata.test.ts (1)
test/harness.ts (1)
  • tempDirWithFiles (258-265)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Format
🔇 Additional comments (2)
src/bun.js/bindings/windows/rescle-binding.cpp (2)

90-94: Good call: explicitly clearing VersionInfo.OriginalFilename.

This directly addresses the “bun.exe” mislabel and aligns with the new tests.


90-94: Clear InternalName and document new error code

  • In src/bun.js/bindings/windows/rescle-binding.cpp, append:
        // Also clear "InternalName" to avoid "bun.exe" showing in some shells/inspectors
        if (!updater.SetVersionString(RU_VS_INTERNAL_NAME, L""))
            return -14;
  • No in-repo callers or docs reference codes -12/-13; update any external error-code documentation or consumer logic to include the new -14 code.

@Jarred-Sumner Jarred-Sumner merged commit 42cec2f into main Sep 4, 2025
60 of 61 checks passed
@Jarred-Sumner Jarred-Sumner deleted the claude/remove-original-filename-metadata branch September 4, 2025 23:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants