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:
|
||||
strategy:
|
||||
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 ]
|
||||
script: [ compress, mocha, release/benchmark, release/jetstream ]
|
||||
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
|
||||
|
||||
@@ -1999,7 +1999,7 @@ TreeWalker.prototype = {
|
||||
},
|
||||
find_parent: function(type) {
|
||||
var stack = this.stack;
|
||||
for (var i = stack.length; --i >= 0;) {
|
||||
for (var i = stack.length - 1; --i >= 0;) {
|
||||
var x = stack[i];
|
||||
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")) {
|
||||
node.process_expression(true);
|
||||
}
|
||||
var merge_vars = this.options.merge_vars;
|
||||
var passes = +this.options.passes || 1;
|
||||
var min_count = 1 / 0;
|
||||
var stopping = false;
|
||||
@@ -211,6 +212,7 @@ merge(Compressor.prototype, {
|
||||
node.figure_out_scope(mangle);
|
||||
if (pass > 0 || this.option("reduce_vars"))
|
||||
node.reset_opt_flags(this);
|
||||
this.options.merge_vars = merge_vars && (stopping || pass == passes - 1);
|
||||
node = node.transform(this);
|
||||
if (passes > 1) {
|
||||
var count = 0;
|
||||
@@ -259,8 +261,8 @@ merge(Compressor.prototype, {
|
||||
descend(node, this);
|
||||
var opt = node.optimize(this);
|
||||
if (is_scope && opt === node && !this.has_directive("use asm") && !opt.pinned()) {
|
||||
opt.merge_variables(this);
|
||||
opt.drop_unused(this);
|
||||
if (opt.merge_variables(this)) opt.drop_unused(this);
|
||||
descend(opt, this);
|
||||
}
|
||||
if (opt === node) opt._squeezed = true;
|
||||
@@ -389,7 +391,18 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
var lhs = is_lhs(node, parent);
|
||||
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_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 (!lazy_op[parent.operator]) return;
|
||||
return is_modified(compressor, tw, parent, parent, level + 1);
|
||||
@@ -445,7 +458,7 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
|
||||
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;
|
||||
return all(def.orig, function(sym) {
|
||||
if (sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet) {
|
||||
@@ -602,12 +615,14 @@ merge(Compressor.prototype, {
|
||||
if (def.single_use == "m") return false;
|
||||
var safe = tw.safe_ids[def.id];
|
||||
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 (is_arguments(def)) return false;
|
||||
if (def.global && def.name == "arguments") return false;
|
||||
tw.loop_ids[def.id] = null;
|
||||
def.fixed = make_node(AST_Undefined, def.orig[0]);
|
||||
if (in_order) delete def.safe_ids;
|
||||
return true;
|
||||
}
|
||||
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) {
|
||||
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];
|
||||
if (def.safe_ids) {
|
||||
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 (!d.escaped.depth || d.escaped.depth > depth) d.escaped.depth = depth;
|
||||
if (d.scope.resolve() !== scope.resolve()) d.escaped.cross_scope = true;
|
||||
if (d.fixed) d.fixed.escaped = d.escaped;
|
||||
return;
|
||||
} else if (value_in_use(node, parent)) {
|
||||
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_Unary && !unary_side_effects[parent.operator]) return;
|
||||
d.direct_access = true;
|
||||
if (d.fixed) d.fixed.direct_access = true;
|
||||
}
|
||||
|
||||
function mark_assignment_to_arguments(node) {
|
||||
@@ -759,11 +776,13 @@ merge(Compressor.prototype, {
|
||||
node.walk(scanner);
|
||||
});
|
||||
if (node.rest) {
|
||||
var fixed_node;
|
||||
if (save) fixed = compressor.option("rests") && function() {
|
||||
var value = save();
|
||||
return value instanceof AST_Array ? make_node(AST_Array, node, {
|
||||
elements: value.elements.slice(node.elements.length),
|
||||
}) : node;
|
||||
if (!(value instanceof AST_Array)) return node;
|
||||
if (!fixed_node) fixed_node = make_node(AST_Array, node);
|
||||
fixed_node.elements = value.elements.slice(node.elements.length);
|
||||
return fixed_node;
|
||||
};
|
||||
node.rest.walk(scanner);
|
||||
}
|
||||
@@ -843,11 +862,12 @@ merge(Compressor.prototype, {
|
||||
return arg || make_node(AST_Undefined, iife);
|
||||
}, visit);
|
||||
});
|
||||
var rest = fn.rest;
|
||||
var rest = fn.rest, fixed_node;
|
||||
if (rest) scan_declaration(tw, compressor, rest, compressor.option("rests") && function() {
|
||||
return fn.rest === rest ? make_node(AST_Array, fn, {
|
||||
elements: iife.args.slice(fn.argnames.length),
|
||||
}) : rest;
|
||||
if (fn.rest !== rest) return rest;
|
||||
if (!fixed_node) fixed_node = make_node(AST_Array, fn);
|
||||
fixed_node.elements = iife.args.slice(fn.argnames.length);
|
||||
return fixed_node;
|
||||
}, visit);
|
||||
walk_lambda(fn, tw);
|
||||
var safe_ids = tw.safe_ids;
|
||||
@@ -899,30 +919,22 @@ merge(Compressor.prototype, {
|
||||
case "&&=":
|
||||
case "||=":
|
||||
case "??=":
|
||||
left.walk(tw);
|
||||
push(tw);
|
||||
if (scan) {
|
||||
right.walk(tw);
|
||||
walk_assign();
|
||||
} else {
|
||||
mark_assignment_to_arguments(left);
|
||||
right.walk(tw);
|
||||
}
|
||||
pop(tw);
|
||||
return true;
|
||||
var lazy = true;
|
||||
default:
|
||||
if (!scan) {
|
||||
mark_assignment_to_arguments(left);
|
||||
return;
|
||||
return walk_lazy();
|
||||
}
|
||||
ld.assignments++;
|
||||
var fixed = ld.fixed;
|
||||
if (is_modified(compressor, tw, node, node, 0)) {
|
||||
ld.fixed = false;
|
||||
return;
|
||||
return walk_lazy();
|
||||
}
|
||||
var safe = safe_to_read(tw, ld);
|
||||
if (lazy) push(tw);
|
||||
right.walk(tw);
|
||||
if (lazy) pop(tw);
|
||||
if (safe && !left.in_arg && safe_to_assign(tw, ld)) {
|
||||
push_ref(ld, left);
|
||||
mark(tw, ld);
|
||||
@@ -978,7 +990,13 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
var d = sym.definition();
|
||||
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);
|
||||
mark(tw, d);
|
||||
if (left instanceof AST_Destructured
|
||||
@@ -986,15 +1004,21 @@ merge(Compressor.prototype, {
|
||||
d.single_use = false;
|
||||
}
|
||||
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.assigns = [ node ];
|
||||
} else {
|
||||
walk();
|
||||
d.fixed = false;
|
||||
mark_escaped(tw, d, sym.scope, node, right, 0, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function walk_lazy() {
|
||||
if (!lazy) return;
|
||||
left.walk(tw);
|
||||
push(tw);
|
||||
right.walk(tw);
|
||||
pop(tw);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
def(AST_Binary, function(tw) {
|
||||
if (!lazy_op[this.operator]) return;
|
||||
@@ -1261,7 +1285,7 @@ merge(Compressor.prototype, {
|
||||
if (!safe) return;
|
||||
safe.assign = true;
|
||||
});
|
||||
if (d.fixed === false) {
|
||||
if (d.fixed === false || d.fixed === 0) {
|
||||
var redef = d.redefined();
|
||||
if (redef && cross_scope(d.scope, this.scope)) redef.single_use = false;
|
||||
} else if (d.fixed === undefined || !safe_to_read(tw, d)) {
|
||||
@@ -1286,7 +1310,7 @@ merge(Compressor.prototype, {
|
||||
if (d.single_use) {
|
||||
d.single_use = "m";
|
||||
} else {
|
||||
d.fixed = false;
|
||||
d.fixed = 0;
|
||||
}
|
||||
}
|
||||
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() {
|
||||
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 (this.fixed) fixed = this.fixed;
|
||||
return fixed instanceof AST_Node ? fixed : fixed();
|
||||
var value = fixed instanceof AST_Node ? fixed : fixed();
|
||||
return value.is_constant() && value;
|
||||
});
|
||||
|
||||
AST_SymbolRef.DEFMETHOD("is_immutable", function() {
|
||||
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);
|
||||
@@ -2879,8 +2908,9 @@ merge(Compressor.prototype, {
|
||||
if (!value) {
|
||||
value = node;
|
||||
var def = node.definition();
|
||||
var escaped = node.fixed && node.fixed.escaped || def.escaped;
|
||||
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))) {
|
||||
well_defined = false;
|
||||
}
|
||||
@@ -2888,8 +2918,33 @@ merge(Compressor.prototype, {
|
||||
} else if (node instanceof AST_ObjectIdentity) {
|
||||
value = node;
|
||||
}
|
||||
if (value) lvalues.add(node.name, is_modified(compressor, tw, node, value, 0));
|
||||
if (find_arguments && node instanceof AST_Sub) {
|
||||
if (value) {
|
||||
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) {
|
||||
if (!compressor.option("reduce_vars") || argname.definition().assignments) {
|
||||
if (!argname.definition().fixed) well_defined = false;
|
||||
@@ -2996,7 +3051,10 @@ merge(Compressor.prototype, {
|
||||
return false;
|
||||
}
|
||||
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) {
|
||||
@@ -3346,10 +3404,10 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
statements.length = n;
|
||||
CHANGED = n != len;
|
||||
if (has_quit) has_quit.forEach(function(stat) {
|
||||
extract_declarations_from_unreachable_code(compressor, stat, statements);
|
||||
});
|
||||
CHANGED = statements.length != len;
|
||||
}
|
||||
|
||||
function sequencesize(statements, compressor) {
|
||||
@@ -3475,15 +3533,26 @@ merge(Compressor.prototype, {
|
||||
var exprs = extract_exprs(body);
|
||||
if (!exprs) return;
|
||||
var trimmed = false;
|
||||
for (var i = exprs.length - 1; --i >= 0;) {
|
||||
for (var i = exprs.length - (keep || 0); --i >= 0;) {
|
||||
var expr = exprs[i];
|
||||
if (!(expr instanceof AST_Assign)) continue;
|
||||
if (expr.operator != "=") continue;
|
||||
if (!(expr.left instanceof AST_SymbolRef)) continue;
|
||||
var tail = exprs.slice(i + 1);
|
||||
if (!can_trim(expr)) continue;
|
||||
var tail;
|
||||
if (expr.left instanceof AST_SymbolRef) {
|
||||
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;
|
||||
trimmed = true;
|
||||
exprs = exprs.slice(0, i + 1).concat(tail);
|
||||
exprs = exprs.slice(0, i).concat(expr, tail);
|
||||
}
|
||||
if (defn instanceof AST_Definitions) {
|
||||
keep = keep || 0;
|
||||
@@ -3497,6 +3566,10 @@ merge(Compressor.prototype, {
|
||||
if (defn instanceof AST_Var && join_var_assign(defn.definitions, exprs, keep)) trimmed = true;
|
||||
}
|
||||
return trimmed && exprs;
|
||||
|
||||
function can_trim(node) {
|
||||
return node instanceof AST_Assign && node.operator == "=";
|
||||
}
|
||||
}
|
||||
|
||||
function merge_assigns(prev, defn) {
|
||||
@@ -3553,22 +3626,35 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
|
||||
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;
|
||||
var trimmed = false;
|
||||
do {
|
||||
var node = exprs[0];
|
||||
if (!(node instanceof AST_Assign)) break;
|
||||
if (node.operator != "=") break;
|
||||
if (!(node.left instanceof AST_PropAccess)) break;
|
||||
if (!try_join(exprs[0])) break;
|
||||
exprs.shift();
|
||||
trimmed = true;
|
||||
} 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;
|
||||
if (!(sym instanceof AST_SymbolRef)) break;
|
||||
if (name.name != sym.name) break;
|
||||
if (!node.right.is_constant_expression(scope)) break;
|
||||
if (!(sym instanceof AST_SymbolRef)) return;
|
||||
if (!(sym.name in names)) return;
|
||||
if (!node.right.is_constant_expression(scope)) return;
|
||||
var prop = node.left.property;
|
||||
if (prop instanceof AST_Node) {
|
||||
if (try_join(prop)) prop = node.left.property = prop.right.clone();
|
||||
prop = prop.evaluate(compressor);
|
||||
}
|
||||
if (prop instanceof AST_Node) break;
|
||||
if (prop instanceof AST_Node) return;
|
||||
prop = "" + prop;
|
||||
var diff = prop == "__proto__" || compressor.has_directive("use strict") ? function(node) {
|
||||
var key = node.key;
|
||||
@@ -3580,15 +3666,13 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
return key !== "__proto__";
|
||||
};
|
||||
if (!all(value.properties, diff)) break;
|
||||
if (!all(value.properties, diff)) return;
|
||||
value.properties.push(make_node(AST_ObjectKeyVal, node, {
|
||||
key: prop,
|
||||
value: node.right
|
||||
value: node.right,
|
||||
}));
|
||||
exprs.shift();
|
||||
trimmed = true;
|
||||
} while (exprs.length);
|
||||
return trimmed;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function join_consecutive_vars(statements) {
|
||||
@@ -5934,6 +6018,7 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
tw.directives = Object.create(compressor.directives);
|
||||
self.walk(tw);
|
||||
var changed = false;
|
||||
var merged = Object.create(null);
|
||||
while (first.length && last.length) {
|
||||
var head = first.pop();
|
||||
@@ -5977,10 +6062,12 @@ merge(Compressor.prototype, {
|
||||
def.references = refs.concat(def.references);
|
||||
def.fixed = tail.definition.fixed && def.fixed;
|
||||
merged[id] = def;
|
||||
changed = true;
|
||||
break;
|
||||
} while (last.length);
|
||||
if (skipped.length) last = last.concat(skipped);
|
||||
}
|
||||
return changed;
|
||||
|
||||
function push() {
|
||||
segment = Object.create(segment);
|
||||
@@ -7157,7 +7244,10 @@ merge(Compressor.prototype, {
|
||||
case 1:
|
||||
if (!drop) break;
|
||||
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, {
|
||||
expression: value,
|
||||
property: make_node(AST_Number, node, { value: 0 }),
|
||||
@@ -7283,7 +7373,10 @@ merge(Compressor.prototype, {
|
||||
if (!drop) break;
|
||||
var prop = properties[0];
|
||||
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, {
|
||||
expression: value,
|
||||
property: make_node_from_constant(prop.key, prop),
|
||||
@@ -7627,6 +7720,7 @@ merge(Compressor.prototype, {
|
||||
right: prop.value,
|
||||
}));
|
||||
});
|
||||
defs.value = node.right;
|
||||
defs_by_id[node.left.definition().id] = defs;
|
||||
self.body.splice(self.body.indexOf(this.stack[1]) + 1, 0, make_node(AST_Var, node, {
|
||||
definitions: decls,
|
||||
@@ -7639,12 +7733,16 @@ merge(Compressor.prototype, {
|
||||
descend(node, this);
|
||||
var defs = new Dictionary();
|
||||
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) {
|
||||
var_defs.push(make_node(AST_VarDef, node, {
|
||||
name: make_sym(node.name.CTOR, node.name, prop.key),
|
||||
value: prop.value,
|
||||
}));
|
||||
});
|
||||
defs.value = node.value;
|
||||
defs_by_id[node.name.definition().id] = defs;
|
||||
return List.splice(var_defs);
|
||||
}
|
||||
@@ -7660,6 +7758,7 @@ merge(Compressor.prototype, {
|
||||
if (!(node.expression instanceof AST_SymbolRef)) return;
|
||||
var defs = defs_by_id[node.expression.definition().id];
|
||||
if (!defs) return;
|
||||
if (node.expression.fixed_value() !== defs.value) return;
|
||||
var def = defs.get(node.get_property());
|
||||
var sym = make_node(AST_SymbolRef, node, {
|
||||
name: def.name,
|
||||
@@ -7670,7 +7769,9 @@ merge(Compressor.prototype, {
|
||||
return sym;
|
||||
}
|
||||
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: [] });
|
||||
}
|
||||
}));
|
||||
@@ -7679,18 +7780,16 @@ merge(Compressor.prototype, {
|
||||
if (!(sym instanceof AST_Symbol)) return;
|
||||
var def = sym.definition();
|
||||
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.single_use) return;
|
||||
if (top_retain(def)) 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
|
||||
&& right.properties.length > 0
|
||||
&& all(right.properties, can_hoist_property)
|
||||
&& all(def.references, function(ref) {
|
||||
return ref.fixed_value() === right;
|
||||
})
|
||||
&& can_drop_symbol(sym, compressor);
|
||||
}
|
||||
});
|
||||
@@ -7758,14 +7857,10 @@ merge(Compressor.prototype, {
|
||||
if (compressor.has_directive("use strict") && expr.is_constant()) return this;
|
||||
}
|
||||
if (left.has_side_effects(compressor)) return this;
|
||||
var right = this.right;
|
||||
if (!lazy_op[this.operator.slice(0, -1)]) {
|
||||
this.write_only = true;
|
||||
if (root_expr(left).is_constant_expression(compressor.find_parent(AST_Scope))) {
|
||||
return right.drop_side_effect_free(compressor);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
if (lazy_op[this.operator.slice(0, -1)]) return this;
|
||||
this.write_only = true;
|
||||
if (!root_expr(left).is_constant_expression(compressor.find_parent(AST_Scope))) return this;
|
||||
return this.right.drop_side_effect_free(compressor);
|
||||
});
|
||||
def(AST_Await, function(compressor) {
|
||||
if (!compressor.option("awaits")) return this;
|
||||
@@ -9016,16 +9111,20 @@ merge(Compressor.prototype, {
|
||||
right: value,
|
||||
});
|
||||
a.push(assign);
|
||||
name.fixed = function() {
|
||||
var fixed = function() {
|
||||
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) {
|
||||
var assigns = ref.fixed && ref.fixed.assigns;
|
||||
if (assigns && assigns[0] === defn) assigns[0] = assign;
|
||||
});
|
||||
def.references.push(name);
|
||||
}
|
||||
def.assignments++;
|
||||
def.eliminated++;
|
||||
def.single_use = false;
|
||||
return a;
|
||||
@@ -9204,6 +9303,13 @@ merge(Compressor.prototype, {
|
||||
}) : 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) {
|
||||
var exp = self.expression;
|
||||
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);
|
||||
if (can_inline && stat instanceof AST_Return) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -9550,7 +9659,7 @@ merge(Compressor.prototype, {
|
||||
if (can_substitute_directly()) {
|
||||
var args = self.args.slice();
|
||||
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) {
|
||||
var def = node.definition();
|
||||
if (fn.variables.get(node.name) !== def) {
|
||||
@@ -9564,12 +9673,20 @@ merge(Compressor.prototype, {
|
||||
var parent = this.parent();
|
||||
return parent ? maintain_this_binding(compressor, parent, node, arg) : arg;
|
||||
}
|
||||
})));
|
||||
}));
|
||||
var save_inlined = fn.inlined;
|
||||
if (exp !== fn) fn.inlined = true;
|
||||
var node = make_sequence(self, args.filter(function(arg) {
|
||||
return arg;
|
||||
})).optimize(compressor);
|
||||
var exprs = [];
|
||||
args.forEach(function(arg) {
|
||||
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;
|
||||
node = maintain_this_binding(compressor, parent, current, node);
|
||||
if (replacing || best_of_expression(node, self) === node) {
|
||||
@@ -9603,7 +9720,7 @@ merge(Compressor.prototype, {
|
||||
&& all(fn.body, is_empty)
|
||||
&& (fn === exp ? fn_name_unused(fn, compressor) : !has_default && !has_destructured && !fn.rest)
|
||||
&& !(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);
|
||||
}
|
||||
}
|
||||
@@ -9711,16 +9828,8 @@ merge(Compressor.prototype, {
|
||||
return args;
|
||||
}
|
||||
|
||||
function avoid_await_yield() {
|
||||
var avoid = [];
|
||||
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();
|
||||
function safe_from_await_yield(node, scope) {
|
||||
var avoid = avoid_await_yield(scope);
|
||||
if (!avoid) return true;
|
||||
var safe = true;
|
||||
var tw = new TreeWalker(function(node) {
|
||||
@@ -9796,8 +9905,9 @@ merge(Compressor.prototype, {
|
||||
if (!fn.variables.all(function(def) {
|
||||
return def.references.length - def.replaced < 2 && def.orig[0] instanceof AST_SymbolFunarg;
|
||||
})) return;
|
||||
var scope = compressor.find_parent(AST_Scope);
|
||||
var abort = false;
|
||||
var avoid = avoid_await_yield();
|
||||
var avoid = avoid_await_yield(scope);
|
||||
var begin;
|
||||
var in_order = [];
|
||||
var side_effects = false;
|
||||
@@ -9841,8 +9951,7 @@ merge(Compressor.prototype, {
|
||||
while (end-- > begin && fn.argnames[end] === in_order.pop());
|
||||
end++;
|
||||
}
|
||||
var scope = side_effects && !in_order && compressor.find_parent(AST_Scope);
|
||||
return end <= begin || all(self.args.slice(begin, end), scope ? function(funarg) {
|
||||
return end <= begin || all(self.args.slice(begin, end), side_effects && !in_order ? function(funarg) {
|
||||
return funarg.is_constant_expression(scope);
|
||||
} : function(funarg) {
|
||||
return !funarg.has_side_effects(compressor);
|
||||
@@ -9912,7 +10021,7 @@ merge(Compressor.prototype, {
|
||||
} while (!(scope instanceof AST_Scope));
|
||||
insert = scope.body.indexOf(child) + 1;
|
||||
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;
|
||||
if (scope instanceof AST_Toplevel) {
|
||||
if (compressor.toplevel.vars) {
|
||||
@@ -12314,19 +12423,34 @@ merge(Compressor.prototype, {
|
||||
for (var i = props.length; --i >= 0;) {
|
||||
var prop = props[i];
|
||||
if (prop.key !== key) continue;
|
||||
if (!all(props, can_hoist_property)) break;
|
||||
if (!safe_to_flatten(prop.value, compressor)) break;
|
||||
props = props.map(function(prop) {
|
||||
return prop.value;
|
||||
});
|
||||
if (prop instanceof AST_ObjectMethod
|
||||
&& prop.value instanceof AST_Function
|
||||
&& !(compressor.parent() instanceof AST_Call)) {
|
||||
if (prop.value.uses_arguments) break;
|
||||
props[i] = make_node(AST_Arrow, prop.value, prop.value);
|
||||
if (!all(props, can_hoist_property)) return;
|
||||
if (!safe_to_flatten(prop.value, compressor)) return;
|
||||
var scope, values = [];
|
||||
for (var j = 0; j < props.length; j++) {
|
||||
var value = props[j].value;
|
||||
if (props[j] instanceof AST_ObjectMethod) {
|
||||
var arrow = !(value.uses_arguments || is_generator(value) || value.contains_this());
|
||||
if (arrow) {
|
||||
if (!scope) scope = compressor.find_parent(AST_Scope);
|
||||
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, {
|
||||
expression: make_node(AST_Array, expr, { elements: props }),
|
||||
expression: make_node(AST_Array, expr, { elements: values }),
|
||||
property: make_node(AST_Number, this, { value: i }),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1152,8 +1152,9 @@ function OutputStream(options) {
|
||||
});
|
||||
}
|
||||
function print_arrow(self, output) {
|
||||
if (self.argnames.length == 1 && self.argnames[0] instanceof AST_SymbolFunarg && !self.rest) {
|
||||
self.argnames[0].print(output);
|
||||
var argname = self.argnames.length == 1 && !self.rest && self.argnames[0];
|
||||
if (argname instanceof AST_SymbolFunarg && argname.name != "yield") {
|
||||
argname.print(output);
|
||||
} else {
|
||||
print_funargs(self, output);
|
||||
}
|
||||
|
||||
@@ -1316,6 +1316,11 @@ function parse($TEXT, options) {
|
||||
}
|
||||
if (node instanceof AST_SymbolFunarg) return 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");
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.14.3",
|
||||
"version": "3.14.4",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
|
||||
@@ -550,6 +550,24 @@ logical_side_effects: {
|
||||
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: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
|
||||
@@ -453,7 +453,7 @@ object_function: {
|
||||
}).f();
|
||||
}
|
||||
expect: {
|
||||
(async function() {
|
||||
(async () => {
|
||||
console.log("PASS");
|
||||
})();
|
||||
}
|
||||
@@ -2212,3 +2212,29 @@ issue_5159_2: {
|
||||
]
|
||||
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);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
var o;
|
||||
var a = "PASS", b;
|
||||
({
|
||||
get PASS() {
|
||||
a = "FAIL";
|
||||
},
|
||||
};
|
||||
var a = "PASS", b;
|
||||
o[b = a];
|
||||
})[b = a];
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
@@ -9283,16 +9283,47 @@ issue_4920_3: {
|
||||
}
|
||||
expect: {
|
||||
var log = console.log;
|
||||
var o = {
|
||||
var o;
|
||||
var a = "PASS", b;
|
||||
({
|
||||
get PASS() {
|
||||
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;
|
||||
o[b = a];
|
||||
log(b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4935: {
|
||||
@@ -9482,3 +9513,56 @@ issue_5112_2: {
|
||||
}
|
||||
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"
|
||||
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"
|
||||
}
|
||||
|
||||
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: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
@@ -3225,3 +3294,75 @@ issue_5153_object_var: {
|
||||
expect_stdout: "PASS"
|
||||
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);
|
||||
}
|
||||
expect: {
|
||||
var b = 1;
|
||||
var a = 1;
|
||||
console.log(0);
|
||||
}
|
||||
expect_stdout: "0"
|
||||
@@ -3062,7 +3062,7 @@ issue_4184: {
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
issue_4235: {
|
||||
issue_4235_1: {
|
||||
options = {
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
@@ -3081,13 +3081,37 @@ issue_4235: {
|
||||
}
|
||||
expect: {
|
||||
void function() {
|
||||
var f;
|
||||
console.log(f);
|
||||
var f = console.log(f);
|
||||
}();
|
||||
}
|
||||
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: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
|
||||
@@ -4857,8 +4857,9 @@ issue_4155: {
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
void console.log(b);
|
||||
var b = function() {};
|
||||
var a;
|
||||
void console.log(a);
|
||||
function b() {}
|
||||
b && console.log(typeof b);
|
||||
})();
|
||||
}
|
||||
@@ -6655,3 +6656,49 @@ issue_5140: {
|
||||
}
|
||||
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_bar = 2;
|
||||
function f() {
|
||||
var obj_foo$0 = 3,
|
||||
var obj,
|
||||
obj_foo$0 = 3,
|
||||
obj_bar = 4,
|
||||
obj_b_r = 5,
|
||||
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);
|
||||
}
|
||||
expect: {
|
||||
var o_p = 1,
|
||||
var o,
|
||||
o_p = 1,
|
||||
o__ = function(x) {
|
||||
return x;
|
||||
},
|
||||
@@ -283,7 +285,8 @@ name_collision_3: {
|
||||
console.log(o.p === o.p, o["+"](4), o["-"](5));
|
||||
}
|
||||
expect: {
|
||||
var o_p = 1,
|
||||
var o,
|
||||
o_p = 1,
|
||||
o__ = function(x) {
|
||||
return x;
|
||||
},
|
||||
@@ -315,7 +318,7 @@ name_collision_4: {
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var o_p$0 = 0, o_q = "PASS";
|
||||
var o, o_p$0 = 0, o_q = "PASS";
|
||||
return function(o_p) {
|
||||
if (!o_p$0) return o_p;
|
||||
}(o_q);
|
||||
@@ -768,7 +771,7 @@ issue_3046: {
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
do {
|
||||
var b_c = a++;
|
||||
var b, b_c = a++;
|
||||
} while (b_c && a);
|
||||
return a;
|
||||
}(0));
|
||||
@@ -931,7 +934,7 @@ issue_3411: {
|
||||
expect: {
|
||||
var c = 1;
|
||||
!function f() {
|
||||
var o_p = --c && f();
|
||||
var o, o_p = --c && f();
|
||||
+{} || console.log("PASS");
|
||||
}();
|
||||
}
|
||||
@@ -1042,9 +1045,7 @@ issue_3945_1: {
|
||||
expect: {
|
||||
function f() {
|
||||
o.p;
|
||||
var o = {
|
||||
q: 0,
|
||||
};
|
||||
var o, o_q = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1063,9 +1064,7 @@ issue_3945_2: {
|
||||
}
|
||||
expect: {
|
||||
console.log(typeof o);
|
||||
var o = {
|
||||
p: 0,
|
||||
};
|
||||
var o, o_p = 0;
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
@@ -1134,10 +1133,46 @@ issue_4985: {
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
var a_p = 42;
|
||||
var a, a_p = 42;
|
||||
console.log(function() {
|
||||
({});
|
||||
}());
|
||||
}
|
||||
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 = {
|
||||
functions: true,
|
||||
hoist_vars: true,
|
||||
@@ -150,16 +150,64 @@ issue_4487: {
|
||||
};
|
||||
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: {
|
||||
function a() {
|
||||
var f;
|
||||
console.log(typeof f);
|
||||
var f = console.log(typeof f);
|
||||
}
|
||||
a();
|
||||
}
|
||||
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: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
@@ -251,18 +299,18 @@ issue_4839: {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = function(a, b) {
|
||||
var log = console.log, o = function(a, b) {
|
||||
return b && b;
|
||||
}("foo");
|
||||
for (var k in o)
|
||||
throw "FAIL";
|
||||
console.log("PASS");
|
||||
log("PASS");
|
||||
}
|
||||
expect: {
|
||||
var k, o = void 0;
|
||||
for (k in o)
|
||||
var k, log = console.log;
|
||||
for (k in void 0)
|
||||
throw "FAIL";
|
||||
console.log("PASS");
|
||||
log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
@@ -288,8 +336,7 @@ issue_4859: {
|
||||
}
|
||||
expect: {
|
||||
(function f(a) {
|
||||
var d = 1 / 0, d = Infinity;
|
||||
console.log(d);
|
||||
console.log(Infinity);
|
||||
return f;
|
||||
})();
|
||||
}
|
||||
@@ -395,3 +442,61 @@ issue_4898: {
|
||||
}
|
||||
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"
|
||||
}
|
||||
|
||||
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: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
@@ -1183,3 +1293,26 @@ assign_sequence_var: {
|
||||
"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 {
|
||||
throw 42;
|
||||
} catch (e) {
|
||||
var a = e;
|
||||
for (e in a);
|
||||
a = function() {};
|
||||
var o = e;
|
||||
for (e in o);
|
||||
function a() {}
|
||||
console.log(typeof a);
|
||||
return a;
|
||||
}
|
||||
@@ -3377,3 +3377,60 @@ issue_4956_2: {
|
||||
}
|
||||
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_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"
|
||||
}
|
||||
|
||||
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: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
|
||||
@@ -7320,6 +7320,64 @@ local_assignment_loop: {
|
||||
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: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
@@ -7435,6 +7493,7 @@ issue_4030: {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
|
||||
@@ -1044,13 +1044,13 @@ issue_5100_1: {
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
[ {
|
||||
({
|
||||
p: {},
|
||||
...a
|
||||
} ] = [ {
|
||||
} = [ {
|
||||
p: [ a = 42["q"] ],
|
||||
r: "PASS",
|
||||
} ];
|
||||
} ][0]);
|
||||
console.log(a.r);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
@@ -1077,12 +1077,12 @@ issue_5100_2: {
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
[ {
|
||||
({
|
||||
p: {},
|
||||
...a
|
||||
} ] = [ {
|
||||
} = [ {
|
||||
p: [ console.log("PASS"), a = 42["q"] ],
|
||||
} ];
|
||||
} ][0]);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=10"
|
||||
@@ -1151,3 +1151,57 @@ issue_5128_2: {
|
||||
expect_stdout: "PASS"
|
||||
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"
|
||||
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"
|
||||
}
|
||||
|
||||
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: {
|
||||
var o_p = "PASS";
|
||||
var o = 0, o_p = "PASS";
|
||||
console.log(o_p);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
@@ -136,7 +136,7 @@ hoist_props_let: {
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
var o_p = "PASS";
|
||||
var o, o_p = "PASS";
|
||||
console.log(o_p);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
|
||||
@@ -96,7 +96,7 @@ pause_resume: {
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
arrow_yield: {
|
||||
arrow_yield_1: {
|
||||
input: {
|
||||
yield = "PASS";
|
||||
console.log(function*() {
|
||||
@@ -108,6 +108,18 @@ arrow_yield: {
|
||||
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: {
|
||||
input: {
|
||||
function* f() {
|
||||
@@ -1275,3 +1287,25 @@ issue_5076: {
|
||||
expect_stdout: "PASS"
|
||||
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([
|
||||
"install",
|
||||
"graceful-fs@4.2.6",
|
||||
"is-my-json-valid@2.20.5",
|
||||
"phantomjs-prebuilt@2.1.14",
|
||||
"--no-audit",
|
||||
"--no-optional",
|
||||
|
||||
@@ -4,34 +4,27 @@ var UglifyJS = require("../..");
|
||||
|
||||
describe("spidermonkey export/import sanity test", function() {
|
||||
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 command = uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey | " +
|
||||
uglifyjs + " -p spidermonkey -cm";
|
||||
|
||||
exec(command, {
|
||||
maxBuffer: 1048576
|
||||
}, function(err, stdout) {
|
||||
var command = [
|
||||
uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey",
|
||||
uglifyjs + " -p spidermonkey -cm",
|
||||
].join(" | ");
|
||||
exec(command, { maxBuffer: 1048576 }, function(err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
eval(stdout);
|
||||
assert.strictEqual(typeof SpiderUglify, "object");
|
||||
var result = SpiderUglify.minify("foo([true,,2+3]);");
|
||||
assert.strictEqual(result.error, undefined);
|
||||
assert.strictEqual(result.code, "foo([!0,,5]);");
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("Should not add unnecessary escape slashes to regexps", function() {
|
||||
it("Should not add unnecessary escape slashes to RegExp", function() {
|
||||
var input = "/[\\\\/]/;";
|
||||
var ast = UglifyJS.parse(input).to_mozilla_ast();
|
||||
assert.equal(
|
||||
UglifyJS.AST_Node.from_mozilla_ast(ast).print_to_string(),
|
||||
input
|
||||
);
|
||||
assert.strictEqual(UglifyJS.AST_Node.from_mozilla_ast(ast).print_to_string(), input);
|
||||
});
|
||||
|
||||
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 ([
|
||||
/\basync[ \t]*\([\s\S]*?\)[ \t]*=>/,
|
||||
/\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) {
|
||||
return pattern.test(code);
|
||||
})) {
|
||||
@@ -202,13 +202,11 @@ function setup(global, builtins, setup_log, setup_tty) {
|
||||
});
|
||||
Object.defineProperties(global, props);
|
||||
// for Node.js v8+
|
||||
if (global.toString !== Object.prototype.toString) {
|
||||
global.__proto__ = Object.defineProperty(Object.create(global.__proto__), "toString", {
|
||||
value: function() {
|
||||
return "[object global]";
|
||||
},
|
||||
});
|
||||
}
|
||||
global.__proto__ = Object.defineProperty(Object.create(global.__proto__), "toString", {
|
||||
value: function() {
|
||||
return "[object global]";
|
||||
},
|
||||
});
|
||||
|
||||
function self() {
|
||||
return this;
|
||||
|
||||
Reference in New Issue
Block a user