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);
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) {
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 ];
+ mark_escaped(tw, d, sym.scope, node, right, 0, 1);
}
});
}
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,
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);
}
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,
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: [] });
}
}));
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);
}
});
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,
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;
},
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;
},
}
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);
expect: {
console.log(function(a) {
do {
- var b_c = a++;
+ var b, b_c = a++;
} while (b_c && a);
return a;
}(0));
expect: {
var c = 1;
!function f() {
- var o_p = --c && f();
+ var o, o_p = --c && f();
+{} || console.log("PASS");
}();
}
expect: {
function f() {
o.p;
- var o = {
- q: 0,
- };
+ var o, o_q = 0;
}
}
}
}
expect: {
console.log(typeof o);
- var o = {
- p: 0,
- };
+ var o, o_p = 0;
}
expect_stdout: "undefined"
}
}());
}
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",
+ ]
+}