Skip to content

Commit

Permalink
improve --reduce-test (#3722)
Browse files Browse the repository at this point in the history
- hoist body of functions and IIFEs
- simplify var declarations
  • Loading branch information
kzc committed Feb 15, 2020
1 parent 5315dd9 commit fbfa617
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 12 deletions.
11 changes: 4 additions & 7 deletions test/input/reduce/unsafe_math.reduced.js
@@ -1,13 +1,10 @@
var b = 0;

function f0() {
var expr2 = (0 - 1 - .1 - .1).toString();
for (var key2 in expr2) {
--b;
}
}
var expr2 = (0 - 1 - .1 - .1).toString();

var a_1 = f0();
for (var key2 in expr2) {
--b;
}

console.log(b);
// output: -19
Expand Down
92 changes: 87 additions & 5 deletions test/reduce.js
Expand Up @@ -61,9 +61,6 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)

var parent = tt.parent();

// ignore call expressions
if (parent instanceof U.AST_Call && parent.expression === node) return;

// ensure that the _permute prop is a number.
// can not use `node.start._permute |= 0;` as it will erase fractional part.
if (typeof node.start._permute === "undefined") node.start._permute = 0;
Expand Down Expand Up @@ -128,11 +125,43 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
var expr = [
node.expression,
node.args[0],
][ node.start._permute++ % 2 ];
null, // intentional
][ ((node.start._permute += step) * steps | 0) % 3 ];
if (expr) {
CHANGED = true;
return expr;
}
if (node.expression instanceof U.AST_Function) {
// hoist and return expressions from the IIFE function expression
var body = node.expression.body;
node.expression.body = [];
var seq = [];
body.forEach(function(node) {
var expr = expr instanceof U.AST_Exit ? node.value : node.body;
if (expr instanceof U.AST_Node && !is_statement(expr)) {
// collect expressions from each statements' body
seq.push(expr);
}
});
CHANGED = true;
return to_sequence(seq);
}
}
else if (node instanceof U.AST_Defun) {
switch (((node.start._permute += step) * steps | 0) % 2) {
case 0:
CHANGED = true;
return List.skip;
case 1:
if (!has_exit(node)) {
// hoist function declaration body
var body = node.body;
node.body = [];
body.push(node); // retain function with empty body to be dropped later
CHANGED = true;
return List.splice(body);
}
}
}
else if (node instanceof U.AST_DWLoop) {
var expr = [
Expand Down Expand Up @@ -212,6 +241,18 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
return expr;
}
}
else if (node instanceof U.AST_SimpleStatement) {
if (node.body instanceof U.AST_Call && node.body.expression instanceof U.AST_Function) {
// hoist simple statement IIFE function expression body
node.start._permute++;
if (!has_exit(node.body.expression)) {
var body = node.body.expression.body;
node.body.expression.body = [];
CHANGED = true;
return List.splice(body);
}
}
}
else if (node instanceof U.AST_Switch) {
var expr = [
node.expression, // switch expression
Expand Down Expand Up @@ -256,6 +297,14 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
CHANGED = true;
return node.expression;
}
else if (node instanceof U.AST_Var) {
if (node.definitions.length == 1 && node.definitions[0].value) {
// first declaration value
node.start._permute++;
CHANGED = true;
return to_statement(node.definitions[0].value);
}
}
else if (node instanceof U.AST_LabeledStatement) {
if (node.body instanceof U.AST_Statement
&& !has_loopcontrol(node.body, node.body, node)) {
Expand Down Expand Up @@ -291,7 +340,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
}

// replace this node
var newNode = new U.parse(REPLACEMENTS[node.start._permute % REPLACEMENTS.length | 0], {
var newNode = U.parse(REPLACEMENTS[node.start._permute % REPLACEMENTS.length | 0], {
expression: true,
});
if (is_statement(node)) {
Expand Down Expand Up @@ -404,6 +453,21 @@ function to_comment(value) {
return ("" + value).replace(/\n/g, "\n// ");
}

function has_exit(fn) {
var found = false;
var tw = new U.TreeWalker(function(node) {
if (found) return found;
if (node instanceof U.AST_Exit) {
return found = true;
}
if (node instanceof U.AST_Scope && node !== fn) {
return true; // don't descend into nested functions
}
});
fn.walk(tw);
return found;
}

function has_loopcontrol(body, loop, label) {
var found = false;
var tw = new U.TreeWalker(function(node) {
Expand All @@ -426,6 +490,24 @@ function is_statement(node) {
return node instanceof U.AST_Statement && !(node instanceof U.AST_Function);
}

function merge_sequence(array, node) {
if (node instanceof U.AST_Sequence) {
array.push.apply(array, node.expressions);
} else {
array.push(node);
}
return array;
}

function to_sequence(expressions) {
if (expressions.length == 0) return new U.AST_Number({value: 0, start: {}});
if (expressions.length == 1) return expressions[0];
return new U.AST_Sequence({
expressions: expressions.reduce(merge_sequence, []),
start: {},
});
}

function to_statement(node) {
return is_statement(node) ? node : new U.AST_SimpleStatement({
body: node,
Expand Down

0 comments on commit fbfa617

Please sign in to comment.