add --illegalmangled option.

list of names that are not o be assigned to vars during mangle/propmangle.
added javascript reserved words as default.
This fixes current issue that in some constalations uglify-js mangles properties to js reserved words e.g. if
This commit is contained in:
Anat Dagan 2017-02-09 13:31:51 +02:00
parent 7f8d72d9d3
commit c7f5c6b36b
5 changed files with 154 additions and 2 deletions

View File

@ -87,6 +87,7 @@ The available options are:
-b, --beautify Beautify output/specify output options.
-m, --mangle Mangle names/pass mangler options.
-r, --reserved Reserved names to exclude from mangling.
--illegalmangled Reserved names to avoid when choosing the mangled name.
-c, --compress Enable compressor/pass compressor options. Pass
options like -c
hoist_vars=false,if_return=false. Use -c with
@ -221,6 +222,16 @@ comma-separated list of names. For example:
to prevent the `require`, `exports` and `$` names from being changed.
When mangling is enabled but you want to prevent certain names from being
chosen as variable names after mangle, you can declare those names with `--illegalmangled — pass a
comma-separated list of names. For example:
uglifyjs ... -m -r '$,if,in,to'
to prevent the `if`, `in` and `to` names from being assigned to variables.
By default the illegal mangled list contains the javascript reserved words.
If you don't want any limitation, you can pass '.'
### Mangling property names (`--mangle-props`)
**Note:** this will probably break your code. Mangling property names is a

View File

@ -37,6 +37,7 @@ the source map and the output file.")
.describe("b", "Beautify output/specify output options.")
.describe("m", "Mangle names/pass mangler options.")
.describe("r", "Reserved names to exclude from mangling.")
.describe("illegalmangled" , "Reserved names to avoid when choosing the mangled name.")
.describe("c", "Enable compressor/pass compressor options. \
Pass options like -c hoist_vars=false,if_return=false. \
Use -c with no argument to use the default compression options.")
@ -174,6 +175,7 @@ var COMPRESS = getOptions("c", true);
var MANGLE = getOptions("m", true);
var BEAUTIFY = getOptions("b", true);
var RESERVED = null;
var ILLEGALMANGLED = null;
if (ARGS.reserved_file) ARGS.reserved_file.forEach(function(filename){
RESERVED = UglifyJS.readReservedFile(filename, RESERVED);
@ -194,6 +196,12 @@ if (ARGS.pure_funcs) {
if (ARGS.r) {
if (MANGLE) MANGLE.except = ARGS.r.replace(/^\s+|\s+$/g).split(/\s*,+\s*/);
}
if (ARGS.illegalmangled) {
ILLEGALMANGLED = (ARGS.illegalmangled === ".")? [] : ARGS.illegalmangled.replace(/^\s+|\s+$/g).split(/\s*,+\s*/);
if (MANGLE) {
MANGLE.illegalmangled = ILLEGALMANGLED;
}
}
if (RESERVED && MANGLE) {
if (!MANGLE.except) MANGLE.except = RESERVED.vars;
@ -417,6 +425,7 @@ async.eachLimit(files, 1, function (file, cb) {
TOPLEVEL = UglifyJS.mangle_properties(TOPLEVEL, {
reserved : reserved,
illegalmangled: ILLEGALMANGLED,
cache : cache,
only_cache : !ARGS.mangle_props,
regex : regex,

View File

@ -59,6 +59,63 @@ function find_builtins() {
}
return a;
}
function find_js_reserved_words() {
return ["abstract", "else", "instanceof", "super",
"boolean", "enum", "int", "switch",
"break", "export", "interface", "synchronized",
"byte", "extends", "let", "this",
"case", "false", "long", "throw",
"catch", "final", "native", "throws",
"char", "finally", "new", "transient",
"class", "float", "null", "true",
"const", "for", "package", "try",
"continue", "function", "private", "typeof",
"debugger", "goto", "protected", "var",
"default", "if", "public", "void",
"delete", "implements", "return", "volatile",
"do", "import", "short", "while",
"double", "in", "static", "with", "alert", "frames", "outerHeight",
"all", "frameRate", "outerWidth",
"anchor", "function", "packages",
"anchors", "getClass", "pageXOffset",
"area", "hasOwnProperty", "pageYOffset",
"Array", "hidden", "parent",
"assign", "history", "parseFloat",
"blur", "image", "parseInt",
"button", "images", "password",
"checkbox", "Infinity", "pkcs11",
"clearInterval", "isFinite", "plugin",
"clearTimeout", "isNaN", "prompt",
"clientInformation", "isPrototypeOf", "propertyIsEnum",
"close", "java", "prototype",
"closed", "JavaArray", "radio",
"confirm", "JavaClass", "reset",
"constructor", "JavaObject", "screenX",
"crypto", "JavaPackage", "screenY",
"Date", "innerHeight", "scroll",
"decodeURI", "innerWidth", "secure",
"decodeURIComponent", "layer", "select",
"defaultStatus", "layers", "self",
"document", "length", "setInterval",
"element", "link", "setTimeout",
"elements", "location", "status",
"embed", "Math", "String",
"embeds", "mimeTypes", "submit",
"encodeURI", "name", "taint",
"encodeURIComponent", "NaN", "text",
"escape", "navigate", "textarea",
"eval", "navigator", "top",
"event", "Number", "toString",
"fileUpload", "Object", "undefined",
"focus", "offscreenBuffering", "unescape",
"form", "open", "untaint",
"forms", "opener", "valueOf",
"frame", "option", "window", "onbeforeunload", "ondragdrop", "onkeyup", "onmouseover",
"onblur", "onerror", "onload", "onmouseup",
"ondragdrop", "onfocus", "onmousedown", "onreset",
"onclick", "onkeydown", "onmousemove", "onsubmit",
"oncontextmenu", "onkeypress", "onmouseout", "onunload"];
}
function mangle_properties(ast, options) {
options = defaults(options, {
@ -67,13 +124,16 @@ function mangle_properties(ast, options) {
only_cache : false,
regex : null,
ignore_quoted : false,
illegal_mangled_names: null,
debug : false
});
var reserved = options.reserved;
if (reserved == null)
reserved = find_builtins();
var illegal_mangled_names = options.illegal_mangled_names;
if (illegal_mangled_names == null)
illegal_mangled_names = find_js_reserved_words();
var cache = options.cache;
if (cache == null) {
cache = {
@ -98,6 +158,9 @@ function mangle_properties(ast, options) {
var unmangleable = [];
var ignored = {};
if (illegal_mangled_names) {
unmangleable = unmangleable.concat(illegal_mangled_names);
}
// step 1: find candidates to mangle
ast.walk(new TreeWalker(function(node){
if (node instanceof AST_ObjectKeyVal) {

View File

@ -306,8 +306,10 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol){
AST_Scope.DEFMETHOD("next_mangled", function(options){
var ext = this.enclosed;
var illegal_mangled_names = options.illegal_mangled_names || [];
out: while (true) {
var m = base54(++this.cname);
if (illegal_mangled_names.indexOf(m) !== -1) continue; //this name is illegal
if (!is_identifier(m)) continue; // skip over "do"
// https://github.com/mishoo/UglifyJS2/issues/242 -- do not
@ -395,13 +397,15 @@ AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
sort : false, // Ignored. Flag retained for backwards compatibility.
toplevel : false,
screw_ie8 : true,
illegal_mangled_names: null,
keep_fnames : false
});
});
AST_Toplevel.DEFMETHOD("mangle_names", function(options){
options = this._default_mangler_options(options);
if (options.illegal_mangled_names == null)
options.illegal_mangled_names = find_js_reserved_words();
// Never mangle arguments
options.except.push('arguments');

View File

@ -0,0 +1,65 @@
/**
* Created by anatd on 2/9/2017.
*/
var assert = require("assert");
var uglify = require("../../");
describe("verify that the mangled names are legal", function () {
it("Should not mangle properties to names in the illegal_mangled_names param", 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,
illegal_mangled_names: ["a"]
},
output: {
keep_quoted_props: true,
quote_style: 3
}
});
assert.strictEqual(result.code,
'a["foo"]="bar",a.b="red",x={"bar":10};');
});
it("Should not mangle names to names in the illegal_mangled_names param", function () {
var js = 'var a; a["foo"] = "bar"; a.color = "red"; x = {"bar": 10};';
var result = uglify.minify(js, {
fromString: true,
compress: {
properties: false
},
mangleProperties: {
ignore_quoted: true
},
mangle: {toplevel: true, illegal_mangled_names: ["r", "a"]},
output: {
keep_quoted_props: true,
quote_style: 3
}
});
assert.strictEqual(result.code,
'var b;b["foo"]="bar",b.a="red",x={"bar":10};');
});
it("Should not fail without illegal_mangled_names param", function () {
var js = 'var b; b["foo"] = "bar"; b.color = "red"; x = {"bar": 10};';
var result = uglify.minify(js, {
fromString: true,
compress: {
properties: false
},
mangleProperties: {
ignore_quoted: true
},
mangle: {toplevel: true},
output: {
keep_quoted_props: true,
quote_style: 3
}
});
assert.strictEqual(result.code,
'var a;a["foo"]="bar",a.a="red",x={"bar":10};');
});
});