bun icon indicating copy to clipboard operation
bun copied to clipboard

Bun.build output hash doesn't account for dynamic import

Open codehz opened this issue 1 year ago • 4 comments

What version of Bun is running?

1.1.18+5a0b93523

What platform is your computer?

Darwin 23.5.0 arm64 arm

What steps can reproduce the bug?

file build.ts:

const result = await Bun.build({
  entrypoints: ["1.ts", "2.ts"],
  splitting: true,
  minify: true
});

for (const output of result.outputs) {
  console.log(output.path, ":", output.hash);
  console.log(
    (await output.text())
      .split("\n")
      .map((x) => "| " + x)
      .join("\n")
  );
}

file 1.ts:

import("./3.ts");

file 2.ts:

import("./3.ts");

file 3.ts:

import { randomInt } from "crypto" with { type: 'macro' };

export const random = randomInt(100)

run build.ts with bun

What is the expected behavior?

the generated hash for entrypoint file will change when 3.ts changed (it use random, so will change every time)

What do you see instead?

got same hash for entrypoint file

./1.js : 8366f94ce3fac3cc
| import{a as i} from"./chunk-12ec8b15ea59dbbf.js";import("./chunk-647af94fa6f1c725.js");
| 
./2.js : 0a07085d284c9942
| import{a as i} from"./chunk-12ec8b15ea59dbbf.js";import("./chunk-647af94fa6f1c725.js");
| 
./chunk-647af94fa6f1c725.js : 647af94fa6f1c725
| import"./chunk-12ec8b15ea59dbbf.js";var o=61;export{o as random};
| 
./chunk-12ec8b15ea59dbbf.js : 12ec8b15ea59dbbf
| var d=((a)=>typeof require!=="undefined"?require:typeof Proxy!=="undefined"?new Proxy(a,{get:(b,c)=>(typeof require!=="undefined"?require:b)[c]}):a)(function(a){if(typeof require!=="undefined")return require.apply(this,arguments);throw Error('Dynamic require of "'+a+'" is not supported')});
| export{d as a};
| 
./1.js : 8366f94ce3fac3cc
| import{a as i} from"./chunk-12ec8b15ea59dbbf.js";import("./chunk-7e1613d5fcd5e8e0.js");
| 
./2.js : 0a07085d284c9942
| import{a as i} from"./chunk-12ec8b15ea59dbbf.js";import("./chunk-7e1613d5fcd5e8e0.js");
| 
./chunk-7e1613d5fcd5e8e0.js : 7e1613d5fcd5e8e0
| import"./chunk-12ec8b15ea59dbbf.js";var o=51;export{o as random};
| 
./chunk-12ec8b15ea59dbbf.js : 12ec8b15ea59dbbf
| var d=((a)=>typeof require!=="undefined"?require:typeof Proxy!=="undefined"?new Proxy(a,{get:(b,c)=>(typeof require!=="undefined"?require:b)[c]}):a)(function(a){if(typeof require!=="undefined")return require.apply(this,arguments);throw Error('Dynamic require of "'+a+'" is not supported')});
| export{d as a};
| 

Additional information

I use randomInt is only for PoC, normal editing will also cause this bug

codehz avatar Jul 08 '24 04:07 codehz

macros aren't yet part of the hash

Jarred-Sumner avatar Jul 08 '24 08:07 Jarred-Sumner

macros aren't yet part of the hash @Jarred-Sumner

Not only macro, I use macro is just for demo, but actually it affect normal code...

aka I changed the 3.ts to:

export const random = 123

got output:

./1.js : 8366f94ce3fac3cc
| import{a as i} from"./chunk-12ec8b15ea59dbbf.js";import("./chunk-5999c678ee417930.js");
| 
./2.js : 0a07085d284c9942
| import{a as i} from"./chunk-12ec8b15ea59dbbf.js";import("./chunk-5999c678ee417930.js");
| 
./chunk-5999c678ee417930.js : 5999c678ee417930
| import"./chunk-12ec8b15ea59dbbf.js";var o=123;export{o as random};
| 
./chunk-12ec8b15ea59dbbf.js : 12ec8b15ea59dbbf
| var d=((a)=>typeof require!=="undefined"?require:typeof Proxy!=="undefined"?new Proxy(a,{get:(b,c)=>(typeof require!=="undefined"?require:b)[c]}):a)(function(a){if(typeof require!=="undefined")return require.apply(this,arguments);throw Error('Dynamic require of "'+a+'" is not supported')});
| export{d as a};
| 

for export const random = 345;, I got

./1.js : 8366f94ce3fac3cc
| import{a as i} from"./chunk-12ec8b15ea59dbbf.js";import("./chunk-3ddf2ce6941a9488.js");
| 
./2.js : 0a07085d284c9942
| import{a as i} from"./chunk-12ec8b15ea59dbbf.js";import("./chunk-3ddf2ce6941a9488.js");
| 
./chunk-3ddf2ce6941a9488.js : 3ddf2ce6941a9488
| import"./chunk-12ec8b15ea59dbbf.js";var o=345;export{o as random};
| 
./chunk-12ec8b15ea59dbbf.js : 12ec8b15ea59dbbf
| var d=((a)=>typeof require!=="undefined"?require:typeof Proxy!=="undefined"?new Proxy(a,{get:(b,c)=>(typeof require!=="undefined"?require:b)[c]}):a)(function(a){if(typeof require!=="undefined")return require.apply(this,arguments);throw Error('Dynamic require of "'+a+'" is not supported')});
| export{d as a};
| 

exactly same hash for different content

and the macro DOES affect the hash, but only for 3.ts the problem here is 1.ts and 2.ts

codehz avatar Jul 08 '24 09:07 codehz

new minimal example (it affect the default chunk file naming)

1.ts:

import("./2.ts");

2.ts:

import("./3.ts");

3.ts:

console.log(1) // change the number manually

use command: bun build --outdir .build --splitting 1.ts

you will get something like this:


  1.js                     0.10 KB

  3-c96b55aede2685f9.js    0.03 KB

  2-8219168fb473146a.js    0.10 KB

  1-10c8d92e4b9ccc65.js    0.38 KB

[3ms] bundle 3 modules

change the 3.ts and rebuild multiple times, you will get a bunch of 3-XXXX.js while 1/2.js keep same name image

codehz avatar Jul 08 '24 09:07 codehz

This issue can cause the CDN to provide old chunk files (because the generated file names are the same).

codehz avatar Jul 08 '24 09:07 codehz

fixed in 1.1.21

codehz avatar Jul 28 '24 07:07 codehz