extend hoist_props (#3073)
- handle `AST_Assign` the same way as `AST_VarDef` - inject `AST_Var` as succeeding statement fixes #3071
This commit is contained in:
@@ -3639,28 +3639,47 @@ merge(Compressor.prototype, {
|
||||
var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
|
||||
var defs_by_id = Object.create(null);
|
||||
return self.transform(new TreeTransformer(function(node, descend) {
|
||||
if (node instanceof AST_VarDef) {
|
||||
var sym = node.name, def, value;
|
||||
if (sym.scope === self
|
||||
&& (def = sym.definition()).escaped != 1
|
||||
&& !def.assignments
|
||||
&& !def.direct_access
|
||||
&& !def.single_use
|
||||
&& !top_retain(def)
|
||||
&& (value = sym.fixed_value()) === node.value
|
||||
&& value instanceof AST_Object) {
|
||||
if (node instanceof AST_Assign && node.operator == "=" && can_hoist(node.left, node.right, 1)) {
|
||||
descend(node, this);
|
||||
var defs = new Dictionary();
|
||||
var assignments = [];
|
||||
value.properties.forEach(function(prop) {
|
||||
assignments.push(make_node(AST_VarDef, node, {
|
||||
name: make_sym(prop.key),
|
||||
var decls = [];
|
||||
node.right.properties.forEach(function(prop) {
|
||||
var decl = make_sym(node.left, prop.key);
|
||||
decls.push(make_node(AST_VarDef, node, {
|
||||
name: decl,
|
||||
value: null
|
||||
}));
|
||||
var sym = make_node(AST_SymbolRef, node, {
|
||||
name: decl.name,
|
||||
scope: self,
|
||||
thedef: decl.definition()
|
||||
});
|
||||
sym.reference({});
|
||||
assignments.push(make_node(AST_Assign, node, {
|
||||
operator: "=",
|
||||
left: sym,
|
||||
right: prop.value
|
||||
}));
|
||||
});
|
||||
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
|
||||
}));
|
||||
return make_sequence(node, assignments);
|
||||
}
|
||||
if (node instanceof AST_VarDef && can_hoist(node.name, node.value, 0)) {
|
||||
descend(node, this);
|
||||
var defs = new Dictionary();
|
||||
var var_defs = [];
|
||||
node.value.properties.forEach(function(prop) {
|
||||
var_defs.push(make_node(AST_VarDef, node, {
|
||||
name: make_sym(node.name, prop.key),
|
||||
value: prop.value
|
||||
}));
|
||||
});
|
||||
defs_by_id[def.id] = defs;
|
||||
return MAP.splice(assignments);
|
||||
}
|
||||
defs_by_id[node.name.definition().id] = 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];
|
||||
@@ -3676,8 +3695,20 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
|
||||
function make_sym(key) {
|
||||
var new_var = make_node(sym.CTOR, 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 == 1) 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) {
|
||||
var new_var = make_node(AST_SymbolVar, sym, {
|
||||
name: self.make_var_name(sym.name + "_" + key),
|
||||
scope: self
|
||||
});
|
||||
|
||||
@@ -742,3 +742,85 @@ issue_3046: {
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_3071_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
join_vars: true,
|
||||
hoist_props: true,
|
||||
passes: 3,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
var obj = {};
|
||||
obj.one = 1;
|
||||
obj.two = 2;
|
||||
console.log(obj.one);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
console.log(1);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_3071_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
join_vars: true,
|
||||
hoist_props: true,
|
||||
passes: 3,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
obj = {};
|
||||
obj.one = 1;
|
||||
obj.two = 2;
|
||||
console.log(obj.one);
|
||||
var obj;
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
console.log(1);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_3071_2_toplevel: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
join_vars: true,
|
||||
hoist_props: true,
|
||||
passes: 3,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
obj = {};
|
||||
obj.one = 1;
|
||||
obj.two = 2;
|
||||
console.log(obj.one);
|
||||
var obj;
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
console.log(1);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user