esbuild icon indicating copy to clipboard operation
esbuild copied to clipboard

Constant folding failure

Open yhx-12243 opened this issue 4 months ago • 6 comments

const a = 256 * 2;

minify to

const a=512;

(https://esbuild.github.io/try/#dAAwLjI1LjgALS1taW5pZnkAY29uc3QgYSA9IDI1NiAqIDI7)

But

0;
const a = 256 * 2;

minify to

const a=256*2;

(https://esbuild.github.io/try/#dAAwLjI1LjgALS1taW5pZnkAMDsKY29uc3QgYSA9IDI1NiAqIDI7), where constant folding fails.

yhx-12243 avatar Aug 08 '25 03:08 yhx-12243

https://github.com/evanw/esbuild/blob/8c71947edbe5a158fec3a6d1cbfea1e8d5cdee70/internal/js_ast/js_ast.go#L1306-L1309

Syntaxe3 avatar Aug 10 '25 17:08 Syntaxe3

How does this come up in practice? What's the real-world example where you're encountering this behavior.

evanw avatar Aug 12 '25 12:08 evanw

How does this come up in practice? What's the real-world example where you're encountering this behavior.

This is just the minimal example. The practical example is commonly appeared and easily made by replacing 0; with a statement (such as import, etc.)

yhx-12243 avatar Aug 12 '25 12:08 yhx-12243

The practical example is commonly appeared

Please provide an example. Code containing a stray 0; does not make sense.

Edit: Sorry, I incorrectly assumed that the person who made #4262 was the same person who made this issue. I asked about real-world use cases because that person wrote some code to specifically only fix this problem for code such as 0; and it seems to me that wouldn't actually address any real-world issues.

Since you mentioned import statements: Code using import statements is not necessarily safe if the constants are exported, as I believe import cycles can potentially cause the constants to be referenced before they are evaluated, which involves temporal dead zone behavior. For example:

// entry.mjs
import './foo.mjs'
export const x = 123
// foo.mjs
import { x } from './entry.mjs'
console.log(x)

Running node ./entry.mjs gives the following:

file://./foo.mjs:2
console.log(x)
            ^

ReferenceError: Cannot access 'x' before initialization
    at file://./foo.mjs:2:13

I understand the desire to want constants to be inlined, but it's not trivially safe to do so. Doing it properly involves analysis of temporal dead zone behavior that can become quite complicated.

evanw avatar Aug 12 '25 18:08 evanw

This does not make sense. Because if we change 256 to 255, the constant folding works.

https://esbuild.github.io/try/#dAAwLjI1LjgALS1taW5pZnkAMDsKY29uc3QgYSA9IDI1NSAqIDI7

@evanw

yhx-12243 avatar Aug 12 '25 23:08 yhx-12243

I asked about real-world use cases because that person wrote some code to specifically only fix this problem for code such as 0; and it seems to me that wouldn't actually address any real-world issues.

The reason I used 0 is because that “ANY STATEMENT” such as console.log(), b += 13, function noop() {}, etc. before const a = 256 * 2 (replace the position of 0) would block the constant folding, and 255 * 2 will be folded correctly. So this SHOULD be fixed!

yhx-12243 avatar Aug 13 '25 00:08 yhx-12243