Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
860aa9531b | ||
|
|
2547542873 | ||
|
|
3f8f0e246e | ||
|
|
12227ebbb0 | ||
|
|
1b4bd7082b | ||
|
|
0b6c185818 | ||
|
|
bfd0ac7f4b | ||
|
|
1a8f2ecc65 | ||
|
|
dc9e1ff0b1 | ||
|
|
ea10498902 | ||
|
|
69636dad69 | ||
|
|
3ee1b0d00d | ||
|
|
1e3ca4c6f7 | ||
|
|
839f4361f4 | ||
|
|
ae5c3ee8a1 | ||
|
|
77f7ae5ba2 | ||
|
|
2d0f8bcff5 | ||
|
|
f97e107c09 | ||
|
|
e9932e1314 | ||
|
|
eaa84d32df | ||
|
|
6e4aa0326f | ||
|
|
f9a4b36dd1 | ||
|
|
3acb5a329e | ||
|
|
6d94242318 |
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -7,7 +7,7 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node: [ '0.10', '0.12', '4', '6', '8', '10', '12', '14', latest ]
|
node: [ '0.10', '0.12', '4', '6', '8', '10', '12', '14', '16', latest ]
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
os: [ ubuntu-latest, windows-latest ]
|
||||||
script: [ compress, mocha, release/benchmark, release/jetstream ]
|
script: [ compress, mocha, release/benchmark, release/jetstream ]
|
||||||
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
|
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
|
||||||
|
|||||||
@@ -1999,7 +1999,7 @@ TreeWalker.prototype = {
|
|||||||
},
|
},
|
||||||
find_parent: function(type) {
|
find_parent: function(type) {
|
||||||
var stack = this.stack;
|
var stack = this.stack;
|
||||||
for (var i = stack.length; --i >= 0;) {
|
for (var i = stack.length - 1; --i >= 0;) {
|
||||||
var x = stack[i];
|
var x = stack[i];
|
||||||
if (x instanceof type) return x;
|
if (x instanceof type) return x;
|
||||||
}
|
}
|
||||||
|
|||||||
342
lib/compress.js
342
lib/compress.js
@@ -203,6 +203,7 @@ merge(Compressor.prototype, {
|
|||||||
if (this.option("expression")) {
|
if (this.option("expression")) {
|
||||||
node.process_expression(true);
|
node.process_expression(true);
|
||||||
}
|
}
|
||||||
|
var merge_vars = this.options.merge_vars;
|
||||||
var passes = +this.options.passes || 1;
|
var passes = +this.options.passes || 1;
|
||||||
var min_count = 1 / 0;
|
var min_count = 1 / 0;
|
||||||
var stopping = false;
|
var stopping = false;
|
||||||
@@ -211,6 +212,7 @@ merge(Compressor.prototype, {
|
|||||||
node.figure_out_scope(mangle);
|
node.figure_out_scope(mangle);
|
||||||
if (pass > 0 || this.option("reduce_vars"))
|
if (pass > 0 || this.option("reduce_vars"))
|
||||||
node.reset_opt_flags(this);
|
node.reset_opt_flags(this);
|
||||||
|
this.options.merge_vars = merge_vars && (stopping || pass == passes - 1);
|
||||||
node = node.transform(this);
|
node = node.transform(this);
|
||||||
if (passes > 1) {
|
if (passes > 1) {
|
||||||
var count = 0;
|
var count = 0;
|
||||||
@@ -259,8 +261,8 @@ merge(Compressor.prototype, {
|
|||||||
descend(node, this);
|
descend(node, this);
|
||||||
var opt = node.optimize(this);
|
var opt = node.optimize(this);
|
||||||
if (is_scope && opt === node && !this.has_directive("use asm") && !opt.pinned()) {
|
if (is_scope && opt === node && !this.has_directive("use asm") && !opt.pinned()) {
|
||||||
opt.merge_variables(this);
|
|
||||||
opt.drop_unused(this);
|
opt.drop_unused(this);
|
||||||
|
if (opt.merge_variables(this)) opt.drop_unused(this);
|
||||||
descend(opt, this);
|
descend(opt, this);
|
||||||
}
|
}
|
||||||
if (opt === node) opt._squeezed = true;
|
if (opt === node) opt._squeezed = true;
|
||||||
@@ -389,7 +391,18 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
var lhs = is_lhs(node, parent);
|
var lhs = is_lhs(node, parent);
|
||||||
if (lhs) return lhs;
|
if (lhs) return lhs;
|
||||||
|
if (level == 0 && value && value.is_constant()) return;
|
||||||
if (parent instanceof AST_Array) return is_modified(compressor, tw, parent, parent, level + 1);
|
if (parent instanceof AST_Array) return is_modified(compressor, tw, parent, parent, level + 1);
|
||||||
|
if (parent instanceof AST_Assign) switch (parent.operator) {
|
||||||
|
case "=":
|
||||||
|
return is_modified(compressor, tw, parent, value, level + 1, immutable, recursive);
|
||||||
|
case "&&=":
|
||||||
|
case "||=":
|
||||||
|
case "??=":
|
||||||
|
return is_modified(compressor, tw, parent, parent, level + 1);
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (parent instanceof AST_Binary) {
|
if (parent instanceof AST_Binary) {
|
||||||
if (!lazy_op[parent.operator]) return;
|
if (!lazy_op[parent.operator]) return;
|
||||||
return is_modified(compressor, tw, parent, parent, level + 1);
|
return is_modified(compressor, tw, parent, parent, level + 1);
|
||||||
@@ -445,7 +458,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function can_drop_symbol(ref, compressor, keep_lambda) {
|
function can_drop_symbol(ref, compressor, keep_lambda) {
|
||||||
var def = ref.definition();
|
var def = ref.redef || ref.definition();
|
||||||
if (ref.in_arg && is_funarg(def)) return false;
|
if (ref.in_arg && is_funarg(def)) return false;
|
||||||
return all(def.orig, function(sym) {
|
return all(def.orig, function(sym) {
|
||||||
if (sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet) {
|
if (sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet) {
|
||||||
@@ -602,12 +615,14 @@ merge(Compressor.prototype, {
|
|||||||
if (def.single_use == "m") return false;
|
if (def.single_use == "m") return false;
|
||||||
var safe = tw.safe_ids[def.id];
|
var safe = tw.safe_ids[def.id];
|
||||||
if (safe) {
|
if (safe) {
|
||||||
if (!HOP(tw.safe_ids, def.id)) safe.read = safe.read && safe.read !== tw.safe_ids ? true : tw.safe_ids;
|
var in_order = HOP(tw.safe_ids, def.id);
|
||||||
|
if (!in_order) safe.read = safe.read && safe.read !== tw.safe_ids ? true : tw.safe_ids;
|
||||||
if (def.fixed == null) {
|
if (def.fixed == null) {
|
||||||
if (is_arguments(def)) return false;
|
if (is_arguments(def)) return false;
|
||||||
if (def.global && def.name == "arguments") return false;
|
if (def.global && def.name == "arguments") return false;
|
||||||
tw.loop_ids[def.id] = null;
|
tw.loop_ids[def.id] = null;
|
||||||
def.fixed = make_node(AST_Undefined, def.orig[0]);
|
def.fixed = make_node(AST_Undefined, def.orig[0]);
|
||||||
|
if (in_order) delete def.safe_ids;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return !safe.assign || safe.assign === tw.safe_ids;
|
return !safe.assign || safe.assign === tw.safe_ids;
|
||||||
@@ -625,7 +640,7 @@ merge(Compressor.prototype, {
|
|||||||
if (def.fixed === undefined) return declare || all(def.orig, function(sym) {
|
if (def.fixed === undefined) return declare || all(def.orig, function(sym) {
|
||||||
return !(sym instanceof AST_SymbolLet);
|
return !(sym instanceof AST_SymbolLet);
|
||||||
});
|
});
|
||||||
if (def.fixed === false) return false;
|
if (def.fixed === false || def.fixed === 0) return false;
|
||||||
var safe = tw.safe_ids[def.id];
|
var safe = tw.safe_ids[def.id];
|
||||||
if (def.safe_ids) {
|
if (def.safe_ids) {
|
||||||
def.safe_ids[def.id] = false;
|
def.safe_ids[def.id] = false;
|
||||||
@@ -690,6 +705,7 @@ merge(Compressor.prototype, {
|
|||||||
if (depth > 1 && !(value && value.is_constant_expression(scope))) depth = 1;
|
if (depth > 1 && !(value && value.is_constant_expression(scope))) depth = 1;
|
||||||
if (!d.escaped.depth || d.escaped.depth > depth) d.escaped.depth = depth;
|
if (!d.escaped.depth || d.escaped.depth > depth) d.escaped.depth = depth;
|
||||||
if (d.scope.resolve() !== scope.resolve()) d.escaped.cross_scope = true;
|
if (d.scope.resolve() !== scope.resolve()) d.escaped.cross_scope = true;
|
||||||
|
if (d.fixed) d.fixed.escaped = d.escaped;
|
||||||
return;
|
return;
|
||||||
} else if (value_in_use(node, parent)) {
|
} else if (value_in_use(node, parent)) {
|
||||||
mark_escaped(tw, d, scope, parent, parent, level + 1, depth);
|
mark_escaped(tw, d, scope, parent, parent, level + 1, depth);
|
||||||
@@ -707,6 +723,7 @@ merge(Compressor.prototype, {
|
|||||||
if (parent instanceof AST_SimpleStatement) return;
|
if (parent instanceof AST_SimpleStatement) return;
|
||||||
if (parent instanceof AST_Unary && !unary_side_effects[parent.operator]) return;
|
if (parent instanceof AST_Unary && !unary_side_effects[parent.operator]) return;
|
||||||
d.direct_access = true;
|
d.direct_access = true;
|
||||||
|
if (d.fixed) d.fixed.direct_access = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mark_assignment_to_arguments(node) {
|
function mark_assignment_to_arguments(node) {
|
||||||
@@ -759,11 +776,13 @@ merge(Compressor.prototype, {
|
|||||||
node.walk(scanner);
|
node.walk(scanner);
|
||||||
});
|
});
|
||||||
if (node.rest) {
|
if (node.rest) {
|
||||||
|
var fixed_node;
|
||||||
if (save) fixed = compressor.option("rests") && function() {
|
if (save) fixed = compressor.option("rests") && function() {
|
||||||
var value = save();
|
var value = save();
|
||||||
return value instanceof AST_Array ? make_node(AST_Array, node, {
|
if (!(value instanceof AST_Array)) return node;
|
||||||
elements: value.elements.slice(node.elements.length),
|
if (!fixed_node) fixed_node = make_node(AST_Array, node);
|
||||||
}) : node;
|
fixed_node.elements = value.elements.slice(node.elements.length);
|
||||||
|
return fixed_node;
|
||||||
};
|
};
|
||||||
node.rest.walk(scanner);
|
node.rest.walk(scanner);
|
||||||
}
|
}
|
||||||
@@ -843,11 +862,12 @@ merge(Compressor.prototype, {
|
|||||||
return arg || make_node(AST_Undefined, iife);
|
return arg || make_node(AST_Undefined, iife);
|
||||||
}, visit);
|
}, visit);
|
||||||
});
|
});
|
||||||
var rest = fn.rest;
|
var rest = fn.rest, fixed_node;
|
||||||
if (rest) scan_declaration(tw, compressor, rest, compressor.option("rests") && function() {
|
if (rest) scan_declaration(tw, compressor, rest, compressor.option("rests") && function() {
|
||||||
return fn.rest === rest ? make_node(AST_Array, fn, {
|
if (fn.rest !== rest) return rest;
|
||||||
elements: iife.args.slice(fn.argnames.length),
|
if (!fixed_node) fixed_node = make_node(AST_Array, fn);
|
||||||
}) : rest;
|
fixed_node.elements = iife.args.slice(fn.argnames.length);
|
||||||
|
return fixed_node;
|
||||||
}, visit);
|
}, visit);
|
||||||
walk_lambda(fn, tw);
|
walk_lambda(fn, tw);
|
||||||
var safe_ids = tw.safe_ids;
|
var safe_ids = tw.safe_ids;
|
||||||
@@ -899,30 +919,22 @@ merge(Compressor.prototype, {
|
|||||||
case "&&=":
|
case "&&=":
|
||||||
case "||=":
|
case "||=":
|
||||||
case "??=":
|
case "??=":
|
||||||
left.walk(tw);
|
var lazy = true;
|
||||||
push(tw);
|
|
||||||
if (scan) {
|
|
||||||
right.walk(tw);
|
|
||||||
walk_assign();
|
|
||||||
} else {
|
|
||||||
mark_assignment_to_arguments(left);
|
|
||||||
right.walk(tw);
|
|
||||||
}
|
|
||||||
pop(tw);
|
|
||||||
return true;
|
|
||||||
default:
|
default:
|
||||||
if (!scan) {
|
if (!scan) {
|
||||||
mark_assignment_to_arguments(left);
|
mark_assignment_to_arguments(left);
|
||||||
return;
|
return walk_lazy();
|
||||||
}
|
}
|
||||||
ld.assignments++;
|
ld.assignments++;
|
||||||
var fixed = ld.fixed;
|
var fixed = ld.fixed;
|
||||||
if (is_modified(compressor, tw, node, node, 0)) {
|
if (is_modified(compressor, tw, node, node, 0)) {
|
||||||
ld.fixed = false;
|
ld.fixed = false;
|
||||||
return;
|
return walk_lazy();
|
||||||
}
|
}
|
||||||
var safe = safe_to_read(tw, ld);
|
var safe = safe_to_read(tw, ld);
|
||||||
|
if (lazy) push(tw);
|
||||||
right.walk(tw);
|
right.walk(tw);
|
||||||
|
if (lazy) pop(tw);
|
||||||
if (safe && !left.in_arg && safe_to_assign(tw, ld)) {
|
if (safe && !left.in_arg && safe_to_assign(tw, ld)) {
|
||||||
push_ref(ld, left);
|
push_ref(ld, left);
|
||||||
mark(tw, ld);
|
mark(tw, ld);
|
||||||
@@ -978,7 +990,13 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
var d = sym.definition();
|
var d = sym.definition();
|
||||||
d.assignments++;
|
d.assignments++;
|
||||||
if (fixed && !modified && !sym.in_arg && safe_to_assign(tw, d)) {
|
if (!fixed || sym.in_arg || !safe_to_assign(tw, d)) {
|
||||||
|
walk();
|
||||||
|
d.fixed = false;
|
||||||
|
} else if (modified) {
|
||||||
|
walk();
|
||||||
|
d.fixed = 0;
|
||||||
|
} else {
|
||||||
push_ref(d, sym);
|
push_ref(d, sym);
|
||||||
mark(tw, d);
|
mark(tw, d);
|
||||||
if (left instanceof AST_Destructured
|
if (left instanceof AST_Destructured
|
||||||
@@ -986,15 +1004,21 @@ merge(Compressor.prototype, {
|
|||||||
d.single_use = false;
|
d.single_use = false;
|
||||||
}
|
}
|
||||||
tw.loop_ids[d.id] = tw.in_loop;
|
tw.loop_ids[d.id] = tw.in_loop;
|
||||||
mark_escaped(tw, d, sym.scope, node, right, 0, 1);
|
|
||||||
sym.fixed = d.fixed = fixed;
|
sym.fixed = d.fixed = fixed;
|
||||||
sym.fixed.assigns = [ node ];
|
sym.fixed.assigns = [ node ];
|
||||||
} else {
|
mark_escaped(tw, d, sym.scope, node, right, 0, 1);
|
||||||
walk();
|
|
||||||
d.fixed = false;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function walk_lazy() {
|
||||||
|
if (!lazy) return;
|
||||||
|
left.walk(tw);
|
||||||
|
push(tw);
|
||||||
|
right.walk(tw);
|
||||||
|
pop(tw);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
def(AST_Binary, function(tw) {
|
def(AST_Binary, function(tw) {
|
||||||
if (!lazy_op[this.operator]) return;
|
if (!lazy_op[this.operator]) return;
|
||||||
@@ -1261,7 +1285,7 @@ merge(Compressor.prototype, {
|
|||||||
if (!safe) return;
|
if (!safe) return;
|
||||||
safe.assign = true;
|
safe.assign = true;
|
||||||
});
|
});
|
||||||
if (d.fixed === false) {
|
if (d.fixed === false || d.fixed === 0) {
|
||||||
var redef = d.redefined();
|
var redef = d.redefined();
|
||||||
if (redef && cross_scope(d.scope, this.scope)) redef.single_use = false;
|
if (redef && cross_scope(d.scope, this.scope)) redef.single_use = false;
|
||||||
} else if (d.fixed === undefined || !safe_to_read(tw, d)) {
|
} else if (d.fixed === undefined || !safe_to_read(tw, d)) {
|
||||||
@@ -1286,7 +1310,7 @@ merge(Compressor.prototype, {
|
|||||||
if (d.single_use) {
|
if (d.single_use) {
|
||||||
d.single_use = "m";
|
d.single_use = "m";
|
||||||
} else {
|
} else {
|
||||||
d.fixed = false;
|
d.fixed = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (d.fixed && tw.loop_ids[d.id] !== tw.in_loop) d.cross_loop = true;
|
if (d.fixed && tw.loop_ids[d.id] !== tw.in_loop) d.cross_loop = true;
|
||||||
@@ -1471,14 +1495,19 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
AST_Symbol.DEFMETHOD("fixed_value", function() {
|
AST_Symbol.DEFMETHOD("fixed_value", function() {
|
||||||
var fixed = this.definition().fixed;
|
var fixed = this.definition().fixed;
|
||||||
|
if (fixed) {
|
||||||
|
if (this.fixed) fixed = this.fixed;
|
||||||
|
return fixed instanceof AST_Node ? fixed : fixed();
|
||||||
|
}
|
||||||
|
fixed = fixed === 0 && this.fixed;
|
||||||
if (!fixed) return fixed;
|
if (!fixed) return fixed;
|
||||||
if (this.fixed) fixed = this.fixed;
|
var value = fixed instanceof AST_Node ? fixed : fixed();
|
||||||
return fixed instanceof AST_Node ? fixed : fixed();
|
return value.is_constant() && value;
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_SymbolRef.DEFMETHOD("is_immutable", function() {
|
AST_SymbolRef.DEFMETHOD("is_immutable", function() {
|
||||||
var def = this.redef || this.definition();
|
var def = this.redef || this.definition();
|
||||||
return def.orig.length == 1 && def.orig[0] instanceof AST_SymbolLambda;
|
return (this.in_arg || def.orig.length == 1) && def.orig[0] instanceof AST_SymbolLambda;
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Node.DEFMETHOD("convert_symbol", noop);
|
AST_Node.DEFMETHOD("convert_symbol", noop);
|
||||||
@@ -2879,8 +2908,9 @@ merge(Compressor.prototype, {
|
|||||||
if (!value) {
|
if (!value) {
|
||||||
value = node;
|
value = node;
|
||||||
var def = node.definition();
|
var def = node.definition();
|
||||||
|
var escaped = node.fixed && node.fixed.escaped || def.escaped;
|
||||||
if (!def.undeclared
|
if (!def.undeclared
|
||||||
&& (def.assignments || !def.escaped || def.escaped.cross_scope)
|
&& (def.assignments || !escaped || escaped.cross_scope)
|
||||||
&& (has_escaped(def, node.scope, node, tw.parent()) || !same_scope(def))) {
|
&& (has_escaped(def, node.scope, node, tw.parent()) || !same_scope(def))) {
|
||||||
well_defined = false;
|
well_defined = false;
|
||||||
}
|
}
|
||||||
@@ -2888,8 +2918,33 @@ merge(Compressor.prototype, {
|
|||||||
} else if (node instanceof AST_ObjectIdentity) {
|
} else if (node instanceof AST_ObjectIdentity) {
|
||||||
value = node;
|
value = node;
|
||||||
}
|
}
|
||||||
if (value) lvalues.add(node.name, is_modified(compressor, tw, node, value, 0));
|
if (value) {
|
||||||
if (find_arguments && node instanceof AST_Sub) {
|
lvalues.add(node.name, is_modified(compressor, tw, node, value, 0));
|
||||||
|
} else if (node instanceof AST_Lambda) {
|
||||||
|
for (var level = 0, parent, child = node; parent = tw.parent(level++); child = parent) {
|
||||||
|
if (parent instanceof AST_Assign) {
|
||||||
|
if (parent.left === child) break;
|
||||||
|
if (parent.operator == "=") continue;
|
||||||
|
if (lazy_op[parent.operator.slice(0, -1)]) continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (parent instanceof AST_Binary) {
|
||||||
|
if (lazy_op[parent.operator]) continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (parent instanceof AST_Call) return;
|
||||||
|
if (parent instanceof AST_Scope) return;
|
||||||
|
if (parent instanceof AST_Sequence) {
|
||||||
|
if (parent.tail_node() === child) continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (parent instanceof AST_Template) {
|
||||||
|
if (parent.tag) return;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else if (find_arguments && node instanceof AST_Sub) {
|
||||||
scope.each_argname(function(argname) {
|
scope.each_argname(function(argname) {
|
||||||
if (!compressor.option("reduce_vars") || argname.definition().assignments) {
|
if (!compressor.option("reduce_vars") || argname.definition().assignments) {
|
||||||
if (!argname.definition().fixed) well_defined = false;
|
if (!argname.definition().fixed) well_defined = false;
|
||||||
@@ -2996,7 +3051,10 @@ merge(Compressor.prototype, {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var def = lhs.definition();
|
var def = lhs.definition();
|
||||||
return def.references.length - def.replaced == referenced;
|
if (def.references.length - def.replaced == referenced) return true;
|
||||||
|
return def.fixed && lhs.fixed && def.references.filter(function(ref) {
|
||||||
|
return ref.fixed === lhs.fixed;
|
||||||
|
}).length == referenced;
|
||||||
}
|
}
|
||||||
|
|
||||||
function symbol_in_lvalues(sym, parent) {
|
function symbol_in_lvalues(sym, parent) {
|
||||||
@@ -3346,10 +3404,10 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
statements.length = n;
|
statements.length = n;
|
||||||
CHANGED = n != len;
|
|
||||||
if (has_quit) has_quit.forEach(function(stat) {
|
if (has_quit) has_quit.forEach(function(stat) {
|
||||||
extract_declarations_from_unreachable_code(compressor, stat, statements);
|
extract_declarations_from_unreachable_code(compressor, stat, statements);
|
||||||
});
|
});
|
||||||
|
CHANGED = statements.length != len;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sequencesize(statements, compressor) {
|
function sequencesize(statements, compressor) {
|
||||||
@@ -3475,15 +3533,26 @@ merge(Compressor.prototype, {
|
|||||||
var exprs = extract_exprs(body);
|
var exprs = extract_exprs(body);
|
||||||
if (!exprs) return;
|
if (!exprs) return;
|
||||||
var trimmed = false;
|
var trimmed = false;
|
||||||
for (var i = exprs.length - 1; --i >= 0;) {
|
for (var i = exprs.length - (keep || 0); --i >= 0;) {
|
||||||
var expr = exprs[i];
|
var expr = exprs[i];
|
||||||
if (!(expr instanceof AST_Assign)) continue;
|
if (!can_trim(expr)) continue;
|
||||||
if (expr.operator != "=") continue;
|
var tail;
|
||||||
if (!(expr.left instanceof AST_SymbolRef)) continue;
|
if (expr.left instanceof AST_SymbolRef) {
|
||||||
var tail = exprs.slice(i + 1);
|
tail = exprs.slice(i + 1);
|
||||||
|
} else if (expr.left instanceof AST_PropAccess && can_trim(expr.left.expression)) {
|
||||||
|
tail = exprs.slice(i + 1);
|
||||||
|
var flattened = expr.clone();
|
||||||
|
expr = expr.left.expression;
|
||||||
|
flattened.left = flattened.left.clone();
|
||||||
|
flattened.left.expression = expr.left.clone();
|
||||||
|
tail.unshift(flattened);
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (tail.length == 0) continue;
|
||||||
if (!trim_assigns(expr.left, expr.right, tail)) continue;
|
if (!trim_assigns(expr.left, expr.right, tail)) continue;
|
||||||
trimmed = true;
|
trimmed = true;
|
||||||
exprs = exprs.slice(0, i + 1).concat(tail);
|
exprs = exprs.slice(0, i).concat(expr, tail);
|
||||||
}
|
}
|
||||||
if (defn instanceof AST_Definitions) {
|
if (defn instanceof AST_Definitions) {
|
||||||
keep = keep || 0;
|
keep = keep || 0;
|
||||||
@@ -3497,6 +3566,10 @@ merge(Compressor.prototype, {
|
|||||||
if (defn instanceof AST_Var && join_var_assign(defn.definitions, exprs, keep)) trimmed = true;
|
if (defn instanceof AST_Var && join_var_assign(defn.definitions, exprs, keep)) trimmed = true;
|
||||||
}
|
}
|
||||||
return trimmed && exprs;
|
return trimmed && exprs;
|
||||||
|
|
||||||
|
function can_trim(node) {
|
||||||
|
return node instanceof AST_Assign && node.operator == "=";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function merge_assigns(prev, defn) {
|
function merge_assigns(prev, defn) {
|
||||||
@@ -3553,22 +3626,35 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function trim_assigns(name, value, exprs) {
|
function trim_assigns(name, value, exprs) {
|
||||||
|
var names = Object.create(null);
|
||||||
|
names[name.name] = true;
|
||||||
|
while (value instanceof AST_Assign && value.operator == "=") {
|
||||||
|
if (value.left instanceof AST_SymbolRef) names[value.left.name] = true;
|
||||||
|
value = value.right;
|
||||||
|
}
|
||||||
if (!(value instanceof AST_Object)) return;
|
if (!(value instanceof AST_Object)) return;
|
||||||
var trimmed = false;
|
var trimmed = false;
|
||||||
do {
|
do {
|
||||||
var node = exprs[0];
|
if (!try_join(exprs[0])) break;
|
||||||
if (!(node instanceof AST_Assign)) break;
|
exprs.shift();
|
||||||
if (node.operator != "=") break;
|
trimmed = true;
|
||||||
if (!(node.left instanceof AST_PropAccess)) break;
|
} while (exprs.length);
|
||||||
|
return trimmed;
|
||||||
|
|
||||||
|
function try_join(node) {
|
||||||
|
if (!(node instanceof AST_Assign)) return;
|
||||||
|
if (node.operator != "=") return;
|
||||||
|
if (!(node.left instanceof AST_PropAccess)) return;
|
||||||
var sym = node.left.expression;
|
var sym = node.left.expression;
|
||||||
if (!(sym instanceof AST_SymbolRef)) break;
|
if (!(sym instanceof AST_SymbolRef)) return;
|
||||||
if (name.name != sym.name) break;
|
if (!(sym.name in names)) return;
|
||||||
if (!node.right.is_constant_expression(scope)) break;
|
if (!node.right.is_constant_expression(scope)) return;
|
||||||
var prop = node.left.property;
|
var prop = node.left.property;
|
||||||
if (prop instanceof AST_Node) {
|
if (prop instanceof AST_Node) {
|
||||||
|
if (try_join(prop)) prop = node.left.property = prop.right.clone();
|
||||||
prop = prop.evaluate(compressor);
|
prop = prop.evaluate(compressor);
|
||||||
}
|
}
|
||||||
if (prop instanceof AST_Node) break;
|
if (prop instanceof AST_Node) return;
|
||||||
prop = "" + prop;
|
prop = "" + prop;
|
||||||
var diff = prop == "__proto__" || compressor.has_directive("use strict") ? function(node) {
|
var diff = prop == "__proto__" || compressor.has_directive("use strict") ? function(node) {
|
||||||
var key = node.key;
|
var key = node.key;
|
||||||
@@ -3580,15 +3666,13 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
return key !== "__proto__";
|
return key !== "__proto__";
|
||||||
};
|
};
|
||||||
if (!all(value.properties, diff)) break;
|
if (!all(value.properties, diff)) return;
|
||||||
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();
|
return true;
|
||||||
trimmed = true;
|
}
|
||||||
} while (exprs.length);
|
|
||||||
return trimmed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function join_consecutive_vars(statements) {
|
function join_consecutive_vars(statements) {
|
||||||
@@ -5934,6 +6018,7 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
tw.directives = Object.create(compressor.directives);
|
tw.directives = Object.create(compressor.directives);
|
||||||
self.walk(tw);
|
self.walk(tw);
|
||||||
|
var changed = false;
|
||||||
var merged = Object.create(null);
|
var merged = Object.create(null);
|
||||||
while (first.length && last.length) {
|
while (first.length && last.length) {
|
||||||
var head = first.pop();
|
var head = first.pop();
|
||||||
@@ -5977,10 +6062,12 @@ merge(Compressor.prototype, {
|
|||||||
def.references = refs.concat(def.references);
|
def.references = refs.concat(def.references);
|
||||||
def.fixed = tail.definition.fixed && def.fixed;
|
def.fixed = tail.definition.fixed && def.fixed;
|
||||||
merged[id] = def;
|
merged[id] = def;
|
||||||
|
changed = true;
|
||||||
break;
|
break;
|
||||||
} while (last.length);
|
} while (last.length);
|
||||||
if (skipped.length) last = last.concat(skipped);
|
if (skipped.length) last = last.concat(skipped);
|
||||||
}
|
}
|
||||||
|
return changed;
|
||||||
|
|
||||||
function push() {
|
function push() {
|
||||||
segment = Object.create(segment);
|
segment = Object.create(segment);
|
||||||
@@ -7157,7 +7244,10 @@ merge(Compressor.prototype, {
|
|||||||
case 1:
|
case 1:
|
||||||
if (!drop) break;
|
if (!drop) break;
|
||||||
var sym = elements[0];
|
var sym = elements[0];
|
||||||
if (!(sym instanceof AST_Symbol)) break;
|
if (sym.has_side_effects(compressor)) break;
|
||||||
|
if (value.has_side_effects(compressor) && sym.match_symbol(function(node) {
|
||||||
|
return node instanceof AST_PropAccess;
|
||||||
|
})) break;
|
||||||
value = make_node(AST_Sub, node, {
|
value = make_node(AST_Sub, node, {
|
||||||
expression: value,
|
expression: value,
|
||||||
property: make_node(AST_Number, node, { value: 0 }),
|
property: make_node(AST_Number, node, { value: 0 }),
|
||||||
@@ -7283,7 +7373,10 @@ merge(Compressor.prototype, {
|
|||||||
if (!drop) break;
|
if (!drop) break;
|
||||||
var prop = properties[0];
|
var prop = properties[0];
|
||||||
if (prop.key instanceof AST_Node) break;
|
if (prop.key instanceof AST_Node) break;
|
||||||
if (!(prop.value instanceof AST_Symbol)) break;
|
if (prop.value.has_side_effects(compressor)) break;
|
||||||
|
if (value.has_side_effects(compressor) && prop.value.match_symbol(function(node) {
|
||||||
|
return node instanceof AST_PropAccess;
|
||||||
|
})) break;
|
||||||
value = make_node(AST_Sub, node, {
|
value = make_node(AST_Sub, node, {
|
||||||
expression: value,
|
expression: value,
|
||||||
property: make_node_from_constant(prop.key, prop),
|
property: make_node_from_constant(prop.key, prop),
|
||||||
@@ -7627,6 +7720,7 @@ merge(Compressor.prototype, {
|
|||||||
right: prop.value,
|
right: prop.value,
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
defs.value = node.right;
|
||||||
defs_by_id[node.left.definition().id] = defs;
|
defs_by_id[node.left.definition().id] = defs;
|
||||||
self.body.splice(self.body.indexOf(this.stack[1]) + 1, 0, make_node(AST_Var, node, {
|
self.body.splice(self.body.indexOf(this.stack[1]) + 1, 0, make_node(AST_Var, node, {
|
||||||
definitions: decls,
|
definitions: decls,
|
||||||
@@ -7639,12 +7733,16 @@ merge(Compressor.prototype, {
|
|||||||
descend(node, this);
|
descend(node, this);
|
||||||
var defs = new Dictionary();
|
var defs = new Dictionary();
|
||||||
var var_defs = [];
|
var var_defs = [];
|
||||||
|
var decl = node.clone();
|
||||||
|
decl.value = node.name instanceof AST_SymbolConst ? make_node(AST_Number, node, { value: 0 }) : null;
|
||||||
|
var_defs.push(decl);
|
||||||
node.value.properties.forEach(function(prop) {
|
node.value.properties.forEach(function(prop) {
|
||||||
var_defs.push(make_node(AST_VarDef, node, {
|
var_defs.push(make_node(AST_VarDef, node, {
|
||||||
name: make_sym(node.name.CTOR, node.name, prop.key),
|
name: make_sym(node.name.CTOR, node.name, prop.key),
|
||||||
value: prop.value,
|
value: prop.value,
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
defs.value = node.value;
|
||||||
defs_by_id[node.name.definition().id] = defs;
|
defs_by_id[node.name.definition().id] = defs;
|
||||||
return List.splice(var_defs);
|
return List.splice(var_defs);
|
||||||
}
|
}
|
||||||
@@ -7660,6 +7758,7 @@ merge(Compressor.prototype, {
|
|||||||
if (!(node.expression instanceof AST_SymbolRef)) return;
|
if (!(node.expression instanceof AST_SymbolRef)) return;
|
||||||
var defs = defs_by_id[node.expression.definition().id];
|
var defs = defs_by_id[node.expression.definition().id];
|
||||||
if (!defs) return;
|
if (!defs) return;
|
||||||
|
if (node.expression.fixed_value() !== defs.value) return;
|
||||||
var def = defs.get(node.get_property());
|
var def = defs.get(node.get_property());
|
||||||
var sym = make_node(AST_SymbolRef, node, {
|
var sym = make_node(AST_SymbolRef, node, {
|
||||||
name: def.name,
|
name: def.name,
|
||||||
@@ -7670,7 +7769,9 @@ merge(Compressor.prototype, {
|
|||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_SymbolRef) {
|
if (node instanceof AST_SymbolRef) {
|
||||||
if (!(node.definition().id in defs_by_id)) return;
|
var defs = defs_by_id[node.definition().id];
|
||||||
|
if (!defs) return;
|
||||||
|
if (node.fixed_value() !== defs.value) return;
|
||||||
return make_node(AST_Object, node, { properties: [] });
|
return make_node(AST_Object, node, { properties: [] });
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
@@ -7679,18 +7780,16 @@ merge(Compressor.prototype, {
|
|||||||
if (!(sym instanceof AST_Symbol)) return;
|
if (!(sym instanceof AST_Symbol)) return;
|
||||||
var def = sym.definition();
|
var def = sym.definition();
|
||||||
if (def.assignments != count) return;
|
if (def.assignments != count) return;
|
||||||
if (def.direct_access) return;
|
|
||||||
if (def.escaped.depth == 1) return;
|
|
||||||
if (def.references.length - def.replaced == count) return;
|
if (def.references.length - def.replaced == count) return;
|
||||||
if (def.single_use) return;
|
if (def.single_use) return;
|
||||||
if (top_retain(def)) return;
|
if (top_retain(def)) return;
|
||||||
if (sym.fixed_value() !== right) return;
|
if (sym.fixed_value() !== right) return;
|
||||||
|
var fixed = sym.fixed || def.fixed;
|
||||||
|
if (fixed.direct_access) return;
|
||||||
|
if (fixed.escaped && fixed.escaped.depth == 1) return;
|
||||||
return right instanceof AST_Object
|
return right instanceof AST_Object
|
||||||
&& right.properties.length > 0
|
&& right.properties.length > 0
|
||||||
&& all(right.properties, can_hoist_property)
|
&& all(right.properties, can_hoist_property)
|
||||||
&& all(def.references, function(ref) {
|
|
||||||
return ref.fixed_value() === right;
|
|
||||||
})
|
|
||||||
&& can_drop_symbol(sym, compressor);
|
&& can_drop_symbol(sym, compressor);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -7758,14 +7857,10 @@ merge(Compressor.prototype, {
|
|||||||
if (compressor.has_directive("use strict") && expr.is_constant()) return this;
|
if (compressor.has_directive("use strict") && expr.is_constant()) return this;
|
||||||
}
|
}
|
||||||
if (left.has_side_effects(compressor)) return this;
|
if (left.has_side_effects(compressor)) return this;
|
||||||
var right = this.right;
|
if (lazy_op[this.operator.slice(0, -1)]) return this;
|
||||||
if (!lazy_op[this.operator.slice(0, -1)]) {
|
this.write_only = true;
|
||||||
this.write_only = true;
|
if (!root_expr(left).is_constant_expression(compressor.find_parent(AST_Scope))) return this;
|
||||||
if (root_expr(left).is_constant_expression(compressor.find_parent(AST_Scope))) {
|
return this.right.drop_side_effect_free(compressor);
|
||||||
return right.drop_side_effect_free(compressor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
});
|
});
|
||||||
def(AST_Await, function(compressor) {
|
def(AST_Await, function(compressor) {
|
||||||
if (!compressor.option("awaits")) return this;
|
if (!compressor.option("awaits")) return this;
|
||||||
@@ -9016,16 +9111,20 @@ merge(Compressor.prototype, {
|
|||||||
right: value,
|
right: value,
|
||||||
});
|
});
|
||||||
a.push(assign);
|
a.push(assign);
|
||||||
name.fixed = function() {
|
var fixed = function() {
|
||||||
return assign.right;
|
return assign.right;
|
||||||
};
|
};
|
||||||
name.fixed.assigns = [ assign ];
|
fixed.assigns = [ assign ];
|
||||||
|
fixed.direct_access = def.direct_access;
|
||||||
|
fixed.escaped = def.escaped;
|
||||||
|
name.fixed = fixed;
|
||||||
def.references.forEach(function(ref) {
|
def.references.forEach(function(ref) {
|
||||||
var assigns = ref.fixed && ref.fixed.assigns;
|
var assigns = ref.fixed && ref.fixed.assigns;
|
||||||
if (assigns && assigns[0] === defn) assigns[0] = assign;
|
if (assigns && assigns[0] === defn) assigns[0] = assign;
|
||||||
});
|
});
|
||||||
def.references.push(name);
|
def.references.push(name);
|
||||||
}
|
}
|
||||||
|
def.assignments++;
|
||||||
def.eliminated++;
|
def.eliminated++;
|
||||||
def.single_use = false;
|
def.single_use = false;
|
||||||
return a;
|
return a;
|
||||||
@@ -9204,6 +9303,13 @@ merge(Compressor.prototype, {
|
|||||||
}) : arg);
|
}) : arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function avoid_await_yield(parent_scope) {
|
||||||
|
var avoid = [];
|
||||||
|
if (is_async(parent_scope)) avoid.push("await");
|
||||||
|
if (is_generator(parent_scope)) avoid.push("yield");
|
||||||
|
return avoid.length && makePredicate(avoid);
|
||||||
|
}
|
||||||
|
|
||||||
OPT(AST_Call, function(self, compressor) {
|
OPT(AST_Call, function(self, compressor) {
|
||||||
var exp = self.expression;
|
var exp = self.expression;
|
||||||
var terminated = trim_optional_chain(self, compressor);
|
var terminated = trim_optional_chain(self, compressor);
|
||||||
@@ -9531,7 +9637,10 @@ merge(Compressor.prototype, {
|
|||||||
var can_inline = can_drop && compressor.option("inline") && !self.is_expr_pure(compressor);
|
var can_inline = can_drop && compressor.option("inline") && !self.is_expr_pure(compressor);
|
||||||
if (can_inline && stat instanceof AST_Return) {
|
if (can_inline && stat instanceof AST_Return) {
|
||||||
var value = stat.value;
|
var value = stat.value;
|
||||||
if (exp === fn && !fn.name && (!value || value.is_constant_expression()) && safe_from_await_yield(fn)) {
|
if (exp === fn
|
||||||
|
&& !fn.name
|
||||||
|
&& (!value || value.is_constant_expression())
|
||||||
|
&& safe_from_await_yield(fn, compressor.find_parent(AST_Scope))) {
|
||||||
return make_sequence(self, convert_args(value)).optimize(compressor);
|
return make_sequence(self, convert_args(value)).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9550,7 +9659,7 @@ merge(Compressor.prototype, {
|
|||||||
if (can_substitute_directly()) {
|
if (can_substitute_directly()) {
|
||||||
var args = self.args.slice();
|
var args = self.args.slice();
|
||||||
var refs = [];
|
var refs = [];
|
||||||
args.push(value.clone(true).transform(new TreeTransformer(function(node) {
|
var retValue = value.clone(true).transform(new TreeTransformer(function(node) {
|
||||||
if (node instanceof AST_SymbolRef) {
|
if (node instanceof AST_SymbolRef) {
|
||||||
var def = node.definition();
|
var def = node.definition();
|
||||||
if (fn.variables.get(node.name) !== def) {
|
if (fn.variables.get(node.name) !== def) {
|
||||||
@@ -9564,12 +9673,20 @@ merge(Compressor.prototype, {
|
|||||||
var parent = this.parent();
|
var parent = this.parent();
|
||||||
return parent ? maintain_this_binding(compressor, parent, node, arg) : arg;
|
return parent ? maintain_this_binding(compressor, parent, node, arg) : arg;
|
||||||
}
|
}
|
||||||
})));
|
}));
|
||||||
var save_inlined = fn.inlined;
|
var save_inlined = fn.inlined;
|
||||||
if (exp !== fn) fn.inlined = true;
|
if (exp !== fn) fn.inlined = true;
|
||||||
var node = make_sequence(self, args.filter(function(arg) {
|
var exprs = [];
|
||||||
return arg;
|
args.forEach(function(arg) {
|
||||||
})).optimize(compressor);
|
if (!arg) return;
|
||||||
|
arg = arg.clone(true);
|
||||||
|
arg.walk(new TreeWalker(function(node) {
|
||||||
|
if (node instanceof AST_SymbolRef) refs.push(node);
|
||||||
|
}));
|
||||||
|
exprs.push(arg);
|
||||||
|
}, []);
|
||||||
|
exprs.push(retValue);
|
||||||
|
var node = make_sequence(self, exprs).optimize(compressor);
|
||||||
fn.inlined = save_inlined;
|
fn.inlined = save_inlined;
|
||||||
node = maintain_this_binding(compressor, parent, current, node);
|
node = maintain_this_binding(compressor, parent, current, node);
|
||||||
if (replacing || best_of_expression(node, self) === node) {
|
if (replacing || best_of_expression(node, self) === node) {
|
||||||
@@ -9603,7 +9720,7 @@ merge(Compressor.prototype, {
|
|||||||
&& all(fn.body, is_empty)
|
&& all(fn.body, is_empty)
|
||||||
&& (fn === exp ? fn_name_unused(fn, compressor) : !has_default && !has_destructured && !fn.rest)
|
&& (fn === exp ? fn_name_unused(fn, compressor) : !has_default && !has_destructured && !fn.rest)
|
||||||
&& !(is_arrow(fn) && fn.value)
|
&& !(is_arrow(fn) && fn.value)
|
||||||
&& safe_from_await_yield(fn)) {
|
&& safe_from_await_yield(fn, compressor.find_parent(AST_Scope))) {
|
||||||
return make_sequence(self, convert_args()).optimize(compressor);
|
return make_sequence(self, convert_args()).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9711,16 +9828,8 @@ merge(Compressor.prototype, {
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
function avoid_await_yield() {
|
function safe_from_await_yield(node, scope) {
|
||||||
var avoid = [];
|
var avoid = avoid_await_yield(scope);
|
||||||
var parent_scope = scope || compressor.find_parent(AST_Scope);
|
|
||||||
if (is_async(parent_scope)) avoid.push("await");
|
|
||||||
if (is_generator(parent_scope)) avoid.push("yield");
|
|
||||||
return avoid.length && makePredicate(avoid);
|
|
||||||
}
|
|
||||||
|
|
||||||
function safe_from_await_yield(node) {
|
|
||||||
var avoid = avoid_await_yield();
|
|
||||||
if (!avoid) return true;
|
if (!avoid) return true;
|
||||||
var safe = true;
|
var safe = true;
|
||||||
var tw = new TreeWalker(function(node) {
|
var tw = new TreeWalker(function(node) {
|
||||||
@@ -9796,8 +9905,9 @@ merge(Compressor.prototype, {
|
|||||||
if (!fn.variables.all(function(def) {
|
if (!fn.variables.all(function(def) {
|
||||||
return def.references.length - def.replaced < 2 && def.orig[0] instanceof AST_SymbolFunarg;
|
return def.references.length - def.replaced < 2 && def.orig[0] instanceof AST_SymbolFunarg;
|
||||||
})) return;
|
})) return;
|
||||||
|
var scope = compressor.find_parent(AST_Scope);
|
||||||
var abort = false;
|
var abort = false;
|
||||||
var avoid = avoid_await_yield();
|
var avoid = avoid_await_yield(scope);
|
||||||
var begin;
|
var begin;
|
||||||
var in_order = [];
|
var in_order = [];
|
||||||
var side_effects = false;
|
var side_effects = false;
|
||||||
@@ -9841,8 +9951,7 @@ merge(Compressor.prototype, {
|
|||||||
while (end-- > begin && fn.argnames[end] === in_order.pop());
|
while (end-- > begin && fn.argnames[end] === in_order.pop());
|
||||||
end++;
|
end++;
|
||||||
}
|
}
|
||||||
var scope = side_effects && !in_order && compressor.find_parent(AST_Scope);
|
return end <= begin || all(self.args.slice(begin, end), side_effects && !in_order ? function(funarg) {
|
||||||
return end <= begin || all(self.args.slice(begin, end), scope ? function(funarg) {
|
|
||||||
return funarg.is_constant_expression(scope);
|
return funarg.is_constant_expression(scope);
|
||||||
} : function(funarg) {
|
} : function(funarg) {
|
||||||
return !funarg.has_side_effects(compressor);
|
return !funarg.has_side_effects(compressor);
|
||||||
@@ -9912,7 +10021,7 @@ merge(Compressor.prototype, {
|
|||||||
} while (!(scope instanceof AST_Scope));
|
} while (!(scope instanceof AST_Scope));
|
||||||
insert = scope.body.indexOf(child) + 1;
|
insert = scope.body.indexOf(child) + 1;
|
||||||
if (!insert) return false;
|
if (!insert) return false;
|
||||||
if (!safe_from_await_yield(fn)) return false;
|
if (!safe_from_await_yield(fn, scope)) return false;
|
||||||
var safe_to_inject = exp !== fn || fn.parent_scope.resolve() === scope;
|
var safe_to_inject = exp !== fn || fn.parent_scope.resolve() === scope;
|
||||||
if (scope instanceof AST_Toplevel) {
|
if (scope instanceof AST_Toplevel) {
|
||||||
if (compressor.toplevel.vars) {
|
if (compressor.toplevel.vars) {
|
||||||
@@ -12314,19 +12423,34 @@ merge(Compressor.prototype, {
|
|||||||
for (var i = props.length; --i >= 0;) {
|
for (var i = props.length; --i >= 0;) {
|
||||||
var prop = props[i];
|
var prop = props[i];
|
||||||
if (prop.key !== key) continue;
|
if (prop.key !== key) continue;
|
||||||
if (!all(props, can_hoist_property)) break;
|
if (!all(props, can_hoist_property)) return;
|
||||||
if (!safe_to_flatten(prop.value, compressor)) break;
|
if (!safe_to_flatten(prop.value, compressor)) return;
|
||||||
props = props.map(function(prop) {
|
var scope, values = [];
|
||||||
return prop.value;
|
for (var j = 0; j < props.length; j++) {
|
||||||
});
|
var value = props[j].value;
|
||||||
if (prop instanceof AST_ObjectMethod
|
if (props[j] instanceof AST_ObjectMethod) {
|
||||||
&& prop.value instanceof AST_Function
|
var arrow = !(value.uses_arguments || is_generator(value) || value.contains_this());
|
||||||
&& !(compressor.parent() instanceof AST_Call)) {
|
if (arrow) {
|
||||||
if (prop.value.uses_arguments) break;
|
if (!scope) scope = compressor.find_parent(AST_Scope);
|
||||||
props[i] = make_node(AST_Arrow, prop.value, prop.value);
|
var avoid = avoid_await_yield(scope);
|
||||||
|
value.each_argname(function(argname) {
|
||||||
|
if (avoid[argname.name]) arrow = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var ctor;
|
||||||
|
if (arrow) {
|
||||||
|
ctor = is_async(value) ? AST_AsyncArrow : AST_Arrow;
|
||||||
|
} else if (i === j && !(compressor.parent() instanceof AST_Call)) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
ctor = value.CTOR;
|
||||||
|
}
|
||||||
|
value = make_node(ctor, value, value);
|
||||||
|
}
|
||||||
|
values.push(value);
|
||||||
}
|
}
|
||||||
return make_node(AST_Sub, this, {
|
return make_node(AST_Sub, this, {
|
||||||
expression: make_node(AST_Array, expr, { elements: props }),
|
expression: make_node(AST_Array, expr, { elements: values }),
|
||||||
property: make_node(AST_Number, this, { value: i }),
|
property: make_node(AST_Number, this, { value: i }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1152,8 +1152,9 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
function print_arrow(self, output) {
|
function print_arrow(self, output) {
|
||||||
if (self.argnames.length == 1 && self.argnames[0] instanceof AST_SymbolFunarg && !self.rest) {
|
var argname = self.argnames.length == 1 && !self.rest && self.argnames[0];
|
||||||
self.argnames[0].print(output);
|
if (argname instanceof AST_SymbolFunarg && argname.name != "yield") {
|
||||||
|
argname.print(output);
|
||||||
} else {
|
} else {
|
||||||
print_funargs(self, output);
|
print_funargs(self, output);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1316,6 +1316,11 @@ function parse($TEXT, options) {
|
|||||||
}
|
}
|
||||||
if (node instanceof AST_SymbolFunarg) return node;
|
if (node instanceof AST_SymbolFunarg) return node;
|
||||||
if (node instanceof AST_SymbolRef) return new AST_SymbolFunarg(node);
|
if (node instanceof AST_SymbolRef) return new AST_SymbolFunarg(node);
|
||||||
|
if (node instanceof AST_Yield) return new AST_SymbolFunarg({
|
||||||
|
start: node.start,
|
||||||
|
name: "yield",
|
||||||
|
end: node.end,
|
||||||
|
});
|
||||||
token_error(node.start, "Invalid arrow parameter");
|
token_error(node.start, "Invalid arrow parameter");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.14.3",
|
"version": "3.14.4",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -550,6 +550,24 @@ logical_side_effects: {
|
|||||||
node_version: ">=15"
|
node_version: ">=15"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
evaluate_lazy_assignment: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 42;
|
||||||
|
console.log(a &&= "PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=15"
|
||||||
|
}
|
||||||
|
|
||||||
issue_4815_1: {
|
issue_4815_1: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
|||||||
@@ -453,7 +453,7 @@ object_function: {
|
|||||||
}).f();
|
}).f();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(async function() {
|
(async () => {
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
@@ -2212,3 +2212,29 @@ issue_5159_2: {
|
|||||||
]
|
]
|
||||||
node_version: ">=8"
|
node_version: ">=8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5177: {
|
||||||
|
options = {
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(async function() {
|
||||||
|
return {
|
||||||
|
p(await) {},
|
||||||
|
}.p;
|
||||||
|
})().then(function(a) {
|
||||||
|
console.log(typeof a);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(async function() {
|
||||||
|
return {
|
||||||
|
p(await) {},
|
||||||
|
}.p;
|
||||||
|
})().then(function(a) {
|
||||||
|
console.log(typeof a);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|||||||
@@ -9253,13 +9253,13 @@ issue_4920_2: {
|
|||||||
console.log(b);
|
console.log(b);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var o = {
|
var o;
|
||||||
|
var a = "PASS", b;
|
||||||
|
({
|
||||||
get PASS() {
|
get PASS() {
|
||||||
a = "FAIL";
|
a = "FAIL";
|
||||||
},
|
},
|
||||||
};
|
})[b = a];
|
||||||
var a = "PASS", b;
|
|
||||||
o[b = a];
|
|
||||||
console.log(b);
|
console.log(b);
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
@@ -9283,16 +9283,47 @@ issue_4920_3: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var log = console.log;
|
var log = console.log;
|
||||||
var o = {
|
var o;
|
||||||
|
var a = "PASS", b;
|
||||||
|
({
|
||||||
get PASS() {
|
get PASS() {
|
||||||
a = "FAIL";
|
a = "FAIL";
|
||||||
},
|
},
|
||||||
|
})[b = a];
|
||||||
|
log(b);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4920_4: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var log = console.log;
|
||||||
|
var o = {
|
||||||
|
get [(a = "FAIL 1", "PASS")]() {
|
||||||
|
a = "FAIL 2";
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var a = "PASS", b;
|
||||||
|
o[b = a];
|
||||||
|
log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var log = console.log;
|
||||||
|
var o = {
|
||||||
|
get [(a = "FAIL 1", "PASS")]() {
|
||||||
|
a = "FAIL 2";
|
||||||
|
},
|
||||||
};
|
};
|
||||||
var a = "PASS", b;
|
var a = "PASS", b;
|
||||||
o[b = a];
|
o[b = a];
|
||||||
log(b);
|
log(b);
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_4935: {
|
issue_4935: {
|
||||||
@@ -9482,3 +9513,56 @@ issue_5112_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5182: {
|
||||||
|
options = {
|
||||||
|
arrows: true,
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
hoist_props: true,
|
||||||
|
inline: true,
|
||||||
|
merge_vars: true,
|
||||||
|
passes: 4,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var con = console;
|
||||||
|
global.log = con.log;
|
||||||
|
var jump = function(x) {
|
||||||
|
console.log("JUMP:", x * 10);
|
||||||
|
return x + x;
|
||||||
|
};
|
||||||
|
var jump2 = jump;
|
||||||
|
var run = function(x) {
|
||||||
|
console.log("RUN:", x * -10);
|
||||||
|
return x * x;
|
||||||
|
};
|
||||||
|
var run2 = run;
|
||||||
|
var bar = (x, y) => {
|
||||||
|
console.log("BAR:", x + y);
|
||||||
|
return x - y;
|
||||||
|
};
|
||||||
|
var bar2 = bar;
|
||||||
|
var obj = {
|
||||||
|
foo: bar2,
|
||||||
|
go: run2,
|
||||||
|
not_used: jump2,
|
||||||
|
};
|
||||||
|
console.log(obj.foo(1, 2), global.log("PASS"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var con = console;
|
||||||
|
global.log = con.log,
|
||||||
|
console.log((console.log("BAR:", 3), -1), global.log("PASS"));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"BAR: 3",
|
||||||
|
"PASS",
|
||||||
|
"-1 undefined",
|
||||||
|
]
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1938,3 +1938,22 @@ issue_5138_2: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5192: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
ie: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function a(a, [] = a = "PASS") {
|
||||||
|
console.log(a);
|
||||||
|
})("FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function a(a, [] = a = "PASS") {
|
||||||
|
console.log(a);
|
||||||
|
})("FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1581,6 +1581,75 @@ hoist_vars: {
|
|||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
singleton_1: {
|
||||||
|
options = {
|
||||||
|
pure_getters: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var [ a ] = "P", b, o = {};
|
||||||
|
[ { 1: o.p } ] = [ "FAIL" ];
|
||||||
|
({ foo: [ o.q ] } = { foo: "S" });
|
||||||
|
[ b = "S" ] = [];
|
||||||
|
console.log(a + o.p + o.q + b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b, a = "P"[0], o = {};
|
||||||
|
o.p = [ "FAIL"["1"] ][0];
|
||||||
|
o.q = { foo: "S"[0] }["foo"];
|
||||||
|
[ b = "S" ] = [];
|
||||||
|
console.log(a + o.p + o.q + b);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
singleton_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
passes: 2,
|
||||||
|
pure_getters: true,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var [ a ] = "P", b, o = {};
|
||||||
|
[ { 1: o.p } ] = [ "FAIL" ];
|
||||||
|
({ foo: [ o.q ] } = { foo: "S" });
|
||||||
|
[ b = "S" ] = [];
|
||||||
|
console.log(a + o.p + o.q + b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b, a = "P", o = {};
|
||||||
|
o.p = "A";
|
||||||
|
o.q = "S";
|
||||||
|
[ b = "S" ] = [];
|
||||||
|
console.log(a + o.p + o.q + b);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
singleton_side_effects: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
[ 42[console.log("foo")] ] = [ console.log("bar") ];
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
[ 42[console.log("foo")] ] = [ console.log("bar") ];
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"bar",
|
||||||
|
"foo",
|
||||||
|
]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
issue_4280: {
|
issue_4280: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
@@ -3225,3 +3294,75 @@ issue_5153_object_var: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5168: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function a({
|
||||||
|
[console.log(typeof function() {
|
||||||
|
++a;
|
||||||
|
return a;
|
||||||
|
}())]: b,
|
||||||
|
}) {
|
||||||
|
var a;
|
||||||
|
})({});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function a({
|
||||||
|
[console.log(typeof function() {
|
||||||
|
++a;
|
||||||
|
return a;
|
||||||
|
}())]: b,
|
||||||
|
}) {
|
||||||
|
var a;
|
||||||
|
})({});
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5189_1: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 42;
|
||||||
|
[ a.p ] = a = "PASS";
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
[ a.p ] = a = "PASS";
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5189_2: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 42;
|
||||||
|
({ p: a.q } = a = "PASS");
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
({ p: a.q } = a = "PASS");
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|||||||
@@ -2916,7 +2916,7 @@ issue_4133: {
|
|||||||
console.log(a);
|
console.log(a);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var b = 1;
|
var a = 1;
|
||||||
console.log(0);
|
console.log(0);
|
||||||
}
|
}
|
||||||
expect_stdout: "0"
|
expect_stdout: "0"
|
||||||
@@ -3062,7 +3062,7 @@ issue_4184: {
|
|||||||
expect_stdout: "42"
|
expect_stdout: "42"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_4235: {
|
issue_4235_1: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
@@ -3081,13 +3081,37 @@ issue_4235: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
void function() {
|
void function() {
|
||||||
var f;
|
var f = console.log(f);
|
||||||
console.log(f);
|
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4235_2: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
varify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
{
|
||||||
|
const f = 0;
|
||||||
|
}
|
||||||
|
(function f() {
|
||||||
|
var f = console.log(f);
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(void 0);
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
issue_4404: {
|
issue_4404: {
|
||||||
options = {
|
options = {
|
||||||
pure_getters: "strict",
|
pure_getters: "strict",
|
||||||
|
|||||||
@@ -4857,8 +4857,9 @@ issue_4155: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function() {
|
(function() {
|
||||||
void console.log(b);
|
var a;
|
||||||
var b = function() {};
|
void console.log(a);
|
||||||
|
function b() {}
|
||||||
b && console.log(typeof b);
|
b && console.log(typeof b);
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
@@ -6655,3 +6656,49 @@ issue_5140: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "42"
|
expect_stdout: "42"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5173_1: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
f([ A = 42, [] + "" || (A = f) ]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
f([ A = 42, [] + "" || (A = f) ]);
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5173_2: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
f([ A = 42, [] + "" || (A = f) ]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
f(A = [] + "" ? 42 : f);
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|||||||
@@ -217,7 +217,8 @@ name_collision_1: {
|
|||||||
var obj_foo = 1;
|
var obj_foo = 1;
|
||||||
var obj_bar = 2;
|
var obj_bar = 2;
|
||||||
function f() {
|
function f() {
|
||||||
var obj_foo$0 = 3,
|
var obj,
|
||||||
|
obj_foo$0 = 3,
|
||||||
obj_bar = 4,
|
obj_bar = 4,
|
||||||
obj_b_r = 5,
|
obj_b_r = 5,
|
||||||
obj_b_r$0 = 6,
|
obj_b_r$0 = 6,
|
||||||
@@ -249,7 +250,8 @@ name_collision_2: {
|
|||||||
console.log(o.p === o.p, o["+"](4), o["-"](5), o__$0, o__$1);
|
console.log(o.p === o.p, o["+"](4), o["-"](5), o__$0, o__$1);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var o_p = 1,
|
var o,
|
||||||
|
o_p = 1,
|
||||||
o__ = function(x) {
|
o__ = function(x) {
|
||||||
return x;
|
return x;
|
||||||
},
|
},
|
||||||
@@ -283,7 +285,8 @@ name_collision_3: {
|
|||||||
console.log(o.p === o.p, o["+"](4), o["-"](5));
|
console.log(o.p === o.p, o["+"](4), o["-"](5));
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var o_p = 1,
|
var o,
|
||||||
|
o_p = 1,
|
||||||
o__ = function(x) {
|
o__ = function(x) {
|
||||||
return x;
|
return x;
|
||||||
},
|
},
|
||||||
@@ -315,7 +318,7 @@ name_collision_4: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function() {
|
console.log(function() {
|
||||||
var o_p$0 = 0, o_q = "PASS";
|
var o, o_p$0 = 0, o_q = "PASS";
|
||||||
return function(o_p) {
|
return function(o_p) {
|
||||||
if (!o_p$0) return o_p;
|
if (!o_p$0) return o_p;
|
||||||
}(o_q);
|
}(o_q);
|
||||||
@@ -768,7 +771,7 @@ issue_3046: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(function(a) {
|
console.log(function(a) {
|
||||||
do {
|
do {
|
||||||
var b_c = a++;
|
var b, b_c = a++;
|
||||||
} while (b_c && a);
|
} while (b_c && a);
|
||||||
return a;
|
return a;
|
||||||
}(0));
|
}(0));
|
||||||
@@ -931,7 +934,7 @@ issue_3411: {
|
|||||||
expect: {
|
expect: {
|
||||||
var c = 1;
|
var c = 1;
|
||||||
!function f() {
|
!function f() {
|
||||||
var o_p = --c && f();
|
var o, o_p = --c && f();
|
||||||
+{} || console.log("PASS");
|
+{} || console.log("PASS");
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
@@ -1042,9 +1045,7 @@ issue_3945_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
function f() {
|
function f() {
|
||||||
o.p;
|
o.p;
|
||||||
var o = {
|
var o, o_q = 0;
|
||||||
q: 0,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1063,9 +1064,7 @@ issue_3945_2: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(typeof o);
|
console.log(typeof o);
|
||||||
var o = {
|
var o, o_p = 0;
|
||||||
p: 0,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
}
|
}
|
||||||
@@ -1134,10 +1133,46 @@ issue_4985: {
|
|||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a_p = 42;
|
var a, a_p = 42;
|
||||||
console.log(function() {
|
console.log(function() {
|
||||||
({});
|
({});
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5182: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
merge_vars: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = console;
|
||||||
|
log = o.log;
|
||||||
|
o = {
|
||||||
|
p: function(a) {
|
||||||
|
console.log(a ? "PASS" : "FAIL");
|
||||||
|
return a;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
log(o.p(42));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o_p = console;
|
||||||
|
log = o_p.log;
|
||||||
|
o_p = function(a) {
|
||||||
|
console.log(a ? "PASS" : "FAIL");
|
||||||
|
return a;
|
||||||
|
};
|
||||||
|
log(o_p(42));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"42",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ issue_2295: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_4487: {
|
issue_4487_1: {
|
||||||
options = {
|
options = {
|
||||||
functions: true,
|
functions: true,
|
||||||
hoist_vars: true,
|
hoist_vars: true,
|
||||||
@@ -150,16 +150,64 @@ issue_4487: {
|
|||||||
};
|
};
|
||||||
var b = a();
|
var b = a();
|
||||||
}
|
}
|
||||||
|
expect: {
|
||||||
|
var a = function f() {
|
||||||
|
var f = console.log(typeof f);
|
||||||
|
};
|
||||||
|
a();
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4487_2: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
hoist_vars: true,
|
||||||
|
keep_fnames: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = function f() {
|
||||||
|
var f = console.log(typeof f);
|
||||||
|
};
|
||||||
|
var b = a();
|
||||||
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function a() {
|
function a() {
|
||||||
var f;
|
var f = console.log(typeof f);
|
||||||
console.log(typeof f);
|
|
||||||
}
|
}
|
||||||
a();
|
a();
|
||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4487_3: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
hoist_vars: true,
|
||||||
|
keep_fnames: true,
|
||||||
|
passes: 3,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = function f() {
|
||||||
|
var f = console.log(typeof f);
|
||||||
|
};
|
||||||
|
var b = a();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function a() {
|
||||||
|
console.log(typeof void 0);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
issue_4489: {
|
issue_4489: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
@@ -251,18 +299,18 @@ issue_4839: {
|
|||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var o = function(a, b) {
|
var log = console.log, o = function(a, b) {
|
||||||
return b && b;
|
return b && b;
|
||||||
}("foo");
|
}("foo");
|
||||||
for (var k in o)
|
for (var k in o)
|
||||||
throw "FAIL";
|
throw "FAIL";
|
||||||
console.log("PASS");
|
log("PASS");
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var k, o = void 0;
|
var k, log = console.log;
|
||||||
for (k in o)
|
for (k in void 0)
|
||||||
throw "FAIL";
|
throw "FAIL";
|
||||||
console.log("PASS");
|
log("PASS");
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
@@ -288,8 +336,7 @@ issue_4859: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function f(a) {
|
(function f(a) {
|
||||||
var d = 1 / 0, d = Infinity;
|
console.log(Infinity);
|
||||||
console.log(d);
|
|
||||||
return f;
|
return f;
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
@@ -395,3 +442,61 @@ issue_4898: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5187: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
hoist_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a = 42;
|
||||||
|
do {
|
||||||
|
var b = { 0: a++ };
|
||||||
|
} while (console.log(b[b ^= 0]));
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
var b, a = 42;
|
||||||
|
do {
|
||||||
|
b = { 0: a++ };
|
||||||
|
} while (console.log(b[b ^= 0]));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5195: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
hoist_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a;
|
||||||
|
do {
|
||||||
|
var b = { p: a };
|
||||||
|
} while (console.log(b += ""));
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
var a, b;
|
||||||
|
do {
|
||||||
|
b = { p: a };
|
||||||
|
} while (console.log(b += ""));
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "[object Object]"
|
||||||
|
}
|
||||||
|
|||||||
@@ -489,6 +489,116 @@ join_object_assignments_regex: {
|
|||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chained_assignments: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b = a = {};
|
||||||
|
b.p = "PASS";
|
||||||
|
console.log(a.p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b = a = {
|
||||||
|
p: "PASS",
|
||||||
|
};
|
||||||
|
console.log(a.p);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
folded_assignments_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = {};
|
||||||
|
a[a.PASS = 42] = "PASS";
|
||||||
|
console.log(a[42], a.PASS);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = {
|
||||||
|
PASS: 42,
|
||||||
|
42: "PASS",
|
||||||
|
};
|
||||||
|
console.log(a[42], a.PASS);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS 42"
|
||||||
|
}
|
||||||
|
|
||||||
|
folded_assignments_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var a = {};
|
||||||
|
a[42] = "FAIL";
|
||||||
|
a[a.PASS = 42] = "PASS";
|
||||||
|
console.log(a[42], a.PASS);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var a = {
|
||||||
|
42: "FAIL",
|
||||||
|
PASS: 42,
|
||||||
|
};
|
||||||
|
a[42] = "PASS";
|
||||||
|
console.log(a[42], a.PASS);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS 42"
|
||||||
|
}
|
||||||
|
|
||||||
|
inlined_assignments: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
(a = {}).p = "PASS";
|
||||||
|
console.log(a.p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = {
|
||||||
|
p: "PASS",
|
||||||
|
};
|
||||||
|
console.log(a.p);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
typescript_enum: {
|
||||||
|
rename = true
|
||||||
|
options = {
|
||||||
|
assignments: true,
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
hoist_props: true,
|
||||||
|
inline: true,
|
||||||
|
join_vars: true,
|
||||||
|
passes: 4,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var Enum;
|
||||||
|
(function (Enum) {
|
||||||
|
Enum[Enum.PASS = 42] = "PASS";
|
||||||
|
})(Enum || (Enum = {}));
|
||||||
|
console.log(Enum[42], Enum.PASS);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("PASS", 42);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS 42"
|
||||||
|
}
|
||||||
|
|
||||||
issue_2816: {
|
issue_2816: {
|
||||||
options = {
|
options = {
|
||||||
join_vars: true,
|
join_vars: true,
|
||||||
@@ -1183,3 +1293,26 @@ assign_sequence_var: {
|
|||||||
"1 2 3",
|
"1 2 3",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5175: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function log(f) {
|
||||||
|
console.log(f(), A.p);
|
||||||
|
}
|
||||||
|
log(function() {
|
||||||
|
return (A = {}).p = "PASS";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function log(f) {
|
||||||
|
console.log(f(), A.p);
|
||||||
|
}
|
||||||
|
log(function() {
|
||||||
|
return (A = {}).p = "PASS";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -476,9 +476,9 @@ issue_4112: {
|
|||||||
try {
|
try {
|
||||||
throw 42;
|
throw 42;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
var a = e;
|
var o = e;
|
||||||
for (e in a);
|
for (e in o);
|
||||||
a = function() {};
|
function a() {}
|
||||||
console.log(typeof a);
|
console.log(typeof a);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
@@ -3377,3 +3377,60 @@ issue_4956_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "42"
|
expect_stdout: "42"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5182: {
|
||||||
|
options = {
|
||||||
|
arrows: true,
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
hoist_props: true,
|
||||||
|
inline: true,
|
||||||
|
merge_vars: true,
|
||||||
|
passes: 4,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
var con = console;
|
||||||
|
} catch (x) {}
|
||||||
|
global.log = con.log;
|
||||||
|
var jump = function(x) {
|
||||||
|
console.log("JUMP:", x * 10);
|
||||||
|
return x + x;
|
||||||
|
};
|
||||||
|
var jump2 = jump;
|
||||||
|
var run = function(x) {
|
||||||
|
console.log("RUN:", x * -10);
|
||||||
|
return x * x;
|
||||||
|
};
|
||||||
|
var run2 = run;
|
||||||
|
var bar = (x, y) => {
|
||||||
|
console.log("BAR:", x + y);
|
||||||
|
return x - y;
|
||||||
|
};
|
||||||
|
var bar2 = bar;
|
||||||
|
var obj = {
|
||||||
|
foo: bar2,
|
||||||
|
go: run2,
|
||||||
|
not_used: jump2,
|
||||||
|
};
|
||||||
|
console.log(obj.foo(1, 2), global.log("PASS"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
var con = console;
|
||||||
|
} catch (x) {}
|
||||||
|
global.log = con.log,
|
||||||
|
console.log((console.log("BAR:", 3), -1), global.log("PASS"));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"BAR: 3",
|
||||||
|
"PASS",
|
||||||
|
"-1 undefined",
|
||||||
|
]
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1510,3 +1510,71 @@ issue_5093_quote_style: {
|
|||||||
expect_exact: 'console.log({a:true,\'42\':"PASS","null":[]}[6*7]);'
|
expect_exact: 'console.log({a:true,\'42\':"PASS","null":[]}[6*7]);'
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object_methods: {
|
||||||
|
options = {
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
({
|
||||||
|
p() {
|
||||||
|
console.log("FAIL 1");
|
||||||
|
},
|
||||||
|
*q() {
|
||||||
|
console.log("FAIL 2");
|
||||||
|
},
|
||||||
|
async r() {
|
||||||
|
console.log("FAIL 3");
|
||||||
|
},
|
||||||
|
async *s() {
|
||||||
|
console.log("PASS");
|
||||||
|
},
|
||||||
|
}).s().next();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
[
|
||||||
|
() => {
|
||||||
|
console.log("FAIL 1");
|
||||||
|
},
|
||||||
|
function*() {
|
||||||
|
console.log("FAIL 2");
|
||||||
|
},
|
||||||
|
async () => {
|
||||||
|
console.log("FAIL 3");
|
||||||
|
},
|
||||||
|
async function*() {
|
||||||
|
console.log("PASS");
|
||||||
|
},
|
||||||
|
][3]().next();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=10"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5177: {
|
||||||
|
options = {
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
var o = { a: "PASS" };
|
||||||
|
o.p = {
|
||||||
|
q() {
|
||||||
|
return this.a;
|
||||||
|
},
|
||||||
|
}.q;
|
||||||
|
console.log(o.p());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
var o = { a: "PASS" };
|
||||||
|
o.p = {
|
||||||
|
q() {
|
||||||
|
return this.a;
|
||||||
|
},
|
||||||
|
}.q;
|
||||||
|
console.log(o.p());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1640,6 +1640,26 @@ nested_property_assignments_3: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nested_property_assignments_4: {
|
||||||
|
options = {
|
||||||
|
pure_getters: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var n, o = { p: { q: { r: "PASS" } } };
|
||||||
|
(n = o.p).r = n.q.r;
|
||||||
|
console.log(o.p.r);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var n, o = { p: { q: { r: "PASS" } } };
|
||||||
|
(n = o.p).r = n.q.r;
|
||||||
|
console.log(o.p.r);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
issue_4939: {
|
issue_4939: {
|
||||||
options = {
|
options = {
|
||||||
pure_getters: "strict",
|
pure_getters: "strict",
|
||||||
|
|||||||
@@ -7320,6 +7320,64 @@ local_assignment_loop: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local_assignment_modified: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
(a = a || {}).p = 42;
|
||||||
|
console.log(a.p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
(a = {}).p = 42;
|
||||||
|
console.log(a.p);
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
local_declaration: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
a || console.log(a = "PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
local_definition_modified: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = a || {};
|
||||||
|
a.p = 42;
|
||||||
|
console.log(a.p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = {};
|
||||||
|
a.p = 42;
|
||||||
|
console.log(a.p);
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
issue_3957_1: {
|
issue_3957_1: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
@@ -7435,6 +7493,7 @@ issue_4030: {
|
|||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
toplevel: true,
|
toplevel: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1044,13 +1044,13 @@ issue_5100_1: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a;
|
var a;
|
||||||
[ {
|
({
|
||||||
p: {},
|
p: {},
|
||||||
...a
|
...a
|
||||||
} ] = [ {
|
} = [ {
|
||||||
p: [ a = 42["q"] ],
|
p: [ a = 42["q"] ],
|
||||||
r: "PASS",
|
r: "PASS",
|
||||||
} ];
|
} ][0]);
|
||||||
console.log(a.r);
|
console.log(a.r);
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
@@ -1077,12 +1077,12 @@ issue_5100_2: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a;
|
var a;
|
||||||
[ {
|
({
|
||||||
p: {},
|
p: {},
|
||||||
...a
|
...a
|
||||||
} ] = [ {
|
} = [ {
|
||||||
p: [ console.log("PASS"), a = 42["q"] ],
|
p: [ console.log("PASS"), a = 42["q"] ],
|
||||||
} ];
|
} ][0]);
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=10"
|
node_version: ">=10"
|
||||||
@@ -1151,3 +1151,57 @@ issue_5128_2: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5165_1: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
rests: true,
|
||||||
|
side_effects: true,
|
||||||
|
switches: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function([ ...a ]) {
|
||||||
|
switch (a) {
|
||||||
|
case a:
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
}([]));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function([ ...a ]) {
|
||||||
|
return "PASS";
|
||||||
|
}([]));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5165_2: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
rests: true,
|
||||||
|
side_effects: true,
|
||||||
|
switches: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(...a) {
|
||||||
|
switch (a) {
|
||||||
|
case a:
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|||||||
@@ -201,3 +201,20 @@ issue_4811_2: {
|
|||||||
expect_stdout: "PASS [object global] true"
|
expect_stdout: "PASS [object global] true"
|
||||||
node_version: ">=8"
|
node_version: ">=8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5197: {
|
||||||
|
rename = true
|
||||||
|
input: {
|
||||||
|
function f(async) {
|
||||||
|
async(")=>{}");
|
||||||
|
}
|
||||||
|
console.log("" + this.__proto__);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
a(")=>{}");
|
||||||
|
}
|
||||||
|
console.log("" + this.__proto__);
|
||||||
|
}
|
||||||
|
expect_stdout: "[object global]"
|
||||||
|
}
|
||||||
|
|||||||
@@ -743,3 +743,29 @@ issue_5145_2: {
|
|||||||
]
|
]
|
||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5199: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = function() {
|
||||||
|
console.log(typeof b);
|
||||||
|
}``;
|
||||||
|
{
|
||||||
|
const b = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = function() {
|
||||||
|
console.log(typeof b);
|
||||||
|
}``;
|
||||||
|
{
|
||||||
|
const b = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ hoist_props_const: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var o_p = "PASS";
|
var o = 0, o_p = "PASS";
|
||||||
console.log(o_p);
|
console.log(o_p);
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
@@ -136,7 +136,7 @@ hoist_props_let: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
"use strict";
|
"use strict";
|
||||||
var o_p = "PASS";
|
var o, o_p = "PASS";
|
||||||
console.log(o_p);
|
console.log(o_p);
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ pause_resume: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
arrow_yield: {
|
arrow_yield_1: {
|
||||||
input: {
|
input: {
|
||||||
yield = "PASS";
|
yield = "PASS";
|
||||||
console.log(function*() {
|
console.log(function*() {
|
||||||
@@ -108,6 +108,18 @@ arrow_yield: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arrow_yield_2: {
|
||||||
|
input: {
|
||||||
|
console.log(typeof function *() {
|
||||||
|
// Syntax error on Node.js v6+
|
||||||
|
return (yield) => {};
|
||||||
|
}().next().value);
|
||||||
|
}
|
||||||
|
expect_exact: "console.log(typeof function*(){return(yield)=>{}}().next().value);"
|
||||||
|
expect_stdout: "function"
|
||||||
|
node_version: "4"
|
||||||
|
}
|
||||||
|
|
||||||
for_of: {
|
for_of: {
|
||||||
input: {
|
input: {
|
||||||
function* f() {
|
function* f() {
|
||||||
@@ -1275,3 +1287,25 @@ issue_5076: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5177: {
|
||||||
|
options = {
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(typeof function*() {
|
||||||
|
return {
|
||||||
|
p(yield) {},
|
||||||
|
}.p;
|
||||||
|
}().next().value);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(typeof function*() {
|
||||||
|
return {
|
||||||
|
p(yield) {},
|
||||||
|
}.p;
|
||||||
|
}().next().value);
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ if (typeof phantom == "undefined") {
|
|||||||
npm([
|
npm([
|
||||||
"install",
|
"install",
|
||||||
"graceful-fs@4.2.6",
|
"graceful-fs@4.2.6",
|
||||||
|
"is-my-json-valid@2.20.5",
|
||||||
"phantomjs-prebuilt@2.1.14",
|
"phantomjs-prebuilt@2.1.14",
|
||||||
"--no-audit",
|
"--no-audit",
|
||||||
"--no-optional",
|
"--no-optional",
|
||||||
|
|||||||
@@ -4,34 +4,27 @@ var UglifyJS = require("../..");
|
|||||||
|
|
||||||
describe("spidermonkey export/import sanity test", function() {
|
describe("spidermonkey export/import sanity test", function() {
|
||||||
it("Should produce a functional build when using --self with spidermonkey", function(done) {
|
it("Should produce a functional build when using --self with spidermonkey", function(done) {
|
||||||
this.timeout(60000);
|
this.timeout(120000);
|
||||||
|
|
||||||
var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs';
|
var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs';
|
||||||
var command = uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey | " +
|
var command = [
|
||||||
uglifyjs + " -p spidermonkey -cm";
|
uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey",
|
||||||
|
uglifyjs + " -p spidermonkey -cm",
|
||||||
exec(command, {
|
].join(" | ");
|
||||||
maxBuffer: 1048576
|
exec(command, { maxBuffer: 1048576 }, function(err, stdout) {
|
||||||
}, function(err, stdout) {
|
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
|
||||||
eval(stdout);
|
eval(stdout);
|
||||||
assert.strictEqual(typeof SpiderUglify, "object");
|
assert.strictEqual(typeof SpiderUglify, "object");
|
||||||
var result = SpiderUglify.minify("foo([true,,2+3]);");
|
var result = SpiderUglify.minify("foo([true,,2+3]);");
|
||||||
assert.strictEqual(result.error, undefined);
|
assert.strictEqual(result.error, undefined);
|
||||||
assert.strictEqual(result.code, "foo([!0,,5]);");
|
assert.strictEqual(result.code, "foo([!0,,5]);");
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should not add unnecessary escape slashes to regexps", function() {
|
it("Should not add unnecessary escape slashes to RegExp", function() {
|
||||||
var input = "/[\\\\/]/;";
|
var input = "/[\\\\/]/;";
|
||||||
var ast = UglifyJS.parse(input).to_mozilla_ast();
|
var ast = UglifyJS.parse(input).to_mozilla_ast();
|
||||||
assert.equal(
|
assert.strictEqual(UglifyJS.AST_Node.from_mozilla_ast(ast).print_to_string(), input);
|
||||||
UglifyJS.AST_Node.from_mozilla_ast(ast).print_to_string(),
|
|
||||||
input
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should judge between directives and strings correctly on import", function() {
|
it("Should judge between directives and strings correctly on import", function() {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ exports.run_code = semver.satisfies(process.version, "0.8") ? function(code, top
|
|||||||
if ([
|
if ([
|
||||||
/\basync[ \t]*\([\s\S]*?\)[ \t]*=>/,
|
/\basync[ \t]*\([\s\S]*?\)[ \t]*=>/,
|
||||||
/\b(async[ \t]+function|Promise|setImmediate|setInterval|setTimeout)\b/,
|
/\b(async[ \t]+function|Promise|setImmediate|setInterval|setTimeout)\b/,
|
||||||
/\basync([ \t]+|[ \t]*#|[ \t]*\*[ \t]*)[^\s()[\]{}#,.&|!~=*%/+-]+(\s*\(|[ \t]*=>)/,
|
/\basync([ \t]+|[ \t]*#|[ \t]*\*[ \t]*)[^\s()[\]{}#:;,.&|!~=*%/+-]+(\s*\(|[ \t]*=>)/,
|
||||||
].some(function(pattern) {
|
].some(function(pattern) {
|
||||||
return pattern.test(code);
|
return pattern.test(code);
|
||||||
})) {
|
})) {
|
||||||
@@ -202,13 +202,11 @@ function setup(global, builtins, setup_log, setup_tty) {
|
|||||||
});
|
});
|
||||||
Object.defineProperties(global, props);
|
Object.defineProperties(global, props);
|
||||||
// for Node.js v8+
|
// for Node.js v8+
|
||||||
if (global.toString !== Object.prototype.toString) {
|
global.__proto__ = Object.defineProperty(Object.create(global.__proto__), "toString", {
|
||||||
global.__proto__ = Object.defineProperty(Object.create(global.__proto__), "toString", {
|
value: function() {
|
||||||
value: function() {
|
return "[object global]";
|
||||||
return "[object global]";
|
},
|
||||||
},
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function self() {
|
function self() {
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
Reference in New Issue
Block a user