Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minifier always assumes globals are not changed #3686

Closed
hyp3rflow opened this issue Mar 8, 2024 · 2 comments
Closed

Minifier always assumes globals are not changed #3686

hyp3rflow opened this issue Mar 8, 2024 · 2 comments

Comments

@hyp3rflow
Copy link

Currently minifier aggressively converts some expression to string value, but it depends on some global methods like Object.prototype.toString, Array.prototype.join.

The code below, which is not minified in terser without unsafe option, is converted in esbuild with --minify option.

console.log([1,2,3] + '')

converts to:

console.log("1,2,3")

which is unsafe when some expression (like delete Array.prototype.join) appends.

So my question is:

  • Does esbuild currently assume that globals are not changed?
  • If so, is there any other assumptions/considerations than minify-considerations @ docs?

Thanks :)

@evanw
Copy link
Owner

evanw commented Mar 14, 2024

  • Does esbuild currently assume that globals are not changed?

Yes esbuild does this. In particular, esbuild hard-codes some well-known JavaScript globals and assumes some properties about them.

For example, one optimization that esbuild does is assuming that accessing console.log has no side effects, which means it may be reordered past other things to improve minification (see a live example). This optimization would not be safe if the optimizer has to guard against the possibility that the property access console.log might change the value of the b or c global variables before it returns.

Another thing that was added recently is that properties of the Symbol global which are known to be symbol instances (such as Symbol.iterator) are special-cased in the minifier to allow them to be tree-shaken. This means the optimizer assumes that both a) the property access for Symbol.iterator has no side effects and b) the value of Symbol.iterator has no side effects when used as a computed property key (e.g. it's not a value with a toString method that has side effects).

Yes, there likely are. JavaScript minification is very complex and esbuild is also very complex. For example, esbuild's optimizer doesn't currently do fixed-point iteration (it instead has a fixed, minimal number of passes) so getting certain minification optimizations to happen can sometimes require knowledge about how esbuild's internal optimizations work. These limitations also change over time. But I didn't intend for that section of the documentation to be a deep dive into the internal details of esbuild's optimizer.

@evanw
Copy link
Owner

evanw commented Apr 27, 2024

I have added documentation about these types of assumptions to the minify considerations docs. I'm closing this issue as it's now documented.

@evanw evanw closed this as completed Apr 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants