From 228cdf8e7e1dc472813f7def780b8608a4f5f485 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Tue, 9 Feb 2021 21:42:27 +0000 Subject: [PATCH] reject invalid `for...of` syntax (#4632) --- lib/parse.js | 3 + test/input/invalid/for-of_1.js | 3 + test/input/invalid/for-of_2.js | 3 + test/mocha/cli.js | 126 +++++++++++++++++++++------------ 4 files changed, 91 insertions(+), 44 deletions(-) create mode 100644 test/input/invalid/for-of_1.js create mode 100644 test/input/invalid/for-of_2.js diff --git a/lib/parse.js b/lib/parse.js index b926f188..ef0fc49a 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -1067,6 +1067,9 @@ function parse($TEXT, options) { if (init.definitions.length > 1) { token_error(init.start, "Only one variable declaration allowed in for..in/of loop"); } + if (ctor !== AST_ForIn && init.definitions[0].value) { + token_error(init.definitions[0].value.start, "No initializers allowed in for..of loop"); + } } else if (!(is_assignable(init) || (init = to_destructured(init)) instanceof AST_Destructured)) { token_error(init.start, "Invalid left-hand side in for..in/of loop"); } diff --git a/test/input/invalid/for-of_1.js b/test/input/invalid/for-of_1.js new file mode 100644 index 00000000..7d4ffe25 --- /dev/null +++ b/test/input/invalid/for-of_1.js @@ -0,0 +1,3 @@ +var a = [ 1 ], b; +for (b = 2 of a) + console.log(b); diff --git a/test/input/invalid/for-of_2.js b/test/input/invalid/for-of_2.js new file mode 100644 index 00000000..52972b80 --- /dev/null +++ b/test/input/invalid/for-of_2.js @@ -0,0 +1,3 @@ +var a = [ 1 ]; +for (var b = 2 of a) + console.log(b); diff --git a/test/mocha/cli.js b/test/mocha/cli.js index af1ed1f8..9e5de83f 100644 --- a/test/mocha/cli.js +++ b/test/mocha/cli.js @@ -333,11 +333,13 @@ describe("bin/uglifyjs", function() { var command = uglifyjscmd + " test/input/invalid/simple.js"; exec(command, function(err, stdout, stderr) { assert.ok(err); - var lines = stderr.split(/\n/); - assert.strictEqual(lines[0], "Parse error at test/input/invalid/simple.js:1,12"); - assert.strictEqual(lines[1], "function f(a{}"); - assert.strictEqual(lines[2], " ^"); - assert.strictEqual(lines[3], "ERROR: Unexpected token: punc «{», expected: punc «,»"); + assert.strictEqual(stdout, ""); + assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ + "Parse error at test/input/invalid/simple.js:1,12", + "function f(a{}", + " ^", + "ERROR: Unexpected token: punc «{», expected: punc «,»", + ].join("\n")); done(); }); }); @@ -345,11 +347,13 @@ describe("bin/uglifyjs", function() { var command = uglifyjscmd + " test/input/invalid/tab.js"; exec(command, function(err, stdout, stderr) { assert.ok(err); - var lines = stderr.split(/\n/); - assert.strictEqual(lines[0], "Parse error at test/input/invalid/tab.js:1,12"); - assert.strictEqual(lines[1], "\t\tfoo(\txyz, 0abc);"); - assert.strictEqual(lines[2], "\t\t \t ^"); - assert.strictEqual(lines[3], "ERROR: Invalid syntax: 0abc"); + assert.strictEqual(stdout, ""); + assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ + "Parse error at test/input/invalid/tab.js:1,12", + "\t\tfoo(\txyz, 0abc);", + "\t\t \t ^", + "ERROR: Invalid syntax: 0abc", + ].join("\n")); done(); }); }); @@ -357,11 +361,13 @@ describe("bin/uglifyjs", function() { var command = uglifyjscmd + " test/input/invalid/eof.js"; exec(command, function(err, stdout, stderr) { assert.ok(err); - var lines = stderr.split(/\n/); - assert.strictEqual(lines[0], "Parse error at test/input/invalid/eof.js:2,0"); - assert.strictEqual(lines[1], "foo, bar("); - assert.strictEqual(lines[2], " ^"); - assert.strictEqual(lines[3], "ERROR: Unexpected token: eof"); + assert.strictEqual(stdout, ""); + assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ + "Parse error at test/input/invalid/eof.js:2,0", + "foo, bar(", + " ^", + "ERROR: Unexpected token: eof", + ].join("\n")); done(); }); }); @@ -369,11 +375,13 @@ describe("bin/uglifyjs", function() { var command = uglifyjscmd + " test/input/invalid/loop-no-body.js"; exec(command, function(err, stdout, stderr) { assert.ok(err); - var lines = stderr.split(/\n/); - assert.strictEqual(lines[0], "Parse error at test/input/invalid/loop-no-body.js:2,0"); - assert.strictEqual(lines[1], "for (var i = 0; i < 1; i++) "); - assert.strictEqual(lines[2], " ^"); - assert.strictEqual(lines[3], "ERROR: Unexpected token: eof"); + assert.strictEqual(stdout, ""); + assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ + "Parse error at test/input/invalid/loop-no-body.js:2,0", + "for (var i = 0; i < 1; i++) ", + " ^", + "ERROR: Unexpected token: eof", + ].join("\n")); done(); }); }); @@ -386,7 +394,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/assign_1.js:1,18", "console.log(1 || 5--);", " ^", - "ERROR: Invalid use of -- operator" + "ERROR: Invalid use of -- operator", ].join("\n")); done(); }); @@ -400,7 +408,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/assign_2.js:1,32", "console.log(2 || (Math.random() /= 2));", " ^", - "ERROR: Invalid assignment" + "ERROR: Invalid assignment", ].join("\n")); done(); }); @@ -414,7 +422,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/assign_3.js:1,17", "console.log(3 || ++this);", " ^", - "ERROR: Invalid use of ++ operator" + "ERROR: Invalid use of ++ operator", ].join("\n")); done(); }); @@ -428,7 +436,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/assign_4.js:1,0", "++null", "^", - "ERROR: Invalid use of ++ operator" + "ERROR: Invalid use of ++ operator", ].join("\n")); done(); }); @@ -442,7 +450,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/dot_1.js:1,2", "a.=", " ^", - "ERROR: Unexpected token: operator «=», expected: name" + "ERROR: Unexpected token: operator «=», expected: name", ].join("\n")); done(); }); @@ -456,7 +464,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/dot_2.js:1,0", "%.a;", "^", - "ERROR: Unexpected token: operator «%»" + "ERROR: Unexpected token: operator «%»", ].join("\n")); done(); }); @@ -470,7 +478,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/dot_3.js:1,2", "a./();", " ^", - "ERROR: Unexpected token: operator «/», expected: name" + "ERROR: Unexpected token: operator «/», expected: name", ].join("\n")); done(); }); @@ -484,7 +492,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/object.js:1,13", "console.log({%: 1});", " ^", - "ERROR: Unexpected token: operator «%»" + "ERROR: Unexpected token: operator «%»", ].join("\n")); done(); }); @@ -498,7 +506,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/delete.js:13,11", " delete x;", " ^", - "ERROR: Calling delete on expression not allowed in strict mode" + "ERROR: Calling delete on expression not allowed in strict mode", ].join("\n")); done(); }); @@ -512,7 +520,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/function_1.js:4,11", "function g(arguments) {", " ^", - "ERROR: Unexpected arguments in strict mode" + "ERROR: Unexpected arguments in strict mode", ].join("\n")); done(); }); @@ -526,7 +534,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/function_2.js:4,9", "function eval() {", " ^", - "ERROR: Unexpected eval in strict mode" + "ERROR: Unexpected eval in strict mode", ].join("\n")); done(); }); @@ -540,7 +548,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/function_3.js:4,10", "!function arguments() {", " ^", - "ERROR: Unexpected arguments in strict mode" + "ERROR: Unexpected arguments in strict mode", ].join("\n")); done(); }); @@ -554,7 +562,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/try.js:7,18", " try {} catch (eval) {}", " ^", - "ERROR: Unexpected eval in strict mode" + "ERROR: Unexpected eval in strict mode", ].join("\n")); done(); }); @@ -568,7 +576,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/var.js:7,8", " var eval;", " ^", - "ERROR: Unexpected eval in strict mode" + "ERROR: Unexpected eval in strict mode", ].join("\n")); done(); }); @@ -582,7 +590,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/destructured_var.js:7,10", " var { eval } = 42;", " ^", - "ERROR: Unexpected eval in strict mode" + "ERROR: Unexpected eval in strict mode", ].join("\n")); done(); }); @@ -596,7 +604,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/else.js:1,7", "if (0) else 1;", " ^", - "ERROR: Unexpected token: keyword «else»" + "ERROR: Unexpected token: keyword «else»", ].join("\n")); done(); }); @@ -610,7 +618,7 @@ describe("bin/uglifyjs", function() { "Parse error at test/input/invalid/return.js:1,0", "return 42;", "^", - "ERROR: 'return' outside of function" + "ERROR: 'return' outside of function", ].join("\n")); done(); }); @@ -624,7 +632,7 @@ describe("bin/uglifyjs", function() { "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/of loop" + "ERROR: Invalid left-hand side in for..in/of loop", ].join("\n")); done(); }); @@ -638,7 +646,35 @@ describe("bin/uglifyjs", function() { "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/of loop" + "ERROR: Only one variable declaration allowed in for..in/of loop", + ].join("\n")); + done(); + }); + }); + it("Should throw syntax error (for-of init)", function(done) { + var command = uglifyjscmd + " test/input/invalid/for-of_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-of_1.js:2,5", + "for (b = 2 of a)", + " ^", + "ERROR: Invalid left-hand side in for..in/of loop", + ].join("\n")); + done(); + }); + }); + it("Should throw syntax error (for-of var)", function(done) { + var command = uglifyjscmd + " test/input/invalid/for-of_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-of_2.js:2,13", + "for (var b = 2 of a)", + " ^", + "ERROR: No initializers allowed in for..of loop", ].join("\n")); done(); }); @@ -647,11 +683,13 @@ describe("bin/uglifyjs", function() { var command = uglifyjscmd + " test/input/invalid/switch.js"; exec(command, function(err, stdout, stderr) { assert.ok(err); - var lines = stderr.split(/\n/); - assert.strictEqual(lines[0], "Parse error at test/input/invalid/switch.js:3,2"); - assert.strictEqual(lines[1], " default:"); - assert.strictEqual(lines[2], " ^"); - assert.strictEqual(lines[3], "ERROR: More than one default clause in switch statement"); + assert.strictEqual(stdout, ""); + assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ + "Parse error at test/input/invalid/switch.js:3,2", + " default:", + " ^", + "ERROR: More than one default clause in switch statement", + ].join("\n")); done(); }); }); -- 2.34.1