Skip to content

Commit

Permalink
harmony-v3.0.23
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlamsl authored Jul 2, 2017
2 parents a9eecd8 + 5ea1da2 commit 33ad0d2
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 93 deletions.
176 changes: 103 additions & 73 deletions lib/compress.js
Original file line number Diff line number Diff line change
Expand Up @@ -749,15 +749,23 @@ merge(Compressor.prototype, {
var candidates = [];
var stat_index = statements.length;
while (--stat_index >= 0) {
// Treat parameters as collapsible in IIFE, i.e.
// function(a, b){ ... }(x());
// would be translated into equivalent assignments:
// var a = x(), b = undefined;
if (stat_index == 0 && compressor.option("unused")) extract_args();
// Find collapsible assignments
extract_candidates(statements[stat_index]);
while (candidates.length > 0) {
var candidate = candidates.pop();
var lhs = get_lhs(candidate);
if (!lhs || is_lhs_read_only(lhs)) continue;
// Locate symbols which may execute code outside of scanning range
var lvalues = get_lvalues(candidate);
if (lhs instanceof AST_SymbolRef) lvalues[lhs.name] = false;
var side_effects = value_has_side_effects(candidate);
var hit = false, abort = false, replaced = false;
var hit = candidate.name instanceof AST_SymbolFunarg;
var abort = false, replaced = false;
var tt = new TreeTransformer(function(node, descend) {
if (abort) return node;
// Skip nodes before `candidate` as quickly as possible
Expand Down Expand Up @@ -840,6 +848,58 @@ merge(Compressor.prototype, {
}
}

function has_overlapping_symbol(fn, arg) {
var found = false;
arg.walk(new TreeWalker(function(node) {
if (found) return true;
if (node instanceof AST_SymbolRef && fn.variables.has(node.name)) {
var s = node.definition().scope;
if (s !== scope) while (s = s.parent_scope) {
if (s === scope) return true;
}
found = true;
}
}));
return found;
}

function extract_args() {
var iife, fn = compressor.self();
if (is_func_expr(fn)
&& !fn.name
&& !fn.uses_arguments
&& !fn.uses_eval
&& (iife = compressor.parent()) instanceof AST_Call
&& iife.expression === fn
&& all(iife.args, function(arg) {
return !(arg instanceof AST_Expansion);
})) {
fn.argnames.forEach(function(sym, i) {
if (sym instanceof AST_Expansion) {
var elements = iife.args.slice(i);
if (all(elements, function(arg) {
return !has_overlapping_symbol(fn, arg);
})) {
candidates.push(make_node(AST_VarDef, sym, {
name: sym.expression,
value: make_node(AST_Array, iife, {
elements: elements
})
}));
}
} else {
var arg = iife.args[i];
if (!arg) arg = make_node(AST_Undefined, sym);
else if (has_overlapping_symbol(fn, arg)) arg = null;
if (arg) candidates.push(make_node(AST_VarDef, sym, {
name: sym,
value: arg
}));
}
});
}
}

function extract_candidates(expr) {
if (expr instanceof AST_Assign && !expr.left.has_side_effects(compressor)
|| expr instanceof AST_Unary && (expr.operator == "++" || expr.operator == "--")) {
Expand All @@ -860,7 +920,7 @@ merge(Compressor.prototype, {
function get_lhs(expr) {
if (expr instanceof AST_VarDef && expr.name instanceof AST_SymbolDeclaration) {
var def = expr.name.definition();
if (def.orig.length > 1
if (def.orig.length > 1 && !(expr.name instanceof AST_SymbolFunarg)
|| def.references.length == 1 && !compressor.exposed(def)) {
return make_node(AST_SymbolRef, expr.name, expr.name);
}
Expand Down Expand Up @@ -903,6 +963,19 @@ merge(Compressor.prototype, {
}

function remove_candidate(expr) {
if (expr.name instanceof AST_SymbolFunarg) {
var iife = compressor.parent(), argnames = compressor.self().argnames;
var index = argnames.indexOf(expr.name);
if (index < 0) {
iife.args.length = Math.min(iife.args.length, argnames.length - 1);
} else {
var args = iife.args;
if (args[index]) args[index] = make_node(AST_Number, args[index], {
value: 0
});
}
return true;
}
var found = false;
return statements[stat_index].transform(new TreeTransformer(function(node, descend, in_list) {
if (found) return node;
Expand Down Expand Up @@ -3105,7 +3178,7 @@ merge(Compressor.prototype, {
var pos = 0, last = 0;
for (var i = 0, len = self.args.length; i < len; i++) {
if (fn.argnames[i] instanceof AST_Expansion) {
if (fn.argnames[i].__unused) while (i < len) {
if (fn.argnames[i].expression.__unused) while (i < len) {
var node = self.args[i++].drop_side_effect_free(compressor);
if (node) {
self.args[pos++] = node;
Expand Down Expand Up @@ -3343,98 +3416,55 @@ merge(Compressor.prototype, {
var value = stat.value;
if (!value || value.is_constant_expression()) {
var args = self.args.concat(value || make_node(AST_Undefined, self));
return make_sequence(self, args).transform(compressor);
return make_sequence(self, args).optimize(compressor);
}
}
if (is_func_expr(exp) && !exp.is_generator && !exp.async) {
if (compressor.option("inline")
&& simple_args
&& !exp.name
&& (exp.body instanceof AST_Node || exp.body.length == 1)
&& !exp.uses_arguments
&& !exp.uses_eval
&& simple_args
&& (exp.body instanceof AST_Node || exp.body.length == 1)
&& all(exp.argnames, function(arg) {
if (arg instanceof AST_Expansion) return arg.expression.__unused;
return arg.__unused;
})
&& !self.has_pure_annotation(compressor)) {
var value;
if (stat instanceof AST_Return) {
value = stat.value.clone(true);
value = stat.value;
} else if (stat instanceof AST_SimpleStatement) {
value = make_node(AST_UnaryPrefix, stat, {
operator: "void",
expression: stat.body.clone(true)
expression: stat.body
});
}
if (value) {
var fn = exp.clone();
fn.argnames = [];
fn.body = [];
if (exp.argnames.length > 0) {
fn.body.push(make_node(AST_Var, self, {
definitions: exp.argnames.map(function(sym, i) {
if (sym instanceof AST_Expansion) {
return make_node(AST_VarDef, sym, {
name: sym.expression,
value: make_node(AST_Array, self, {
elements: self.args.slice(i).map(function(arg) {
return arg.clone(true);
})
})
});
}
var arg = self.args[i];
return make_node(AST_VarDef, sym, {
name: sym,
value: arg ? arg.clone(true) : make_node(AST_Undefined, self)
});
})
}));
}
if (self.args.length > exp.argnames.length && !(exp.argnames[exp.argnames.length - 1] instanceof AST_Expansion)) {
fn.body.push(make_node(AST_SimpleStatement, self, {
body: make_sequence(self, self.args.slice(exp.argnames.length).map(function(node) {
return node.clone(true);
}))
}));
}
fn.body.push(make_node(AST_Return, self, {
value: value
}));
var body = fn.transform(compressor).body;
if (body instanceof AST_Node) {
body = [
make_node(AST_Return, body, {
value: body
})
];
}
if (body.length == 0) return make_node(AST_Undefined, self);
if (body.length == 1 && body[0] instanceof AST_Return) {
value = body[0].value;
if (!value) return make_node(AST_Undefined, self);
var tw = new TreeWalker(function(node) {
if (value === self) return true;
if (node instanceof AST_SymbolRef) {
var ref = node.scope.find_variable(node);
if (ref && ref.scope.parent_scope === fn.parent_scope) {
value = self;
return true;
}
}
if (node instanceof AST_This && !tw.find_parent(AST_Scope)) {
value = self;
var tw = new TreeWalker(function(node) {
if (!value) return true;
if (node instanceof AST_SymbolRef) {
var ref = node.scope.find_variable(node);
if (ref && ref.scope.parent_scope === fn.parent_scope) {
value = null;
return true;
}
});
value.walk(tw);
if (value !== self) value = best_of(compressor, value, self);
} else {
value = self;
}
if (value !== self) return value;
}
if (node instanceof AST_This && !tw.find_parent(AST_Scope)) {
value = null;
return true;
}
});
value.walk(tw);
}
if (value) {
var args = self.args.concat(value);
return make_sequence(self, args).optimize(compressor);
}
}
if (compressor.option("side_effects") && !(exp.body instanceof AST_Node) && all(exp.body, is_empty)) {
var args = self.args.concat(make_node(AST_Undefined, self));
return make_sequence(self, args).transform(compressor);
return make_sequence(self, args).optimize(compressor);
}
}
if (compressor.option("drop_console")) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
"author": "Mihai Bazon <[email protected]> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.0.22",
"version": "3.0.23",
"engines": {
"node": ">=0.8.0"
},
Expand Down
6 changes: 4 additions & 2 deletions test/compress/arrow.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ issue_2105_1: {
collapse_vars: true,
ecma: 6,
inline: true,
passes: 3,
reduce_vars: true,
side_effects: true,
unused: true,
Expand All @@ -312,7 +313,7 @@ issue_2105_1: {
});
}
expect: {
void (() => {
(() => {
var quux = () => {
console.log("PASS");
};
Expand All @@ -332,6 +333,7 @@ issue_2105_2: {
options = {
collapse_vars: true,
inline: true,
passes: 2,
reduce_vars: true,
side_effects: true,
unused: true,
Expand All @@ -357,7 +359,7 @@ issue_2105_2: {
});
}
expect: {
void (() => {
(() => {
var quux = () => {
console.log("PASS");
};
Expand Down
74 changes: 72 additions & 2 deletions test/compress/collapse_vars.js
Original file line number Diff line number Diff line change
Expand Up @@ -2077,10 +2077,10 @@ chained_3: {
}
expect: {
console.log(function(a, b) {
var c = a, c = b;
var c = 1, c = b;
b++;
return c;
}(1, 2));
}(0, 2));
}
expect_stdout: "2"
}
Expand Down Expand Up @@ -2330,3 +2330,73 @@ reassign_const_2: {
}
expect_stdout: true
}

issue_2187_1: {
options = {
collapse_vars: true,
unused: true,
}
input: {
var a = 1;
!function(foo) {
foo();
var a = 2;
console.log(a);
}(function() {
console.log(a);
});
}
expect: {
var a = 1;
!function(foo) {
foo();
var a = 2;
console.log(a);
}(function() {
console.log(a);
});
}
expect_stdout: [
"1",
"2",
]
}

issue_2187_2: {
options = {
collapse_vars: true,
unused: true,
}
input: {
var b = 1;
console.log(function(a) {
return a && ++b;
}(b--));
}
expect: {
var b = 1;
console.log(function(a) {
return b-- && ++b;
}());
}
expect_stdout: "1"
}

issue_2187_3: {
options = {
collapse_vars: true,
inline: true,
unused: true,
}
input: {
var b = 1;
console.log(function(a) {
return a && ++b;
}(b--));
}
expect: {
var b = 1;
console.log(b-- && ++b);
}
expect_stdout: "1"
}
Loading

0 comments on commit 33ad0d2

Please sign in to comment.