From 6b03b800b3d77506f75ed3c789dc0d40ea140149 Mon Sep 17 00:00:00 2001 From: Anthony Van de Gejuchte Date: Sun, 12 Jun 2016 22:40:07 +0200 Subject: [PATCH] Only last parameter between parentheses can have spread --- lib/parse.js | 4 ++ test/compress/arrow.js | 85 ++++++++++++++++++++++++++++++++++++++++++ test/mocha/arrow.js | 25 +++++++++++++ test/mocha/class.js | 26 +++++++++++++ test/mocha/function.js | 30 +++++++++++++++ 5 files changed, 170 insertions(+) create mode 100644 test/compress/arrow.js create mode 100644 test/mocha/arrow.js create mode 100644 test/mocha/class.js create mode 100644 test/mocha/function.js diff --git a/lib/parse.js b/lib/parse.js index 9f7193ce..6298419b 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -1163,12 +1163,16 @@ function parse($TEXT, options) { while (!is("punc", ")")) { if (first) first = false; else expect(","); if (is("expand", "...")) { + var spread_token = S.token; next(); a.push(new AST_Expansion({ start: prev(), expression: as_symbol(AST_SymbolFunarg), end: S.token, })); + if (!is("punc", ")")) { + unexpected(spread_token); + } } else { a.push(expression(false)); } diff --git a/test/compress/arrow.js b/test/compress/arrow.js new file mode 100644 index 00000000..c5838537 --- /dev/null +++ b/test/compress/arrow.js @@ -0,0 +1,85 @@ +arrow_functions_without_body: { + input: { + var a1 = () => 42; + var a2 = (p) => p; + var a3 = p => p; + var a4 = (...p) => p; + var a5 = (b, c) => b + c; + var a6 = (b, ...c) => b + c[0]; + var a7 = (...b) => b.join(); + } + expect: { + var a1 = () => 42; + var a2 = (p) => p; + var a3 = p => p; + var a4 = (...p) => p; + var a5 = (b, c) => b + c; + var a6 = (b, ...c) => b + c[0]; + var a7 = (...b) => b.join(); + } +} + +arrow_functions_with_body: { + input: { + var a1 = () => { + var a = 42 * Math.random(); + return a; + }; + var a2 = (p) => { + var a = Math.random() * p; + return a; + }; + var a3 = p => { + var a = Math.random() * p; + return a; + }; + var a4 = (...p) => { + var a = Math.random() * p; + return a; + }; + var a5 = (b, c) => { + var result = b * c + b / c; + return result + }; + var a6 = (b, ...c) => { + var result = b; + for (var i = 0; i < c.length; i++) + result += c[i]; + return result + }; + var a7 = (...b) => { + b.join(); + } + } + expect: { + var a1 = () => { + var a = 42 * Math.random(); + return a; + }; + var a2 = (p) => { + var a = Math.random() * p; + return a; + }; + var a3 = p => { + var a = Math.random() * p; + return a; + }; + var a4 = (...p) => { + var a = Math.random() * p; + return a; + }; + var a5 = (b, c) => { + var result = b * c + b / c; + return result + }; + var a6 = (b, ...c) => { + var result = b; + for (var i = 0; i < c.length; i++) + result += c[i]; + return result + }; + var a7 = (...b) => { + b.join(); + }; + } +} \ No newline at end of file diff --git a/test/mocha/arrow.js b/test/mocha/arrow.js new file mode 100644 index 00000000..19bbb429 --- /dev/null +++ b/test/mocha/arrow.js @@ -0,0 +1,25 @@ +var assert = require("assert"); +var uglify = require("../../"); + +describe("Arrow functions", function() { + it("Should not accept spread tokens on non-last parameters or without arguments parentheses", function() { + var tests = [ + "var a = ...a => {return a.join()}", + "var b = (a, ...b, c) => { return a + b.join() + c}", + "var c = (...a, b) => a.join()" + ]; + var test = function(code) { + return function() { + uglify.parse(code, {fromString: true}); + } + } + var error = function(e) { + return e instanceof uglify.JS_Parse_Error && + e.message === "Unexpected token: expand (...)"; + } + + for (var i = 0; i < tests.length; i++) { + assert.throws(test(tests[i]), error); + } + }); +}); \ No newline at end of file diff --git a/test/mocha/class.js b/test/mocha/class.js new file mode 100644 index 00000000..e0b1fbd1 --- /dev/null +++ b/test/mocha/class.js @@ -0,0 +1,26 @@ +var assert = require("assert"); +var uglify = require("../../"); + +describe("Class", function() { + it("Should not accept spread on non-last parameters in methods", function() { + var tests = [ + "class foo { bar(...a, b) { return a.join(b) } }", + "class foo { bar(a, b, ...c, d) { return c.join(a + b) + d } }", + "class foo { *bar(...a, b) { return a.join(b) } }", + "class foo { *bar(a, b, ...c, d) { return c.join(a + b) + d } }" + ]; + var test = function(code) { + return function() { + uglify.parse(code, {fromString: true}); + } + } + var error = function(e) { + return e instanceof uglify.JS_Parse_Error && + e.message === "Unexpected token: expand (...)"; + } + + for (var i = 0; i < tests.length; i++) { + assert.throws(test(tests[i]), error); + } + }); +}); \ No newline at end of file diff --git a/test/mocha/function.js b/test/mocha/function.js new file mode 100644 index 00000000..cdfb5cee --- /dev/null +++ b/test/mocha/function.js @@ -0,0 +1,30 @@ +var assert = require("assert"); +var uglify = require("../../"); + +describe("Function", function() { + it("Should not accept spread on non-last parameters", function() { + var tests = [ + "var a = function(...a, b) { return a.join(b) }", + "var b = function(a, b, ...c, d) { return c.join(a + b) + d }", + "function foo(...a, b) { return a.join(b) }", + "function bar(a, b, ...c, d) { return c.join(a + b) + d }", + "var a = function*(...a, b) { return a.join(b) }", + "var b = function*(a, b, ...c, d) { return c.join(a + b) + d }", + "function* foo(...a, b) { return a.join(b) }", + "function* bar(a, b, ...c, d) { return c.join(a + b) + d }" + ]; + var test = function(code) { + return function() { + uglify.parse(code, {fromString: true}); + } + } + var error = function(e) { + return e instanceof uglify.JS_Parse_Error && + e.message === "Unexpected token: expand (...)"; + } + + for (var i = 0; i < tests.length; i++) { + assert.throws(test(tests[i]), error); + } + }); +}); \ No newline at end of file