diff --git a/README.md b/README.md index a8b55843db..9825afc74f 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,7 @@ The available options are: notation. You can override these by setting them explicitly on the command line. --mangle-regex Only mangle property names matching the regex + --mangle-props-prefix Prefix added to the property name after mangling --name-cache File to hold mangled names mappings --pure-funcs List of functions that can be safely removed if their return value is not used [array] diff --git a/bin/uglifyjs b/bin/uglifyjs index 8cb2f0df7c..da0379da84 100755 --- a/bin/uglifyjs +++ b/bin/uglifyjs @@ -74,6 +74,7 @@ You need to pass an argument to this option to specify the name that your module .describe("reserve-domprops", "Make (most?) DOM properties reserved for --mangle-props") .describe("mangle-props", "Mangle property names (0 - disabled, 1 - mangle all properties, 2 - mangle unquoted properies)") .describe("mangle-regex", "Only mangle property names matching the regex") + .describe("mangle-props-prefix", "Prefix added to the property name after mangling") .describe("name-cache", "File to hold mangled names mappings") .describe("pure-funcs", "List of functions that can be safely removed if their return value is not used") .describe("dump-spidermonkey-ast", "Dump SpiderMonkey AST to stdout.") @@ -110,6 +111,7 @@ You need to pass an argument to this option to specify the name that your module .string("p") .string("prefix") .string("name-cache") + .string("mangle-props-prefix") .array("reserved-file") .array("pure-funcs") @@ -421,6 +423,7 @@ async.eachLimit(files, 1, function (file, cb) { only_cache : !ARGS.mangle_props, regex : regex, ignore_quoted : ARGS.mangle_props == 2, + prefix : ARGS.mangle_props_prefix || "", debug : typeof ARGS.mangle_props_debug === "undefined" ? false : ARGS.mangle_props_debug }); writeNameCache("props", cache); diff --git a/lib/propmangle.js b/lib/propmangle.js index f2777475d2..e40f5c6ad5 100644 --- a/lib/propmangle.js +++ b/lib/propmangle.js @@ -67,7 +67,8 @@ function mangle_properties(ast, options) { only_cache : false, regex : null, ignore_quoted : false, - debug : false + debug : false, + prefix: "" }); var reserved = options.reserved; @@ -202,7 +203,7 @@ function mangle_properties(ast, options) { // (filled with quoted properties when ignore_quoted set). Make sure we add this // check so we don't collide with a quoted name. do { - mangled = base54(++cache.cname); + mangled = options.prefix + base54(++cache.cname); } while (!can_mangle(mangled) || (ignore_quoted && mangled in ignored)); } diff --git a/test/compress/mangle-prefix.js b/test/compress/mangle-prefix.js new file mode 100644 index 0000000000..f8e5dd32e6 --- /dev/null +++ b/test/compress/mangle-prefix.js @@ -0,0 +1,57 @@ +prefix_no_debug: { + mangle_props = { + ignore_quoted: true, + prefix: "__" + } + input: { + var x = {}; + x.foo = 1; + x["a"] = 2 * x.foo; + console.log(x.foo, x["a"]); + } + expect: { + var x = {}; + x.__a = 1; + x["a"] = 2 * x.__a; + console.log(x.__a, x["a"]); + } +} + +prefix_debug: { + mangle_props = { + ignore_quoted: true, + debug: "", + prefix: "__" + } + input: { + var x = {}; + x.foo = 1; + x["_$foo$_"] = 2 * x.foo; + console.log(x.foo, x["_$foo$_"]); + } + expect: { + var x = {}; + x.__a = 1; + x["_$foo$_"] = 2 * x.__a; + console.log(x.__a, x["_$foo$_"]); + } +} + +prefix_with_quoted: { + mangle_props = { + ignore_quoted: false, + prefix: "__" + } + input: { + var x = {}; + x.foo = 1; + x["a"] = 2 * x.foo; + console.log(x.foo, x["a"]); + } + expect: { + var x = {}; + x.__a = 1; + x["__b"] = 2 * x.__a; + console.log(x.__a, x["__b"]); + } +} diff --git a/test/input/mangle-prefix/sample.js b/test/input/mangle-prefix/sample.js new file mode 100644 index 0000000000..899782b736 --- /dev/null +++ b/test/input/mangle-prefix/sample.js @@ -0,0 +1,20 @@ +var Test = function() { + this.someVar = 123; +}; + +Test.prototype.someMethod = function() { + console.log(this.someVar); +} + +Test.prototype.someOther = function() { + console.log("other"); + this.someMethod(); + this.__special(); +} + +Test.prototype.__special = function() { + console.log("special"); +} + +var oTest = new Test(); +oTest.someOther(); diff --git a/test/mocha/cli.js b/test/mocha/cli.js index a8de05c525..b8bfb6f34d 100644 --- a/test/mocha/cli.js +++ b/test/mocha/cli.js @@ -100,4 +100,24 @@ describe("bin/uglifyjs", function () { done(); }); }); + it("Should work with --mangle-props-prefix", function (done) { + var command = uglifyjscmd + ' test/input/mangle-prefix/sample.js --mangle-props --mangle-props-prefix="__"'; + + exec(command, function (err, stdout) { + if (err) throw err; + + assert.strictEqual(stdout, "var Test=function(){this.__a=123};Test.prototype.__b=function(){console.log(this.__a)};Test.prototype.__c=function(){console.log(\"other\");this.__b();this.__d()};Test.prototype.__d=function(){console.log(\"special\")};var oTest=new Test;oTest.__c();\n"); + done(); + }); + }); + it("Should work with --mangle-props-prefix and --mangle-props-regex", function (done) { + var command = uglifyjscmd + ' test/input/mangle-prefix/sample.js --mangle-props --mangle-regex="/^__/" --mangle-props-prefix="__"'; + + exec(command, function (err, stdout) { + if (err) throw err; + + assert.strictEqual(stdout, "var Test=function(){this.someVar=123};Test.prototype.someMethod=function(){console.log(this.someVar)};Test.prototype.someOther=function(){console.log(\"other\");this.someMethod();this.__a()};Test.prototype.__a=function(){console.log(\"special\")};var oTest=new Test;oTest.someOther();\n"); + done(); + }); + }); }); diff --git a/test/mocha/minify.js b/test/mocha/minify.js index 70cf73ae1b..f04c847af9 100644 --- a/test/mocha/minify.js +++ b/test/mocha/minify.js @@ -58,6 +58,44 @@ describe("minify", function() { assert.strictEqual(result.code, 'a["foo"]="bar",a.a="red",x={"bar":10};'); }); + + it("Should add prefix for mangle properties (not quoted)", function() { + var js = 'a["foo"] = "bar"; a.color = "red"; x = {"bar": 10};'; + var result = Uglify.minify(js, { + fromString: true, + compress: { + properties: false + }, + mangleProperties: { + ignore_quoted: true, + prefix: "__" + }, + output: { + keep_quoted_props: true, + quote_style: 3 + } + }); + assert.strictEqual(result.code, 'a["foo"]="bar",a.__a="red",x={"bar":10};'); + }); + + it("Should add prefix for mangle properties (with quoted)", function() { + var js = 'a["foo"] = "bar"; a.color = "red"; x = {"bar": 10};'; + var result = Uglify.minify(js, { + fromString: true, + compress: { + properties: false + }, + mangleProperties: { + ignore_quoted: false, + prefix: "__" + }, + output: { + keep_quoted_props: true, + quote_style: 3 + } + }); + assert.strictEqual(result.code, 'a["__a"]="bar",a.__b="red",x={"__c":10};'); + }); }); describe("inSourceMap", function() {