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) {
- 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),
- value: prop.value
- }));
+ if (node instanceof AST_Assign && node.operator == "=" && can_hoist(node.left, node.right, 1)) {
+ descend(node, this);
+ var defs = new Dictionary();
+ var assignments = [];
+ 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()
});
- defs_by_id[def.id] = defs;
- return MAP.splice(assignments);
- }
+ 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[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];
}
}
- 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
});