Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
787dfbed64 | ||
|
|
6b23899ef3 | ||
|
|
8c5a899986 | ||
|
|
ed36c1ec5c | ||
|
|
ce8ef52e2b | ||
|
|
6669ea19ef | ||
|
|
205a1d1f19 | ||
|
|
95d3ede664 | ||
|
|
8195a664fd | ||
|
|
9c80456634 | ||
|
|
dc7aa32172 | ||
|
|
23d74bedeb | ||
|
|
f31311e439 | ||
|
|
87c9edbbc7 | ||
|
|
8dc99fa25f | ||
|
|
dc51a23d31 |
10
README.md
10
README.md
@@ -779,11 +779,11 @@ to be `false` and all symbol names will be omitted.
|
||||
overhead (compression will be slower). Make sure symbols under `pure_funcs`
|
||||
are also under `mangle.reserved` to avoid mangling.
|
||||
|
||||
- `pure_getters` (default: `"strict"`) — If you pass `true` for
|
||||
this, UglifyJS will assume that object property access
|
||||
(e.g. `foo.bar` or `foo["bar"]`) doesn't have any side effects.
|
||||
Specify `"strict"` to treat `foo.bar` as side-effect-free only when
|
||||
`foo` is certain to not throw, i.e. not `null` or `undefined`.
|
||||
- `pure_getters` (default: `"strict"`) — Pass `true` for UglifyJS to assume that
|
||||
object property access (e.g. `foo.bar` or `a[42]`) does not throw exception or
|
||||
alter program states via getter function. Pass `"strict"` to allow dropping or
|
||||
reordering `foo.bar` only if `foo` is not `null` or `undefined` and is safe to
|
||||
access as a variable. Pass `false` to retain all property accesses.
|
||||
|
||||
- `reduce_funcs` (default: `true`) — Allows single-use functions to be
|
||||
inlined as function expressions when permissible allowing further
|
||||
|
||||
@@ -169,8 +169,6 @@ DEF_BITPROPS(AST_Node, [
|
||||
"private",
|
||||
// AST_Call
|
||||
"pure",
|
||||
// AST_Assign
|
||||
"redundant",
|
||||
// AST_Node
|
||||
"single_use",
|
||||
// AST_ClassProperty
|
||||
|
||||
205
lib/compress.js
205
lib/compress.js
@@ -185,7 +185,7 @@ function Compressor(options, false_by_default) {
|
||||
};
|
||||
}
|
||||
|
||||
Compressor.prototype = new TreeTransformer(function(node, descend, in_list) {
|
||||
Compressor.prototype = new TreeTransformer(function(node, descend) {
|
||||
if (node._squeezed) return node;
|
||||
var is_scope = node instanceof AST_Scope;
|
||||
if (is_scope) {
|
||||
@@ -270,7 +270,7 @@ Compressor.prototype.compress = function(node) {
|
||||
};
|
||||
|
||||
(function(OPT) {
|
||||
OPT(AST_Node, function(self, compressor) {
|
||||
OPT(AST_Node, function(self) {
|
||||
return self;
|
||||
});
|
||||
|
||||
@@ -638,15 +638,30 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
|
||||
function push(tw, sequential) {
|
||||
var defined_ids = Object.create(tw.defined_ids);
|
||||
var safe_ids = Object.create(tw.safe_ids);
|
||||
if (!sequential) safe_ids.seq = {};
|
||||
if (!sequential) {
|
||||
defined_ids.seq = {};
|
||||
safe_ids.seq = {};
|
||||
}
|
||||
tw.defined_ids = defined_ids;
|
||||
tw.safe_ids = safe_ids;
|
||||
}
|
||||
|
||||
function pop(tw) {
|
||||
tw.defined_ids = Object.getPrototypeOf(tw.defined_ids);
|
||||
tw.safe_ids = Object.getPrototypeOf(tw.safe_ids);
|
||||
}
|
||||
|
||||
function access(tw, def) {
|
||||
tw.defined_ids[def.id] = [ tw.defined_ids.seq ];
|
||||
}
|
||||
|
||||
function assign(tw, def) {
|
||||
var defined = tw.defined_ids[def.id];
|
||||
if (defined) defined[0] = false;
|
||||
}
|
||||
|
||||
function mark(tw, def) {
|
||||
tw.safe_ids[def.id] = {};
|
||||
}
|
||||
@@ -939,9 +954,13 @@ Compressor.prototype.compress = function(node) {
|
||||
return fixed_node;
|
||||
}, visit);
|
||||
walk_lambda(fn, tw);
|
||||
var defined_ids = tw.defined_ids;
|
||||
var safe_ids = tw.safe_ids;
|
||||
pop_scope(tw, fn);
|
||||
if (!aborts) tw.safe_ids = safe_ids;
|
||||
if (!aborts) {
|
||||
tw.defined_ids = defined_ids;
|
||||
tw.safe_ids = safe_ids;
|
||||
}
|
||||
return true;
|
||||
|
||||
function visit(node, fixed) {
|
||||
@@ -969,7 +988,6 @@ Compressor.prototype.compress = function(node) {
|
||||
if (left.equals(right) && !left.has_side_effects(compressor)) {
|
||||
right.walk(tw);
|
||||
walk_prop(left);
|
||||
node.redundant = true;
|
||||
return true;
|
||||
}
|
||||
if (ld && right instanceof AST_LambdaExpression) {
|
||||
@@ -995,6 +1013,7 @@ Compressor.prototype.compress = function(node) {
|
||||
mark_assignment_to_arguments(left);
|
||||
return walk_lazy();
|
||||
}
|
||||
assign(tw, ld);
|
||||
ld.assignments++;
|
||||
var fixed = ld.fixed;
|
||||
if (is_modified(compressor, tw, node, node, 0)) {
|
||||
@@ -1063,6 +1082,7 @@ Compressor.prototype.compress = function(node) {
|
||||
return;
|
||||
}
|
||||
var d = sym.definition();
|
||||
assign(tw, d);
|
||||
d.assignments++;
|
||||
if (!fixed || sym.in_arg || !safe_to_assign(tw, d)) {
|
||||
walk();
|
||||
@@ -1103,7 +1123,7 @@ Compressor.prototype.compress = function(node) {
|
||||
def(AST_BlockScope, function(tw, descend, compressor) {
|
||||
reset_block_variables(tw, compressor, this);
|
||||
});
|
||||
def(AST_Call, function(tw, descend) {
|
||||
def(AST_Call, function(tw) {
|
||||
var node = this;
|
||||
var exp = node.expression;
|
||||
if (exp instanceof AST_LambdaExpression) {
|
||||
@@ -1134,6 +1154,7 @@ Compressor.prototype.compress = function(node) {
|
||||
if (fixed instanceof AST_Lambda) {
|
||||
mark_fn_def(tw, exp.definition(), fixed);
|
||||
} else {
|
||||
tw.defined_ids.seq = {};
|
||||
tw.find_parent(AST_Scope).may_call_this();
|
||||
}
|
||||
return true;
|
||||
@@ -1238,6 +1259,13 @@ Compressor.prototype.compress = function(node) {
|
||||
tw.in_loop = save_loop;
|
||||
return true;
|
||||
});
|
||||
def(AST_Dot, function(tw, descend) {
|
||||
descend();
|
||||
var node = this;
|
||||
var expr = node.expression;
|
||||
if (!node.optional && expr instanceof AST_SymbolRef) access(tw, expr.definition());
|
||||
return true;
|
||||
});
|
||||
def(AST_For, function(tw, descend, compressor) {
|
||||
var node = this;
|
||||
reset_block_variables(tw, compressor, node);
|
||||
@@ -1335,12 +1363,18 @@ Compressor.prototype.compress = function(node) {
|
||||
pop_scope(tw, fn);
|
||||
return true;
|
||||
});
|
||||
def(AST_Sub, function(tw) {
|
||||
if (!this.optional) return;
|
||||
this.expression.walk(tw);
|
||||
push(tw, true);
|
||||
this.property.walk(tw);
|
||||
pop(tw);
|
||||
def(AST_Sub, function(tw, descend) {
|
||||
var node = this;
|
||||
var expr = node.expression;
|
||||
if (node.optional) {
|
||||
expr.walk(tw);
|
||||
push(tw, true);
|
||||
node.property.walk(tw);
|
||||
pop(tw);
|
||||
} else {
|
||||
descend();
|
||||
if (expr instanceof AST_SymbolRef) access(tw, expr.definition());
|
||||
}
|
||||
return true;
|
||||
});
|
||||
def(AST_Switch, function(tw, descend, compressor) {
|
||||
@@ -1390,6 +1424,8 @@ Compressor.prototype.compress = function(node) {
|
||||
var d = ref.definition();
|
||||
var fixed = d.fixed || d.last_ref && d.last_ref.fixed;
|
||||
push_ref(d, ref);
|
||||
var defined = tw.defined_ids[d.id];
|
||||
if (defined && defined[0] === tw.defined_ids.seq) ref.defined = true;
|
||||
if (d.references.length == 1 && !d.fixed && d.orig[0] instanceof AST_SymbolDefun) {
|
||||
tw.loop_ids[d.id] = tw.in_loop;
|
||||
}
|
||||
@@ -1577,6 +1613,7 @@ Compressor.prototype.compress = function(node) {
|
||||
return node.value || make_node(AST_Undefined, node);
|
||||
}, function(name, fixed) {
|
||||
var d = name.definition();
|
||||
assign(tw, d);
|
||||
if (!d.first_decl && d.references.length == 0) d.first_decl = name;
|
||||
if (fixed && safe_to_assign(tw, d, true)) {
|
||||
mark(tw, d);
|
||||
@@ -1618,6 +1655,9 @@ Compressor.prototype.compress = function(node) {
|
||||
reset_flags(node);
|
||||
return node.reduce_vars(tw, descend, compressor);
|
||||
} : reset_flags);
|
||||
// Side-effect tracking on sequential property access
|
||||
tw.defined_ids = Object.create(null);
|
||||
tw.defined_ids.seq = {};
|
||||
// Flow control for visiting lambda definitions
|
||||
tw.fn_scanning = null;
|
||||
tw.fn_visited = [];
|
||||
@@ -2653,13 +2693,13 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
if (node instanceof AST_ObjectIdentity) return symbol_in_lvalues(node, parent);
|
||||
if (node instanceof AST_PropAccess) {
|
||||
if (side_effects) return true;
|
||||
var exp = node.expression;
|
||||
if (exp instanceof AST_SymbolRef && is_arguments(exp.definition())) return true;
|
||||
if (compressor.option("unsafe")) {
|
||||
if (is_undeclared_ref(exp) && global_names[exp.name]) return false;
|
||||
if (is_static_fn(exp)) return false;
|
||||
}
|
||||
if (exp instanceof AST_SymbolRef && is_arguments(exp.definition())) return true;
|
||||
if (side_effects) return true;
|
||||
if (!well_defined) return true;
|
||||
if (value_def) return false;
|
||||
if (!in_try && lhs_local) return false;
|
||||
@@ -2668,6 +2708,7 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
if (node instanceof AST_Spread) return true;
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
if (is_undeclared_ref(node) && node.is_declared(compressor)) return false;
|
||||
if (symbol_in_lvalues(node, parent)) return !is_direct_assignment(node, parent);
|
||||
if (side_effects && may_modify(node)) return true;
|
||||
var def = node.definition();
|
||||
@@ -2687,8 +2728,10 @@ Compressor.prototype.compress = function(node) {
|
||||
if (sym instanceof AST_PropAccess) return true;
|
||||
if (check_destructured(sym)) return true;
|
||||
return sym.match_symbol(function(node) {
|
||||
return node instanceof AST_SymbolRef
|
||||
&& (lvalues.has(node.name) || read_toplevel && compressor.exposed(node.definition()));
|
||||
if (node instanceof AST_PropAccess) return true;
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
return lvalues.has(node.name) || read_toplevel && compressor.exposed(node.definition());
|
||||
}
|
||||
}, true);
|
||||
|
||||
function reject(node) {
|
||||
@@ -3284,10 +3327,14 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
|
||||
function update_symbols(value, node) {
|
||||
var clear_defined = node instanceof AST_SymbolRef && !node.defined;
|
||||
var scope = node.scope || find_scope(scanner) || block_scope;
|
||||
value.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_BlockScope) return true;
|
||||
if (node instanceof AST_Symbol) node.scope = scope;
|
||||
if (node instanceof AST_Symbol) {
|
||||
if (clear_defined && node instanceof AST_SymbolRef) node.defined = false;
|
||||
node.scope = scope;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -4300,18 +4347,18 @@ Compressor.prototype.compress = function(node) {
|
||||
if (prop instanceof AST_Node) return;
|
||||
if (!RE_POSITIVE_INTEGER.test("" + prop)) return;
|
||||
prop = +prop;
|
||||
var len = value.elements.length;
|
||||
var elements = value.elements;
|
||||
var len = elements.length;
|
||||
if (prop > len + 4) return;
|
||||
for (var i = Math.min(len, prop + 1); --i >= 0;) {
|
||||
if (elements[i] instanceof AST_Spread) return;
|
||||
}
|
||||
if (prop < len) {
|
||||
var element = value.elements[prop];
|
||||
if (element instanceof AST_Hole) {
|
||||
value.elements[prop] = node.right;
|
||||
} else {
|
||||
value.elements[prop] = make_sequence(node, [ element, node.right ]).optimize(compressor);
|
||||
}
|
||||
var element = elements[prop].drop_side_effect_free(compressor);
|
||||
elements[prop] = element ? make_sequence(node, [ element, node.right ]) : node.right;
|
||||
} else {
|
||||
while (prop > len) value.elements[len++] = make_node(AST_Hole, value);
|
||||
value.elements[prop] = node.right;
|
||||
while (prop > len) elements[len++] = make_node(AST_Hole, value);
|
||||
elements[prop] = node.right;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -4712,6 +4759,7 @@ Compressor.prototype.compress = function(node) {
|
||||
return this.tail_node()._dot_throw(compressor);
|
||||
});
|
||||
def(AST_SymbolRef, function(compressor, force) {
|
||||
if (this.defined) return false;
|
||||
if (this.is_undefined) return true;
|
||||
if (!is_strict(compressor, force)) return false;
|
||||
if (is_undeclared_ref(this) && this.is_declared(compressor)) return false;
|
||||
@@ -7982,8 +8030,14 @@ Compressor.prototype.compress = function(node) {
|
||||
prop.walk(tw);
|
||||
});
|
||||
if (node instanceof AST_Assign) {
|
||||
var right = get_rhs(node), shared = false;
|
||||
if (init && node.write_only === true && !right.has_side_effects(compressor)) {
|
||||
var fixed = sym.fixed_value();
|
||||
var right = get_rhs(node);
|
||||
var safe = fixed && fixed.is_constant();
|
||||
var shared = false;
|
||||
if (init
|
||||
&& node.write_only === true
|
||||
&& (safe || node.left === sym || right.equals(sym))
|
||||
&& !right.has_side_effects(compressor)) {
|
||||
initializations.add(node_def.id, right);
|
||||
} else {
|
||||
right.walk(tw);
|
||||
@@ -7993,11 +8047,8 @@ Compressor.prototype.compress = function(node) {
|
||||
if (!node.write_only || shared) {
|
||||
verify_safe_usage(node_def, sym, value_modified[node_def.id]);
|
||||
}
|
||||
} else {
|
||||
var fixed = sym.fixed_value();
|
||||
if (!fixed || !fixed.is_constant()) {
|
||||
verify_safe_usage(node_def, value_read[node_def.id], true);
|
||||
}
|
||||
} else if (!safe) {
|
||||
verify_safe_usage(node_def, value_read[node_def.id], true);
|
||||
}
|
||||
}
|
||||
if (track_assigns(node_def, sym) && is_lhs(sym, node) !== sym) add_assigns(node_def, sym);
|
||||
@@ -8083,6 +8134,7 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
|
||||
function trim_destructured(node, value, process, drop, root) {
|
||||
var unwind = true;
|
||||
var trimmer = new TreeTransformer(function(node) {
|
||||
if (node instanceof AST_DefaultValue) {
|
||||
if (!(compressor.option("default_values") && value && value.is_defined(compressor))) {
|
||||
@@ -8100,21 +8152,27 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
if (node instanceof AST_DestructuredArray) {
|
||||
var save_drop = drop;
|
||||
var save_unwind = unwind;
|
||||
var save_value = value;
|
||||
if (value instanceof AST_SymbolRef) {
|
||||
drop = false;
|
||||
value = value.fixed_value();
|
||||
}
|
||||
var native, values;
|
||||
var last_side_effects, native, values;
|
||||
if (value instanceof AST_Array) {
|
||||
native = true;
|
||||
values = value.elements;
|
||||
if (save_unwind) for (last_side_effects = values.length; --last_side_effects >= 0;) {
|
||||
if (values[last_side_effects].has_side_effects(compressor)) break;
|
||||
}
|
||||
} else {
|
||||
native = value && value.is_string(compressor);
|
||||
values = false;
|
||||
last_side_effects = node.elements.length;
|
||||
}
|
||||
var elements = [], newValues = drop && [], pos = 0;
|
||||
node.elements.forEach(function(element, index) {
|
||||
if (save_unwind) unwind = index >= last_side_effects;
|
||||
value = values && values[index];
|
||||
if (value instanceof AST_Hole) {
|
||||
value = null;
|
||||
@@ -8157,6 +8215,7 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
}
|
||||
value = save_value;
|
||||
unwind = save_unwind;
|
||||
drop = save_drop;
|
||||
if (values && newValues) {
|
||||
fill_holes(value, newValues);
|
||||
@@ -8165,22 +8224,34 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
if (!native) {
|
||||
elements.length = node.elements.length;
|
||||
} else if (!node.rest) switch (elements.length) {
|
||||
} else if (!node.rest) SHORTHAND: switch (elements.length) {
|
||||
case 0:
|
||||
if (node === root) break;
|
||||
if (drop) value = value.drop_side_effect_free(compressor);
|
||||
return null;
|
||||
case 1:
|
||||
default:
|
||||
if (!drop) break;
|
||||
if (!unwind) break;
|
||||
if (node === root) break;
|
||||
var sym = elements[0];
|
||||
var pos = elements.length, sym;
|
||||
while (--pos >= 0) {
|
||||
var element = elements[pos];
|
||||
if (element) {
|
||||
sym = element;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pos < 0) break;
|
||||
for (var i = pos; --i >= 0;) {
|
||||
if (elements[i]) break SHORTHAND;
|
||||
}
|
||||
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 }),
|
||||
property: make_node(AST_Number, node, { value: pos }),
|
||||
});
|
||||
return sym;
|
||||
}
|
||||
@@ -8190,16 +8261,19 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
if (node instanceof AST_DestructuredObject) {
|
||||
var save_drop = drop;
|
||||
var save_unwind = unwind;
|
||||
var save_value = value;
|
||||
if (value instanceof AST_SymbolRef) {
|
||||
drop = false;
|
||||
value = value.fixed_value();
|
||||
}
|
||||
var prop_keys, prop_map, values;
|
||||
var last_side_effects, prop_keys, prop_map, values;
|
||||
if (value instanceof AST_Object) {
|
||||
last_side_effects = -1;
|
||||
prop_keys = [];
|
||||
prop_map = new Dictionary();
|
||||
values = value.properties.map(function(prop, index) {
|
||||
if (save_unwind && prop.has_side_effects(compressor)) last_side_effects = index;
|
||||
prop = prop.clone();
|
||||
if (prop instanceof AST_Spread) {
|
||||
prop_map = false;
|
||||
@@ -8215,6 +8289,8 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
return prop;
|
||||
});
|
||||
} else {
|
||||
last_side_effects = node.properties.length;
|
||||
}
|
||||
if (node.rest) {
|
||||
value = false;
|
||||
@@ -8237,6 +8313,7 @@ Compressor.prototype.compress = function(node) {
|
||||
return key;
|
||||
}).forEach(function(key, index) {
|
||||
var prop = node.properties[index], trimmed;
|
||||
if (save_unwind) unwind = index >= last_side_effects;
|
||||
if (key instanceof AST_Node) {
|
||||
drop = false;
|
||||
value = false;
|
||||
@@ -8277,6 +8354,7 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
});
|
||||
value = save_value;
|
||||
unwind = save_unwind;
|
||||
drop = save_drop;
|
||||
if (drop_keys && prop_keys) {
|
||||
value = value.clone();
|
||||
@@ -8284,6 +8362,7 @@ Compressor.prototype.compress = function(node) {
|
||||
if (prop instanceof AST_Spread) return prop;
|
||||
var key = prop_keys[index];
|
||||
if (key instanceof AST_Node) return prop;
|
||||
if (key === "__proto__") return prop;
|
||||
if (drop_keys.has(key)) {
|
||||
var mapped = drop_keys.get(key);
|
||||
if (!mapped) return prop;
|
||||
@@ -8310,6 +8389,7 @@ Compressor.prototype.compress = function(node) {
|
||||
return null;
|
||||
case 1:
|
||||
if (!drop) break;
|
||||
if (!unwind) break;
|
||||
if (node === root) break;
|
||||
var prop = properties[0];
|
||||
if (prop.key instanceof AST_Node) break;
|
||||
@@ -8317,7 +8397,10 @@ Compressor.prototype.compress = function(node) {
|
||||
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 = is_identifier_string(prop.key) ? make_node(AST_Dot, node, {
|
||||
expression: value,
|
||||
property: prop.key,
|
||||
}) : make_node(AST_Sub, node, {
|
||||
expression: value,
|
||||
property: make_node_from_constant(prop.key, prop),
|
||||
});
|
||||
@@ -8434,7 +8517,8 @@ Compressor.prototype.compress = function(node) {
|
||||
&& self.find_variable(sym.name) === sym.definition();
|
||||
})) return node;
|
||||
node.definitions.forEach(function(defn) {
|
||||
vars.set(defn.name.name, defn);
|
||||
var name = defn.name.name;
|
||||
if (!vars.has(name)) vars.set(name, defn);
|
||||
});
|
||||
var seq = node.to_assignments();
|
||||
if (p instanceof AST_ForEnumeration && p.init === node) {
|
||||
@@ -8461,13 +8545,14 @@ Compressor.prototype.compress = function(node) {
|
||||
return !ref.in_arg;
|
||||
})) vars.del(argname.name);
|
||||
});
|
||||
vars.each(function(defn, name) {
|
||||
vars.each(function(defn) {
|
||||
var name = defn.name;
|
||||
defn = defn.clone();
|
||||
defn.name = defn.name.clone();
|
||||
defn.name = name.clone();
|
||||
defn.value = null;
|
||||
defns.push(defn);
|
||||
vars.set(name, defn);
|
||||
defn.name.definition().orig.unshift(defn.name);
|
||||
var orig = name.definition().orig;
|
||||
orig.splice(orig.indexOf(name), 0, defn.name);
|
||||
});
|
||||
if (defns.length > 0) hoisted.push(make_node(AST_Var, self, { definitions: defns }));
|
||||
}
|
||||
@@ -10298,10 +10383,9 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
});
|
||||
def.references.push(name);
|
||||
def.assignments++;
|
||||
}
|
||||
def.assignments++;
|
||||
def.eliminated++;
|
||||
def.single_use = false;
|
||||
return a;
|
||||
}, []);
|
||||
if (assignments.length == 0) return null;
|
||||
@@ -10924,9 +11008,11 @@ Compressor.prototype.compress = function(node) {
|
||||
&& (value = can_flatten_body(stat))) {
|
||||
var replacing = exp === fn || def.single_use && def.references.length - def.replaced == 1;
|
||||
if (can_substitute_directly()) {
|
||||
self._optimized = true;
|
||||
var retValue = value.optimize(compressor).clone(true);
|
||||
var args = self.args.slice();
|
||||
var refs = [];
|
||||
var retValue = value.clone(true).transform(new TreeTransformer(function(node) {
|
||||
retValue = retValue.transform(new TreeTransformer(function(node) {
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
var def = node.definition();
|
||||
if (fn.variables.get(node.name) !== def) {
|
||||
@@ -11158,6 +11244,10 @@ Compressor.prototype.compress = function(node) {
|
||||
return;
|
||||
}
|
||||
if (node instanceof AST_Class) return abort = true;
|
||||
if (node instanceof AST_Destructured) {
|
||||
side_effects = true;
|
||||
return;
|
||||
}
|
||||
if (node instanceof AST_Scope) return abort = true;
|
||||
if (avoid && node instanceof AST_Symbol && avoid[node.name]) return abort = true;
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
@@ -12945,16 +13035,14 @@ Compressor.prototype.compress = function(node) {
|
||||
if (compressor.option("dead_code")) {
|
||||
if (self.left instanceof AST_PropAccess) {
|
||||
if (self.operator == "=") {
|
||||
if (self.redundant) {
|
||||
var exprs = [ self.left.expression ];
|
||||
if (self.left instanceof AST_Sub) exprs.push(self.left.property);
|
||||
exprs.push(self.right);
|
||||
return make_sequence(self, exprs).optimize(compressor);
|
||||
}
|
||||
if (self.left.equals(self.right) && !self.left.has_side_effects(compressor)) {
|
||||
return self.right;
|
||||
}
|
||||
var exp = self.left.expression;
|
||||
if (self.left.equals(self.right)) {
|
||||
var defined = exp.defined;
|
||||
exp.defined = false;
|
||||
var drop_lhs = !self.left.has_side_effects(compressor);
|
||||
exp.defined = defined;
|
||||
if (drop_lhs) return self.right;
|
||||
}
|
||||
if (exp instanceof AST_Lambda
|
||||
|| !compressor.has_directive("use strict")
|
||||
&& exp instanceof AST_Constant
|
||||
@@ -14162,7 +14250,8 @@ Compressor.prototype.compress = function(node) {
|
||||
stat.walk(new TreeWalker(function(node) {
|
||||
if (abort) return true;
|
||||
if (node instanceof AST_Try) {
|
||||
if (node.bfinally && all(node.body, function(stat) {
|
||||
if (!node.bfinally) return;
|
||||
if (all(node.body, function(stat) {
|
||||
stat.walk(find_return);
|
||||
return !abort;
|
||||
}) && node.bcatch) node.bcatch.walk(find_return);
|
||||
|
||||
@@ -1312,7 +1312,7 @@ issue_5653: {
|
||||
}
|
||||
expect: {
|
||||
console.log((a => {
|
||||
return console, +{};
|
||||
return +{};
|
||||
})());
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
|
||||
@@ -4996,7 +4996,7 @@ cascade_forin: {
|
||||
]
|
||||
}
|
||||
|
||||
unsafe_builtin: {
|
||||
unsafe_builtin_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
pure_getters: "strict",
|
||||
@@ -5020,6 +5020,46 @@ unsafe_builtin: {
|
||||
expect_stdout: "1 4"
|
||||
}
|
||||
|
||||
unsafe_builtin_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
A = "PASS";
|
||||
var a = A;
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
console.log(A = "PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
unsafe_builtin_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
A = "PASS";
|
||||
(function() {
|
||||
var a = A;
|
||||
console.log(a);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
A = "PASS";
|
||||
(function() {
|
||||
console.log(A);
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
return_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
@@ -7350,30 +7390,39 @@ substitution_assign: {
|
||||
b = 1 + (b = a);
|
||||
console.log(a, b);
|
||||
}
|
||||
function f4(a, b) {
|
||||
b = 1 + (a = b);
|
||||
console.log(a, b);
|
||||
}
|
||||
f1(42, "foo");
|
||||
f2(42, "foo");
|
||||
f3(42, "foo");
|
||||
f4("bar", 41);
|
||||
}
|
||||
expect: {
|
||||
function f1(a, b) {
|
||||
console.log(f1 = a, a);
|
||||
}
|
||||
function f2(a, b) {
|
||||
a = 1 + (b = a);
|
||||
console.log(a, b);
|
||||
console.log(a = 1 + (b = a), b);
|
||||
}
|
||||
function f3(a, b) {
|
||||
b = 1 + (b = a);
|
||||
console.log(a, b = 1 + (b = a));
|
||||
}
|
||||
function f4(a, b) {
|
||||
b = 1 + (a = b);
|
||||
console.log(a, b);
|
||||
}
|
||||
f1(42, "foo");
|
||||
f2(42, "foo");
|
||||
f3(42, "foo");
|
||||
f4("bar", 41);
|
||||
}
|
||||
expect_stdout: [
|
||||
"42 42",
|
||||
"43 42",
|
||||
"42 43",
|
||||
"41 42",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -10284,3 +10333,27 @@ issue_1666_undefined_strict: {
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_5869: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a, b, log = console.log;
|
||||
log();
|
||||
a.p = 0;
|
||||
b = a;
|
||||
log(b);
|
||||
}
|
||||
expect: {
|
||||
var a, log = console.log;
|
||||
log();
|
||||
log(void (a.p = 0));
|
||||
}
|
||||
expect_stdout: TypeError("Cannot set properties of undefined")
|
||||
}
|
||||
|
||||
@@ -2293,7 +2293,7 @@ issue_5340_3: {
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
(function() {})(a = true["p"]);
|
||||
(function() {})(a = true.p);
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
@@ -3107,3 +3107,31 @@ issue_5774: {
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5863: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
hoist_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(typeof function f(a = function() {
|
||||
f = 42;
|
||||
return f;
|
||||
}()) {
|
||||
var f;
|
||||
var f;
|
||||
return a;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(typeof function f(a = function() {
|
||||
f = 42;
|
||||
return f;
|
||||
}()) {
|
||||
var f;
|
||||
return a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "function"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
@@ -1339,7 +1339,7 @@ maintain_position_var: {
|
||||
}
|
||||
expect: {
|
||||
A = "FAIL";
|
||||
var [ , b ] = [ A ];
|
||||
var b = [ A ][1];
|
||||
console.log(b || "PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
@@ -1382,7 +1382,7 @@ side_effects_object: {
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var a = null, c = (console, 42["c"]);
|
||||
var a = null, c = (console, 42..c);
|
||||
try {
|
||||
c[a = "PASS"];
|
||||
} catch (e) {
|
||||
@@ -1684,7 +1684,7 @@ singleton_1: {
|
||||
expect: {
|
||||
var b, a = "P"[0], o = {};
|
||||
o.p = [ "FAIL"["1"] ][0];
|
||||
o.q = { foo: "S"[0] }["foo"];
|
||||
o.q = { foo: "S"[0] }.foo;
|
||||
[ b = "S" ] = [];
|
||||
console.log(a + o.p + o.q + b);
|
||||
}
|
||||
@@ -3886,3 +3886,358 @@ issue_5651: {
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5843_1: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var { p: a } = {
|
||||
__proto__: {
|
||||
p: "PASS",
|
||||
},
|
||||
};
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = {
|
||||
__proto__: {
|
||||
p: "PASS",
|
||||
},
|
||||
}.p;
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5843_2: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
({ p: a } = {
|
||||
__proto__: {
|
||||
p: "PASS",
|
||||
},
|
||||
});
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
a = {
|
||||
__proto__: {
|
||||
p: "PASS",
|
||||
},
|
||||
}.p;
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5844: {
|
||||
options = {
|
||||
inline: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
(function(a) {
|
||||
[ a.p ] = 42;
|
||||
})(console.log("PASS"));
|
||||
} catch (e) {}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
(function(a) {
|
||||
[ a.p ] = 42;
|
||||
})(console.log("PASS"));
|
||||
} catch (e) {}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5854_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
var b = a;
|
||||
a++;
|
||||
[ b[0] ] = [ "foo" ];
|
||||
return a;
|
||||
}([]) ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
var b = a;
|
||||
a++;
|
||||
[ b[0] ] = [ "foo" ];
|
||||
return a;
|
||||
}([]) ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5854_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
var b = a;
|
||||
a++;
|
||||
({ p: b[0] } = { p: "foo" });
|
||||
return a;
|
||||
}([]) ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
var b = a;
|
||||
a++;
|
||||
({ p: b[0] } = { p: "foo" });
|
||||
return a;
|
||||
}([]) ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5866_1: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = {};
|
||||
var { p: { q: b } } = {
|
||||
p: a,
|
||||
r: a.q = "PASS",
|
||||
};
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var a = {};
|
||||
var { q: b } = {
|
||||
p: a,
|
||||
r: a.q = "PASS",
|
||||
}.p;
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5866_2: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = {}, b;
|
||||
({ p: { q: b } } = {
|
||||
p: a,
|
||||
r: a.q = "PASS",
|
||||
});
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var b, a = {};
|
||||
({ q: b } = {
|
||||
p: a,
|
||||
r: a.q = "PASS",
|
||||
}.p);
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5866_3: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = {};
|
||||
var [ { p: b } ] = [ a, a.p = "PASS" ];
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var a = {};
|
||||
var { p: b } = [ a, a.p = "PASS" ][0];
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5866_4: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = {}, b;
|
||||
[ { p: b } ] = [ a, a.p = "PASS" ];
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var b, a = {};
|
||||
({ p: b } = [ a, a.p = "PASS" ][0]);
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5866_5: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = [];
|
||||
var [ [ b ] ] = [ a, a[0] = "PASS" ];
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var a = [];
|
||||
var [ b ] = [ a, a[0] = "PASS" ][0];
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5866_6: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = [], b;
|
||||
[ [ b ] ] = [ a, a[0] = "PASS" ];
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var b, a = [];
|
||||
[ b ] = [ a, a[0] = "PASS" ][0];
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5866_7: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = {};
|
||||
var [ { p: b }, c ] = [ a, a.p = {} ];
|
||||
console.log(b === c ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
var a = {};
|
||||
var [ { p: b }, c ] = [ a, a.p = {} ];
|
||||
console.log(b === c ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5866_8: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = {}, b, c;
|
||||
[ { p: b }, c ] = [ a, a.p = {} ];
|
||||
console.log(b === c ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
var b, c, a = {};
|
||||
[ { p: b }, c ] = [ a, a.p = {} ];
|
||||
console.log(b === c ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5866_9: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = {};
|
||||
var [ b, { p: c } ] = [ a.p = {}, a ];
|
||||
console.log(b === c ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
var a = {};
|
||||
var [ b, c ] = [ a.p = {}, a.p ];
|
||||
console.log(b === c ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5866_10: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = {}, b, c;
|
||||
[ b, { p: c } ] = [ a.p = {}, a ];
|
||||
console.log(b === c ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
var b, c, a = {};
|
||||
[ b, c ] = [ a.p = {}, a.p ];
|
||||
console.log(b === c ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5866_11: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = {};
|
||||
var { p: { q: b } } = { p: a = { q: {} } };
|
||||
console.log(a.q === b ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
var a = {};
|
||||
var b = { p: (a = { q: {} }).q }.p;
|
||||
console.log(a.q === b ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5866_12: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = {}, b;
|
||||
({ p: { q: b } } = { p: a = { q: {} } });
|
||||
console.log(a.q === b ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
var b, a = {};
|
||||
b = { p: (a = { q: {} }).q }.p;
|
||||
console.log(a.q === b ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ hoist_exports_2: {
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
let e, a = 42["foo"];
|
||||
let e, a = 42..foo;
|
||||
function f(t, { [e]: o }) {
|
||||
t(o, f);
|
||||
}
|
||||
|
||||
@@ -8817,3 +8817,157 @@ issue_5766_2: {
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
issue_5841_1: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
join_vars: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 42;
|
||||
(function() {
|
||||
f();
|
||||
var b = f();
|
||||
function f() {
|
||||
if (console && a)
|
||||
g && g();
|
||||
}
|
||||
function g() {
|
||||
var c;
|
||||
for (;console.log("foo"););
|
||||
(function h(d) {
|
||||
d && d.p;
|
||||
})();
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
var a = 42;
|
||||
(function() {
|
||||
f();
|
||||
f();
|
||||
function f() {
|
||||
{
|
||||
if (console && a) {
|
||||
for (;console.log("foo"););
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"foo",
|
||||
]
|
||||
}
|
||||
|
||||
issue_5841_2: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
if_return: true,
|
||||
inline: true,
|
||||
join_vars: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 42;
|
||||
(function() {
|
||||
f();
|
||||
var b = f();
|
||||
function f() {
|
||||
if (console && a)
|
||||
g && g();
|
||||
}
|
||||
function g() {
|
||||
var c;
|
||||
for (;console.log("foo"););
|
||||
(function h(d) {
|
||||
d && d.p;
|
||||
})();
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
var a = 42;
|
||||
(function() {
|
||||
f();
|
||||
f();
|
||||
function f() {
|
||||
if (console && a)
|
||||
for (;console.log("foo"););
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"foo",
|
||||
]
|
||||
}
|
||||
|
||||
issue_5851_1: {
|
||||
options = {
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
console.log("PASS") && f();
|
||||
function f() {
|
||||
return f();
|
||||
}
|
||||
f;
|
||||
}
|
||||
expect: {
|
||||
console.log("PASS") && f();
|
||||
function f() {
|
||||
return f();
|
||||
}
|
||||
f;
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_5851_2: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = f();
|
||||
f();
|
||||
function f() {
|
||||
if (console.log("foo"))
|
||||
console && f();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
f();
|
||||
f();
|
||||
function f() {
|
||||
console.log("foo") && console && f();
|
||||
}
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"foo",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -228,6 +228,7 @@ issue_4489: {
|
||||
evaluate: true,
|
||||
hoist_vars: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -363,6 +364,7 @@ issue_4893_1: {
|
||||
evaluate: true,
|
||||
hoist_vars: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -383,9 +385,8 @@ issue_4893_1: {
|
||||
}
|
||||
expect: {
|
||||
try{
|
||||
(function f() {
|
||||
(function() {
|
||||
null.p += 42;
|
||||
f;
|
||||
})();
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
@@ -422,9 +423,7 @@ issue_4893_2: {
|
||||
expect: {
|
||||
try{
|
||||
(function() {
|
||||
var a;
|
||||
a = null;
|
||||
a.p += 42;
|
||||
null.p += 42;
|
||||
})();
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
@@ -610,6 +609,7 @@ issue_5411_2: {
|
||||
evaluate: true,
|
||||
hoist_vars: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -622,9 +622,9 @@ issue_5411_2: {
|
||||
}
|
||||
expect: {
|
||||
var b, c;
|
||||
b++;
|
||||
b++,
|
||||
b = "PASS",
|
||||
c;
|
||||
c,
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
|
||||
@@ -26,7 +26,7 @@ record_update: {
|
||||
currying: {
|
||||
options = {
|
||||
inline: true,
|
||||
passes: 2,
|
||||
passes: 3,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
|
||||
@@ -23,7 +23,7 @@ join_array_assignments_1: {
|
||||
}
|
||||
input: {
|
||||
console.log(function () {
|
||||
var a = ["foo", , "bar"];
|
||||
var a = [ "foo", , "bar" ];
|
||||
a[1] = "baz";
|
||||
a[7] = "moo";
|
||||
a[0] = "moz";
|
||||
@@ -32,7 +32,7 @@ join_array_assignments_1: {
|
||||
}
|
||||
expect: {
|
||||
console.log(function () {
|
||||
var a = [("foo", "moz"), "baz", "bar", , , , , "moo"];
|
||||
var a = [ "moz", "baz", "bar", , , , , "moo" ];
|
||||
return a;
|
||||
}().join());
|
||||
}
|
||||
@@ -46,7 +46,7 @@ join_array_assignments_2: {
|
||||
}
|
||||
input: {
|
||||
console.log(function () {
|
||||
var a = ["foo"];
|
||||
var a = [ "foo" ];
|
||||
a[1] = "bar";
|
||||
a[7] = "baz";
|
||||
a[2] = "moo";
|
||||
@@ -55,7 +55,7 @@ join_array_assignments_2: {
|
||||
}
|
||||
expect: {
|
||||
console.log(function () {
|
||||
var a = ["foo", "bar"];
|
||||
var a = [ "foo", "bar" ];
|
||||
a[7] = "baz";
|
||||
a[2] = "moo";
|
||||
return a;
|
||||
@@ -71,7 +71,7 @@ join_array_assignments_3: {
|
||||
}
|
||||
input: {
|
||||
console.log(function () {
|
||||
var a = ["foo"];
|
||||
var a = [ "foo" ];
|
||||
a[1] = "bar";
|
||||
a.b = "baz";
|
||||
a[2] = "moo";
|
||||
@@ -80,7 +80,7 @@ join_array_assignments_3: {
|
||||
}
|
||||
expect: {
|
||||
console.log(function () {
|
||||
var a = ["foo", "bar"];
|
||||
var a = [ "foo", "bar" ];
|
||||
a.b = "baz";
|
||||
a[2] = "moo";
|
||||
return a;
|
||||
@@ -97,7 +97,7 @@ join_array_assignments_4: {
|
||||
}
|
||||
input: {
|
||||
console.log(function () {
|
||||
var a = ["foo"];
|
||||
var a = [ "foo" ];
|
||||
a[0] = "bar";
|
||||
a[1] = a;
|
||||
a[2] = "baz";
|
||||
@@ -106,7 +106,7 @@ join_array_assignments_4: {
|
||||
}
|
||||
expect: {
|
||||
console.log(function () {
|
||||
var a = ["bar"];
|
||||
var a = [ "bar" ];
|
||||
a[1] = a;
|
||||
a[2] = "baz";
|
||||
return a;
|
||||
@@ -1508,3 +1508,22 @@ issue_5831: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_5849: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
a = [ 42 ];
|
||||
a[0] = "PASS";
|
||||
console.log(a.join(""));
|
||||
}
|
||||
expect: {
|
||||
var a, a = [ "PASS" ];
|
||||
console.log(a.join(""));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -617,3 +617,33 @@ issue_5292_sub_pure_getters_strict: {
|
||||
]
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
issue_5856: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
var a;
|
||||
a?.p;
|
||||
a.q;
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
var a;
|
||||
a?.p;
|
||||
a.q;
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=14"
|
||||
}
|
||||
|
||||
@@ -1687,3 +1687,31 @@ issue_4939: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_5856: {
|
||||
options = {
|
||||
pure_getters: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = [ "FAIL", "PASS" ];
|
||||
(function(b) {
|
||||
var c = b[0];
|
||||
b[0] = b[1];
|
||||
b[1] = c;
|
||||
})(a);
|
||||
console.log(a[0]);
|
||||
}
|
||||
expect: {
|
||||
var a = [ "FAIL", "PASS" ];
|
||||
(function(b) {
|
||||
var c = b[0];
|
||||
b[0] = b[1];
|
||||
b[1] = c;
|
||||
})(a);
|
||||
console.log(a[0]);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -724,3 +724,246 @@ retain_instanceof: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
drop_access: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o.p;
|
||||
try {
|
||||
(function() {
|
||||
o.q;
|
||||
})();
|
||||
console.log("PASS");
|
||||
} catch (e) {
|
||||
console.log("FAIL");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var o = {};
|
||||
o.p;
|
||||
try {
|
||||
console.log("PASS");
|
||||
} catch (e) {
|
||||
console.log("FAIL");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
keep_access: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o.p;
|
||||
o = null;
|
||||
try {
|
||||
(function() {
|
||||
o.q;
|
||||
})();
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var o = {};
|
||||
o.p;
|
||||
o = null;
|
||||
try {
|
||||
(function() {
|
||||
o.q;
|
||||
})();
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
keep_access_after_call: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o.p;
|
||||
o.q;
|
||||
f();
|
||||
try {
|
||||
o.r;
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
function f() {
|
||||
o = null;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var o = {};
|
||||
o.p;
|
||||
f();
|
||||
try {
|
||||
o.r;
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
function f() {
|
||||
o = null;
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_5860_drop_1: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a = {};
|
||||
a.p;
|
||||
var a;
|
||||
a.q;
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
var a = {};
|
||||
a.p;
|
||||
var a;
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_5860_drop_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
a = {};
|
||||
a.p;
|
||||
var a;
|
||||
a.q;
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
a = {};
|
||||
a.p;
|
||||
var a;
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_5860_keep_1: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a = {};
|
||||
a.p;
|
||||
a.q;
|
||||
var a = null;
|
||||
try {
|
||||
a.r;
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var a = {};
|
||||
a.p;
|
||||
var a = null;
|
||||
try {
|
||||
a.r;
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_5860_keep_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
a = {};
|
||||
a.p;
|
||||
a.q;
|
||||
var a = null;
|
||||
try {
|
||||
a.r;
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
a = {};
|
||||
a.p;
|
||||
var a = null;
|
||||
try {
|
||||
a.r;
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_5860_keep_3: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a = {};
|
||||
a.p;
|
||||
a.q;
|
||||
a = null;
|
||||
try {
|
||||
a.r;
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var a = {};
|
||||
a.p;
|
||||
a = null;
|
||||
try {
|
||||
a.r;
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -1253,3 +1253,24 @@ issue_5602: {
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5850: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = [ ..."FAIL" ];
|
||||
a[0] = "P";
|
||||
a[2] = a[3] = "S";
|
||||
console.log(a.join(""));
|
||||
}
|
||||
expect: {
|
||||
var a = [ ..."FAIL" ];
|
||||
a[0] = "P";
|
||||
a[2] = a[3] = "S";
|
||||
console.log(a.join(""));
|
||||
}
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
@@ -1386,7 +1386,7 @@ issue_5076_1: {
|
||||
expect: {
|
||||
var a;
|
||||
console.log("PASS"),
|
||||
a = 42["a"];
|
||||
a = 42..a;
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
@@ -2207,3 +2207,43 @@ issue_5754: {
|
||||
]
|
||||
node_version: ">=10"
|
||||
}
|
||||
|
||||
issue_5842: {
|
||||
options = {
|
||||
inline: true,
|
||||
}
|
||||
input: {
|
||||
var a = "FAIL";
|
||||
(async function*() {
|
||||
(function() {
|
||||
try {
|
||||
try {
|
||||
return console;
|
||||
} finally {
|
||||
a = "PASS";
|
||||
}
|
||||
} catch (e) {}
|
||||
FAIL;
|
||||
})();
|
||||
})().next();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "FAIL";
|
||||
(async function*() {
|
||||
(function() {
|
||||
try {
|
||||
try {
|
||||
return console;
|
||||
} finally {
|
||||
a = "PASS";
|
||||
}
|
||||
} catch (e) {}
|
||||
FAIL;
|
||||
})();
|
||||
})().next();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=10"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user