@@ -4062,10 +4062,11 @@ merge(Compressor.prototype, {
|
|||||||
var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
|
var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
|
||||||
var defs_by_id = Object.create(null);
|
var defs_by_id = Object.create(null);
|
||||||
self.transform(new TreeTransformer(function(node, descend) {
|
self.transform(new TreeTransformer(function(node, descend) {
|
||||||
if (node instanceof AST_Assign
|
if (node instanceof AST_Assign) {
|
||||||
&& node.operator == "="
|
if (node.operator != "=") return;
|
||||||
&& node.write_only
|
if (!node.write_only) return;
|
||||||
&& can_hoist(node.left, node.right, 1)) {
|
if (node.left.scope !== self) return;
|
||||||
|
if (!can_hoist(node.left, node.right, 1)) return;
|
||||||
descend(node, this);
|
descend(node, this);
|
||||||
var defs = new Dictionary();
|
var defs = new Dictionary();
|
||||||
var assignments = [];
|
var assignments = [];
|
||||||
@@ -4094,17 +4095,9 @@ merge(Compressor.prototype, {
|
|||||||
}));
|
}));
|
||||||
return make_sequence(node, assignments);
|
return make_sequence(node, assignments);
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Unary
|
if (node instanceof AST_Scope) return node === self ? undefined : node;
|
||||||
&& !unary_side_effects[node.operator]
|
if (node instanceof AST_VarDef) {
|
||||||
&& node.expression instanceof AST_SymbolRef
|
if (!can_hoist(node.name, node.value, 0)) return;
|
||||||
&& node.expression.definition().id in defs_by_id) {
|
|
||||||
node = node.clone();
|
|
||||||
node.expression = make_node(AST_Object, node, {
|
|
||||||
properties: []
|
|
||||||
});
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
if (node instanceof AST_VarDef && can_hoist(node.name, node.value, 0)) {
|
|
||||||
descend(node, this);
|
descend(node, this);
|
||||||
var defs = new Dictionary();
|
var defs = new Dictionary();
|
||||||
var var_defs = [];
|
var var_defs = [];
|
||||||
@@ -4117,32 +4110,6 @@ merge(Compressor.prototype, {
|
|||||||
defs_by_id[node.name.definition().id] = defs;
|
defs_by_id[node.name.definition().id] = defs;
|
||||||
return MAP.splice(var_defs);
|
return MAP.splice(var_defs);
|
||||||
}
|
}
|
||||||
if (node instanceof AST_PropAccess && node.expression instanceof AST_SymbolRef) {
|
|
||||||
var defs = defs_by_id[node.expression.definition().id];
|
|
||||||
if (defs) {
|
|
||||||
var def = defs.get(node.getProperty());
|
|
||||||
var sym = make_node(AST_SymbolRef, node, {
|
|
||||||
name: def.name,
|
|
||||||
scope: node.expression.scope,
|
|
||||||
thedef: def
|
|
||||||
});
|
|
||||||
sym.reference({});
|
|
||||||
return sym;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function can_hoist(sym, right, count) {
|
|
||||||
if (sym.scope !== self) 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 == count) return;
|
|
||||||
if (def.single_use) return;
|
|
||||||
if (top_retain(def)) return;
|
|
||||||
if (sym.fixed_value() !== right) return;
|
|
||||||
return right instanceof AST_Object;
|
|
||||||
}
|
|
||||||
|
|
||||||
function make_sym(sym, key) {
|
function make_sym(sym, key) {
|
||||||
var new_var = make_node(AST_SymbolVar, sym, {
|
var new_var = make_node(AST_SymbolVar, sym, {
|
||||||
@@ -4155,6 +4122,43 @@ merge(Compressor.prototype, {
|
|||||||
return new_var;
|
return new_var;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
self.transform(new TreeTransformer(function(node, descend) {
|
||||||
|
if (node instanceof AST_PropAccess) {
|
||||||
|
if (!(node.expression instanceof AST_SymbolRef)) return;
|
||||||
|
var defs = defs_by_id[node.expression.definition().id];
|
||||||
|
if (!defs) return;
|
||||||
|
var def = defs.get(node.getProperty());
|
||||||
|
var sym = make_node(AST_SymbolRef, node, {
|
||||||
|
name: def.name,
|
||||||
|
scope: node.expression.scope,
|
||||||
|
thedef: def
|
||||||
|
});
|
||||||
|
sym.reference({});
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_Unary) {
|
||||||
|
if (unary_side_effects[node.operator]) return;
|
||||||
|
if (!(node.expression instanceof AST_SymbolRef)) return;
|
||||||
|
if (!(node.expression.definition().id in defs_by_id)) return;
|
||||||
|
var opt = node.clone();
|
||||||
|
opt.expression = make_node(AST_Object, node, {
|
||||||
|
properties: []
|
||||||
|
});
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
function can_hoist(sym, right, count) {
|
||||||
|
var def = sym.definition();
|
||||||
|
if (def.assignments != count) return;
|
||||||
|
if (def.direct_access) return;
|
||||||
|
if (def.escaped.depth == 1) return;
|
||||||
|
if (def.references.length == count) return;
|
||||||
|
if (def.single_use) return;
|
||||||
|
if (top_retain(def)) return;
|
||||||
|
if (sym.fixed_value() !== right) return;
|
||||||
|
return right instanceof AST_Object;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// drop_side_effect_free()
|
// drop_side_effect_free()
|
||||||
|
|||||||
@@ -886,3 +886,31 @@ issue_3411: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3440: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
function f() {
|
||||||
|
console.log(o.p);
|
||||||
|
}
|
||||||
|
var o = {
|
||||||
|
p: "PASS",
|
||||||
|
};
|
||||||
|
return f;
|
||||||
|
})()();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
var o_p = "PASS";
|
||||||
|
return function() {
|
||||||
|
console.log(o_p);
|
||||||
|
};
|
||||||
|
})()();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user