@@ -1101,10 +1101,10 @@ merge(Compressor.prototype, {
|
|||||||
stop_if_hit = parent;
|
stop_if_hit = parent;
|
||||||
}
|
}
|
||||||
// Replace variable with assignment when found
|
// Replace variable with assignment when found
|
||||||
var hit_lhs, hit_rhs;
|
var hit_rhs;
|
||||||
if (can_replace
|
if (can_replace
|
||||||
&& !(node instanceof AST_SymbolDeclaration)
|
&& !(node instanceof AST_SymbolDeclaration)
|
||||||
&& (scan_lhs && (hit_lhs = lhs.equivalent_to(node))
|
&& (scan_lhs && lhs.equivalent_to(node)
|
||||||
|| scan_rhs && (hit_rhs = scan_rhs(node, this)))) {
|
|| scan_rhs && (hit_rhs = scan_rhs(node, this)))) {
|
||||||
if (stop_if_hit && (hit_rhs || !lhs_local || !replace_all)) {
|
if (stop_if_hit && (hit_rhs || !lhs_local || !replace_all)) {
|
||||||
abort = true;
|
abort = true;
|
||||||
@@ -1194,10 +1194,9 @@ merge(Compressor.prototype, {
|
|||||||
var stop_after = null;
|
var stop_after = null;
|
||||||
var stop_if_hit = null;
|
var stop_if_hit = null;
|
||||||
var lhs = get_lhs(candidate);
|
var lhs = get_lhs(candidate);
|
||||||
var rhs = get_rhs(candidate);
|
|
||||||
var side_effects = lhs && lhs.has_side_effects(compressor);
|
var side_effects = lhs && lhs.has_side_effects(compressor);
|
||||||
var scan_lhs = lhs && !side_effects && !is_lhs_read_only(lhs);
|
var scan_lhs = lhs && !side_effects && !is_lhs_read_only(lhs);
|
||||||
var scan_rhs = rhs && foldable(rhs);
|
var scan_rhs = foldable(get_rhs(candidate));
|
||||||
if (!scan_lhs && !scan_rhs) continue;
|
if (!scan_lhs && !scan_rhs) continue;
|
||||||
// Locate symbols which may execute code outside of scanning range
|
// Locate symbols which may execute code outside of scanning range
|
||||||
var lvalues = get_lvalues(candidate);
|
var lvalues = get_lvalues(candidate);
|
||||||
@@ -1524,6 +1523,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function foldable(expr) {
|
function foldable(expr) {
|
||||||
|
if (!expr) return false;
|
||||||
if (expr instanceof AST_SymbolRef) {
|
if (expr instanceof AST_SymbolRef) {
|
||||||
var value = expr.evaluate(compressor);
|
var value = expr.evaluate(compressor);
|
||||||
if (value === expr) return rhs_exact_match;
|
if (value === expr) return rhs_exact_match;
|
||||||
@@ -1545,10 +1545,10 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
return !circular && rhs_exact_match;
|
return !circular && rhs_exact_match;
|
||||||
}
|
|
||||||
|
|
||||||
function rhs_exact_match(node) {
|
function rhs_exact_match(node) {
|
||||||
return rhs.equivalent_to(node);
|
return expr.equivalent_to(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function rhs_fuzzy_match(value, fallback) {
|
function rhs_fuzzy_match(value, fallback) {
|
||||||
@@ -4073,19 +4073,6 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Function, function(compressor) {
|
def(AST_Function, function(compressor) {
|
||||||
return this.name && compressor.option("ie8") ? this : null;
|
return this.name && compressor.option("ie8") ? this : null;
|
||||||
});
|
});
|
||||||
def(AST_Unary, function(compressor, first_in_statement) {
|
|
||||||
if (unary_side_effects[this.operator]) {
|
|
||||||
this.write_only = !this.expression.has_side_effects(compressor);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
if (this.operator == "typeof" && this.expression instanceof AST_SymbolRef) return null;
|
|
||||||
var expression = this.expression.drop_side_effect_free(compressor, first_in_statement);
|
|
||||||
if (first_in_statement && expression && is_iife_call(expression)) {
|
|
||||||
if (expression === this.expression && this.operator == "!") return this;
|
|
||||||
return expression.negate(compressor, first_in_statement);
|
|
||||||
}
|
|
||||||
return expression;
|
|
||||||
});
|
|
||||||
def(AST_Object, function(compressor, first_in_statement) {
|
def(AST_Object, function(compressor, first_in_statement) {
|
||||||
var values = trim(this.properties, compressor, first_in_statement);
|
var values = trim(this.properties, compressor, first_in_statement);
|
||||||
return values && make_sequence(this, values);
|
return values && make_sequence(this, values);
|
||||||
@@ -4110,9 +4097,27 @@ merge(Compressor.prototype, {
|
|||||||
return make_sequence(this, [ expression, property ]);
|
return make_sequence(this, [ expression, property ]);
|
||||||
});
|
});
|
||||||
def(AST_SymbolRef, function(compressor) {
|
def(AST_SymbolRef, function(compressor) {
|
||||||
return this.is_declared(compressor) ? null : this;
|
if (!this.is_declared(compressor)) return this;
|
||||||
|
this.definition().replaced++;
|
||||||
|
return null;
|
||||||
});
|
});
|
||||||
def(AST_This, return_null);
|
def(AST_This, return_null);
|
||||||
|
def(AST_Unary, function(compressor, first_in_statement) {
|
||||||
|
if (unary_side_effects[this.operator]) {
|
||||||
|
this.write_only = !this.expression.has_side_effects(compressor);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
if (this.operator == "typeof" && this.expression instanceof AST_SymbolRef) {
|
||||||
|
this.expression.definition().replaced++;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var expression = this.expression.drop_side_effect_free(compressor, first_in_statement);
|
||||||
|
if (first_in_statement && expression && is_iife_call(expression)) {
|
||||||
|
if (expression === this.expression && this.operator == "!") return this;
|
||||||
|
return expression.negate(compressor, first_in_statement);
|
||||||
|
}
|
||||||
|
return expression;
|
||||||
|
});
|
||||||
})(function(node, func) {
|
})(function(node, func) {
|
||||||
node.DEFMETHOD("drop_side_effect_free", func);
|
node.DEFMETHOD("drop_side_effect_free", func);
|
||||||
});
|
});
|
||||||
@@ -4607,9 +4612,7 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_Definitions, function(self, compressor) {
|
OPT(AST_Definitions, function(self, compressor) {
|
||||||
if (self.definitions.length == 0)
|
return self.definitions.length ? self : make_node(AST_EmptyStatement, self);
|
||||||
return make_node(AST_EmptyStatement, self);
|
|
||||||
return self;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Call.DEFMETHOD("lift_sequences", function(compressor) {
|
AST_Call.DEFMETHOD("lift_sequences", function(compressor) {
|
||||||
@@ -5855,6 +5858,7 @@ merge(Compressor.prototype, {
|
|||||||
value = fixed.optimize(compressor);
|
value = fixed.optimize(compressor);
|
||||||
if (value === fixed) value = fixed.clone(true);
|
if (value === fixed) value = fixed.clone(true);
|
||||||
}
|
}
|
||||||
|
def.replaced++;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
if (fixed && def.should_replace === undefined) {
|
if (fixed && def.should_replace === undefined) {
|
||||||
@@ -5897,7 +5901,9 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (def.should_replace) {
|
if (def.should_replace) {
|
||||||
return def.should_replace();
|
var value = def.should_replace();
|
||||||
|
def.replaced++;
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
var exec = require("child_process").exec;
|
var exec = require("child_process").exec;
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
|
var run_code = require("../sandbox").run_code;
|
||||||
|
|
||||||
function read(path) {
|
function read(path) {
|
||||||
return fs.readFileSync(path, "utf8");
|
return fs.readFileSync(path, "utf8");
|
||||||
@@ -714,4 +715,32 @@ describe("bin/uglifyjs", function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Should compress swarm of unused variables with reasonable performance", function(done) {
|
||||||
|
var code = [
|
||||||
|
"console.log(function() {",
|
||||||
|
];
|
||||||
|
for (var i = 0; i < 10000; i++) {
|
||||||
|
code.push("var obj" + i + " = {p: " + i + "};");
|
||||||
|
}
|
||||||
|
code.push("var map = {");
|
||||||
|
for (var i = 0; i < 10000; i++) {
|
||||||
|
code.push("obj" + i + ": obj" + i + ",");
|
||||||
|
}
|
||||||
|
code = code.concat([
|
||||||
|
"};",
|
||||||
|
"return obj25.p + obj121.p + obj1024.p;",
|
||||||
|
"}());",
|
||||||
|
]).join("\n");
|
||||||
|
exec(uglifyjscmd + " -mc", function(err, stdout) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(stdout, [
|
||||||
|
"console.log(function(){",
|
||||||
|
"var p={p:25},n={p:121},o={p:1024};",
|
||||||
|
"return p.p+n.p+o.p",
|
||||||
|
"}());\n",
|
||||||
|
].join(""));
|
||||||
|
assert.strictEqual(run_code(stdout), run_code(code));
|
||||||
|
done();
|
||||||
|
}).stdin.end(code);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user