Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f83adcc995 | ||
|
|
df8a99439a | ||
|
|
6b91d12ec3 | ||
|
|
f37b91879f | ||
|
|
d835c72c80 | ||
|
|
c4cebb4b01 | ||
|
|
d51a00a450 | ||
|
|
fc0f168a0c | ||
|
|
a0ca595c2c | ||
|
|
1a314e9f60 |
@@ -544,11 +544,10 @@ var AST_Call = DEFNODE("Call", "expression args", {
|
|||||||
},
|
},
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function() {
|
return visitor._visit(this, function() {
|
||||||
var args = this.args;
|
|
||||||
for (var i = 0, len = args.length; i < len; i++) {
|
|
||||||
args[i]._walk(visitor);
|
|
||||||
}
|
|
||||||
this.expression._walk(visitor);
|
this.expression._walk(visitor);
|
||||||
|
this.args.forEach(function(node) {
|
||||||
|
node._walk(visitor);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
177
lib/compress.js
177
lib/compress.js
@@ -343,7 +343,7 @@ merge(Compressor.prototype, {
|
|||||||
(function(def) {
|
(function(def) {
|
||||||
def(AST_Node, noop);
|
def(AST_Node, noop);
|
||||||
|
|
||||||
function reset_def(compressor, def) {
|
function reset_def(tw, compressor, def) {
|
||||||
def.assignments = 0;
|
def.assignments = 0;
|
||||||
def.chained = false;
|
def.chained = false;
|
||||||
def.direct_access = false;
|
def.direct_access = false;
|
||||||
@@ -355,15 +355,23 @@ merge(Compressor.prototype, {
|
|||||||
} else {
|
} else {
|
||||||
def.fixed = false;
|
def.fixed = false;
|
||||||
}
|
}
|
||||||
|
if (def.init instanceof AST_Defun && !all(def.references, function(ref) {
|
||||||
|
var scope = ref.scope;
|
||||||
|
do {
|
||||||
|
if (def.scope === scope) return true;
|
||||||
|
} while (scope instanceof AST_Function && (scope = scope.parent_scope));
|
||||||
|
})) {
|
||||||
|
tw.defun_ids[def.id] = undefined;
|
||||||
|
}
|
||||||
def.recursive_refs = 0;
|
def.recursive_refs = 0;
|
||||||
def.references = [];
|
def.references = [];
|
||||||
def.should_replace = undefined;
|
def.should_replace = undefined;
|
||||||
def.single_use = undefined;
|
def.single_use = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function reset_variables(tw, compressor, node) {
|
function reset_variables(tw, compressor, scope) {
|
||||||
node.variables.each(function(def) {
|
scope.variables.each(function(def) {
|
||||||
reset_def(compressor, def);
|
reset_def(tw, compressor, def);
|
||||||
if (def.fixed === null) {
|
if (def.fixed === null) {
|
||||||
def.safe_ids = tw.safe_ids;
|
def.safe_ids = tw.safe_ids;
|
||||||
mark(tw, def, true);
|
mark(tw, def, true);
|
||||||
@@ -374,6 +382,33 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mark_defun(tw, def) {
|
||||||
|
if (def.id in tw.defun_ids) {
|
||||||
|
var marker = tw.defun_ids[def.id];
|
||||||
|
if (!marker) return;
|
||||||
|
if (marker !== tw.safe_ids) {
|
||||||
|
tw.defun_ids[def.id] = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return def.fixed;
|
||||||
|
}
|
||||||
|
if (!tw.in_loop) {
|
||||||
|
tw.defun_ids[def.id] = tw.safe_ids;
|
||||||
|
return def.fixed;
|
||||||
|
} else if (tw.defun_ids[def.id] !== false) {
|
||||||
|
tw.defun_ids[def.id] = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function walk_defuns(tw, scope) {
|
||||||
|
scope.functions.each(function(def) {
|
||||||
|
if (def.init instanceof AST_Defun && tw.defun_ids[def.id] === undefined) {
|
||||||
|
tw.defun_ids[def.id] = tw.safe_ids;
|
||||||
|
def.init.walk(tw);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function push(tw) {
|
function push(tw) {
|
||||||
tw.safe_ids = Object.create(tw.safe_ids);
|
tw.safe_ids = Object.create(tw.safe_ids);
|
||||||
}
|
}
|
||||||
@@ -398,7 +433,7 @@ merge(Compressor.prototype, {
|
|||||||
return def.fixed instanceof AST_Defun;
|
return def.fixed instanceof AST_Defun;
|
||||||
}
|
}
|
||||||
|
|
||||||
function safe_to_assign(tw, def, value) {
|
function safe_to_assign(tw, def, scope, value) {
|
||||||
if (def.fixed === undefined) return true;
|
if (def.fixed === undefined) return true;
|
||||||
if (def.fixed === null && def.safe_ids) {
|
if (def.fixed === null && def.safe_ids) {
|
||||||
def.safe_ids[def.id] = false;
|
def.safe_ids[def.id] = false;
|
||||||
@@ -409,6 +444,9 @@ merge(Compressor.prototype, {
|
|||||||
if (!safe_to_read(tw, def)) return false;
|
if (!safe_to_read(tw, def)) return false;
|
||||||
if (def.fixed === false) return false;
|
if (def.fixed === false) return false;
|
||||||
if (def.fixed != null && (!value || def.references.length > def.assignments)) return false;
|
if (def.fixed != null && (!value || def.references.length > def.assignments)) return false;
|
||||||
|
if (def.fixed instanceof AST_Defun) {
|
||||||
|
return value instanceof AST_Node && def.fixed.parent_scope === scope;
|
||||||
|
}
|
||||||
return all(def.orig, function(sym) {
|
return all(def.orig, function(sym) {
|
||||||
return !(sym instanceof AST_SymbolDefun
|
return !(sym instanceof AST_SymbolDefun
|
||||||
|| sym instanceof AST_SymbolLambda);
|
|| sym instanceof AST_SymbolLambda);
|
||||||
@@ -453,7 +491,10 @@ merge(Compressor.prototype, {
|
|||||||
mark_escaped(tw, d, scope, parent, value, level + 1, depth + 1);
|
mark_escaped(tw, d, scope, parent, value, level + 1, depth + 1);
|
||||||
if (value) return;
|
if (value) return;
|
||||||
}
|
}
|
||||||
if (level == 0) d.direct_access = true;
|
if (level > 0) return;
|
||||||
|
if (parent instanceof AST_Sequence && node !== parent.tail_node()) return;
|
||||||
|
if (parent instanceof AST_SimpleStatement) return;
|
||||||
|
d.direct_access = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var suppressor = new TreeWalker(function(node) {
|
var suppressor = new TreeWalker(function(node) {
|
||||||
@@ -468,19 +509,24 @@ merge(Compressor.prototype, {
|
|||||||
reset_variables(tw, compressor, this);
|
reset_variables(tw, compressor, this);
|
||||||
descend();
|
descend();
|
||||||
pop(tw);
|
pop(tw);
|
||||||
|
walk_defuns(tw, this);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
def(AST_Assign, function(tw) {
|
def(AST_Assign, function(tw, descend, compressor) {
|
||||||
var node = this;
|
var node = this;
|
||||||
if (!(node.left instanceof AST_SymbolRef)) return;
|
var sym = node.left;
|
||||||
var d = node.left.definition();
|
if (!(sym instanceof AST_SymbolRef)) return;
|
||||||
|
var d = sym.definition();
|
||||||
var fixed = d.fixed;
|
var fixed = d.fixed;
|
||||||
if (!fixed && node.operator != "=") return;
|
if (!fixed && node.operator != "=") return;
|
||||||
if (!safe_to_assign(tw, d, node.right)) return;
|
if (!safe_to_assign(tw, d, sym.scope, node.right)) return;
|
||||||
d.references.push(node.left);
|
var eq = node.operator == "=";
|
||||||
|
var value = eq ? node.right : node;
|
||||||
|
if (is_modified(compressor, tw, node, value, 0)) return;
|
||||||
|
d.references.push(sym);
|
||||||
d.assignments++;
|
d.assignments++;
|
||||||
if (node.operator != "=") d.chained = true;
|
if (!eq) d.chained = true;
|
||||||
d.fixed = node.operator == "=" ? function() {
|
d.fixed = eq ? function() {
|
||||||
return node.right;
|
return node.right;
|
||||||
} : function() {
|
} : function() {
|
||||||
return make_node(AST_Binary, node, {
|
return make_node(AST_Binary, node, {
|
||||||
@@ -492,6 +538,7 @@ merge(Compressor.prototype, {
|
|||||||
mark(tw, d, false);
|
mark(tw, d, false);
|
||||||
node.right.walk(tw);
|
node.right.walk(tw);
|
||||||
mark(tw, d, true);
|
mark(tw, d, true);
|
||||||
|
mark_escaped(tw, d, sym.scope, node, value, 0, 1);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
def(AST_Binary, function(tw) {
|
def(AST_Binary, function(tw) {
|
||||||
@@ -502,6 +549,17 @@ merge(Compressor.prototype, {
|
|||||||
pop(tw);
|
pop(tw);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
def(AST_Call, function(tw, descend) {
|
||||||
|
var exp = this.expression;
|
||||||
|
if (!(exp instanceof AST_SymbolRef)) return;
|
||||||
|
var def = exp.definition();
|
||||||
|
if (!(def.fixed instanceof AST_Defun)) return;
|
||||||
|
var defun = mark_defun(tw, def);
|
||||||
|
if (!defun) return;
|
||||||
|
descend();
|
||||||
|
defun.walk(tw);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
def(AST_Case, function(tw) {
|
def(AST_Case, function(tw) {
|
||||||
push(tw);
|
push(tw);
|
||||||
this.expression.walk(tw);
|
this.expression.walk(tw);
|
||||||
@@ -528,12 +586,15 @@ merge(Compressor.prototype, {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
def(AST_Defun, function(tw, descend, compressor) {
|
def(AST_Defun, function(tw, descend, compressor) {
|
||||||
|
var id = this.name.definition().id;
|
||||||
|
if (tw.defun_ids[id] !== tw.safe_ids) return true;
|
||||||
|
tw.defun_ids[id] = false;
|
||||||
this.inlined = false;
|
this.inlined = false;
|
||||||
var save_ids = tw.safe_ids;
|
push(tw);
|
||||||
tw.safe_ids = Object.create(null);
|
|
||||||
reset_variables(tw, compressor, this);
|
reset_variables(tw, compressor, this);
|
||||||
descend();
|
descend();
|
||||||
tw.safe_ids = save_ids;
|
pop(tw);
|
||||||
|
walk_defuns(tw, this);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
def(AST_Do, function(tw) {
|
def(AST_Do, function(tw) {
|
||||||
@@ -606,6 +667,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
descend();
|
descend();
|
||||||
pop(tw);
|
pop(tw);
|
||||||
|
walk_defuns(tw, node);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
def(AST_If, function(tw) {
|
def(AST_If, function(tw) {
|
||||||
@@ -659,12 +721,23 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mark_escaped(tw, d, this.scope, this, value, 0, 1);
|
mark_escaped(tw, d, this.scope, this, value, 0, 1);
|
||||||
|
var parent;
|
||||||
|
if (d.fixed instanceof AST_Defun
|
||||||
|
&& !((parent = tw.parent()) instanceof AST_Call && parent.expression === this)) {
|
||||||
|
var defun = mark_defun(tw, d);
|
||||||
|
if (defun) defun.walk(tw);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
def(AST_Toplevel, function(tw, descend, compressor) {
|
def(AST_Toplevel, function(tw, descend, compressor) {
|
||||||
this.globals.each(function(def) {
|
this.globals.each(function(def) {
|
||||||
reset_def(compressor, def);
|
reset_def(tw, compressor, def);
|
||||||
});
|
});
|
||||||
|
push(tw);
|
||||||
reset_variables(tw, compressor, this);
|
reset_variables(tw, compressor, this);
|
||||||
|
descend();
|
||||||
|
pop(tw);
|
||||||
|
walk_defuns(tw, this);
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
def(AST_Try, function(tw) {
|
def(AST_Try, function(tw) {
|
||||||
push(tw);
|
push(tw);
|
||||||
@@ -681,12 +754,13 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Unary, function(tw, descend) {
|
def(AST_Unary, function(tw, descend) {
|
||||||
var node = this;
|
var node = this;
|
||||||
if (node.operator != "++" && node.operator != "--") return;
|
if (node.operator != "++" && node.operator != "--") return;
|
||||||
if (!(node.expression instanceof AST_SymbolRef)) return;
|
var exp = node.expression;
|
||||||
var d = node.expression.definition();
|
if (!(exp instanceof AST_SymbolRef)) return;
|
||||||
|
var d = exp.definition();
|
||||||
var fixed = d.fixed;
|
var fixed = d.fixed;
|
||||||
if (!fixed) return;
|
if (!fixed) return;
|
||||||
if (!safe_to_assign(tw, d, true)) return;
|
if (!safe_to_assign(tw, d, exp.scope, true)) return;
|
||||||
d.references.push(node.expression);
|
d.references.push(exp);
|
||||||
d.assignments++;
|
d.assignments++;
|
||||||
d.chained = true;
|
d.chained = true;
|
||||||
d.fixed = function() {
|
d.fixed = function() {
|
||||||
@@ -708,7 +782,7 @@ merge(Compressor.prototype, {
|
|||||||
var node = this;
|
var node = this;
|
||||||
var d = node.name.definition();
|
var d = node.name.definition();
|
||||||
if (node.value) {
|
if (node.value) {
|
||||||
if (safe_to_assign(tw, d, node.value)) {
|
if (safe_to_assign(tw, d, node.name.scope, node.value)) {
|
||||||
d.fixed = function() {
|
d.fixed = function() {
|
||||||
return node.value;
|
return node.value;
|
||||||
};
|
};
|
||||||
@@ -736,19 +810,24 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("reset_opt_flags", function(compressor) {
|
AST_Toplevel.DEFMETHOD("reset_opt_flags", function(compressor) {
|
||||||
var reduce_vars = compressor.option("reduce_vars");
|
var tw = new TreeWalker(compressor.option("reduce_vars") ? function(node, descend) {
|
||||||
var tw = new TreeWalker(function(node, descend) {
|
node._squeezed = false;
|
||||||
|
node._optimized = false;
|
||||||
|
return node.reduce_vars(tw, descend, compressor);
|
||||||
|
} : function(node) {
|
||||||
node._squeezed = false;
|
node._squeezed = false;
|
||||||
node._optimized = false;
|
node._optimized = false;
|
||||||
if (reduce_vars) return node.reduce_vars(tw, descend, compressor);
|
|
||||||
});
|
});
|
||||||
|
// Flow control for visiting `AST_Defun`s
|
||||||
|
tw.defun_ids = Object.create(null);
|
||||||
|
// Record the loop body in which `AST_SymbolDeclaration` is first encountered
|
||||||
|
tw.in_loop = null;
|
||||||
|
tw.loop_ids = Object.create(null);
|
||||||
// Stack of look-up tables to keep track of whether a `SymbolDef` has been
|
// Stack of look-up tables to keep track of whether a `SymbolDef` has been
|
||||||
// properly assigned before use:
|
// properly assigned before use:
|
||||||
// - `push()` & `pop()` when visiting conditional branches
|
// - `push()` & `pop()` when visiting conditional branches
|
||||||
// - backup & restore via `save_ids` when visiting out-of-order sections
|
// - backup & restore via `save_ids` when visiting out-of-order sections
|
||||||
tw.safe_ids = Object.create(null);
|
tw.safe_ids = Object.create(null);
|
||||||
tw.in_loop = null;
|
|
||||||
tw.loop_ids = Object.create(null);
|
|
||||||
this.walk(tw);
|
this.walk(tw);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -847,7 +926,7 @@ merge(Compressor.prototype, {
|
|||||||
// the func (becomes lexical instead of global).
|
// the func (becomes lexical instead of global).
|
||||||
function maintain_this_binding(parent, orig, val) {
|
function maintain_this_binding(parent, orig, val) {
|
||||||
if (parent instanceof AST_UnaryPrefix && parent.operator == "delete"
|
if (parent instanceof AST_UnaryPrefix && parent.operator == "delete"
|
||||||
|| parent instanceof AST_Call && parent.expression === orig
|
|| parent.TYPE == "Call" && parent.expression === orig
|
||||||
&& (val instanceof AST_PropAccess || val instanceof AST_SymbolRef && val.name == "eval")) {
|
&& (val instanceof AST_PropAccess || val instanceof AST_SymbolRef && val.name == "eval")) {
|
||||||
return make_sequence(orig, [ make_node(AST_Number, orig, { value: 0 }), val ]);
|
return make_sequence(orig, [ make_node(AST_Number, orig, { value: 0 }), val ]);
|
||||||
}
|
}
|
||||||
@@ -1001,9 +1080,11 @@ merge(Compressor.prototype, {
|
|||||||
if (is_lhs(node, parent)) {
|
if (is_lhs(node, parent)) {
|
||||||
if (value_def) replaced++;
|
if (value_def) replaced++;
|
||||||
return node;
|
return node;
|
||||||
|
} else {
|
||||||
|
replaced++;
|
||||||
|
if (value_def && candidate instanceof AST_VarDef) return node;
|
||||||
}
|
}
|
||||||
CHANGED = abort = true;
|
CHANGED = abort = true;
|
||||||
replaced++;
|
|
||||||
compressor.info("Collapsing {name} [{file}:{line},{col}]", {
|
compressor.info("Collapsing {name} [{file}:{line},{col}]", {
|
||||||
name: node.print_to_string(),
|
name: node.print_to_string(),
|
||||||
file: node.start.file,
|
file: node.start.file,
|
||||||
@@ -1014,10 +1095,6 @@ merge(Compressor.prototype, {
|
|||||||
return make_node(AST_UnaryPrefix, candidate, candidate);
|
return make_node(AST_UnaryPrefix, candidate, candidate);
|
||||||
}
|
}
|
||||||
if (candidate instanceof AST_VarDef) {
|
if (candidate instanceof AST_VarDef) {
|
||||||
if (value_def) {
|
|
||||||
abort = false;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
var def = candidate.name.definition();
|
var def = candidate.name.definition();
|
||||||
if (def.references.length - def.replaced == 1 && !compressor.exposed(def)) {
|
if (def.references.length - def.replaced == 1 && !compressor.exposed(def)) {
|
||||||
def.replaced++;
|
def.replaced++;
|
||||||
@@ -1062,7 +1139,7 @@ merge(Compressor.prototype, {
|
|||||||
if (is_lhs(node, multi_replacer.parent())) return node;
|
if (is_lhs(node, multi_replacer.parent())) return node;
|
||||||
def.replaced++;
|
def.replaced++;
|
||||||
value_def.replaced--;
|
value_def.replaced--;
|
||||||
return candidate.value;
|
return candidate.value.clone();
|
||||||
}
|
}
|
||||||
// Skip (non-executed) functions and (leading) default case in switch statements
|
// Skip (non-executed) functions and (leading) default case in switch statements
|
||||||
if (node instanceof AST_Default || node instanceof AST_Scope) return node;
|
if (node instanceof AST_Default || node instanceof AST_Scope) return node;
|
||||||
@@ -4395,7 +4472,24 @@ merge(Compressor.prototype, {
|
|||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
AST_Call.DEFMETHOD("lift_sequences", function(compressor) {
|
||||||
|
if (!compressor.option("sequences")) return this;
|
||||||
|
var exp = this.expression;
|
||||||
|
if (!(exp instanceof AST_Sequence)) return this;
|
||||||
|
var tail = exp.tail_node();
|
||||||
|
if (tail instanceof AST_PropAccess && !(this instanceof AST_New)) return this;
|
||||||
|
var expressions = exp.expressions.slice(0, -1);
|
||||||
|
var node = this.clone();
|
||||||
|
node.expression = tail;
|
||||||
|
expressions.push(node);
|
||||||
|
return make_sequence(this, expressions).optimize(compressor);
|
||||||
|
});
|
||||||
|
|
||||||
OPT(AST_Call, function(self, compressor) {
|
OPT(AST_Call, function(self, compressor) {
|
||||||
|
var seq = self.lift_sequences(compressor);
|
||||||
|
if (seq !== self) {
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
var exp = self.expression;
|
var exp = self.expression;
|
||||||
var fn = exp;
|
var fn = exp;
|
||||||
if (compressor.option("reduce_vars") && fn instanceof AST_SymbolRef) {
|
if (compressor.option("reduce_vars") && fn instanceof AST_SymbolRef) {
|
||||||
@@ -4596,13 +4690,16 @@ merge(Compressor.prototype, {
|
|||||||
func = func.fixed_value();
|
func = func.fixed_value();
|
||||||
}
|
}
|
||||||
if (func instanceof AST_Lambda && !func.contains_this()) {
|
if (func instanceof AST_Lambda && !func.contains_this()) {
|
||||||
return make_sequence(this, [
|
return (self.args.length ? make_sequence(this, [
|
||||||
self.args[0],
|
self.args[0],
|
||||||
make_node(AST_Call, self, {
|
make_node(AST_Call, self, {
|
||||||
expression: exp.expression,
|
expression: exp.expression,
|
||||||
args: self.args.slice(1)
|
args: self.args.slice(1)
|
||||||
})
|
})
|
||||||
]).optimize(compressor);
|
]) : make_node(AST_Call, self, {
|
||||||
|
expression: exp.expression,
|
||||||
|
args: []
|
||||||
|
})).optimize(compressor);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -4904,6 +5001,10 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_New, function(self, compressor) {
|
OPT(AST_New, function(self, compressor) {
|
||||||
|
var seq = self.lift_sequences(compressor);
|
||||||
|
if (seq !== self) {
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
if (compressor.option("unsafe")) {
|
if (compressor.option("unsafe")) {
|
||||||
var exp = self.expression;
|
var exp = self.expression;
|
||||||
if (is_undeclared_ref(exp)) {
|
if (is_undeclared_ref(exp)) {
|
||||||
@@ -4959,15 +5060,13 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
AST_Unary.DEFMETHOD("lift_sequences", function(compressor){
|
AST_Unary.DEFMETHOD("lift_sequences", function(compressor){
|
||||||
if (compressor.option("sequences")) {
|
if (compressor.option("sequences") && this.expression instanceof AST_Sequence) {
|
||||||
if (this.expression instanceof AST_Sequence) {
|
|
||||||
var x = this.expression.expressions.slice();
|
var x = this.expression.expressions.slice();
|
||||||
var e = this.clone();
|
var e = this.clone();
|
||||||
e.expression = x.pop();
|
e.expression = x.pop();
|
||||||
x.push(e);
|
x.push(e);
|
||||||
return make_sequence(this, x).optimize(compressor);
|
return make_sequence(this, x).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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.23",
|
"version": "3.3.24",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4056,6 +4056,36 @@ replace_all_var: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
replace_all_var_scope: {
|
||||||
|
rename = true;
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
(function(r, a) {
|
||||||
|
switch (~a) {
|
||||||
|
case (b += a):
|
||||||
|
case a++:
|
||||||
|
}
|
||||||
|
})(--b, a);
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
(function(c, o) {
|
||||||
|
switch (~a) {
|
||||||
|
case (b += a):
|
||||||
|
case o++:
|
||||||
|
}
|
||||||
|
})(--b, a);
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "100 109"
|
||||||
|
}
|
||||||
|
|
||||||
cascade_statement: {
|
cascade_statement: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
|||||||
@@ -2303,3 +2303,19 @@ issue_3076: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3125: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
return "PASS";
|
||||||
|
}.call());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1476,18 +1476,18 @@ defun_redefine: {
|
|||||||
};
|
};
|
||||||
return g() + h();
|
return g() + h();
|
||||||
}
|
}
|
||||||
|
console.log(f());
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f() {
|
function f() {
|
||||||
function g() {
|
(function() {
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
g = function() {
|
|
||||||
return 3;
|
return 3;
|
||||||
};
|
});
|
||||||
return g() + 2;
|
return 3 + 2;
|
||||||
}
|
}
|
||||||
|
console.log(f());
|
||||||
}
|
}
|
||||||
|
expect_stdout: "5"
|
||||||
}
|
}
|
||||||
|
|
||||||
func_inline: {
|
func_inline: {
|
||||||
@@ -1527,23 +1527,37 @@ func_modified: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f(a) {
|
function f(a) {
|
||||||
function a() { return 1; }
|
function a() {
|
||||||
function b() { return 2; }
|
return 1;
|
||||||
function c() { return 3; }
|
}
|
||||||
|
function b() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
function c() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
b.inject = [];
|
b.inject = [];
|
||||||
c = function() { return 4; };
|
c = function() {
|
||||||
|
return 4;
|
||||||
|
};
|
||||||
return a() + b() + c();
|
return a() + b() + c();
|
||||||
}
|
}
|
||||||
|
console.log(f());
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f(a) {
|
function f(a) {
|
||||||
function b() { return 2; }
|
function b() {
|
||||||
function c() { return 3; }
|
return 2;
|
||||||
|
}
|
||||||
b.inject = [];
|
b.inject = [];
|
||||||
c = function() { return 4; };
|
(function() {
|
||||||
return 1 + 2 + c();
|
return 4;
|
||||||
|
});
|
||||||
|
return 1 + 2 + 4;
|
||||||
}
|
}
|
||||||
|
console.log(f());
|
||||||
}
|
}
|
||||||
|
expect_stdout: "7"
|
||||||
}
|
}
|
||||||
|
|
||||||
defun_label: {
|
defun_label: {
|
||||||
@@ -5054,9 +5068,7 @@ defun_var_1: {
|
|||||||
console.log(typeof a, typeof b);
|
console.log(typeof a, typeof b);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = 42;
|
console.log("number", "function");
|
||||||
function a() {}
|
|
||||||
console.log(typeof a, "function");
|
|
||||||
}
|
}
|
||||||
expect_stdout: "number function"
|
expect_stdout: "number function"
|
||||||
}
|
}
|
||||||
@@ -5076,9 +5088,7 @@ defun_var_2: {
|
|||||||
console.log(typeof a, typeof b);
|
console.log(typeof a, typeof b);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function a() {}
|
console.log("number", "function");
|
||||||
var a = 42;
|
|
||||||
console.log(typeof a, "function");
|
|
||||||
}
|
}
|
||||||
expect_stdout: "number function"
|
expect_stdout: "number function"
|
||||||
}
|
}
|
||||||
@@ -5710,3 +5720,429 @@ issue_3068_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3110_1: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 3,
|
||||||
|
properties: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
function foo() {
|
||||||
|
return isDev ? "foo" : "bar";
|
||||||
|
}
|
||||||
|
var isDev = true;
|
||||||
|
var obj = {
|
||||||
|
foo: foo
|
||||||
|
};
|
||||||
|
console.log(foo());
|
||||||
|
console.log(obj.foo());
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("foo"),
|
||||||
|
console.log("foo");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"foo",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3110_2: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 4,
|
||||||
|
properties: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
function foo() {
|
||||||
|
return isDev ? "foo" : "bar";
|
||||||
|
}
|
||||||
|
var isDev = true;
|
||||||
|
console.log(foo());
|
||||||
|
var obj = {
|
||||||
|
foo: foo
|
||||||
|
};
|
||||||
|
console.log(obj.foo());
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("foo"),
|
||||||
|
console.log("foo");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"foo",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3110_3: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
properties: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
function foo() {
|
||||||
|
return isDev ? "foo" : "bar";
|
||||||
|
}
|
||||||
|
console.log(foo());
|
||||||
|
var isDev = true;
|
||||||
|
var obj = {
|
||||||
|
foo: foo
|
||||||
|
};
|
||||||
|
console.log(obj.foo());
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
function foo() {
|
||||||
|
return isDev ? "foo" : "bar";
|
||||||
|
}
|
||||||
|
console.log(foo());
|
||||||
|
var isDev = true;
|
||||||
|
var obj = {
|
||||||
|
foo: foo
|
||||||
|
};
|
||||||
|
console.log(obj.foo());
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"bar",
|
||||||
|
"foo",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3113_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
(function() {
|
||||||
|
function f() {
|
||||||
|
while (g());
|
||||||
|
}
|
||||||
|
var a = f();
|
||||||
|
function g() {
|
||||||
|
a && a[c++];
|
||||||
|
}
|
||||||
|
g(a = 1);
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
(function() {
|
||||||
|
function f() {
|
||||||
|
while (g());
|
||||||
|
}
|
||||||
|
var a = f();
|
||||||
|
function g() {
|
||||||
|
a && a[c++];
|
||||||
|
}
|
||||||
|
g(a = 1);
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3113_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
(function() {
|
||||||
|
function f() {
|
||||||
|
while (g());
|
||||||
|
}
|
||||||
|
var a = f();
|
||||||
|
function g() {
|
||||||
|
a && a[c++];
|
||||||
|
}
|
||||||
|
a = 1;
|
||||||
|
g();
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
(function() {
|
||||||
|
function f() {
|
||||||
|
while (g());
|
||||||
|
}
|
||||||
|
var a = f();
|
||||||
|
function g() {
|
||||||
|
a && a[c++];
|
||||||
|
}
|
||||||
|
a = 1;
|
||||||
|
g();
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3113_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
(function() {
|
||||||
|
function f() {
|
||||||
|
while (g());
|
||||||
|
}
|
||||||
|
var a;
|
||||||
|
function g() {
|
||||||
|
a && a[c++];
|
||||||
|
}
|
||||||
|
g(a = 1);
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
c++;
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3113_4: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b = 0;
|
||||||
|
function f() {
|
||||||
|
b += a;
|
||||||
|
}
|
||||||
|
f(f(), ++a);
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0, b = 0;
|
||||||
|
function f() {
|
||||||
|
b += a;
|
||||||
|
}
|
||||||
|
f(f(), ++a);
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "1 1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3113_5: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
function g() {
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
while (g());
|
||||||
|
var a = 1;
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
function g() {
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
while (g());
|
||||||
|
var a = 1;
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined",
|
||||||
|
"1",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional_nested_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1, b = 0;
|
||||||
|
(function f(c) {
|
||||||
|
function g() {
|
||||||
|
c && (c.a = 0);
|
||||||
|
c && (c.a = 0);
|
||||||
|
c && (c[b++] *= 0);
|
||||||
|
}
|
||||||
|
g(a-- && f(g(c = 42)));
|
||||||
|
})();
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1, b = 0;
|
||||||
|
(function f(c) {
|
||||||
|
function g() {
|
||||||
|
c && (c.a = 0);
|
||||||
|
c && (c.a = 0);
|
||||||
|
c && (c[b++] *= 0);
|
||||||
|
}
|
||||||
|
g(a-- && f(g(c = 42)));
|
||||||
|
})();
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional_nested_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
(function(a) {
|
||||||
|
function f() {
|
||||||
|
a && c++;
|
||||||
|
}
|
||||||
|
f(!c && f(), a = 1);
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
(function(a) {
|
||||||
|
function f() {
|
||||||
|
a && c++;
|
||||||
|
}
|
||||||
|
f(!c && f(), a = 1);
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2436: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c;
|
||||||
|
console.log(((c = {
|
||||||
|
a: 1,
|
||||||
|
b: 2
|
||||||
|
}).a = 3, {
|
||||||
|
x: c.a,
|
||||||
|
y: c.b
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c;
|
||||||
|
console.log(((c = {
|
||||||
|
a: 1,
|
||||||
|
b: 2
|
||||||
|
}).a = 3, {
|
||||||
|
x: c.a,
|
||||||
|
y: c.b
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2916: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function(b) {
|
||||||
|
(function(d) {
|
||||||
|
d[0] = 1;
|
||||||
|
})(b);
|
||||||
|
+b && (c = "PASS");
|
||||||
|
})([]);
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function(b) {
|
||||||
|
b[0] = 1;
|
||||||
|
+b && (c = "PASS");
|
||||||
|
})([]);
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3125: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o;
|
||||||
|
console.log((function() {
|
||||||
|
this.p++;
|
||||||
|
}.call(o = {
|
||||||
|
p: 6
|
||||||
|
}), o.p));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o;
|
||||||
|
console.log((function() {
|
||||||
|
this.p++;
|
||||||
|
}.call(o = {
|
||||||
|
p: 6
|
||||||
|
}), o.p));
|
||||||
|
}
|
||||||
|
expect_stdout: "7"
|
||||||
|
}
|
||||||
|
|||||||
@@ -876,3 +876,59 @@ forin: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
call: {
|
||||||
|
options = {
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = function() {
|
||||||
|
return this;
|
||||||
|
}();
|
||||||
|
function b() {
|
||||||
|
console.log("foo");
|
||||||
|
}
|
||||||
|
b.c = function() {
|
||||||
|
console.log(this === b ? "bar" : "baz");
|
||||||
|
};
|
||||||
|
(a, b)();
|
||||||
|
(a, b.c)();
|
||||||
|
(a, function() {
|
||||||
|
console.log(this === a);
|
||||||
|
})();
|
||||||
|
new (a, b)();
|
||||||
|
new (a, b.c)();
|
||||||
|
new (a, function() {
|
||||||
|
console.log(this === a);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = function() {
|
||||||
|
return this;
|
||||||
|
}();
|
||||||
|
function b() {
|
||||||
|
console.log("foo");
|
||||||
|
}
|
||||||
|
b.c = function() {
|
||||||
|
console.log(this === b ? "bar" : "baz");
|
||||||
|
},
|
||||||
|
a, b(),
|
||||||
|
(a, b.c)(),
|
||||||
|
a, function() {
|
||||||
|
console.log(this === a);
|
||||||
|
}(),
|
||||||
|
a, new b(),
|
||||||
|
a, new b.c(),
|
||||||
|
a, new function() {
|
||||||
|
console.log(this === a);
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"baz",
|
||||||
|
"true",
|
||||||
|
"foo",
|
||||||
|
"baz",
|
||||||
|
"false",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -90,17 +90,11 @@ typeof_defun_1: {
|
|||||||
"function" == typeof h && h();
|
"function" == typeof h && h();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function g() {
|
|
||||||
h = 42;
|
|
||||||
console.log("NOPE");
|
|
||||||
}
|
|
||||||
function h() {
|
function h() {
|
||||||
console.log("YUP");
|
console.log("YUP");
|
||||||
}
|
}
|
||||||
g = 42;
|
|
||||||
console.log("YES");
|
console.log("YES");
|
||||||
"function" == typeof g && g();
|
h();
|
||||||
"function" == typeof h && h();
|
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
"YES",
|
"YES",
|
||||||
|
|||||||
@@ -18,6 +18,13 @@
|
|||||||
{
|
{
|
||||||
"toplevel": true
|
"toplevel": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"compress": {
|
||||||
|
"passes": 1e6,
|
||||||
|
"unsafe": true
|
||||||
|
},
|
||||||
|
"toplevel": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"compress": {
|
"compress": {
|
||||||
"keep_fargs": false,
|
"keep_fargs": false,
|
||||||
|
|||||||
Reference in New Issue
Block a user