oven-sh / bun

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

`__dirname` is hardcoded with local path value in bundled code when source is `CommonJS` #13921

Open ghoullier opened 4 weeks ago

ghoullier commented 4 weeks ago

What version of Bun is running?

1.1.27+267afa293

What platform is your computer?

Darwin 23.5.0 arm64 arm

What steps can reproduce the bug?

Problem

The way Bun convert __dirname for CommonJS source is not portable because the value is hardcoded in output file.

CommonJS Behavior

Source file

const { readFile } = require('fs').promises;
const { resolve } = require('path');

async function main() {
  const [template] = await Promise.all([readFile(resolve(__dirname, './templates/template.hbs'), 'utf-8')]);

  return { template };
}

main().then(console.log).catch(console.error);

Output file

import {createRequire} from "node:module";
var __require = /* @__PURE__ */ createRequire(import.meta.url);

// src/index.ts
async function main() {
  const [template] = await Promise.all([readFile(resolve(__dirname, "./templates/template.hbs"), "utf-8")]);
  return { template };
}
var __dirname = "/Users/gregory.houllier/Workspace/bun-app/src";
var { readFile } = __require("fs").promises;
var { resolve } = __require("path");
main().then(console.log).catch(console.error);

ESM Behavior

Source file

import { readFile } from 'fs/promises';
import { resolve } from 'path';
import { fileURLToPath } from 'url';

const dirname = fileURLToPath(new URL('.', import.meta.url));

async function main() {
  const [template] = await Promise.all([readFile(resolve(dirname, './templates/template.hbs'), 'utf-8')]);

  return { template };
}

main().then(console.log).catch(console.error);

Output file

// src/index.ts
import {readFile} from "fs/promises";
import {resolve} from "path";
import {fileURLToPath} from "url";
async function main() {
  const [template] = await Promise.all([readFile(resolve(dirname, "./templates/template.hbs"), "utf-8")]);
  return { template };
}
var dirname = fileURLToPath(new URL(".", import.meta.url));
main().then(console.log).catch(console.error);

What is the expected behavior?

__dirname and fileURLToPath(new URL('.', import.meta.url)) should have the same behavior.

What do you see instead?

__dirname is interpotaled by the path of the user who run the build command.

Additional information

No response

mohas commented 5 days ago

I use import.meta.dir instead of dirname in my own code, the main problem is the dependencies in which the package author used dirname, which will translate into a hardcoded value, for example using 'svg-captcha' package, the author imports a font file using dirname and there is no option for specifying path to the font file. We will take this to the package author as well but there is a need for an option to leave dirname as is or specify a function for it, like process.cwd()