ensure valid generated cases in `--reduce-test` (#4787)
authorAlex Lam S.L <alexlamsl@gmail.com>
Tue, 16 Mar 2021 10:14:24 +0000 (10:14 +0000)
committerGitHub <noreply@github.com>
Tue, 16 Mar 2021 10:14:24 +0000 (18:14 +0800)
closes #4786

test/reduce.js

index 6f41378..231e958 100644 (file)
@@ -208,12 +208,10 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
                 }
                 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) {
+                    node.expression.body.forEach(function(node) {
                         var expr = expr instanceof U.AST_Exit ? node.value : node.body;
-                        if (expr instanceof U.AST_Node && !U.is_statement(expr)) {
+                        if (expr instanceof U.AST_Node && !U.is_statement(expr) && can_hoist(expr)) {
                             // collect expressions from each statements' body
                             seq.push(expr);
                         }
@@ -264,7 +262,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
                     CHANGED = true;
                     return List.skip;
                   default:
-                    if (!has_exit(node)) {
+                    if (!has_exit(node) && can_hoist(node)) {
                         // hoist function declaration body
                         var body = node.body;
                         node.body = [];
@@ -381,11 +379,9 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
                 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 = [];
+                    if (!has_exit(node.body.expression) && can_hoist(node.body.expression)) {
                         CHANGED = true;
-                        return List.splice(body);
+                        return List.splice(node.body.expression.body);
                     }
                 }
             }
@@ -673,6 +669,20 @@ function has_loopcontrol(body, loop, label) {
     return found;
 }
 
+function can_hoist(body) {
+    var found = false;
+    body.walk(new U.TreeWalker(function(node) {
+        if (found) return true;
+        if (node instanceof U.AST_NewTarget) return found = true;
+        if (node instanceof U.AST_Scope) {
+            if (node === body) return;
+            return true;
+        }
+        if (node instanceof U.AST_Super) return found = true;
+    }));
+    return !found;
+}
+
 function is_timed_out(result) {
     return sandbox.is_error(result) && /timed out/.test(result.message);
 }