function shouldBe(actual, expected) { if (actual !== expected) throw new Error('bad value: ' + actual); } function shouldThrow(func, errorMessage) { var errorThrown = false; var error = null; try { func(); } catch (e) { errorThrown = true; error = e; } if (!errorThrown) throw new Error('not thrown'); if (String(error) !== errorMessage) throw new Error(`bad error: ${String(error)}`); } function testSyntaxError(script, message) { var error = null; try { eval(script); } catch (e) { error = e; } if (!error) throw new Error("Expected syntax error not thrown"); if (String(error) !== message) throw new Error("Bad error: " + String(error)); } (function () { var [a, b, ...c] = "Cocoa"; shouldBe(a, 'C'); shouldBe(b, 'o'); shouldBe(JSON.stringify(c), String.raw`["c","o","a"]`); }()); (function () { var [a, b, ...c] = "Co"; shouldBe(a, 'C'); shouldBe(b, 'o'); shouldBe(JSON.stringify(c), String.raw`[]`); }()); (function () { var [a, b, ...c] = "C"; shouldBe(a, 'C'); shouldBe(b, undefined); shouldBe(JSON.stringify(c), String.raw`[]`); }()); (function () { var a, b, c; [a, b, ...c] = "Cocoa"; shouldBe(a, 'C'); shouldBe(b, 'o'); shouldBe(JSON.stringify(c), String.raw`["c","o","a"]`); }()); (function () { var a, b, c; [a, b, ...c] = "Co"; shouldBe(a, 'C'); shouldBe(b, 'o'); shouldBe(JSON.stringify(c), String.raw`[]`); }()); (function () { var a, b, c; [a, b, ...c] = "C"; shouldBe(a, 'C'); shouldBe(b, undefined); shouldBe(JSON.stringify(c), String.raw`[]`); }()); (function ([a, b, ...c]) { shouldBe(a, 'C'); shouldBe(b, 'o'); shouldBe(JSON.stringify(c), String.raw`["c","o","a"]`); }("Cocoa")); (function ([a, b, ...c]) { shouldBe(a, 'C'); shouldBe(b, 'o'); shouldBe(JSON.stringify(c), String.raw`[]`); }("Co")); (function ([a, b, ...c]) { shouldBe(a, 'C'); shouldBe(b, undefined); shouldBe(JSON.stringify(c), String.raw`[]`); }("C")); testSyntaxError(String.raw`var [a, ...b, c] = 20`, String.raw`SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.`); testSyntaxError(String.raw`var [a, ...b,] = 20`, String.raw`SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.`); testSyntaxError(String.raw`var [a, ...b,,] = 20`, String.raw`SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.`); testSyntaxError(String.raw`var [a, ...b = 20] = 20`, String.raw`SyntaxError: Unexpected token '='. Expected a closing ']' following a rest element destructuring pattern.`); testSyntaxError(String.raw`var [a, ...[b, c]] = 20`, String.raw`SyntaxError: Unexpected token ']'. Expected identifier for a rest element destructuring pattern.`); testSyntaxError(String.raw`var [a, ...{ b, c }] = 20`, String.raw`SyntaxError: Unexpected token ']'. Expected identifier for a rest element destructuring pattern.`); testSyntaxError(String.raw`(function ([a, ...b, c]) { })`, String.raw`SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.`); testSyntaxError(String.raw`(function ([a, ...b,]) { })`, String.raw`SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.`); testSyntaxError(String.raw`(function ([a, ...b,,]) { })`, String.raw`SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.`); testSyntaxError(String.raw`(function ([a, ...b = 20,,]) { })`, String.raw`SyntaxError: Unexpected token '='. Expected a closing ']' following a rest element destructuring pattern.`); testSyntaxError(String.raw`(function ([a, ...[b, c]]) { })`, String.raw`SyntaxError: Unexpected token ']'. Expected identifier for a rest element destructuring pattern.`); testSyntaxError(String.raw`(function ([a, ...{ b, c }]) { })`, String.raw`SyntaxError: Unexpected token ']'. Expected identifier for a rest element destructuring pattern.`); shouldThrow(function () { [a, ...b, c] = 20; }, "ReferenceError: Left side of assignment is not a reference."); shouldThrow(function () { [a, ...b,] = 20 }, "ReferenceError: Left side of assignment is not a reference."); shouldThrow(function () { [a, ...b,,] = 20 }, "ReferenceError: Left side of assignment is not a reference."); shouldThrow(function () { [a, ...b = 20] = 20 }, "ReferenceError: Left side of assignment is not a reference."); (function () { var a, b, c; [a, b, ...[...c]] = "Cocoa"; shouldBe(a, 'C'); shouldBe(b, 'o'); shouldBe(JSON.stringify(c), String.raw`["c","o","a"]`); }()); (function () { var a, b, c, d, e, f; [a, b, ...{ 0: c, 1: d, 2: e, 3: f }] = "Cocoa"; shouldBe(a, 'C'); shouldBe(b, 'o'); shouldBe(c, 'c'); shouldBe(d, 'o'); shouldBe(f, undefined); }()); (function () { var a, b, c, d, e; [a, b, ...[c, d, ...e]] = "Cocoa"; shouldBe(a, 'C'); shouldBe(b, 'o'); shouldBe(c, 'c'); shouldBe(d, 'o'); shouldBe(JSON.stringify(e), String.raw`["a"]`); }()); function iterator(array) { var nextCount = 0; var returnCount = 0; var original = array.values(); return { [Symbol.iterator]() { return this; }, next() { ++nextCount; return original.next(); }, return() { ++returnCount; return { done: true }; }, reportNext() { return nextCount; }, reportReturn() { return returnCount; } }; }; (function () { var iter = iterator([1, 2, 3]); var [...a] = iter; shouldBe(iter.reportNext(), 4); shouldBe(iter.reportReturn(), 0); shouldBe(JSON.stringify(a), String.raw`[1,2,3]`); }()); (function () { var iter = iterator([1, 2, 3]); var [a, b, ...c] = iter; shouldBe(iter.reportNext(), 4); shouldBe(iter.reportReturn(), 0); shouldBe(a, 1); shouldBe(b, 2); shouldBe(JSON.stringify(c), String.raw`[3]`); }()); (function () { var iter = iterator([1, 2, 3]); var [a, b, c, d, ...e] = iter; shouldBe(iter.reportNext(), 4); shouldBe(iter.reportReturn(), 0); shouldBe(a, 1); shouldBe(b, 2); shouldBe(c, 3); shouldBe(d, undefined); shouldBe(JSON.stringify(e), String.raw`[]`); }()); (function () { var iter = iterator([1, 2, 3]); var a, b; [...[a, b]] = iter; shouldBe(iter.reportNext(), 4); shouldBe(iter.reportReturn(), 0); shouldBe(a, 1); shouldBe(b, 2); }());