extend trailing comma support (#4334)
authorAlex Lam S.L <alexlamsl@gmail.com>
Mon, 7 Dec 2020 02:07:34 +0000 (02:07 +0000)
committerGitHub <noreply@github.com>
Mon, 7 Dec 2020 02:07:34 +0000 (10:07 +0800)
lib/parse.js
test/compress/functions.js
test/ufuzz/index.js

index b3c3f97..5a07ef6 100644 (file)
@@ -1053,12 +1053,9 @@ function parse($TEXT, options) {
         if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
             unexpected(prev());
         expect("(");
-        var argnames = [];
-        for (var first = true; !is("punc", ")");) {
-            if (first) first = false; else expect(",");
-            argnames.push(maybe_destructured(AST_SymbolFunarg));
-        }
-        next();
+        var argnames = expr_list(")", !options.strict, false, function() {
+            return maybe_destructured(AST_SymbolFunarg);
+        });
         var loop = S.in_loop;
         var labels = S.labels;
         ++S.in_function;
@@ -1233,7 +1230,7 @@ function parse($TEXT, options) {
         var newexp = expr_atom(false), args;
         if (is("punc", "(")) {
             next();
-            args = expr_list(")");
+            args = expr_list(")", !options.strict);
         } else {
             args = [];
         }
@@ -1351,9 +1348,9 @@ function parse($TEXT, options) {
         while (!is("punc", closing)) {
             if (first) first = false; else expect(",");
             if (allow_trailing_comma && is("punc", closing)) break;
-            if (is("punc", ",") && allow_empty) {
+            if (allow_empty && is("punc", ",")) {
                 a.push(new AST_Hole({ start: S.token, end: S.token }));
-            } else if (is("operator", "...") && parser === expression) {
+            } else if (parser === expression && is("operator", "...")) {
                 a.push(new AST_Spread({
                     start: S.token,
                     expression: (next(), parser()),
@@ -1593,7 +1590,7 @@ function parse($TEXT, options) {
             var call = new AST_Call({
                 start      : start,
                 expression : expr,
-                args       : expr_list(")"),
+                args       : expr_list(")", !options.strict),
                 end        : prev()
             });
             mark_pure(call);
index 49bbfac..1e7d3e2 100644 (file)
@@ -5213,3 +5213,13 @@ issue_4265: {
     }
     expect_stdout: "undefined"
 }
+
+trailing_comma: {
+    input: {
+        new function(a, b,) {
+            console.log(b, a,);
+        }(42, "PASS",);
+    }
+    expect_exact: 'new function(a,b){console.log(b,a)}(42,"PASS");'
+    expect_stdout: "PASS 42"
+}
index e47e541..2d2956b 100644 (file)
@@ -362,6 +362,10 @@ function createFunctions(n, recurmax, allowDefun, canThrow, stmtDepth) {
     return s;
 }
 
+function addTrailingComma(list) {
+    return list && rng(20) == 0 ? list + "," : list;
+}
+
 function createParams(noDuplicate) {
     var len = unique_vars.length;
     var params = [];
@@ -371,7 +375,7 @@ function createParams(noDuplicate) {
         params.push(name);
     }
     unique_vars.length = len;
-    return params.join(", ");
+    return addTrailingComma(params.join(", "));
 }
 
 function createArgs(recurmax, stmtDepth, canThrow) {
@@ -394,7 +398,7 @@ function createArgs(recurmax, stmtDepth, canThrow) {
         args.push(rng(2) ? createValue() : createExpression(recurmax, COMMA_OK, stmtDepth, canThrow));
         break;
     }
-    return args.join(", ");
+    return addTrailingComma(args.join(", "));
 }
 
 function createAssignmentPairs(recurmax, noComma, stmtDepth, canThrow, varNames, was_async) {
@@ -463,7 +467,10 @@ function createAssignmentPairs(recurmax, noComma, stmtDepth, canThrow, varNames,
                 while (!rng(10)) {
                     var index = rng(pairs.names.length + 1);
                     pairs.names.splice(index, 0, "");
-                    pairs.values.splice(index, 0, rng(2) ? createAssignmentValue(recurmax) : "");
+                    if (rng(2)) {
+                        if (index > pairs.values.length) pairs.values.length = index;
+                        pairs.values.splice(index, 0, createAssignmentValue(recurmax));
+                    }
                 }
                 names.unshift("[ " + pairs.names.join(", ") + " ]");
                 values.unshift("[ " + pairs.values.join(", ") + " ]");
@@ -485,14 +492,14 @@ function createAssignmentPairs(recurmax, noComma, stmtDepth, canThrow, varNames,
                         keys[index] = key;
                     }
                 });
-                names.unshift("{ " + pairs.names.map(function(name, index) {
+                names.unshift("{ " + addTrailingComma(pairs.names.map(function(name, index) {
                     var key = index in keys ? keys[index] : rng(10) && createKey(recurmax, keys);
                     return key ? key + ": " + name : name;
-                }).join(", ") + " }");
-                values.unshift("{ " + pairs.values.map(function(value, index) {
+                }).join(", ")) + " }");
+                values.unshift("{ " + addTrailingComma(pairs.values.map(function(value, index) {
                     var key = index in keys ? keys[index] : createKey(recurmax, keys);
                     return key + ": " + value;
-                }).join(", ") + " }");
+                }).join(", ")) + " }");
             }
             break;
           default:
@@ -603,8 +610,8 @@ function createFunction(recurmax, allowDefun, canThrow, stmtDepth) {
         if ((!allowDefun || !(name in called)) && rng(2)) {
             called[name] = false;
             var pairs = createAssignmentPairs(recurmax, COMMA_OK, stmtDepth, canThrow, varNames, save_async);
-            params = pairs.names.join(", ");
-            args = pairs.values.join(", ");
+            params = addTrailingComma(pairs.names.join(", "));
+            args = addTrailingComma(pairs.values.join(", "));
         } else {
             params = createParams();
         }
@@ -968,7 +975,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
             createBlockVariables(recurmax, stmtDepth, canThrow, function(defns) {
                 var instantiate = rng(4) ? "new " : "";
                 s.push(
-                    instantiate + "function " + name + "(){",
+                    instantiate + "function " + name + "(" + createParams() + "){",
                     strictMode(),
                     defns()
                 );
@@ -976,11 +983,11 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
                     if (rng(2)) s.push("this." + getDotKey(true) + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ";");
                     else  s.push("this[" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "]" + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ";");
                 }
-                s.push(
-                    _createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
-                    rng(2) == 0 ? "}" : "}()"
-                );
+                s.push(_createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth));
             });
+            async = save_async;
+            VAR_NAMES.length = nameLenBefore;
+            s.push(rng(2) == 0 ? "}" : "}(" + createArgs(recurmax, stmtDepth, canThrow) + ")");
             break;
         }
         async = save_async;