enforce toplevel on other compress options (#1855)
Respect "funcs" and "vars" properly. fixes #1850
This commit is contained in:
@@ -109,6 +109,14 @@ function Compressor(options, false_by_default) {
|
|||||||
return top_retain.indexOf(def.name) >= 0;
|
return top_retain.indexOf(def.name) >= 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
var toplevel = this.options["toplevel"];
|
||||||
|
if (typeof toplevel == "string") {
|
||||||
|
this.toplevel.funcs = /funcs/.test(toplevel);
|
||||||
|
this.toplevel.vars = /vars/.test(toplevel);
|
||||||
|
} else {
|
||||||
|
this.toplevel = toplevel ? return_true : return_false;
|
||||||
|
this.toplevel.funcs = this.toplevel.vars = toplevel;
|
||||||
|
}
|
||||||
var sequences = this.options["sequences"];
|
var sequences = this.options["sequences"];
|
||||||
this.sequences_limit = sequences == 1 ? 800 : sequences | 0;
|
this.sequences_limit = sequences == 1 ? 800 : sequences | 0;
|
||||||
this.warnings_produced = {};
|
this.warnings_produced = {};
|
||||||
@@ -117,6 +125,12 @@ function Compressor(options, false_by_default) {
|
|||||||
Compressor.prototype = new TreeTransformer;
|
Compressor.prototype = new TreeTransformer;
|
||||||
merge(Compressor.prototype, {
|
merge(Compressor.prototype, {
|
||||||
option: function(key) { return this.options[key] },
|
option: function(key) { return this.options[key] },
|
||||||
|
toplevel: function(def) {
|
||||||
|
for (var i = 0, len = def.orig.length; i < len; i++)
|
||||||
|
if (!this.toplevel[def.orig[i] instanceof AST_SymbolDefun ? "funcs" : "vars"])
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
compress: function(node) {
|
compress: function(node) {
|
||||||
if (this.option("expression")) {
|
if (this.option("expression")) {
|
||||||
node.process_expression(true);
|
node.process_expression(true);
|
||||||
@@ -249,7 +263,6 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
AST_Node.DEFMETHOD("reset_opt_flags", function(compressor, rescan) {
|
AST_Node.DEFMETHOD("reset_opt_flags", function(compressor, rescan) {
|
||||||
var reduce_vars = rescan && compressor.option("reduce_vars");
|
var reduce_vars = rescan && compressor.option("reduce_vars");
|
||||||
var toplevel = compressor.option("toplevel");
|
|
||||||
var safe_ids = Object.create(null);
|
var safe_ids = Object.create(null);
|
||||||
var suppressor = new TreeWalker(function(node) {
|
var suppressor = new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_Symbol) {
|
if (node instanceof AST_Symbol) {
|
||||||
@@ -310,7 +323,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (node instanceof AST_Defun) {
|
if (node instanceof AST_Defun) {
|
||||||
var d = node.name.definition();
|
var d = node.name.definition();
|
||||||
if (!toplevel && d.global || safe_to_read(d)) {
|
if (d.global && !compressor.toplevel(d) || safe_to_read(d)) {
|
||||||
d.fixed = false;
|
d.fixed = false;
|
||||||
} else {
|
} else {
|
||||||
d.fixed = node;
|
d.fixed = node;
|
||||||
@@ -469,7 +482,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function reset_def(def) {
|
function reset_def(def) {
|
||||||
if (toplevel || !def.global || def.orig[0] instanceof AST_SymbolConst) {
|
if (!def.global || def.orig[0] instanceof AST_SymbolConst || compressor.toplevel(def)) {
|
||||||
def.fixed = undefined;
|
def.fixed = undefined;
|
||||||
} else {
|
} else {
|
||||||
def.fixed = false;
|
def.fixed = false;
|
||||||
@@ -643,7 +656,6 @@ merge(Compressor.prototype, {
|
|||||||
// in the statement with the var value and then erase the var definition.
|
// in the statement with the var value and then erase the var definition.
|
||||||
|
|
||||||
var scope = compressor.find_parent(AST_Scope);
|
var scope = compressor.find_parent(AST_Scope);
|
||||||
var toplevel = compressor.option("toplevel");
|
|
||||||
var stat_index;
|
var stat_index;
|
||||||
var prev_stat_index;
|
var prev_stat_index;
|
||||||
var def_stat_index;
|
var def_stat_index;
|
||||||
@@ -694,7 +706,8 @@ merge(Compressor.prototype, {
|
|||||||
// Only interested in cases with just one reference to the variable.
|
// Only interested in cases with just one reference to the variable.
|
||||||
var def = var_decl.name.definition();
|
var def = var_decl.name.definition();
|
||||||
if (def.references.length !== 1
|
if (def.references.length !== 1
|
||||||
|| var_name == "arguments" || (!toplevel && def.global)) {
|
|| var_name == "arguments"
|
||||||
|
|| def.global && !compressor.toplevel(def)) {
|
||||||
side_effects_encountered = true;
|
side_effects_encountered = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1825,19 +1838,14 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("drop_unused", function(compressor){
|
AST_Scope.DEFMETHOD("drop_unused", function(compressor){
|
||||||
|
if (!compressor.option("unused")) return;
|
||||||
|
if (compressor.has_directive("use asm")) return;
|
||||||
var self = this;
|
var self = this;
|
||||||
if (compressor.has_directive("use asm")) return self;
|
if (self.uses_eval || self.uses_with) return;
|
||||||
var toplevel = compressor.option("toplevel");
|
var drop_funcs = !(self instanceof AST_Toplevel) || compressor.toplevel.funcs;
|
||||||
if (compressor.option("unused")
|
var drop_vars = !(self instanceof AST_Toplevel) || compressor.toplevel.vars;
|
||||||
&& (!(self instanceof AST_Toplevel) || toplevel)
|
if (!drop_funcs && !drop_vars) return;
|
||||||
&& !self.uses_eval
|
|
||||||
&& !self.uses_with) {
|
|
||||||
var assign_as_unused = !/keep_assign/.test(compressor.option("unused"));
|
var assign_as_unused = !/keep_assign/.test(compressor.option("unused"));
|
||||||
var drop_funcs = /funcs/.test(toplevel);
|
|
||||||
var drop_vars = /vars/.test(toplevel);
|
|
||||||
if (!(self instanceof AST_Toplevel) || toplevel == true) {
|
|
||||||
drop_funcs = drop_vars = true;
|
|
||||||
}
|
|
||||||
var in_use = [];
|
var in_use = [];
|
||||||
var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use
|
var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use
|
||||||
if (self instanceof AST_Toplevel && compressor.top_retain) {
|
if (self instanceof AST_Toplevel && compressor.top_retain) {
|
||||||
@@ -2107,7 +2115,6 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
self.transform(tt);
|
self.transform(tt);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){
|
AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){
|
||||||
@@ -3683,7 +3690,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
var name = d.name.length;
|
var name = d.name.length;
|
||||||
var overhead = 0;
|
var overhead = 0;
|
||||||
if (compressor.option("unused") && (!d.global || compressor.option("toplevel"))) {
|
if (compressor.option("unused") && (!d.global || compressor.toplevel(d))) {
|
||||||
overhead = (name + 2 + value) / d.references.length;
|
overhead = (name + 2 + value) / d.references.length;
|
||||||
}
|
}
|
||||||
d.should_replace = value <= name + overhead ? fn : false;
|
d.should_replace = value <= name + overhead ? fn : false;
|
||||||
|
|||||||
@@ -2327,3 +2327,93 @@ iife_assign: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_1850_1: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: false,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
console.log(a, a, a);
|
||||||
|
}
|
||||||
|
var a = 1;
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
console.log(a, a, a);
|
||||||
|
}
|
||||||
|
var a = 1;
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1850_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: "funcs",
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
console.log(a, a, a);
|
||||||
|
}
|
||||||
|
var a = 1;
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
(function() {
|
||||||
|
console.log(a, a, a);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1850_3: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: "vars",
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
console.log(a, a, a);
|
||||||
|
}
|
||||||
|
var a = 1;
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
console.log(a, a, a);
|
||||||
|
}
|
||||||
|
var a = 1;
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1850_4: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
console.log(a, a, a);
|
||||||
|
}
|
||||||
|
var a = 1;
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
(function() {
|
||||||
|
console.log(a, a, a);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user