Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59eecb6bf5 | ||
|
|
d83c6490ab | ||
|
|
7362f57966 | ||
|
|
eaa2c1f6af | ||
|
|
6a916523d4 | ||
|
|
ba7069d52b | ||
|
|
4dd7d0e39b | ||
|
|
90199d0a96 | ||
|
|
b82fd0ad41 | ||
|
|
183da16896 |
@@ -685,7 +685,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
pass `pure_funcs: [ 'Math.floor' ]` to let it know that this
|
pass `pure_funcs: [ 'Math.floor' ]` to let it know that this
|
||||||
function won't produce any side effect, in which case the whole
|
function won't produce any side effect, in which case the whole
|
||||||
statement would get discarded. The current implementation adds some
|
statement would get discarded. The current implementation adds some
|
||||||
overhead (compression will be slower).
|
overhead (compression will be slower). Make sure symbols under `pure_funcs`
|
||||||
|
are also under `mangle.reserved` to avoid mangling.
|
||||||
|
|
||||||
- `pure_getters` (default: `"strict"`) -- If you pass `true` for
|
- `pure_getters` (default: `"strict"`) -- If you pass `true` for
|
||||||
this, UglifyJS will assume that object property access
|
this, UglifyJS will assume that object property access
|
||||||
|
|||||||
200
lib/compress.js
200
lib/compress.js
@@ -530,11 +530,16 @@ merge(Compressor.prototype, {
|
|||||||
tw.safe_ids = save_ids;
|
tw.safe_ids = save_ids;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
def(AST_DWLoop, function(tw, descend) {
|
def(AST_Do, function(tw) {
|
||||||
var saved_loop = tw.in_loop;
|
var saved_loop = tw.in_loop;
|
||||||
tw.in_loop = this;
|
tw.in_loop = this;
|
||||||
push(tw);
|
push(tw);
|
||||||
descend();
|
this.body.walk(tw);
|
||||||
|
if (has_break_or_continue(this)) {
|
||||||
|
pop(tw);
|
||||||
|
push(tw);
|
||||||
|
}
|
||||||
|
this.condition.walk(tw);
|
||||||
pop(tw);
|
pop(tw);
|
||||||
tw.in_loop = saved_loop;
|
tw.in_loop = saved_loop;
|
||||||
return true;
|
return true;
|
||||||
@@ -543,19 +548,17 @@ merge(Compressor.prototype, {
|
|||||||
if (this.init) this.init.walk(tw);
|
if (this.init) this.init.walk(tw);
|
||||||
var saved_loop = tw.in_loop;
|
var saved_loop = tw.in_loop;
|
||||||
tw.in_loop = this;
|
tw.in_loop = this;
|
||||||
if (this.condition) {
|
|
||||||
push(tw);
|
|
||||||
this.condition.walk(tw);
|
|
||||||
pop(tw);
|
|
||||||
}
|
|
||||||
push(tw);
|
push(tw);
|
||||||
|
if (this.condition) this.condition.walk(tw);
|
||||||
this.body.walk(tw);
|
this.body.walk(tw);
|
||||||
pop(tw);
|
|
||||||
if (this.step) {
|
if (this.step) {
|
||||||
push(tw);
|
if (has_break_or_continue(this)) {
|
||||||
|
pop(tw);
|
||||||
|
push(tw);
|
||||||
|
}
|
||||||
this.step.walk(tw);
|
this.step.walk(tw);
|
||||||
pop(tw);
|
|
||||||
}
|
}
|
||||||
|
pop(tw);
|
||||||
tw.in_loop = saved_loop;
|
tw.in_loop = saved_loop;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@@ -713,6 +716,15 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
def(AST_While, function(tw, descend) {
|
||||||
|
var saved_loop = tw.in_loop;
|
||||||
|
tw.in_loop = this;
|
||||||
|
push(tw);
|
||||||
|
descend();
|
||||||
|
pop(tw);
|
||||||
|
tw.in_loop = saved_loop;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
})(function(node, func){
|
})(function(node, func){
|
||||||
node.DEFMETHOD("reduce_vars", func);
|
node.DEFMETHOD("reduce_vars", func);
|
||||||
});
|
});
|
||||||
@@ -1336,8 +1348,9 @@ merge(Compressor.prototype, {
|
|||||||
if (expr instanceof AST_VarDef) {
|
if (expr instanceof AST_VarDef) {
|
||||||
var def = expr.name.definition();
|
var def = expr.name.definition();
|
||||||
if (!member(expr.name, def.orig)) return;
|
if (!member(expr.name, def.orig)) return;
|
||||||
var declared = def.orig.length - def.eliminated;
|
|
||||||
var referenced = def.references.length - def.replaced;
|
var referenced = def.references.length - def.replaced;
|
||||||
|
if (!referenced) return;
|
||||||
|
var declared = def.orig.length - def.eliminated;
|
||||||
if (declared > 1 && !(expr.name instanceof AST_SymbolFunarg)
|
if (declared > 1 && !(expr.name instanceof AST_SymbolFunarg)
|
||||||
|| (referenced > 1 ? mangleable_var(expr) : !compressor.exposed(def))) {
|
|| (referenced > 1 ? mangleable_var(expr) : !compressor.exposed(def))) {
|
||||||
return make_node(AST_SymbolRef, expr.name, expr.name);
|
return make_node(AST_SymbolRef, expr.name, expr.name);
|
||||||
@@ -1870,9 +1883,6 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function join_object_assignments(defn, body) {
|
function join_object_assignments(defn, body) {
|
||||||
if (!(defn instanceof AST_Definitions)) return;
|
|
||||||
var def = defn.definitions[defn.definitions.length - 1];
|
|
||||||
if (!(def.value instanceof AST_Object)) return;
|
|
||||||
var exprs;
|
var exprs;
|
||||||
if (body instanceof AST_Assign) {
|
if (body instanceof AST_Assign) {
|
||||||
exprs = [ body ];
|
exprs = [ body ];
|
||||||
@@ -1880,6 +1890,23 @@ merge(Compressor.prototype, {
|
|||||||
exprs = body.expressions.slice();
|
exprs = body.expressions.slice();
|
||||||
}
|
}
|
||||||
if (!exprs) return;
|
if (!exprs) return;
|
||||||
|
if (defn instanceof AST_Definitions) {
|
||||||
|
var def = defn.definitions[defn.definitions.length - 1];
|
||||||
|
if (trim_object_assignments(def.name, def.value, exprs)) return exprs;
|
||||||
|
}
|
||||||
|
for (var i = exprs.length - 1; --i >= 0;) {
|
||||||
|
var expr = exprs[i];
|
||||||
|
if (!(expr instanceof AST_Assign)) continue;
|
||||||
|
if (expr.operator != "=") continue;
|
||||||
|
if (!(expr.left instanceof AST_SymbolRef)) continue;
|
||||||
|
var tail = exprs.slice(i + 1);
|
||||||
|
if (!trim_object_assignments(expr.left, expr.right, tail)) continue;
|
||||||
|
return exprs.slice(0, i + 1).concat(tail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function trim_object_assignments(name, value, exprs) {
|
||||||
|
if (!(value instanceof AST_Object)) return;
|
||||||
var trimmed = false;
|
var trimmed = false;
|
||||||
do {
|
do {
|
||||||
var node = exprs[0];
|
var node = exprs[0];
|
||||||
@@ -1888,7 +1915,7 @@ merge(Compressor.prototype, {
|
|||||||
if (!(node.left instanceof AST_PropAccess)) break;
|
if (!(node.left instanceof AST_PropAccess)) break;
|
||||||
var sym = node.left.expression;
|
var sym = node.left.expression;
|
||||||
if (!(sym instanceof AST_SymbolRef)) break;
|
if (!(sym instanceof AST_SymbolRef)) break;
|
||||||
if (def.name.name != sym.name) break;
|
if (name.name != sym.name) break;
|
||||||
if (!node.right.is_constant_expression(scope)) break;
|
if (!node.right.is_constant_expression(scope)) break;
|
||||||
var prop = node.left.property;
|
var prop = node.left.property;
|
||||||
if (prop instanceof AST_Node) {
|
if (prop instanceof AST_Node) {
|
||||||
@@ -1901,15 +1928,15 @@ merge(Compressor.prototype, {
|
|||||||
} : function(node) {
|
} : function(node) {
|
||||||
return node.key.name != prop;
|
return node.key.name != prop;
|
||||||
};
|
};
|
||||||
if (!all(def.value.properties, diff)) break;
|
if (!all(value.properties, diff)) break;
|
||||||
def.value.properties.push(make_node(AST_ObjectKeyVal, node, {
|
value.properties.push(make_node(AST_ObjectKeyVal, node, {
|
||||||
key: prop,
|
key: prop,
|
||||||
value: node.right
|
value: node.right
|
||||||
}));
|
}));
|
||||||
exprs.shift();
|
exprs.shift();
|
||||||
trimmed = true;
|
trimmed = true;
|
||||||
} while (exprs.length);
|
} while (exprs.length);
|
||||||
return trimmed && exprs;
|
return trimmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
function join_consecutive_vars(statements) {
|
function join_consecutive_vars(statements) {
|
||||||
@@ -3613,28 +3640,50 @@ merge(Compressor.prototype, {
|
|||||||
var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
|
var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
|
||||||
var defs_by_id = Object.create(null);
|
var defs_by_id = Object.create(null);
|
||||||
return self.transform(new TreeTransformer(function(node, descend) {
|
return self.transform(new TreeTransformer(function(node, descend) {
|
||||||
if (node instanceof AST_VarDef) {
|
if (node instanceof AST_Assign
|
||||||
var sym = node.name, def, value;
|
&& node.operator == "="
|
||||||
if (sym.scope === self
|
&& node.write_only
|
||||||
&& (def = sym.definition()).escaped != 1
|
&& can_hoist(node.left, node.right, 1)) {
|
||||||
&& !def.assignments
|
descend(node, this);
|
||||||
&& !def.direct_access
|
var defs = new Dictionary();
|
||||||
&& !def.single_use
|
var assignments = [];
|
||||||
&& !top_retain(def)
|
var decls = [];
|
||||||
&& (value = sym.fixed_value()) === node.value
|
node.right.properties.forEach(function(prop) {
|
||||||
&& value instanceof AST_Object) {
|
var decl = make_sym(node.left, prop.key);
|
||||||
descend(node, this);
|
decls.push(make_node(AST_VarDef, node, {
|
||||||
var defs = new Dictionary();
|
name: decl,
|
||||||
var assignments = [];
|
value: null
|
||||||
value.properties.forEach(function(prop) {
|
}));
|
||||||
assignments.push(make_node(AST_VarDef, node, {
|
var sym = make_node(AST_SymbolRef, node, {
|
||||||
name: make_sym(prop.key),
|
name: decl.name,
|
||||||
value: prop.value
|
scope: self,
|
||||||
}));
|
thedef: decl.definition()
|
||||||
});
|
});
|
||||||
defs_by_id[def.id] = defs;
|
sym.reference({});
|
||||||
return MAP.splice(assignments);
|
assignments.push(make_node(AST_Assign, node, {
|
||||||
}
|
operator: "=",
|
||||||
|
left: sym,
|
||||||
|
right: prop.value
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
defs_by_id[node.left.definition().id] = defs;
|
||||||
|
self.body.splice(self.body.indexOf(this.stack[1]) + 1, 0, make_node(AST_Var, node, {
|
||||||
|
definitions: decls
|
||||||
|
}));
|
||||||
|
return make_sequence(node, assignments);
|
||||||
|
}
|
||||||
|
if (node instanceof AST_VarDef && can_hoist(node.name, node.value, 0)) {
|
||||||
|
descend(node, this);
|
||||||
|
var defs = new Dictionary();
|
||||||
|
var var_defs = [];
|
||||||
|
node.value.properties.forEach(function(prop) {
|
||||||
|
var_defs.push(make_node(AST_VarDef, node, {
|
||||||
|
name: make_sym(node.name, prop.key),
|
||||||
|
value: prop.value
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
defs_by_id[node.name.definition().id] = defs;
|
||||||
|
return MAP.splice(var_defs);
|
||||||
}
|
}
|
||||||
if (node instanceof AST_PropAccess && node.expression instanceof AST_SymbolRef) {
|
if (node instanceof AST_PropAccess && node.expression instanceof AST_SymbolRef) {
|
||||||
var defs = defs_by_id[node.expression.definition().id];
|
var defs = defs_by_id[node.expression.definition().id];
|
||||||
@@ -3650,8 +3699,20 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function make_sym(key) {
|
function can_hoist(sym, right, count) {
|
||||||
var new_var = make_node(sym.CTOR, sym, {
|
if (sym.scope !== self) return;
|
||||||
|
var def = sym.definition();
|
||||||
|
if (def.assignments != count) return;
|
||||||
|
if (def.direct_access) return;
|
||||||
|
if (def.escaped == 1) return;
|
||||||
|
if (def.single_use) return;
|
||||||
|
if (top_retain(def)) return;
|
||||||
|
if (sym.fixed_value() !== right) return;
|
||||||
|
return right instanceof AST_Object;
|
||||||
|
}
|
||||||
|
|
||||||
|
function make_sym(sym, key) {
|
||||||
|
var new_var = make_node(AST_SymbolVar, sym, {
|
||||||
name: self.make_var_name(sym.name + "_" + key),
|
name: self.make_var_name(sym.name + "_" + key),
|
||||||
scope: self
|
scope: self
|
||||||
});
|
});
|
||||||
@@ -3837,6 +3898,20 @@ merge(Compressor.prototype, {
|
|||||||
return compressor.option("loops") ? make_node(AST_For, self, self).optimize(compressor) : self;
|
return compressor.option("loops") ? make_node(AST_For, self, self).optimize(compressor) : self;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function has_break_or_continue(loop, parent) {
|
||||||
|
var found = false;
|
||||||
|
var tw = new TreeWalker(function(node) {
|
||||||
|
if (found || node instanceof AST_Scope) return true;
|
||||||
|
if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === loop) {
|
||||||
|
return found = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (parent instanceof AST_LabeledStatement) tw.push(parent);
|
||||||
|
tw.push(loop);
|
||||||
|
loop.body.walk(tw);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
OPT(AST_Do, function(self, compressor){
|
OPT(AST_Do, function(self, compressor){
|
||||||
if (!compressor.option("loops")) return self;
|
if (!compressor.option("loops")) return self;
|
||||||
var cond = self.condition.is_truthy() || self.condition.tail_node().evaluate(compressor);
|
var cond = self.condition.is_truthy() || self.condition.tail_node().evaluate(compressor);
|
||||||
@@ -3851,22 +3926,16 @@ merge(Compressor.prototype, {
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
var has_loop_control = false;
|
if (!has_break_or_continue(self, compressor.parent())) {
|
||||||
var tw = new TreeWalker(function(node) {
|
return make_node(AST_BlockStatement, self.body, {
|
||||||
if (node instanceof AST_Scope || has_loop_control) return true;
|
body: [
|
||||||
if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === self)
|
self.body,
|
||||||
return has_loop_control = true;
|
make_node(AST_SimpleStatement, self.condition, {
|
||||||
});
|
body: self.condition
|
||||||
var parent = compressor.parent();
|
})
|
||||||
(parent instanceof AST_LabeledStatement ? parent : self).walk(tw);
|
]
|
||||||
if (!has_loop_control) return make_node(AST_BlockStatement, self.body, {
|
}).optimize(compressor);
|
||||||
body: [
|
}
|
||||||
self.body,
|
|
||||||
make_node(AST_SimpleStatement, self.condition, {
|
|
||||||
body: self.condition
|
|
||||||
})
|
|
||||||
]
|
|
||||||
}).optimize(compressor);
|
|
||||||
}
|
}
|
||||||
if (self.body instanceof AST_SimpleStatement) return make_node(AST_For, self, {
|
if (self.body instanceof AST_SimpleStatement) return make_node(AST_For, self, {
|
||||||
condition: make_sequence(self.condition, [
|
condition: make_sequence(self.condition, [
|
||||||
@@ -4573,7 +4642,8 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
var stat = is_func && fn.body[0];
|
var stat = is_func && fn.body[0];
|
||||||
if (compressor.option("inline") && stat instanceof AST_Return) {
|
var can_inline = compressor.option("inline") && !self.is_expr_pure(compressor);
|
||||||
|
if (can_inline && stat instanceof AST_Return) {
|
||||||
var value = stat.value;
|
var value = stat.value;
|
||||||
if (!value || value.is_constant_expression()) {
|
if (!value || value.is_constant_expression()) {
|
||||||
if (value) {
|
if (value) {
|
||||||
@@ -4587,7 +4657,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (is_func) {
|
if (is_func) {
|
||||||
var def, value, scope, in_loop, level = -1;
|
var def, value, scope, in_loop, level = -1;
|
||||||
if (compressor.option("inline")
|
if (can_inline
|
||||||
&& !fn.uses_arguments
|
&& !fn.uses_arguments
|
||||||
&& !fn.uses_eval
|
&& !fn.uses_eval
|
||||||
&& !(fn.name && fn instanceof AST_Function)
|
&& !(fn.name && fn instanceof AST_Function)
|
||||||
@@ -4772,6 +4842,11 @@ merge(Compressor.prototype, {
|
|||||||
for (var j = 0, defs = stat.definitions.length; j < defs; j++) {
|
for (var j = 0, defs = stat.definitions.length; j < defs; j++) {
|
||||||
var var_def = stat.definitions[j];
|
var var_def = stat.definitions[j];
|
||||||
var name = var_def.name;
|
var name = var_def.name;
|
||||||
|
var redef = name.definition().redefined();
|
||||||
|
if (redef) {
|
||||||
|
name = name.clone();
|
||||||
|
name.thedef = redef;
|
||||||
|
}
|
||||||
append_var(decls, expressions, name, var_def.value);
|
append_var(decls, expressions, name, var_def.value);
|
||||||
if (in_loop && all(fn.argnames, function(argname) {
|
if (in_loop && all(fn.argnames, function(argname) {
|
||||||
return argname.name != name.name;
|
return argname.name != name.name;
|
||||||
@@ -5460,11 +5535,12 @@ merge(Compressor.prototype, {
|
|||||||
return make_node(AST_Infinity, self).optimize(compressor);
|
return make_node(AST_Infinity, self).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (compressor.option("reduce_vars")
|
var parent = compressor.parent();
|
||||||
&& is_lhs(self, compressor.parent()) !== self) {
|
if (compressor.option("reduce_vars") && is_lhs(self, parent) !== self) {
|
||||||
var d = self.definition();
|
var d = self.definition();
|
||||||
var fixed = self.fixed_value();
|
var fixed = self.fixed_value();
|
||||||
var single_use = d.single_use;
|
var single_use = d.single_use
|
||||||
|
&& !(parent instanceof AST_Call && parent.is_expr_pure(compressor));
|
||||||
if (single_use && fixed instanceof AST_Lambda) {
|
if (single_use && fixed instanceof AST_Lambda) {
|
||||||
if (d.scope !== self.scope
|
if (d.scope !== self.scope
|
||||||
&& (!compressor.option("reduce_funcs")
|
&& (!compressor.option("reduce_funcs")
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "3.3.20",
|
"version": "3.3.22",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2267,3 +2267,39 @@ issue_3054: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "true true"
|
expect_stdout: "true true"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3076: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
inline: true,
|
||||||
|
sequences: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = "PASS";
|
||||||
|
(function(b) {
|
||||||
|
var n = 2;
|
||||||
|
while (--b + function() {
|
||||||
|
e && (c = "FAIL");
|
||||||
|
e = 5;
|
||||||
|
return 1;
|
||||||
|
try {
|
||||||
|
var a = 5;
|
||||||
|
} catch (e) {
|
||||||
|
var e;
|
||||||
|
}
|
||||||
|
}().toString() && --n > 0);
|
||||||
|
})(2);
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = "PASS";
|
||||||
|
(function(b) {
|
||||||
|
var n = 2;
|
||||||
|
while (--b + (e = void 0, e && (c = "FAIL"), e = 5, 1).toString() && --n > 0);
|
||||||
|
var e;
|
||||||
|
})(2),
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -742,3 +742,117 @@ issue_3046: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3071_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
join_vars: true,
|
||||||
|
hoist_props: true,
|
||||||
|
passes: 3,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var obj = {};
|
||||||
|
obj.one = 1;
|
||||||
|
obj.two = 2;
|
||||||
|
console.log(obj.one);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(1);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3071_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
join_vars: true,
|
||||||
|
hoist_props: true,
|
||||||
|
passes: 3,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
obj = {};
|
||||||
|
obj.one = 1;
|
||||||
|
obj.two = 2;
|
||||||
|
console.log(obj.one);
|
||||||
|
var obj;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(1);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3071_2_toplevel: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
join_vars: true,
|
||||||
|
hoist_props: true,
|
||||||
|
passes: 3,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
obj = {};
|
||||||
|
obj.one = 1;
|
||||||
|
obj.two = 2;
|
||||||
|
console.log(obj.one);
|
||||||
|
var obj;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(1);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3071_3: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
(function(a, b) {
|
||||||
|
(function f(o) {
|
||||||
|
var n = 2;
|
||||||
|
while (--b + (o = {
|
||||||
|
p: c++,
|
||||||
|
}) && --n > 0);
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
(function(a, b) {
|
||||||
|
(function f(o) {
|
||||||
|
var n = 2;
|
||||||
|
while (--b + (o = {
|
||||||
|
p: c++,
|
||||||
|
}) && --n > 0);
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1208,6 +1208,37 @@ join_object_assignments_3: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
join_object_assignments_4: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o;
|
||||||
|
console.log(o);
|
||||||
|
o = {};
|
||||||
|
o.a = "foo";
|
||||||
|
console.log(o.b);
|
||||||
|
o.b = "bar";
|
||||||
|
console.log(o.a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o;
|
||||||
|
console.log(o),
|
||||||
|
o = {
|
||||||
|
a: "foo",
|
||||||
|
},
|
||||||
|
console.log(o.b),
|
||||||
|
o.b = "bar",
|
||||||
|
console.log(o.a);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined",
|
||||||
|
"undefined",
|
||||||
|
"foo",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
join_object_assignments_return_1: {
|
join_object_assignments_return_1: {
|
||||||
options = {
|
options = {
|
||||||
join_vars: true,
|
join_vars: true,
|
||||||
|
|||||||
@@ -535,3 +535,110 @@ issue_2705_6: {
|
|||||||
"/* */new(/* */a()||b())(c(),d());",
|
"/* */new(/* */a()||b())(c(),d());",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3065_1: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
pure_funcs: [ "pureFunc" ],
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function modifyWrapper(a, f, wrapper) {
|
||||||
|
wrapper.a = a;
|
||||||
|
wrapper.f = f;
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
function pureFunc(fun) {
|
||||||
|
return modifyWrapper(1, fun, function(a) {
|
||||||
|
return fun(a);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var unused = pureFunc(function(x) {
|
||||||
|
return x;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3065_2: {
|
||||||
|
rename = true
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
pure_funcs: [ "pureFunc" ],
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
reserved: [ "pureFunc" ],
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function modifyWrapper(a, f, wrapper) {
|
||||||
|
wrapper.a = a;
|
||||||
|
wrapper.f = f;
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
function pureFunc(fun) {
|
||||||
|
return modifyWrapper(1, fun, function(a) {
|
||||||
|
return fun(a);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var unused = pureFunc(function(x) {
|
||||||
|
return x;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3065_3: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: [ "debug" ],
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function debug(msg) {
|
||||||
|
console.log(msg);
|
||||||
|
}
|
||||||
|
debug(function() {
|
||||||
|
console.log("PASS");
|
||||||
|
return "FAIL";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3065_4: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: [ "debug" ],
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var debug = function(msg) {
|
||||||
|
console.log(msg);
|
||||||
|
};
|
||||||
|
debug(function() {
|
||||||
|
console.log("PASS");
|
||||||
|
return "FAIL";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5654,3 +5654,59 @@ issue_3042_2: {
|
|||||||
"true",
|
"true",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3068_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
do {
|
||||||
|
continue;
|
||||||
|
var b = "defined";
|
||||||
|
} while (b && b.c);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
do {
|
||||||
|
continue;
|
||||||
|
var b = "defined";
|
||||||
|
} while (b && b.c);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3068_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
while ("" == typeof a);
|
||||||
|
} finally {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var b = "defined";
|
||||||
|
} while (b && b.c);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
while ("" == typeof a);
|
||||||
|
} finally {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var b = "defined";
|
||||||
|
} while (b && b.c);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ function safe_log(arg, level) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function strip_func_ids(text) {
|
function strip_func_ids(text) {
|
||||||
return text.toString().replace(/F[0-9]{6}N/g, "<F<>N>");
|
return ("" + text).replace(/F[0-9]{6}N/g, "<F<>N>");
|
||||||
}
|
}
|
||||||
|
|
||||||
var context;
|
var context;
|
||||||
|
|||||||
Reference in New Issue
Block a user