Make debug option take a string suffix

Debug option (and CLI) now take a string to enable, and the string is
used as the (possibly empty) suffix. Instead of generating a random
number, the caller can do that if they wish. Updated tests accordingly
(no need for regex now).
This commit is contained in:
Ashley (Scirra) 2016-10-06 16:42:23 +01:00
parent b28d2d3cf2
commit 7de8ffe77b
5 changed files with 99 additions and 42 deletions

View File

@ -288,18 +288,16 @@ single call to UglifyJS.
You can also pass `--mangle-debug` in order to mangle property names
without completely obscuring them. For example the property `o.foo`
would mangle to `o._$foo$123_` with this option. This allows property mangling
would mangle to `o._$foo$_` with this option. This allows property mangling
of a large codebase while still being able to debug the code and identify
where mangling is breaking things.
Note that by default a random number is added to the name per invocation,
e.g. the `123` in `_$foo$123_` is random. This is because normal property
mangling is non-deterministic. It makes sure that if you mangle two scripts
separately without sharing a cache, they will be broken. It also makes sure
that if you accidentally attempt to use a mangled key name in storage, then
the storage reads will be broken between builds. This allows you to fix these
issues with readable keys, and then turning off this option should continue to
work with unreadable names.
You can also pass a custom suffix using `--mangle-debug=XYZ`. This would then
mangle `o.foo` to `o._$foo$XYZ_`. You can change this each time you compile a
script to identify how a property got mangled. One technique is to pass a
random number on every compile to simulate mangling changing with different
inputs (e.g. as you update the input script with new properties), and to help
identify mistakes like writing mangled keys to storage.
## Compressor options
@ -760,7 +758,7 @@ Other options:
- `regex` — Pass a RegExp to only mangle certain names (maps to the `--mangle-regex` CLI arguments option)
- `ignore_quoted` Only mangle unquoted property names (maps to the `--mangle-props 2` CLI arguments option)
- `debug` Mangle names with the original name still present (maps to the `--mangle-debug` CLI arguments option)
- `debug` Mangle names with the original name still present (maps to the `--mangle-debug` CLI arguments option). Defaults to `false`. Pass an empty string to enable, or a non-empty string to set the suffix.
We could add more options to `UglifyJS.minify` — if you need additional
functionality please suggest!

View File

@ -71,12 +71,12 @@ You need to pass an argument to this option to specify the name that your module
.describe("quotes", "Quote style (0 - auto, 1 - single, 2 - double, 3 - original)")
.describe("reserved-file", "File containing reserved names")
.describe("reserve-domprops", "Make (most?) DOM properties reserved for --mangle-props")
.describe("mangle-debug", "Use debug mode for diagnosing property mangling errors. Optionally provide a mangled name suffix.")
.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("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.")
.describe("mangle-debug", "Use debug mode for diagnosing property mangling errors.")
.alias("p", "prefix")
.alias("o", "output")
@ -97,6 +97,7 @@ You need to pass an argument to this option to specify the name that your module
.string("beautify")
.string("m")
.string("mangle")
.string("mangle-debug")
.string("c")
.string("compress")
.string("d")
@ -131,7 +132,6 @@ You need to pass an argument to this option to specify the name that your module
.boolean("bare-returns")
.boolean("keep-fnames")
.boolean("reserve-domprops")
.boolean("mangle-debug")
.wrap(80)
@ -428,7 +428,7 @@ async.eachLimit(files, 1, function (file, cb) {
only_cache : !ARGS.mangle_props,
regex : regex,
ignore_quoted : ARGS.mangle_props == 2,
debug : ARGS.mangle_debug
debug : typeof ARGS.mangle_debug === "undefined" ? false : ARGS.mangle_debug
});
writeNameCache("props", cache);
})();

View File

@ -101,10 +101,13 @@ function mangle_properties(ast, options) {
var regex = options.regex;
var ignore_quoted = options.ignore_quoted;
var debug = options.debug;
// Simulate non-deterministic mangling in debug mode by adding a random number to the name
var debug_cache_name = Math.floor(Math.random() * 1000).toString();
// note debug is either false (disabled), or a string of the debug cache name to use (enabled).
// note debug may be enabled as an empty string, which is falsey.
var debug = (options.debug !== false);
var debug_cache_name;
if (debug)
debug_cache_name = options.debug;
var names_to_mangle = [];
var unmangleable = [];
@ -213,10 +216,10 @@ function mangle_properties(ast, options) {
if (can_mangle(debug_mangled))
mangled = debug_mangled;
else
mangled = name;
}
else {
// either debug mode is off, or it is on and can_mangle returned false
if (!mangled) {
do {
mangled = base54(++cache.cname);
} while (!can_mangle(mangled));

View File

@ -143,6 +143,84 @@ mangle_unquoted_properties: {
}
}
mangle_debug: {
mangle_props = {
debug: ""
};
input: {
a.foo = "bar";
x = { baz: "ban" };
}
expect: {
a._$foo$_ = "bar";
x = { _$baz$_: "ban" };
}
}
mangle_debug_suffix: {
mangle_props = {
debug: "XYZ"
};
input: {
a.foo = "bar";
x = { baz: "ban" };
}
expect: {
a._$foo$XYZ_ = "bar";
x = { _$baz$XYZ_: "ban" };
}
}
mangle_debug_suffix_ignore_quoted: {
options = {
properties: false
}
mangle_props = {
ignore_quoted: true,
debug: "XYZ",
reserved: []
}
beautify = {
beautify: false,
quote_style: 3,
keep_quoted_props: true,
}
input: {
a.top = 1;
function f1() {
a["foo"] = "bar";
a.color = "red";
a.stuff = 2;
x = {"bar": 10, size: 7};
a.size = 9;
}
function f2() {
a.foo = "bar";
a['color'] = "red";
x = {bar: 10, size: 7};
a.size = 9;
a.stuff = 3;
}
}
expect: {
a._$top$XYZ_ = 1;
function f1() {
a["foo"] = "bar";
a.color = "red";
a._$stuff$XYZ_ = 2;
x = {"bar": 10, _$size$XYZ_: 7};
a._$size$XYZ_ = 9;
}
function f2() {
a.foo = "bar";
a['color'] = "red";
x = {bar: 10, _$size$XYZ_: 7};
a._$size$XYZ_ = 9;
a._$stuff$XYZ_ = 3;
}
}
}
first_256_chars_as_properties: {
beautify = {
ascii_only: true,

View File

@ -1,22 +0,0 @@
var Uglify = require('../../');
var assert = require("assert");
describe("mangle_properties 'debug' option ", function() {
it("Should test the 'debug' option of mangle_properties works as expected", function() {
var js = 'var o = {}; o.foo = "bar";';
var ast = Uglify.parse(js);
ast.figure_out_scope();
ast = Uglify.mangle_properties(ast, {
debug: true
});
var stream = Uglify.OutputStream();
ast.print(stream);
var result = stream.toString();
// Should match: var o={};o._$foo$NNN="bar";
// where NNN is a number.
assert(/var o=\{\};o\._\$foo\$\d+_="bar";/.test(result));
});
});