google / google/closure-compiler
Allow unknown global variables in ADVANCED mode
- Dominant language
- JavaScript
- Stars
- 7.7k
- Forks
- 1.2k
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 6
Description
We have a large (>400k LOC) JavaScript project we'd like to move over from babel-minify to compiling with Closure Compiler. We are only interested in using it for minifying code, and the polyfilling and type checking features are not relevant to us. However the main problem we have is the use of code like the following, which uses a global variable Closure Compiler hasn't seen before:
```js
function func()
{
MyGlobal.Create();
}
```
Currently without using any externs, Closure Compiler throws an error on seeing `MyGlobal`. In this case it's defined in a script loaded later on, as an optimisation to speed up startup. Our code guarantees that script has finished loading before `func()` is ever called, so the code always works in production.
If we change it to `window.MyGlobal.Create()` or `self.MyGlobal.Create()`, compilation logs a warning but appears to work fine, and the name `MyGlobal` is mangled.
If we add an extern for MyGlobal it won't be mangled, but we want it to be.
This seems to be an odd inconsistency between using `self.Name` and just `Name`: both refer to the same thing but one is an error in Closure Compiler and the other is not. Fixing it in our codebase would be a fairly significant refactoring project, and arguably will make the code less readable as we have to sprinkle a lot of `self.` all over the place just for the benefit of Closure Compiler.
It seems Closure Compiler ought to accept using `Name` as well as `self.Name` and mangle it the same way too. It just needs to do is make sure every identifier it sees is mangled to the same name and everything will still work. It can be awkward to deal with name collisions with local variables, e.g. if `MyGlobal` is renamed to `a`, then no function that uses `MyGlobal` can select `a` as a local variable name, which would require scanning ahead. The simplest solution is to use a different namespace for globals, e.g. mangle `MyGlobal` to `g_a` and then never choose a local variable name beginning with `g_`.
This is how the [babel-plugin-minify-mangle-properties](https://github.com/AshleyScirra/babel-plugin-minify-mangle-properties) plugin I wrote for babel works, and has worked well for our large production codebase. I'd be fine with this being a special opt-in flag.
Contributor guide
Assessment
This issue has not been assessed yet.