trailing_comma_parameters.js (5120B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 // Trailing comma in functions and methods. 6 7 // 14.1 Function Definitions 8 // FunctionExpression: 9 // function BindingIdentifier[~Yield]opt ( FormalParameters[~Yield] ) { FunctionBody[~Yield] } 10 11 // 14.3 Method Definitions 12 // MethodDefinition[Yield]: 13 // PropertyName[?Yield] ( UniqueFormalParameters[~Yield] ) { FunctionBody[~Yield] } 14 // GeneratorMethod[?Yield] 15 // PropertySetParameterList: 16 // FormalParameter[~Yield] 17 18 // 14.4 Generator Function Definitions 19 // GeneratorExpression: 20 // function * BindingIdentifier[+Yield]opt ( FormalParameters[+Yield] ) { GeneratorBody } 21 // GeneratorMethod[Yield]: 22 // * PropertyName[?Yield] ( UniqueFormalParameters[+Yield] ) { GeneratorBody } 23 24 25 function functionExpression(argList, parameters = "", returnExpr = "") { 26 return eval(`(function f(${argList}) { 27 var fun = f; 28 return ${returnExpr}; 29 })(${parameters})`); 30 } 31 32 function generatorExpression(argList, parameters = "", returnExpr = "") { 33 return eval(`(function* f(${argList}) { 34 var fun = f; 35 return ${returnExpr}; 36 })(${parameters}).next().value`); 37 } 38 39 function objectMethod(argList, parameters = "", returnExpr = "") { 40 return eval(`({ 41 m(${argList}) { 42 var fun = this.m; 43 return ${returnExpr}; 44 } 45 }).m(${parameters})`); 46 } 47 48 function objectGeneratorMethod(argList, parameters = "", returnExpr = "") { 49 return eval(`({ 50 * m(${argList}) { 51 var fun = this.m; 52 return ${returnExpr}; 53 } 54 }).m(${parameters}).next().value`); 55 } 56 57 function classMethod(argList, parameters = "", returnExpr = "") { 58 return eval(`(new class { 59 m(${argList}) { 60 var fun = this.m; 61 return ${returnExpr}; 62 } 63 }).m(${parameters})`); 64 } 65 66 function classStaticMethod(argList, parameters = "", returnExpr = "") { 67 return eval(`(class { 68 static m(${argList}) { 69 var fun = this.m; 70 return ${returnExpr}; 71 } 72 }).m(${parameters})`); 73 } 74 75 function classGeneratorMethod(argList, parameters = "", returnExpr = "") { 76 return eval(`(new class { 77 * m(${argList}) { 78 var fun = this.m; 79 return ${returnExpr}; 80 } 81 }).m(${parameters}).next().value`); 82 } 83 84 function classStaticGeneratorMethod(argList, parameters = "", returnExpr = "") { 85 return eval(`(class { 86 static * m(${argList}) { 87 var fun = this.m; 88 return ${returnExpr}; 89 } 90 }).m(${parameters}).next().value`); 91 } 92 93 function classConstructorMethod(argList, parameters = "", returnExpr = "null") { 94 return eval(`new (class { 95 constructor(${argList}) { 96 var fun = this.constructor; 97 return { value: ${returnExpr} }; 98 } 99 })(${parameters}).value`); 100 } 101 102 const tests = [ 103 functionExpression, 104 generatorExpression, 105 objectMethod, 106 objectGeneratorMethod, 107 classMethod, 108 classStaticMethod, 109 classGeneratorMethod, 110 classStaticGeneratorMethod, 111 classConstructorMethod, 112 ]; 113 114 // Ensure parameters are passed correctly. 115 for (let test of tests) { 116 assertEq(test("a, ", "10", "a"), 10); 117 assertEq(test("a, b, ", "10, 20", "a + b"), 30); 118 assertEq(test("a = 30, ", "", "a"), 30); 119 assertEq(test("a = 30, b = 40, ", "", "a + b"), 70); 120 121 assertEq(test("[a], ", "[10]", "a"), 10); 122 assertEq(test("[a], [b], ", "[10], [20]", "a + b"), 30); 123 assertEq(test("[a] = [30], ", "", "a"), 30); 124 assertEq(test("[a] = [30], [b] = [40], ", "", "a + b"), 70); 125 126 assertEq(test("{a}, ", "{a: 10}", "a"), 10); 127 assertEq(test("{a}, {b}, ", "{a: 10}, {b: 20}", "a + b"), 30); 128 assertEq(test("{a} = {a: 30}, ", "", "a"), 30); 129 assertEq(test("{a} = {a: 30}, {b} = {b: 40}, ", "", "a + b"), 70); 130 } 131 132 // Ensure function length doesn't change. 133 for (let test of tests) { 134 assertEq(test("a, ", "", "fun.length"), 1); 135 assertEq(test("a, b, ", "", "fun.length"), 2); 136 137 assertEq(test("[a], ", "[]", "fun.length"), 1); 138 assertEq(test("[a], [b], ", "[], []", "fun.length"), 2); 139 140 assertEq(test("{a}, ", "{}", "fun.length"), 1); 141 assertEq(test("{a}, {b}, ", "{}, {}", "fun.length"), 2); 142 } 143 144 for (let test of tests) { 145 // Trailing comma in empty parameters list. 146 assertThrowsInstanceOf(() => test(","), SyntaxError); 147 148 // Leading comma. 149 assertThrowsInstanceOf(() => test(", a"), SyntaxError); 150 assertThrowsInstanceOf(() => test(", ...a"), SyntaxError); 151 152 // Multiple trailing comma. 153 assertThrowsInstanceOf(() => test("a, , "), SyntaxError); 154 assertThrowsInstanceOf(() => test("a..., , "), SyntaxError); 155 156 // Trailing comma after rest parameter. 157 assertThrowsInstanceOf(() => test("...a, "), SyntaxError); 158 assertThrowsInstanceOf(() => test("a, ...b, "), SyntaxError); 159 160 // Elision. 161 assertThrowsInstanceOf(() => test("a, , b"), SyntaxError); 162 } 163 164 if (typeof reportCompare === "function") 165 reportCompare(0, 0);