fix mangling collision with keep_fnames#1431
Conversation
6758402 to
1d215e5
Compare
|
One of the CI tests timed out - probably a fluke, re-opening to re-test. |
|
Just to leave a quick note to say that this may be sub-optimal as the parent scope's mangling will need to avoid all sub-scopes' variables, regardless of whether a sub-scope uses the parent scope's variable or not. I have an idea of coming up with a proper solution, but need to pop out now and will work on this later on tonight. |
|
@alexlamsl Thanks for creating this PR. A fix by removing code - impressive. Your comments above make sense but scope handling is probably the thing I understand least about Uglify. I think we need to get the opinion of @mishoo and @rvanvelzen on this issue.
I'm not worried about My main concern is whether regular default mangling ( (Edit: fixed mangle.keep_fnames=true in suboptimal comment) |
|
Unfortunately this PR makes uglify significantly slower in default mangle mode: Without fix: With fix: The input file It's slower as the input file size increases. Without fix: With fix: Three times slower for a 5.2MB input file. We can't use this fix in its present form without some adjustments. On the plus side, all input files I've tried still produce the same (Edit: I had the with/without timings reversed - fixed) |
|
In light of these timings, I think it would be preferable to reintroduce the code removed by this PR and put them within |
|
Unrelated side note: this project should put together a test suite of a large number of JS input files (of commonly used frameworks and applications) and their corresponding shasums to test |
|
@kzc the identical results with Luckily I'll put up this minimal fix with sub-optimal impact to |
1d215e5 to
ccfab65
Compare
It may be due to uglify's use of arrays and linear lookup scans. I made another fix a while back to replace an array with a map and it made it considerably faster: #1024 I'm not suggesting this PR alter a data structure, just something to be aware of. |
lib/scope.js
Outdated
| while (s) { | ||
| push_uniq(s.enclosed, def); | ||
| if (s === def.scope) break; | ||
| if (s === def.scope && !options.keep_fnames) break; |
There was a problem hiding this comment.
Can you please add a comment above this line why the && !options.keep_fnames clause is important. Otherwise it may be inadvertently removed in the future.
ccfab65 to
f328438
Compare
lib/scope.js
Outdated
| while (s) { | ||
| push_uniq(s.enclosed, def); | ||
| if (s === def.scope) break; | ||
| // propagate unmangleable function names to top level |
There was a problem hiding this comment.
Could you please use this comment? (assuming it is accurate)
// Propagate unmangleable function names to top level.
// Although `&& !options.keep_fnames` is not strictly needed,
// it improves the speed of default mangling.
// See: https://github.com/mishoo/UglifyJS2/pull/1431
There was a problem hiding this comment.
Thanks for typing it out - included in code 😉
|
@alexlamsl With your latest revision the default mangle speed regression is now gone: With latest fix: Great stuff! |
f328438 to
61e9ff2
Compare
|
LGTM. Impressed with the elegance of this fix. Is the alternate "optimal" fix #1432 for |
61e9ff2 to
4b4c7db
Compare
|
@kzc thanks for testing and review as always 👍 So the reason why this new fix works on more cases is due to Fun fact: if (just read your comments about array vs. object (id's) - will keep that in mind going forward) |
|
LGTM @alexlamsl Confirmed that latest PR produces identical default mangle results on the two large javascript input files above with no speed regressions. Nice work! |
|
Also worth noting that using |
bring command-line in line with minify()
|
Thanks @alexlamsl. The CLI fix and new tests look good. |
Historically,
AST_Scope.enclosedis used byAST_Scope.references()andAST_Scope.next_mangled(), with the former (now) unused within the code base.Removing this line introduced years ago would ensure all child symbol references to be scanned by
next_mangled()for possible name collision. Before this change, the scan would only work if all the children would rename itself after their parents settle down onto a mangled value, which cannot happen if the child is unmangleable, e.g.keep_fnames = true.Fixes #1423