-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
WIP: Enable mangling of global references #1326
base: harmony
Are you sure you want to change the base?
Conversation
This enables mangling of global references using a given list of global alias names, which can be e.g. "window", "self", etc. depending on context.
lib/propmangle.js
Outdated
@@ -83,7 +83,8 @@ function mangle_properties(ast, options) { | |||
cache : null, | |||
only_cache : false, | |||
regex : null, | |||
ignore_quoted : false | |||
ignore_quoted : false, | |||
treat_as_global : [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add a trailing comma to make smaller diffs for future options
lib/propmangle.js
Outdated
|
||
// TODO: don't know if this is necessary to get scope information? | ||
//if (mangle_globals) | ||
// ast.figure_out_scope(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not necessary.
lib/propmangle.js
Outdated
node.expression.global() && | ||
is_global_alias(node.expression.name) && | ||
!is_global_alias(node.property)) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uglify code style puts the appends {
to the previous line while leaving indenting as you have it. Yes it's unusual.
lib/propmangle.js
Outdated
if (mangle_globals && | ||
node.global() && | ||
!is_global_alias(node.name)) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code style
// HACK: to avoid mangled global references colliding with local variable names, use | ||
// a prefix on all mangled global names to effectively move them to a different namespace. | ||
if (mangle_globals && name in cache.global_defs) | ||
mangled = "g_" + mangled; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not crazy about this hack. Collisions can be avoided in a similar fashion to the other PR you wrote.
lib/propmangle.js
Outdated
if (mangle_globals && | ||
node.global() && | ||
node.name in cache.global_defs) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code style
Neutral on the PR, but the concept seems okay behind a flag defaulting to false. Needs a command line flag and documentation. Please put a |
Can you point me in the direction of how to fix the failing test case? I just need a reliable way to identify if a symbol refers to a local variable or not. |
AST_SymbolRef#global() will tell you whether it's global or not. Mind you if a global is aliased via assignment or passed via a function argument all bets are off. There's no data flow analysis in uglify. |
Update style and remove some commented code
I only intend to statically identify local variables, so the |
AST_SymbolRef#global() does work. Something else is wrong in your algorithm. Add some debug print statements. You still have to handle AST_Sub cases and mangle collisions as well. |
This is an experimental work-in-progress patch to fix issue #1313.
The problem is currently
window.Foo
will mangle "Foo", but thenFoo.bar
will not mangle "Foo", breaking code. This patch attempts to recognise global references which are not identified as referencing any local variables, then also mangle them. The intent is to mangle "Foo" in both cases in the previous example.The caller must pass a new
treat_as_global
array. If this is non-empty it enables the new mode. The caller can pass e.g.window
to then recognisewindow.Foo
as declaring "Foo" as global.I don't really understand how the existing APIs work and a failing test is also included because I can't figure out how to get it to work. The intent is that if the left side of a dot expression refers to a local variable, then it should not treat it as defining a global property. For example if the caller passes "self" in
treat_as_global
, then the following should work:To try to identify this I call
node.global()
but it does not seem to properly identify this case. I am also unsure as to whether to callfigure_out_scope
, which seems to be a destructive operation that appeared to partially undo previous mangling in my testing, so I'm not sure what's happening there.There is also one more big hack: renaming globals opens the possibility of name collisions with local variables. For example:
could be mangled as:
To avoid this I simply prefix all globally-mangled names with
g_
, in the hope thatg_XYZ
will never collide with local variables (which I assume possibly incorrectly can never start withg_
). Obviously this isn't a great solution and there are a range of alternative ways to solve this. For example local variables could use only lowercase names, and globals uppercase. Alternatively local and global mangling could share dictionaries of the names they use so globals will never mangle to the name of a local variable used anywhere in the program. These require wider changes though, and I would prefer to hear from other devs before implementing one of them.Sorry about the partial state of all this, it's a complex codebase which I am unfamiliar with.