enhance collapse_vars (#3611)
This commit is contained in:
@@ -1415,7 +1415,9 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
function extract_candidates(expr) {
|
function extract_candidates(expr) {
|
||||||
hit_stack.push(expr);
|
hit_stack.push(expr);
|
||||||
if (expr instanceof AST_Assign) {
|
if (expr instanceof AST_Array) {
|
||||||
|
expr.elements.forEach(extract_candidates);
|
||||||
|
} else if (expr instanceof AST_Assign) {
|
||||||
candidates.push(hit_stack.slice());
|
candidates.push(hit_stack.slice());
|
||||||
extract_candidates(expr.left);
|
extract_candidates(expr.left);
|
||||||
extract_candidates(expr.right);
|
extract_candidates(expr.right);
|
||||||
@@ -1462,6 +1464,14 @@ merge(Compressor.prototype, {
|
|||||||
if (expr.alternative && !(expr.alternative instanceof AST_Block)) {
|
if (expr.alternative && !(expr.alternative instanceof AST_Block)) {
|
||||||
extract_candidates(expr.alternative);
|
extract_candidates(expr.alternative);
|
||||||
}
|
}
|
||||||
|
} else if (expr instanceof AST_Object) {
|
||||||
|
expr.properties.forEach(function(prop) {
|
||||||
|
if (prop instanceof AST_ObjectKeyVal) {
|
||||||
|
hit_stack.push(prop);
|
||||||
|
extract_candidates(prop.value);
|
||||||
|
hit_stack.pop();
|
||||||
|
}
|
||||||
|
});
|
||||||
} else if (expr instanceof AST_Sequence) {
|
} else if (expr instanceof AST_Sequence) {
|
||||||
expr.expressions.forEach(extract_candidates);
|
expr.expressions.forEach(extract_candidates);
|
||||||
} else if (expr instanceof AST_SimpleStatement) {
|
} else if (expr instanceof AST_SimpleStatement) {
|
||||||
@@ -1492,6 +1502,7 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
function find_stop(node, level) {
|
function find_stop(node, level) {
|
||||||
var parent = scanner.parent(level);
|
var parent = scanner.parent(level);
|
||||||
|
if (parent instanceof AST_Array) return node;
|
||||||
if (parent instanceof AST_Assign) return node;
|
if (parent instanceof AST_Assign) return node;
|
||||||
if (parent instanceof AST_Binary) return node;
|
if (parent instanceof AST_Binary) return node;
|
||||||
if (parent instanceof AST_Call) return node;
|
if (parent instanceof AST_Call) return node;
|
||||||
@@ -1501,6 +1512,7 @@ merge(Compressor.prototype, {
|
|||||||
if (parent instanceof AST_Exit) return node;
|
if (parent instanceof AST_Exit) return node;
|
||||||
if (parent instanceof AST_If) return node;
|
if (parent instanceof AST_If) return node;
|
||||||
if (parent instanceof AST_IterationStatement) return node;
|
if (parent instanceof AST_IterationStatement) return node;
|
||||||
|
if (parent instanceof AST_ObjectKeyVal) return node;
|
||||||
if (parent instanceof AST_PropAccess) return node;
|
if (parent instanceof AST_PropAccess) return node;
|
||||||
if (parent instanceof AST_Sequence) {
|
if (parent instanceof AST_Sequence) {
|
||||||
return (parent.tail_node() === node ? find_stop : find_stop_unused)(parent, level + 1);
|
return (parent.tail_node() === node ? find_stop : find_stop_unused)(parent, level + 1);
|
||||||
@@ -1516,6 +1528,7 @@ merge(Compressor.prototype, {
|
|||||||
var parent = scanner.parent(level);
|
var parent = scanner.parent(level);
|
||||||
if (is_last_node(node, parent)) return node;
|
if (is_last_node(node, parent)) return node;
|
||||||
if (in_conditional(node, parent)) return node;
|
if (in_conditional(node, parent)) return node;
|
||||||
|
if (parent instanceof AST_Array) return find_stop_unused(parent, level + 1);
|
||||||
if (parent instanceof AST_Assign) return find_stop_unused(parent, level + 1);
|
if (parent instanceof AST_Assign) return find_stop_unused(parent, level + 1);
|
||||||
if (parent instanceof AST_Binary) return find_stop_unused(parent, level + 1);
|
if (parent instanceof AST_Binary) return find_stop_unused(parent, level + 1);
|
||||||
if (parent instanceof AST_Call) return find_stop_unused(parent, level + 1);
|
if (parent instanceof AST_Call) return find_stop_unused(parent, level + 1);
|
||||||
@@ -1525,6 +1538,7 @@ merge(Compressor.prototype, {
|
|||||||
if (parent instanceof AST_Exit) return find_stop_unused(parent, level + 1);
|
if (parent instanceof AST_Exit) return find_stop_unused(parent, level + 1);
|
||||||
if (parent instanceof AST_If) return find_stop_unused(parent, level + 1);
|
if (parent instanceof AST_If) return find_stop_unused(parent, level + 1);
|
||||||
if (parent instanceof AST_IterationStatement) return node;
|
if (parent instanceof AST_IterationStatement) return node;
|
||||||
|
if (parent instanceof AST_ObjectKeyVal) return find_stop_unused(scanner.parent(level + 1), level + 2);
|
||||||
if (parent instanceof AST_PropAccess) {
|
if (parent instanceof AST_PropAccess) {
|
||||||
var exp = parent.expression;
|
var exp = parent.expression;
|
||||||
if (exp === node) return find_stop_unused(parent, level + 1);
|
if (exp === node) return find_stop_unused(parent, level + 1);
|
||||||
@@ -1668,20 +1682,21 @@ merge(Compressor.prototype, {
|
|||||||
var found = false;
|
var found = false;
|
||||||
return statements[stat_index].transform(new TreeTransformer(function(node, descend, in_list) {
|
return statements[stat_index].transform(new TreeTransformer(function(node, descend, in_list) {
|
||||||
if (found) return node;
|
if (found) return node;
|
||||||
|
if (node instanceof AST_Scope) return node;
|
||||||
if (node !== expr && node.body !== expr) return;
|
if (node !== expr && node.body !== expr) return;
|
||||||
|
found = true;
|
||||||
if (node instanceof AST_VarDef) {
|
if (node instanceof AST_VarDef) {
|
||||||
found = true;
|
|
||||||
node.value = null;
|
node.value = null;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if (in_list) {
|
var parent = this.parent();
|
||||||
found = true;
|
if (!parent) return in_list ? MAP.skip : null;
|
||||||
return MAP.skip;
|
if (parent instanceof AST_Sequence) return MAP.skip;
|
||||||
}
|
var value = expr;
|
||||||
if (!this.parent()) {
|
do {
|
||||||
found = true;
|
value = get_rvalue(value);
|
||||||
return null;
|
} while (value instanceof AST_Assign);
|
||||||
}
|
return value;
|
||||||
}, function(node) {
|
}, function(node) {
|
||||||
if (node instanceof AST_Sequence) switch (node.expressions.length) {
|
if (node instanceof AST_Sequence) switch (node.expressions.length) {
|
||||||
case 0: return null;
|
case 0: return null;
|
||||||
|
|||||||
@@ -669,7 +669,7 @@ collapse_vars_throw: {
|
|||||||
expect_stdout: "13"
|
expect_stdout: "13"
|
||||||
}
|
}
|
||||||
|
|
||||||
collapse_vars_switch: {
|
collapse_vars_switch_1: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
@@ -721,6 +721,31 @@ collapse_vars_switch: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
collapse_vars_switch_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
(function(b) {
|
||||||
|
switch (b && [ b = 0, (c++, 0) ]) {
|
||||||
|
case c = 1 + c:
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
(function(b) {
|
||||||
|
switch (b && [ b = 0, (c++, 0) ]) {
|
||||||
|
case c = 1 + c:
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
collapse_vars_assignment: {
|
collapse_vars_assignment: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
@@ -1234,7 +1259,7 @@ collapse_vars_try: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
collapse_vars_array: {
|
collapse_vars_array_1: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
@@ -1280,7 +1305,58 @@ collapse_vars_array: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
collapse_vars_object: {
|
collapse_vars_array_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var b;
|
||||||
|
return [ (b = a, b.g()) ];
|
||||||
|
}
|
||||||
|
console.log(f({
|
||||||
|
g: function() {
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
})[0]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
return [ a.g() ];
|
||||||
|
}
|
||||||
|
console.log(f({
|
||||||
|
g: function() {
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
})[0]);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
collapse_vars_array_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var b;
|
||||||
|
return [ b = a, b, b ];
|
||||||
|
}
|
||||||
|
console.log(f().length);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
var b;
|
||||||
|
return [ b = a, b, b ];
|
||||||
|
}
|
||||||
|
console.log(f().length);
|
||||||
|
}
|
||||||
|
expect_stdout: "3"
|
||||||
|
}
|
||||||
|
|
||||||
|
collapse_vars_object_1: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
@@ -1360,6 +1436,69 @@ collapse_vars_object: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
collapse_vars_object_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var b;
|
||||||
|
return {
|
||||||
|
p: (b = a, b.g())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
console.log(f({
|
||||||
|
g: function() {
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
}).p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
return {
|
||||||
|
p: a.g()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
console.log(f({
|
||||||
|
g: function() {
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
}).p);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
collapse_vars_object_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var b;
|
||||||
|
return {
|
||||||
|
p: b = a,
|
||||||
|
q: b,
|
||||||
|
r: b,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
console.log(f("PASS").r);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
var b;
|
||||||
|
return {
|
||||||
|
p: b = a,
|
||||||
|
q: b,
|
||||||
|
r: b,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
console.log(f("PASS").r);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
collapse_vars_eval_and_with: {
|
collapse_vars_eval_and_with: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
@@ -6624,3 +6763,45 @@ local_value_replacement: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
array_in_object_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 2;
|
||||||
|
console.log({
|
||||||
|
p: [ a, a-- ],
|
||||||
|
q: a,
|
||||||
|
}.q, a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 2;
|
||||||
|
console.log({
|
||||||
|
p: [ a, a-- ],
|
||||||
|
q: a,
|
||||||
|
}.q, a);
|
||||||
|
}
|
||||||
|
expect_stdout: "1 1"
|
||||||
|
}
|
||||||
|
|
||||||
|
array_in_object_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 2;
|
||||||
|
console.log({
|
||||||
|
p: [ a, (a--, 42) ],
|
||||||
|
q: a,
|
||||||
|
}.q, a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 2;
|
||||||
|
console.log({
|
||||||
|
p: [ a, 42 ],
|
||||||
|
q: --a,
|
||||||
|
}.q, a);
|
||||||
|
}
|
||||||
|
expect_stdout: "1 1"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user