oven-sh / bun

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one
https://bun.sh
Other
73.26k stars 2.69k forks source link

Bundling with --target=bun changes __dirname references to hardcoded values #4216

Open infrahead opened 1 year ago

infrahead commented 1 year ago

What version of Bun is running?

0.7.3

What platform is your computer?

Linux 5.15.90.1-microsoft-standard-WSL2 x86_64 x86_64

What steps can reproduce the bug?

Bundle any Node.js code with __dirname usage, using bun build example.js --target=bun --outfile=bundle.mjs

example.js:

console.log(__dirname)

What is the expected behavior?

The bundled code would work from any runtime location

What do you see instead?

__dirname references are hardcoded to where bundling occurred...

var __dirname = "/tmp/example";
console.log(__dirname);

Additional information

I believe __dirname references should be transpiled to import.meta.dir.

Actually, I've learned Bun seems to support __dirname directly in ESM too, so it could simply be left alone?

Somewhat related to #2865

zbauman3 commented 1 year ago

Bumping this, as I have the same issue with --target="node". This makes bundling nodejs code that uses __dirname impossible, since the resolved location of the file changes from machine to machine, but __dirname is always the value form the original machine.

This is happening on 1.0.1.

Bessonov commented 1 year ago

In addition, it adds absolute paths to files, such as:

/home/myuser/workspace/test/node_modules/raw-body/node_modules/http-errors/node_modules/toidentifier/index.js

This not only leaks parts of credentials but also makes builds non-reproducible.

richardguerre commented 11 months ago

Having the same issue, but found 2 workarounds when target is bun:

  1. Use patch-package to patch the source files that contain references of __dirname and change them to import.meta.dir (and __filename to import.meta.file).
  2. Or use the define config to map __dirname to import.meta.dir.
    bun build ./index.ts --outdir ./build --target bun --define "__dirname=import.meta.dir" --define "__filename=import.meta.file"

EDIT: the second workaround does not work. It actually replaces __dirname with "import.meta.dir" as a string. It removed my error but introduced a new one. Going back to the first workaround.

haovei commented 6 months ago

I also encountered the same problem. My solution was to use import.meta.url, it is compatible with the node environment。

import { fileURLToPath } from 'url';
import { dirname } from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);