uglify-js
Advanced tools
Comparing version 3.10.1 to 3.10.2
@@ -200,5 +200,3 @@ "use strict"; | ||
if (timings) timings.properties = Date.now(); | ||
if (options.mangle && options.mangle.properties) { | ||
toplevel = mangle_properties(toplevel, options.mangle.properties); | ||
} | ||
if (options.mangle && options.mangle.properties) mangle_properties(toplevel, options.mangle.properties); | ||
if (timings) timings.output = Date.now(); | ||
@@ -205,0 +203,0 @@ var result = {}; |
@@ -1177,6 +1177,3 @@ /*********************************************************************** | ||
/* -----[ other expressions ]----- */ | ||
DEFPRINT(AST_Call, function(self, output) { | ||
self.expression.print(output); | ||
if (self instanceof AST_New && !need_constructor_parens(self, output)) | ||
return; | ||
function print_call_args(self, output) { | ||
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) { | ||
@@ -1191,2 +1188,6 @@ output.add_mapping(self.start); | ||
}); | ||
} | ||
DEFPRINT(AST_Call, function(self, output) { | ||
self.expression.print(output); | ||
print_call_args(self, output); | ||
}); | ||
@@ -1196,3 +1197,4 @@ DEFPRINT(AST_New, function(self, output) { | ||
output.space(); | ||
AST_Call.prototype._codegen(self, output); | ||
self.expression.print(output); | ||
if (need_constructor_parens(self, output)) print_call_args(self, output); | ||
}); | ||
@@ -1199,0 +1201,0 @@ DEFPRINT(AST_Sequence, function(self, output) { |
@@ -1095,3 +1095,3 @@ /*********************************************************************** | ||
expect("{"); | ||
var a = [], cur = null, branch = null, tmp; | ||
var a = [], branch, cur, default_branch, tmp; | ||
while (!is("punc", "}")) { | ||
@@ -1111,2 +1111,3 @@ if (is("eof")) expect_token("punc", "}"); | ||
if (branch) branch.end = prev(); | ||
if (default_branch) croak("More than one default clause in switch statement"); | ||
cur = []; | ||
@@ -1118,2 +1119,3 @@ branch = new AST_Default({ | ||
a.push(branch); | ||
default_branch = branch; | ||
} else { | ||
@@ -1120,0 +1122,0 @@ if (!cur) unexpected(); |
@@ -46,3 +46,4 @@ /*********************************************************************** | ||
function find_builtins(reserved) { | ||
var builtins = function() { | ||
var names = []; | ||
// NaN will be included due to Number.NaN | ||
@@ -71,15 +72,17 @@ [ | ||
if (ctor.prototype) { | ||
Object.getOwnPropertyNames(new ctor()).map(add); | ||
Object.getOwnPropertyNames(ctor.prototype).map(add); | ||
} | ||
}); | ||
return makePredicate(names); | ||
function add(name) { | ||
push_uniq(reserved, name); | ||
names.push(name); | ||
} | ||
} | ||
}(); | ||
function reserve_quoted_keys(ast, reserved) { | ||
ast.walk(new TreeWalker(function(node) { | ||
if (node instanceof AST_ObjectKeyVal && node.quote) { | ||
add(node.key); | ||
if (node instanceof AST_ObjectKeyVal) { | ||
if (node.quote) add(node.key); | ||
} else if (node instanceof AST_Sub) { | ||
@@ -96,13 +99,10 @@ addStrings(node.property, add); | ||
function addStrings(node, add) { | ||
node.walk(new TreeWalker(function(node) { | ||
if (node instanceof AST_Sequence) { | ||
addStrings(node.tail_node(), add); | ||
} else if (node instanceof AST_String) { | ||
add(node.value); | ||
} else if (node instanceof AST_Conditional) { | ||
addStrings(node.consequent, add); | ||
addStrings(node.alternative, add); | ||
} | ||
return true; | ||
})); | ||
if (node instanceof AST_Conditional) { | ||
addStrings(node.consequent, add); | ||
addStrings(node.alternative, add); | ||
} else if (node instanceof AST_Sequence) { | ||
addStrings(node.tail_node(), add); | ||
} else if (node instanceof AST_String) { | ||
add(node.value); | ||
} | ||
} | ||
@@ -121,5 +121,6 @@ | ||
var reserved = options.reserved; | ||
if (!Array.isArray(reserved)) reserved = []; | ||
if (!options.builtins) find_builtins(reserved); | ||
var reserved = Object.create(options.builtins ? null : builtins); | ||
if (Array.isArray(options.reserved)) options.reserved.forEach(function(name) { | ||
reserved[name] = true; | ||
}); | ||
@@ -130,4 +131,4 @@ var cname = -1; | ||
cache = options.cache.props; | ||
cache.each(function(mangled_name) { | ||
push_uniq(reserved, mangled_name); | ||
cache.each(function(name) { | ||
reserved[name] = true; | ||
}); | ||
@@ -147,8 +148,29 @@ } else { | ||
var names_to_mangle = []; | ||
var unmangleable = []; | ||
var names_to_mangle = Object.create(null); | ||
var unmangleable = Object.create(reserved); | ||
// step 1: find candidates to mangle | ||
ast.walk(new TreeWalker(function(node) { | ||
if (node instanceof AST_ObjectKeyVal) { | ||
if (node instanceof AST_Binary) { | ||
if (node.operator == "in") addStrings(node.left, add); | ||
} else if (node.TYPE == "Call") { | ||
var exp = node.expression; | ||
if (exp instanceof AST_Dot) switch (exp.property) { | ||
case "defineProperty": | ||
case "getOwnPropertyDescriptor": | ||
if (node.args.length < 2) break; | ||
exp = exp.expression; | ||
if (!(exp instanceof AST_SymbolRef)) break; | ||
if (exp.name != "Object") break; | ||
if (!exp.definition().undeclared) break; | ||
addStrings(node.args[1], add); | ||
break; | ||
case "hasOwnProperty": | ||
if (node.args.length < 1) break; | ||
addStrings(node.args[0], add); | ||
break; | ||
} | ||
} else if (node instanceof AST_Dot) { | ||
add(node.property); | ||
} else if (node instanceof AST_ObjectKeyVal) { | ||
add(node.key); | ||
@@ -158,15 +180,31 @@ } else if (node instanceof AST_ObjectProperty) { | ||
add(node.key.name); | ||
} else if (node instanceof AST_Dot) { | ||
add(node.property); | ||
} else if (node instanceof AST_Sub) { | ||
addStrings(node.property, add); | ||
} else if (node instanceof AST_Call | ||
&& node.expression.print_to_string() == "Object.defineProperty") { | ||
addStrings(node.args[1], add); | ||
} | ||
})); | ||
// step 2: transform the tree, renaming properties | ||
return ast.transform(new TreeTransformer(function(node) { | ||
if (node instanceof AST_ObjectKeyVal) { | ||
// step 2: renaming properties | ||
ast.walk(new TreeWalker(function(node) { | ||
if (node instanceof AST_Binary) { | ||
if (node.operator == "in") mangleStrings(node.left); | ||
} else if (node.TYPE == "Call") { | ||
var exp = node.expression; | ||
if (exp instanceof AST_Dot) switch (exp.property) { | ||
case "defineProperty": | ||
case "getOwnPropertyDescriptor": | ||
if (node.args.length < 2) break; | ||
exp = exp.expression; | ||
if (!(exp instanceof AST_SymbolRef)) break; | ||
if (exp.name != "Object") break; | ||
if (!exp.definition().undeclared) break; | ||
mangleStrings(node.args[1]); | ||
break; | ||
case "hasOwnProperty": | ||
if (node.args.length < 1) break; | ||
mangleStrings(node.args[0]); | ||
break; | ||
} | ||
} else if (node instanceof AST_Dot) { | ||
node.property = mangle(node.property); | ||
} else if (node instanceof AST_ObjectKeyVal) { | ||
node.key = mangle(node.key); | ||
@@ -176,9 +214,4 @@ } else if (node instanceof AST_ObjectProperty) { | ||
node.key.name = mangle(node.key.name); | ||
} else if (node instanceof AST_Dot) { | ||
node.property = mangle(node.property); | ||
} else if (!options.keep_quoted && node instanceof AST_Sub) { | ||
node.property = mangleStrings(node.property); | ||
} else if (node instanceof AST_Call | ||
&& node.expression.print_to_string() == "Object.defineProperty") { | ||
node.args[1] = mangleStrings(node.args[1]); | ||
} else if (node instanceof AST_Sub) { | ||
if (!options.keep_quoted) mangleStrings(node.property); | ||
} | ||
@@ -190,4 +223,3 @@ })); | ||
function can_mangle(name) { | ||
if (unmangleable.indexOf(name) >= 0) return false; | ||
if (reserved.indexOf(name) >= 0) return false; | ||
if (unmangleable[name]) return false; | ||
if (options.only_cache) return cache.has(name); | ||
@@ -199,10 +231,10 @@ if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false; | ||
function should_mangle(name) { | ||
if (reserved[name]) return false; | ||
if (regex && !regex.test(name)) return false; | ||
if (reserved.indexOf(name) >= 0) return false; | ||
return cache.has(name) || names_to_mangle.indexOf(name) >= 0; | ||
return cache.has(name) || names_to_mangle[name]; | ||
} | ||
function add(name) { | ||
if (can_mangle(name)) push_uniq(names_to_mangle, name); | ||
if (!should_mangle(name)) push_uniq(unmangleable, name); | ||
if (can_mangle(name)) names_to_mangle[name] = true; | ||
if (!should_mangle(name)) unmangleable[name] = true; | ||
} | ||
@@ -231,15 +263,11 @@ | ||
function mangleStrings(node) { | ||
return node.transform(new TreeTransformer(function(node) { | ||
if (node instanceof AST_Sequence) { | ||
var last = node.expressions.length - 1; | ||
node.expressions[last] = mangleStrings(node.expressions[last]); | ||
} else if (node instanceof AST_String) { | ||
node.value = mangle(node.value); | ||
} else if (node instanceof AST_Conditional) { | ||
node.consequent = mangleStrings(node.consequent); | ||
node.alternative = mangleStrings(node.alternative); | ||
} | ||
return node; | ||
})); | ||
if (node instanceof AST_Sequence) { | ||
mangleStrings(node.expressions.tail_node()); | ||
} else if (node instanceof AST_String) { | ||
node.value = mangle(node.value); | ||
} else if (node instanceof AST_Conditional) { | ||
mangleStrings(node.consequent); | ||
mangleStrings(node.alternative); | ||
} | ||
} | ||
} |
@@ -562,17 +562,19 @@ /*********************************************************************** | ||
try { | ||
AST_Node.prototype.print = function(stream, force_parens) { | ||
this._print(stream, force_parens); | ||
if (this instanceof AST_Symbol && !this.unmangleable(options)) { | ||
base54.consider(this.name, -1); | ||
} else if (options.properties) { | ||
if (this instanceof AST_Dot) { | ||
base54.consider(this.property, -1); | ||
} else if (this instanceof AST_Sub) { | ||
skip_string(this.property); | ||
} | ||
} | ||
var fn = AST_Symbol.prototype.add_source_map; | ||
AST_Symbol.prototype.add_source_map = function() { | ||
if (!this.unmangleable(options)) base54.consider(this.name, -1); | ||
}; | ||
if (options.properties) { | ||
AST_Dot.prototype.add_source_map = function() { | ||
base54.consider(this.property, -1); | ||
}; | ||
AST_Sub.prototype.add_source_map = function() { | ||
skip_string(this.property); | ||
}; | ||
} | ||
base54.consider(this.print_to_string(), 1); | ||
} finally { | ||
AST_Node.prototype.print = AST_Node.prototype._print; | ||
AST_Symbol.prototype.add_source_map = fn; | ||
delete AST_Dot.prototype.add_source_map; | ||
delete AST_Sub.prototype.add_source_map; | ||
} | ||
@@ -579,0 +581,0 @@ base54.sort(); |
@@ -6,3 +6,3 @@ { | ||
"license": "BSD-2-Clause", | ||
"version": "3.10.1", | ||
"version": "3.10.2", | ||
"engines": { | ||
@@ -9,0 +9,0 @@ "node": ">=0.8.0" |
@@ -215,14 +215,13 @@ UglifyJS 3 | ||
- `toplevel` (default `false`) -- mangle names declared in the top level scope. | ||
- `eval` (default `false`) -- mangle names visible in scopes where `eval` or | ||
`with` are used. | ||
- `eval` (default `false`) -- mangle names visible in scopes where `eval` or `with` are used. | ||
- `reserved` (default: `[]`) -- when mangling is enabled but you want to | ||
prevent certain names from being mangled, you can declare those names with | ||
`--mangle reserved` — pass a comma-separated list of names. For example: | ||
When mangling is enabled but you want to prevent certain names from being | ||
mangled, you can declare those names with `--mangle reserved` — pass a | ||
comma-separated list of names. For example: | ||
uglifyjs ... -m reserved=['$','require','exports'] | ||
uglifyjs ... -m reserved=['$','require','exports'] | ||
to prevent the `require`, `exports` and `$` names from being changed. | ||
to prevent the `require`, `exports` and `$` names from being changed. | ||
### CLI mangling property names (`--mangle-props`) | ||
@@ -661,4 +660,4 @@ | ||
`var o={p:1, q:2}; f(o.p, o.q);` is converted to `f(1, 2);`. Note: `hoist_props` | ||
works best with `mangle` enabled, the `compress` option `passes` set to `2` or higher, | ||
and the `compress` option `toplevel` enabled. | ||
works best with `toplevel` and `mangle` enabled, alongside with `compress` option | ||
`passes` set to `2` or higher. | ||
@@ -1162,1 +1161,17 @@ - `hoist_vars` (default: `false`) -- hoist `var` declarations (this is `false` | ||
`Object.preventExtensions()` or `Object.seal()`). | ||
- When `toplevel` is enabled, UglifyJS effectively assumes input code is wrapped | ||
within `function(){ ... }`, thus forbids aliasing of declared global variables: | ||
```js | ||
A = "FAIL"; | ||
var B = "FAIL"; | ||
// can be `global`, `self`, `window` etc. | ||
var top = function() { | ||
return this; | ||
}(); | ||
// "PASS" | ||
top.A = "PASS"; | ||
console.log(A); | ||
// "FAIL" after compress and/or mangle | ||
top.B = "PASS"; | ||
console.log(B); | ||
``` |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
889871
23170
1175