From: Alex Lam S.L Date: Sat, 19 Sep 2020 03:16:23 +0000 (+0100) Subject: enhance `merge_vars` (#4125) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=3ac533e6444aba234151ebb53e775d164d4f8120;p=UglifyJS.git enhance `merge_vars` (#4125) --- diff --git a/lib/compress.js b/lib/compress.js index cfd3e2b2..c30e4b83 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -4322,7 +4322,7 @@ merge(Compressor.prototype, { AST_Scope.DEFMETHOD("merge_variables", function(compressor) { if (!compressor.option("merge_vars")) return; - var self = this, segment = null; + var self = this, segment = {}; var first = [], last = [], index = 0; var declarations = new Dictionary(); var references = Object.create(null); @@ -4331,9 +4331,9 @@ merge(Compressor.prototype, { if (node instanceof AST_Assign) { var sym = node.left; if (!(sym instanceof AST_SymbolRef)) return; - if (node.operator != "=") mark(sym); + if (node.operator != "=") mark(sym, true, false); node.right.walk(tw); - mark(sym, true); + mark(sym, false, true); return true; } if (node instanceof AST_Binary) { @@ -4357,6 +4357,7 @@ merge(Compressor.prototype, { if (node instanceof AST_For) { if (node.init) node.init.walk(tw); push(); + segment.block = node; if (node.condition) node.condition.walk(tw); node.body.walk(tw); if (node.step) node.step.walk(tw); @@ -4366,6 +4367,7 @@ merge(Compressor.prototype, { if (node instanceof AST_ForIn) { node.object.walk(tw); push(); + segment.block = node; node.init.walk(tw); node.body.walk(tw); pop(); @@ -4385,12 +4387,14 @@ merge(Compressor.prototype, { } if (node instanceof AST_IterationStatement) { push(); + segment.block = node; descend(); pop(); return true; } if (node instanceof AST_LabeledStatement) { push(); + segment.block = node; node.body.walk(tw); pop(); return true; @@ -4401,6 +4405,7 @@ merge(Compressor.prototype, { if (node.name) references[node.name.definition().id] = false; } push(); + segment.block = node; descend(); pop(); return true; @@ -4422,11 +4427,11 @@ merge(Compressor.prototype, { return true; } if (node instanceof AST_SymbolFunarg) { - if (!node.__unused) mark(node, true); + if (!node.__unused) mark(node, false, true); return true; } if (node instanceof AST_SymbolRef) { - mark(node); + mark(node, true, false); return true; } if (node instanceof AST_Try) { @@ -4446,13 +4451,13 @@ merge(Compressor.prototype, { if (!unary_arithmetic[node.operator]) return; var sym = node.expression; if (!(sym instanceof AST_SymbolRef)) return; - mark(sym); + mark(sym, true, true); return true; } if (node instanceof AST_VarDef) { if (node.value) { node.value.walk(tw); - mark(node.name, true); + mark(node.name, false, true); } else { var id = node.name.definition().id; if (!(id in references)) { @@ -4479,7 +4484,7 @@ merge(Compressor.prototype, { if (tail.index > head.index) continue; var id = tail.definition.id; if (!references[id]) continue; - if (references[def.id].segment !== references[id].segment) { + if (!mergeable()) { skipped.unshift(tail); continue; } @@ -4510,40 +4515,52 @@ merge(Compressor.prototype, { segment = Object.getPrototypeOf(segment); } - function read(def) { - prev[def.id] = last.length; - last.push({ - index: index++, - definition: def, - }); - } - - function mark(sym, write_only) { + function mark(sym, read, write) { var def = sym.definition(); if (def.id in references) { var refs = references[def.id]; if (!refs) return; - if (refs.segment !== segment) return references[def.id] = false; + if (write ? refs.start !== segment : refs.start.block !== segment.block) { + return references[def.id] = false; + } refs.push(sym); - if (def.id in prev) last[prev[def.id]] = null; - read(def); + refs.end = segment; + if (def.id in prev) { + last[prev[def.id]] = null; + } else if (!read) { + return; + } } else if (self.variables.get(def.name) !== def || compressor.exposed(def)) { - references[def.id] = false; + return references[def.id] = false; } else { var refs = declarations.get(def.id) || []; refs.push(sym); references[def.id] = refs; - if (write_only) { - refs.segment = segment; - first.push({ + if (!read) { + refs.start = segment; + return first.push({ index: index++, definition: def, }); - } else { - refs.segment = self; - read(def); } + refs.start = self; } + prev[def.id] = last.length; + last.push({ + index: index++, + definition: def, + }); + } + + function must_visit(base, segment) { + return base === segment || base.isPrototypeOf(segment); + } + + function mergeable() { + var head = references[def.id]; + var tail = references[id]; + if (head.start.block !== tail.start.block) return false; + return must_visit(head.start, head.end) || must_visit(head.start, tail.start); } }); diff --git a/test/compress/merge_vars.js b/test/compress/merge_vars.js index c63f33d0..f1b0e701 100644 --- a/test/compress/merge_vars.js +++ b/test/compress/merge_vars.js @@ -344,8 +344,8 @@ issue_4107: { } expect: { (function() { - (function(c) { - var a = console || c; + (function(a) { + a = console || a; console.log(typeof a); })(); })(); @@ -512,3 +512,2085 @@ issue_4115: { } expect_stdout: "undefined" } + +cross_branch_1_1: { + options = { + merge_vars: true, + } + input: { + var a; + function f() { + var x, y; + if (a) + x = "foo"; + console.log(x); + y = "bar"; + console.log(y); + } + a = 0; + f(); + a = 1; + f(); + } + expect: { + var a; + function f() { + var y, y; + if (a) + y = "foo"; + console.log(y); + y = "bar"; + console.log(y); + } + a = 0; + f(); + a = 1; + f(); + } + expect_stdout: [ + "undefined", + "bar", + "foo", + "bar", + ] +} + +cross_branch_1_2: { + options = { + merge_vars: true, + } + input: { + var a; + function f() { + var x, y; + if (a) { + x = "foo"; + console.log(x); + } + y = "bar"; + console.log(y); + } + a = 0; + f(); + a = 1; + f(); + } + expect: { + var a; + function f() { + var y, y; + if (a) { + y = "foo"; + console.log(y); + } + y = "bar"; + console.log(y); + } + a = 0; + f(); + a = 1; + f(); + } + expect_stdout: [ + "bar", + "foo", + "bar", + ] +} + +cross_branch_1_3: { + options = { + merge_vars: true, + } + input: { + var a; + function f() { + var x, y; + if (a) { + x = "foo"; + console.log(x); + y = "bar"; + } + console.log(y); + } + a = 0; + f(); + a = 1; + f(); + } + expect: { + var a; + function f() { + var y, y; + if (a) { + y = "foo"; + console.log(y); + y = "bar"; + } + console.log(y); + } + a = 0; + f(); + a = 1; + f(); + } + expect_stdout: [ + "undefined", + "foo", + "bar", + ] +} + +cross_branch_1_4: { + options = { + merge_vars: true, + } + input: { + var a; + function f() { + var x, y; + x = "foo"; + if (a) + console.log(x); + y = "bar"; + console.log(y); + } + a = 0; + f(); + a = 1; + f(); + } + expect: { + var a; + function f() { + var y, y; + y = "foo"; + if (a) + console.log(y); + y = "bar"; + console.log(y); + } + a = 0; + f(); + a = 1; + f(); + } + expect_stdout: [ + "bar", + "foo", + "bar", + ] +} + +cross_branch_1_5: { + options = { + merge_vars: true, + } + input: { + var a; + function f() { + var x, y; + x = "foo"; + if (a) { + console.log(x); + y = "bar"; + } + console.log(y); + } + a = 0; + f(); + a = 1; + f(); + } + expect: { + var a; + function f() { + var x, y; + x = "foo"; + if (a) { + console.log(x); + y = "bar"; + } + console.log(y); + } + a = 0; + f(); + a = 1; + f(); + } + expect_stdout: [ + "undefined", + "foo", + "bar", + ] +} + +cross_branch_1_6: { + options = { + merge_vars: true, + } + input: { + var a; + function f() { + var x, y; + x = "foo"; + if (a) { + console.log(x); + y = "bar"; + console.log(y); + } + } + a = 0; + f(); + a = 1; + f(); + } + expect: { + var a; + function f() { + var y, y; + y = "foo"; + if (a) { + console.log(y); + y = "bar"; + console.log(y); + } + } + a = 0; + f(); + a = 1; + f(); + } + expect_stdout: [ + "foo", + "bar", + ] +} + +cross_branch_1_7: { + options = { + merge_vars: true, + } + input: { + var a; + function f() { + var x, y; + x = "foo"; + console.log(x); + if (a) + y = "bar"; + console.log(y); + } + a = 0; + f(); + a = 1; + f(); + } + expect: { + var a; + function f() { + var x, y; + x = "foo"; + console.log(x); + if (a) + y = "bar"; + console.log(y); + } + a = 0; + f(); + a = 1; + f(); + } + expect_stdout: [ + "foo", + "undefined", + "foo", + "bar", + ] +} + +cross_branch_1_8: { + options = { + merge_vars: true, + } + input: { + var a; + function f() { + var x, y; + x = "foo"; + console.log(x); + if (a) { + y = "bar"; + console.log(y); + } + } + a = 0; + f(); + a = 1; + f(); + } + expect: { + var a; + function f() { + var y, y; + y = "foo"; + console.log(y); + if (a) { + y = "bar"; + console.log(y); + } + } + a = 0; + f(); + a = 1; + f(); + } + expect_stdout: [ + "foo", + "foo", + "bar", + ] +} + +cross_branch_1_9: { + options = { + merge_vars: true, + } + input: { + var a; + function f() { + var x, y; + x = "foo"; + console.log(x); + y = "bar"; + if (a) + console.log(y); + } + a = 0; + f(); + a = 1; + f(); + } + expect: { + var a; + function f() { + var y, y; + y = "foo"; + console.log(y); + y = "bar"; + if (a) + console.log(y); + } + a = 0; + f(); + a = 1; + f(); + } + expect_stdout: [ + "foo", + "foo", + "bar", + ] +} + +cross_branch_2a_1: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) { + if (b) + x = "foo"; + console.log(x); + } + y = "bar"; + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + if (a) { + if (b) + y = "foo"; + console.log(y); + } + y = "bar"; + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "bar", + "undefined", + "bar", + "bar", + "foo", + "bar", + ] +} + +cross_branch_2a_2: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) { + x = "foo"; + if (b) + console.log(x); + } + y = "bar"; + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + if (a) { + y = "foo"; + if (b) + console.log(y); + } + y = "bar"; + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "bar", + "bar", + "bar", + "foo", + "bar", + ] +} + +cross_branch_2a_3: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) { + if (b) + x = "foo"; + console.log(x); + y = "bar"; + } + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + if (a) { + if (b) + y = "foo"; + console.log(y); + y = "bar"; + } + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "undefined", + "undefined", + "bar", + "undefined", + "foo", + "bar", + ] +} + +cross_branch_2a_4: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) { + if (b) { + x = "foo"; + console.log(x); + } + y = "bar"; + } + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + if (a) { + if (b) { + y = "foo"; + console.log(y); + } + y = "bar"; + } + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "undefined", + "bar", + "undefined", + "foo", + "bar", + ] +} + +cross_branch_2a_5: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) { + x = "foo"; + if (b) + console.log(x); + y = "bar"; + } + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + if (a) { + y = "foo"; + if (b) + console.log(y); + y = "bar"; + } + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "undefined", + "bar", + "undefined", + "foo", + "bar", + ] +} + +cross_branch_2a_6: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) { + x = "foo"; + if (b) { + console.log(x); + y = "bar"; + } + } + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var x, y; + if (a) { + x = "foo"; + if (b) { + console.log(x); + y = "bar"; + } + } + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "undefined", + "undefined", + "undefined", + "foo", + "bar", + ] +} + +cross_branch_2a_7: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) { + x = "foo"; + console.log(x); + if (b) + y = "bar"; + } + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var x, y; + if (a) { + x = "foo"; + console.log(x); + if (b) + y = "bar"; + } + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "undefined", + "foo", + "undefined", + "undefined", + "foo", + "bar", + ] +} + +cross_branch_2a_8: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) { + if (b) + console.log(x); + y = "bar"; + } + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) { + if (b) + console.log(x); + y = "bar"; + } + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "undefined", + "bar", + "undefined", + "foo", + "bar", + ] +} + +cross_branch_2a_9: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) { + console.log(x); + if (b) + y = "bar"; + } + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) { + console.log(x); + if (b) + y = "bar"; + } + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "undefined", + "foo", + "undefined", + "undefined", + "foo", + "bar", + ] +} + +cross_branch_2a_10: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) { + if (b) + console.log(x); + y = "bar"; + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + y = "foo"; + if (a) { + if (b) + console.log(y); + y = "bar"; + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "bar", + "foo", + "bar", + ] +} + +cross_branch_2a_11: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) { + if (b) { + console.log(x); + y = "bar"; + } + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) { + if (b) { + console.log(x); + y = "bar"; + } + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "undefined", + "foo", + "bar", + ] +} + +cross_branch_2a_12: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) { + console.log(x); + if (b) + y = "bar"; + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) { + console.log(x); + if (b) + y = "bar"; + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "foo", + "undefined", + "foo", + "bar", + ] +} + +cross_branch_2a_13: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) { + console.log(x); + if (b) { + y = "bar"; + console.log(y); + } + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + y = "foo"; + if (a) { + console.log(y); + if (b) { + y = "bar"; + console.log(y); + } + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "foo", + "foo", + "bar", + ] +} + +cross_branch_2a_14: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) { + console.log(x); + y = "bar"; + if (b) + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + y = "foo"; + if (a) { + console.log(y); + y = "bar"; + if (b) + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "foo", + "foo", + "bar", + ] +} + +cross_branch_2a_15: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + x = "foo"; + console.log(x); + if (a) { + if (b) + y = "bar"; + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var x, y; + x = "foo"; + console.log(x); + if (a) { + if (b) + y = "bar"; + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "foo", + "foo", + "undefined", + "foo", + "foo", + "bar", + ] +} + +cross_branch_2a_16: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + x = "foo"; + console.log(x); + if (a) { + y = "bar"; + if (b) + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + y = "foo"; + console.log(y); + if (a) { + y = "bar"; + if (b) + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "foo", + "foo", + "foo", + "foo", + "bar", + ] +} + +cross_branch_2b_1: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) + x = "foo"; + if (b) + console.log(x); + y = "bar"; + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + if (a) + y = "foo"; + if (b) + console.log(y); + y = "bar"; + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "bar", + "bar", + "undefined", + "bar", + "foo", + "bar", + ] +} + +cross_branch_2b_2: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) + x = "foo"; + if (b) { + console.log(x); + y = "bar"; + } + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var x, y; + if (a) + x = "foo"; + if (b) { + console.log(x); + y = "bar"; + } + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "undefined", + "undefined", + "undefined", + "bar", + "foo", + "bar", + ] +} + +cross_branch_2b_3: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) + x = "foo"; + if (b) { + console.log(x); + y = "bar"; + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + if (a) + y = "foo"; + if (b) { + console.log(y); + y = "bar"; + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "undefined", + "bar", + "foo", + "bar", + ] +} + +cross_branch_2b_4: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) + x = "foo"; + console.log(x); + if (b) + y = "bar"; + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var x, y; + if (a) + x = "foo"; + console.log(x); + if (b) + y = "bar"; + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "undefined", + "undefined", + "foo", + "undefined", + "undefined", + "bar", + "foo", + "bar", + ] +} + +cross_branch_2b_5: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) + x = "foo"; + console.log(x); + if (b) { + y = "bar"; + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + if (a) + y = "foo"; + console.log(y); + if (b) { + y = "bar"; + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "undefined", + "foo", + "undefined", + "bar", + "foo", + "bar", + ] +} + +cross_branch_2b_6: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) { + x = "foo"; + console.log(x); + } + if (b) + y = "bar"; + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var x, y; + if (a) { + x = "foo"; + console.log(x); + } + if (b) + y = "bar"; + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "undefined", + "foo", + "undefined", + "bar", + "foo", + "bar", + ] +} + +cross_branch_2b_7: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) { + x = "foo"; + console.log(x); + } + if (b) { + y = "bar"; + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + if (a) { + y = "foo"; + console.log(y); + } + if (b) { + y = "bar"; + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "foo", + "bar", + "foo", + "bar", + ] +} + +cross_branch_2b_8: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) + x = "foo"; + console.log(x); + y = "bar"; + if (b) + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + if (a) + y = "foo"; + console.log(y); + y = "bar"; + if (b) + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "undefined", + "foo", + "undefined", + "bar", + "foo", + "bar", + ] +} + +cross_branch_2b_9: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) { + x = "foo"; + console.log(x); + } + y = "bar"; + if (b) + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + if (a) { + y = "foo"; + console.log(y); + } + y = "bar"; + if (b) + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "foo", + "bar", + "foo", + "bar", + ] +} + +cross_branch_2b_10: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + if (a) { + x = "foo"; + console.log(x); + y = "bar"; + } + if (b) + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + if (a) { + y = "foo"; + console.log(y); + y = "bar"; + } + if (b) + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "foo", + "undefined", + "foo", + "bar", + ] +} + +cross_branch_2b_11: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) + console.log(x); + if (b) + y = "bar"; + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) + console.log(x); + if (b) + y = "bar"; + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "undefined", + "foo", + "undefined", + "bar", + "foo", + "bar", + ] +} + +cross_branch_2b_12: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) + console.log(x); + if (b) { + y = "bar"; + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + y = "foo"; + if (a) + console.log(y); + if (b) { + y = "bar"; + console.log(y); + } + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "foo", + "bar", + "foo", + "bar", + ] +} + +cross_branch_2b_13: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) + console.log(x); + y = "bar"; + if (b) + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var y, y; + y = "foo"; + if (a) + console.log(y); + y = "bar"; + if (b) + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "foo", + "bar", + "foo", + "bar", + ] +} + +cross_branch_2b_14: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) { + console.log(x); + y = "bar"; + } + if (b) + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var x, y; + x = "foo"; + if (a) { + console.log(x); + y = "bar"; + } + if (b) + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "foo", + "undefined", + "foo", + "bar", + ] +} + +cross_branch_2b_15: { + options = { + merge_vars: true, + } + input: { + var a, b; + function f() { + var x, y; + x = "foo"; + console.log(x); + if (a) + y = "bar"; + if (b) + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect: { + var a, b; + function f() { + var x, y; + x = "foo"; + console.log(x); + if (a) + y = "bar"; + if (b) + console.log(y); + } + a = 0, b = 0; + f(); + a = 1, b = 0; + f(); + a = 0, b = 1; + f(); + a = 1, b = 1; + f(); + } + expect_stdout: [ + "foo", + "foo", + "foo", + "undefined", + "foo", + "bar", + ] +}