aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/compress.js71
-rw-r--r--test/compress/merge_vars.js2086
2 files changed, 2128 insertions, 29 deletions
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",
+ ]
+}