-
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
Include an option to mangle private/all method names #103
Comments
+1 for renaming private properties with the '_' prefix. Currently I have to use another app to perform this action before running UglifyJS. |
A better way is with JSDoc I suppose. I believe Google Closure is using this also. /**
* this method does nothing
* @private
*/
function whatever() {
// really!
} |
Would it be possible to also do this for entire objects? /** @private **/
var obj = { someKey : 'foo', someOtherKey : 'bar' }; which would yield: var a={b:'foo',c:'bar'};
...
fn(a.b); Though I object to tacking onto something in JSDoc because although I'm perfectly okay obfuscating out a private method / object in my own code, it's very possible that doing this in general would break things because people do hook into and use things that would be "private" code in general libraries. I suppose as long as it's an opt-in flag in uglifyjs it would be ok? Though I realize this entire concept is destructive, which uglifyjs is somewhat opposed to, so I'm not sure exactly how to handle it? It's just ugly seeing my "uglified" code look like: this.__someMethod(this.__someProperty); when it could be: this.a(this.b); |
How could that possibly work, when the program could access "a[foo]" where the value of foo is computed? |
@rtm If you want to access a property via a[foo] you should access it via a['foo'] with a string literal and assign the property to a string literal. +1 for this. We can't switch from Closure to Uglify until this is an option. There is a 60KB difference in file size between the two right now. |
+1 |
I'm also looking for this option. Yes its unsafe since would break. or if an object would be JSONfied But honestly, I'd be happy if I'd give a list of names I'd like to be mangled, since I know I'm not doing stuff like that with. |
I came up with a solution for myself: It walks the tree after being parsed and replaces all tokens marked as OK to be mangled with a respective shortcut. I got little idea how uglifyjs2 works internally so it may be a bit of naive approach. It requires a manually maintained config file which marks all properties that are ok to be mangled and those that are not to be touched. Respective string literals will also be mangled! It assumes that no property is named anything starting with "$$" so far. Maintaining that list is a bit tricky, since anything that interacts with the browser, becomes a JSON object to be interacted with the server or which is a string literal that can be seen by the user must not be mangled. To make this somewhat maintainable the list of properties not to be mangled is also managed and the tool warns about any properties that is in neither. I'm wondering if distinguishing single and double quote string literals would be a nice idea for a given project. Like single quotes "this literal is okay to be mangled" and double quotes "do not touch this". However, as far I can see, the current parser drops this detail. |
+1 |
Nice 👍 Im looking for this options also.. Thank you :) |
+1 has been done for ages using Dean Edwards Packer |
+1 I like both ideas: mangle prototype methods starting with underscore or marked as @Private with JSDocs syntax (like @jtangelder said). Would it be possible to mangle constructor properties as well with this right? /**
* @constructor
* @private
*/
function Mangle(what, when) {
this.whatToMangle = what;
this.whenToMangle = when;
}
Mangle.prototype.doit = function () {
return 'mangle ' + this.whatToMangle + ' on ' + this.whenToMangle;
}
// uglified to:
function M(w,h) { this.a = w; this.h = h; }
M.prototype.d = function () { return 'mangle ' + this.a + ' on ' + this.h; } Is that doable? |
I'd like to request this feature as well, with a config parameter to allow for @Protected symbols to be mangled as well. |
The latest release of uglify (today) has object property mangling, see v2.4.18. It also supports reserved files for excluding both object properties and variables that you don't want mangled. Check it out. |
Is it possible to use this feature via the uglify-js library (not the command line tool)? I'm not seeing any version of it in |
Yes, just call it like this: UglifyJS.mangle_properties(topLevel, { reserved: You only need to pass in cache if you want or are using the new {
} Then just pass in the 'props' array to the call to On Mon, Mar 30, 2015 at 4:25 AM, Dan Vanderkam notifications@github.com
|
Thanks. Is there a reason this feature couldn't be done via the usual |
I'm not exactly sure, you'll have to ask the original author of uglify. I Indeed, I worked on a PR On Mon, Mar 30, 2015 at 9:07 AM, Dan Vanderkam notifications@github.com
|
I agree with @danvk. There are other projects that expose the |
+1 |
2 similar comments
+1 |
+1 |
+1 train |
+1 for mangle_properties on .minify() |
@jrhite, could you give a full example of using mangle_properties programmatically? I tryied to use your sugestion (mar 29) but it didn't work and I can't figure it out from reading the source code. |
+1 |
The best working example (most-used?) is probably just to point directly to https://github.com/jrhite/grunt-contrib-uglify/blob/master/tasks/lib/uglify.js#L120-L137 Cheers! On Fri, Aug 28, 2015 at 10:59 PM, Ulrik Moe notifications@github.com
|
Actually, oops...just pointed you to my local copy of the code which might https://github.com/gruntjs/grunt-contrib-uglify/blob/master/tasks/lib/uglify.js#L120-L134 On Sat, Aug 29, 2015 at 1:44 PM, Jacob Hite jrhite@gmail.com wrote:
|
+1 for this. It seems that stuff like WebPack and some other minifiers relying on Uglfy do not support this option, leaving me with no way to properly mangle things... |
+1 |
|
+1 |
Since |
for what it worth, personally I would love to see that implemented as well! |
I just realised that we can't implement
When compressing the argument to We may be able to reach it by looking at the symbol's definition, but once you go cross-function, cross-module, or global, things fall apart. |
I am just throwing this out there, warts and all. I too want to be able to comment members of objects as private, as too with variables in general, but I would be content with private scope limited to declaring objects. As I see the example above, correct,
would work, even it had been compressed to something like
would work. I should really think about this more before posting, so forgive if me if I missed the overall context of what was said there. I think if private was absolutely strict about access to object members then private declarations would work without flow analysis... without flow analysis, it would break, as would be intended, no? |
In your above example, this line:
To do this you need flow analysis. At the point that this call is being mangled, uglifyjs doesn't know what object
(notice that the second is not private) Which is a very basic set-up, but since uglify doesn't know where this The current solution of using --mangle-regex pretty well if you enforce a private naming convention. If I say "everything that starts with a _ is private" we don't need flow analysis because all the information uglifyjs needs is written in the name. |
If i use
gonna translate to something like that:
(this is compiled code of browserify) If i use So! If there is the way to mix |
Just an idea, but I think this feature can be implemented by 100%-compatibility with the original code. That is, replace any call for properties with string literals and mangle long string literals to variables. An example follows. Original code: var foo = 'length';
var bar = {
baz: 'boo',
length: 10,
};
if ('string'.length === foo.length) {
bar['length'] = bar.baz.length;
} Replace all calls for property names with string literal: var foo = 'length';
var bar = {
baz: 'boo',
length: 10,
};
if ('string'['length'] === foo['length']) {
bar['length'] = bar['baz']['length'];
} Then search for all occurrence of string literals in code, and mangle them with variables. var a = 'length', b = 'boo', c = 'string', d = 'baz';
var foo = a;
var bar = {
baz: b,
length: 10,
};
if (c[a] === foo[a]) {
bar[a] = bar[d][a];
}
|
Any update on this? |
@skaharmor Your question is a bit too broad. You can already let UglifyJS mangle properties based on a regex - https://github.com/mishoo/UglifyJS2#mangleproperties-options |
I think this issue should be closed, advanced flow control to find private methods will never be implemented, so mangle-regex is all we have. |
I agree, as posted before, I'm fiddling with Uglifyies internals to decide on a predefined list on to be mangled names and those not to be touched. Would be nice if this feature would have a more defined/documented API, but yes otherwise I agree, Uglify will never make full flow control, this kind of automatic mangling would need a full transpiled language, possible but not within the scope of uglify. |
FWIW, I had the same idea as @hakatashi and did a test implementation here. It walks each top-level scope collecting stats on all property accesses and identifiers in that scope, checks to see which ones would actually save a bit of space by being hoisted, and then replaces the accesses like Running that on some large-ish (~450k that uglified to ~210k before doing the hoist) code saved about 15% (~180k), and depending on the code, looks like that's a pretty decent average figure. The minified code stays roughly as gzippable (60k) as it was before, so there's no real improvement on that front. A bit of performance testing seems to indicate a small performance penalty for doing the hoisting on Chrome. I haven't done any extensive testing on any other browsers. I looked into implementing the transform on uglify originally, but the code is a bit over my head 😄 |
I think there should be an option (off by default) to mangle some/all method names:
In cases where the entire codebase is minified into one file, you should be able to mangle
this.<<anything>>
.In cases where some methods are marked as "private" using the underscore prefix convention, you should be able to mangle
this._<<anything>>
. This will potentially break something, but since everything is "private" anyway, I find it to be an acceptable risk and so will many other people. Possibly have a regex here to determine which methods to mangle to allow for different coding conventions.The text was updated successfully, but these errors were encountered: