destructuring-rest.js (4847B)
1 load(libdir + 'asserts.js'); 2 load(libdir + 'eqArrayHelper.js'); 3 4 assertThrowsInstanceOf(() => new Function('[...a, ,] = []'), SyntaxError, 'trailing elision'); 5 assertThrowsInstanceOf(() => new Function('[a, ...b, c] = []'), SyntaxError, 'trailing param'); 6 assertThrowsInstanceOf(() => new Function('[...a=b] = []'), SyntaxError, 'assignment expression'); 7 assertThrowsInstanceOf(() => new Function('[...a()] = []'), SyntaxError, 'call expression'); 8 assertThrowsInstanceOf(() => new Function('[...(a,b)] = []'), SyntaxError, 'comma expression'); 9 assertThrowsInstanceOf(() => new Function('[...a++] = []'), SyntaxError, 'postfix expression'); 10 assertThrowsInstanceOf(() => new Function('[...!a] = []'), SyntaxError, 'unary expression'); 11 assertThrowsInstanceOf(() => new Function('[...a+b] = []'), SyntaxError, 'binary expression'); 12 assertThrowsInstanceOf(() => new Function('var [...a.x] = []'), SyntaxError, 'lvalue expression in declaration'); 13 assertThrowsInstanceOf(() => new Function('var [...(b)] = []'), SyntaxError); 14 assertThrowsInstanceOf(() => new Function('[...b,] = []'), SyntaxError); 15 16 assertThrowsInstanceOf(() => { 17 try { 18 eval('let [...[...x]] = (() => { throw "foo"; } )();'); 19 } catch(e) { 20 assertEq(e, "foo"); 21 } 22 x; 23 }, ReferenceError); 24 25 var inputArray = [1, 2, 3]; 26 var inputDeep = [1, inputArray]; 27 var inputObject = {a: inputArray}; 28 var inputStr = 'str'; 29 function *inputGenerator() { 30 yield 1; 31 yield 2; 32 yield 3; 33 } 34 35 var o = {prop: null, call: function () { return o; }}; 36 37 var expected = [2, 3]; 38 var expectedStr = ['t', 'r']; 39 40 function testAll(fn) { 41 testDeclaration(fn); 42 43 o.prop = null; 44 assertEqArray(fn('[, ...(o.prop)]', inputArray, 'o.prop'), expected); 45 o.prop = null; 46 assertEqArray(fn('[, ...(o.call().prop)]', inputArray, 'o.prop'), expected); 47 48 o.prop = null; 49 assertEqArray(fn('[, ...[...(o.prop)]]', inputArray, 'o.prop'), expected); 50 o.prop = null; 51 assertEqArray(fn('[, ...[...(o.call().prop)]]', inputArray, 'o.prop'), expected); 52 } 53 function testDeclaration(fn) { 54 testStr(fn); 55 56 assertEqArray(fn('[, ...rest]', inputArray), expected); 57 assertEqArray(fn('[, ...rest]', inputGenerator()), expected); 58 assertEqArray(fn('[, [, ...rest]]', inputDeep), expected); 59 assertEqArray(fn('{a: [, ...rest]}', inputObject), expected); 60 61 assertEqArray(fn('[, ...[...rest]]', inputArray), expected); 62 assertEqArray(fn('[, ...[...rest]]', inputGenerator()), expected); 63 assertEqArray(fn('[, [, ...[...rest]]]', inputDeep), expected); 64 assertEqArray(fn('{a: [, ...[...rest]]}', inputObject), expected); 65 66 assertEqArray(fn('[, ...{0: a, 1: b}]', inputArray, '[a, b]'), expected); 67 assertEqArray(fn('[, ...{0: a, 1: b}]', inputGenerator(), '[a, b]'), expected); 68 assertEqArray(fn('[, [, ...{0: a, 1: b}]]', inputDeep, '[a, b]'), expected); 69 assertEqArray(fn('{a: [, ...{0: a, 1: b}]}', inputObject, '[a, b]'), expected); 70 } 71 72 function testStr(fn) { 73 assertEqArray(fn('[, ...rest]', inputStr), expectedStr); 74 75 assertEqArray(fn('[, ...[...rest]]', inputStr), expectedStr); 76 77 assertEqArray(fn('[, ...{0: a, 1: b}]', inputStr, '[a, b]'), expectedStr); 78 } 79 80 function testForIn(pattern, input, binding) { 81 binding = binding || 'rest'; 82 return new Function('input', 83 'for (var ' + pattern + ' in {[input]: 1}) {}' + 84 'return ' + binding 85 )(input); 86 } 87 testStr(testForIn); 88 89 function testVar(pattern, input, binding) { 90 binding = binding || 'rest'; 91 return new Function('input', 92 'var ' + pattern + ' = input;' + 93 'return ' + binding 94 )(input); 95 } 96 testDeclaration(testVar); 97 98 function testGlobal(pattern, input, binding) { 99 binding = binding || 'rest'; 100 return new Function('input', 101 '(' + pattern + ' = input);' + 102 'return ' + binding 103 )(input); 104 } 105 testAll(testGlobal); 106 107 function testClosure(pattern, input, binding) { 108 binding = binding || 'rest'; 109 const decl = binding.replace('[', '').replace(']', ''); 110 return new Function('input', 111 'var ' + decl + '; (function () {' + 112 '(' + pattern + ' = input);' + 113 '})();' + 114 'return ' + binding 115 )(input); 116 } 117 testDeclaration(testClosure); 118 119 function testArgument(pattern, input, binding) { 120 binding = binding || 'rest'; 121 return new Function('input', 122 'return (function (' + pattern + ') {' + 123 'return ' + binding + '; })(input);' 124 )(input); 125 } 126 testDeclaration(testArgument); 127 128 function testArgumentFunction(pattern, input, binding) { 129 binding = binding || 'rest'; 130 return new Function(pattern, 131 'return ' + binding 132 )(input); 133 } 134 // ES6 requires the `Function` constructor to accept arbitrary 135 // `BindingElement`s as formal parameters. 136 testDeclaration(testArgumentFunction); 137 138 function testThrow(pattern, input, binding) { 139 binding = binding || 'rest'; 140 return new Function('input', 141 'try { throw input }' + 142 'catch(' + pattern + ') {' + 143 'return ' + binding + '; }' 144 )(input); 145 } 146 testDeclaration(testThrow);