--- /dev/null
+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 () {
+ var [a, b, c] = [1, 2, 3];
+ shouldBe(a, 1);
+ shouldBe(b, 2);
+ shouldBe(c, 3);
+}());
+
+(function () {
+ var [a, b, c] = [1, 2, 3].keys();
+ shouldBe(a, 0);
+ shouldBe(b, 1);
+ shouldBe(c, 2);
+}());
+
+(function () {
+ var [a, b, c] = [1, 2, 3].values();
+ shouldBe(a, 1);
+ shouldBe(b, 2);
+ shouldBe(c, 3);
+}());
+
+(function () {
+ var [a, , c] = [1, 2, 3].values();
+ shouldBe(a, 1);
+ shouldBe(c, 3);
+}());
+
+(function () {
+ var [a, b, c] = [1, , 3].values();
+ shouldBe(a, 1);
+ shouldBe(b, undefined);
+ shouldBe(c, 3);
+}());
+
+(function () {
+ var [, b, c] = [1, 2, 3, 4, 5, 6].values();
+ shouldBe(b, 2);
+ shouldBe(c, 3);
+}());
+
+(function () {
+ var [a, b, c] = [1].values();
+ shouldBe(a, 1);
+ shouldBe(b, undefined);
+ shouldBe(c, undefined);
+}());
+
+(function ([a, b, c]) {
+ shouldBe(a, 1);
+ shouldBe(b, undefined);
+ shouldBe(c, undefined);
+}([1].values()));
+
+(function () {
+ var [a = 0, b = 2, c = 3] = [1].values();
+ shouldBe(a, 1);
+ shouldBe(b, 2);
+ shouldBe(c, 3);
+}());
+
+(function () {
+ var [a = 1, b = 2, c = 3] = [undefined, undefined, undefined];
+ shouldBe(a, 1);
+ shouldBe(b, 2);
+ shouldBe(c, 3);
+}());
+
+// String with a surrogate pair.
+(function () {
+ var string = "𠮷野家";
+ var [a, b, c] = string;
+ shouldBe(string.length, 4);
+ shouldBe(a, '𠮷');
+ shouldBe(b, '野');
+ shouldBe(c, '家');
+}());
+
+(function () {
+ var set = new Set([1, 2, 3]);
+ var [a, b, c] = set;
+ shouldBe(set.has(a), true);
+ shouldBe(set.has(b), true);
+ shouldBe(set.has(c), true);
+}());
+
+(function () {
+ var map = new Map([[1, 1], [2, 2], [3, 3]]);
+ var [a, b, c] = map;
+ shouldBe(Array.isArray(a), true);
+ shouldBe(Array.isArray(b), true);
+ shouldBe(Array.isArray(c), true);
+ shouldBe(map.has(a[0]), true);
+ shouldBe(map.has(b[0]), true);
+ shouldBe(map.has(c[0]), true);
+}());
+
+// Errors
+
+shouldThrow(function () {
+ var [a, b, c] = {
+ [Symbol.iterator]() {
+ return 42;
+ }
+ };
+}, "TypeError: [a, b, c] is not a function. (In '[a, b, c]', '[a, b, c]' is undefined)");
+
+shouldThrow(function () {
+ var [a, b, c] = {
+ [Symbol.iterator]() {
+ return {};
+ }
+ };
+}, "TypeError: [a, b, c] is not a function. (In '[a, b, c]', '[a, b, c]' is undefined)");
+
+shouldThrow(function () {
+ var [a, b, c] = {
+ [Symbol.iterator]() {
+ return this;
+ },
+
+ next() {
+ throw new Error('out');
+ }
+ };
+}, 'Error: out');
+
+shouldThrow(function () {
+ var [a, b, c] = {
+ [Symbol.iterator]() {
+ return this;
+ },
+
+ next() {
+ return 42;
+ }
+ };
+}, 'TypeError: Iterator result interface is not an object.');
+
+(function () {
+ var ok = 0;
+ shouldThrow(function () {
+ var [a, b, c] = {
+ [Symbol.iterator]() {
+ return this;
+ },
+
+ return() {
+ ok++;
+ },
+
+ next() {
+ return 42;
+ }
+ };
+ }, 'TypeError: Iterator result interface is not an object.');
+
+ shouldBe(ok, 0);
+}());
+
+(function () {
+ var ok = 0;
+ shouldThrow(function () {
+ var [a, b, c] = {
+ [Symbol.iterator]() {
+ return this;
+ },
+
+ return() {
+ ok++;
+ },
+
+ next() {
+ return { value: 20, done: false };
+ }
+ };
+ }, 'TypeError: Iterator result interface is not an object.');
+
+ shouldBe(ok, 1);
+}());
+
+(function () {
+ var ok = 0;
+
+ var [a, b, c] = {
+ [Symbol.iterator]() {
+ return this;
+ },
+
+ return() {
+ ok++;
+ },
+
+ next() {
+ return { value: 20, done: true };
+ }
+ };
+
+ shouldBe(a, undefined);
+ shouldBe(b, undefined);
+ shouldBe(c, undefined);
+ shouldBe(ok, 0);
+}());
+
+(function () {
+ var ok = 0;
+ var n = 0;
+
+ var done = false;
+ var [a, b, c] = {
+ [Symbol.iterator]() {
+ return this;
+ },
+
+ return() {
+ ok++;
+ },
+
+ next() {
+ var prev = done;
+ done = true;
+ ++n;
+ return { value: 20, done: prev };
+ }
+ };
+
+ shouldBe(a, 20);
+ shouldBe(b, undefined);
+ shouldBe(c, undefined);
+ shouldBe(n, 2);
+ shouldBe(ok, 0);
+}());
+
+(function () {
+ var ok = 0;
+ var n = 0;
+
+ var done = false;
+ var [a, b, c] = {
+ [Symbol.iterator]() {
+ return this;
+ },
+
+ return() {
+ ++ok;
+ return { done: true };
+ },
+
+ next() {
+ ++n;
+ return { value: 20, done: false };
+ }
+ };
+
+ shouldBe(a, 20);
+ shouldBe(b, 20);
+ shouldBe(c, 20);
+ shouldBe(n, 3);
+ shouldBe(ok, 1);
+}());
+
+(function () {
+ var ok = 0;
+ var n = 0;
+
+ var done = false;
+ var [a, b, c] = {
+ [Symbol.iterator]() {
+ return this;
+ },
+
+ return() {
+ ++ok;
+ return { done: true };
+ },
+
+ count: 0,
+
+ next() {
+ ++n;
+ var done = ++this.count === 3;
+ return { value: 20, done };
+ }
+ };
+
+ shouldBe(a, 20);
+ shouldBe(b, 20);
+ shouldBe(c, undefined);
+ shouldBe(n, 3);
+ shouldBe(ok, 0);
+}());
+
+(function () {
+ var ok = 0;
+ var n = 0;
+
+ var done = false;
+ var [a, b, c] = {
+ [Symbol.iterator]() {
+ return this;
+ },
+
+ return() {
+ ++ok;
+ return { done: true };
+ },
+
+ count: 0,
+
+ next() {
+ ++n;
+ var done = ++this.count === 4;
+ return { value: 20, done };
+ }
+ };
+
+ shouldBe(a, 20);
+ shouldBe(b, 20);
+ shouldBe(c, 20);
+ shouldBe(n, 3);
+ shouldBe(ok, 1);
+}());
+
+(function () {
+ var ok = 0;
+ var n = 0;
+ shouldThrow(function () {
+ var [a, b, c] = {
+ [Symbol.iterator]() {
+ return this;
+ },
+
+ return() {
+ ok++;
+ throw new Error('out');
+ },
+
+ next() {
+ n++;
+ return { value: 20, done: false };
+ }
+ };
+ }, 'Error: out');
+
+ shouldBe(n, 3);
+ shouldBe(ok, 1);
+}());
+
+(function () {
+ var ok = 0;
+ var n = 0;
+ shouldThrow(function () {
+ var [a, b, c] = {
+ [Symbol.iterator]() {
+ return this;
+ },
+
+ get return() {
+ ok++;
+ throw new Error('out');
+ },
+
+ next() {
+ n++;
+ return { value: 20, done: false };
+ }
+ };
+ }, 'Error: out');
+
+ shouldBe(n, 3);
+ shouldBe(ok, 1);
+}());
+
+(function () {
+ var ok = 0;
+ var n = 0;
+ shouldThrow(function () {
+ var [a, b, c] = {
+ [Symbol.iterator]() {
+ return this;
+ },
+
+ get return() {
+ ok++;
+ throw new Error('ng');
+ },
+
+ next() {
+ n++;
+ throw new Error('out');
+ }
+ };
+ }, 'Error: out');
+
+ shouldBe(n, 1);
+ shouldBe(ok, 0);
+}());
+
+(function () {
+ var ok = 0;
+ var n = 0;
+ shouldThrow(function () {
+ var [a, b, c] = {
+ [Symbol.iterator]() {
+ return this;
+ },
+
+ get return() {
+ ok++;
+ throw new Error('ng');
+ },
+
+ get next() {
+ ++n;
+ throw new Error('out');
+ }
+ };
+ }, 'Error: out');
+
+ shouldBe(n, 1);
+ shouldBe(ok, 0);
+}());