fix for-in loop parsing (#2144)
authorAlex Lam S.L <alexlamsl@gmail.com>
Thu, 22 Jun 2017 20:14:30 +0000 (04:14 +0800)
committerGitHub <noreply@github.com>
Thu, 22 Jun 2017 20:14:30 +0000 (04:14 +0800)
lib/parse.js
test/input/invalid/for-in_1.js [new file with mode: 0644]
test/input/invalid/for-in_2.js [new file with mode: 0644]
test/mocha/cli.js

index 553568e..e2dd04b 100644 (file)
@@ -1010,8 +1010,12 @@ function parse($TEXT, options) {
                 ? (next(), var_(true))
                 : expression(true, true);
             if (is("operator", "in")) {
-                if (init instanceof AST_Var && init.definitions.length > 1)
-                    croak("Only one variable declaration allowed in for..in loop");
+                if (init instanceof AST_Var) {
+                    if (init.definitions.length > 1)
+                        croak("Only one variable declaration allowed in for..in loop", init.start.line, init.start.col, init.start.pos);
+                } else if (!is_assignable(init)) {
+                    croak("Invalid left-hand side in for..in loop", init.start.line, init.start.col, init.start.pos);
+                }
                 next();
                 return for_in(init);
             }
diff --git a/test/input/invalid/for-in_1.js b/test/input/invalid/for-in_1.js
new file mode 100644 (file)
index 0000000..4d872d1
--- /dev/null
@@ -0,0 +1,4 @@
+var a, b = [1, 2];
+for (1, 2, a in b) {
+    console.log(a, b[a]);
+}
diff --git a/test/input/invalid/for-in_2.js b/test/input/invalid/for-in_2.js
new file mode 100644 (file)
index 0000000..57d861e
--- /dev/null
@@ -0,0 +1,4 @@
+var c = [1, 2];
+for (var a, b in c) {
+    console.log(a, c[a]);
+}
index b54044e..4c4943c 100644 (file)
@@ -518,6 +518,36 @@ describe("bin/uglifyjs", function () {
             done();
         });
     });
+    it("Should throw syntax error (for-in init)", function(done) {
+        var command = uglifyjscmd + ' test/input/invalid/for-in_1.js';
+
+        exec(command, function (err, stdout, stderr) {
+            assert.ok(err);
+            assert.strictEqual(stdout, "");
+            assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
+                "Parse error at test/input/invalid/for-in_1.js:2,5",
+                "for (1, 2, a in b) {",
+                "     ^",
+                "ERROR: Invalid left-hand side in for..in loop"
+            ].join("\n"));
+            done();
+        });
+    });
+    it("Should throw syntax error (for-in var)", function(done) {
+        var command = uglifyjscmd + ' test/input/invalid/for-in_2.js';
+
+        exec(command, function (err, stdout, stderr) {
+            assert.ok(err);
+            assert.strictEqual(stdout, "");
+            assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
+                "Parse error at test/input/invalid/for-in_2.js:2,5",
+                "for (var a, b in c) {",
+                "     ^",
+                "ERROR: Only one variable declaration allowed in for..in loop"
+            ].join("\n"));
+            done();
+        });
+    });
     it("Should handle literal string as source map input", function(done) {
         var command = [
             uglifyjscmd,