| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
- var emptyIterator = function(){ return {next: function () { return { done: true, value: 0};}}}
- var simpleIterator = function(args) {
- var iter = (function(args) {
- var j = 0;
- var length = args.length;
- return function Iterator() {
- return {next: function() {
- if (j < length)
- {
- return { value: args[j++], done: false };
- }
- else
- {
- j = 0;
- return { done: true };
- }
- }}}})(args)
- return iter;};
- function __createIterableObject(a, b, c) {
- if (typeof Symbol === "function" && Symbol.iterator) {
- var arr = [a, b, c, ,];
- var iterable = {
- next: function() {
- return { value: arr.shift(), done: arr.length <= 0 };
- },
- };
- iterable[Symbol.iterator] = function(){ return iterable; }
- return iterable;
- }
- else {
- return eval("(function*() { yield a; yield b; yield c; }())");
- }
- }
- var tests = [
- {
- name: "Spread TypeError: Function expected",
- body: function ()
- {
- var a = [1, 2];
- a[Symbol.iterator] = 0;
- assert.throws(function () { var b = [...1]; }, TypeError, "1 is not iterable", "Function expected");
- assert.throws(function () { var b = [...a]; }, TypeError, "Spread when the iterator is not a function", "Function expected");
- var noNextIterator = function(){ return {done: true, value: 0};}
- a[Symbol.iterator] = noNextIterator;
- assert.throws(function () { var b = [...a]; }, TypeError, "Spread when the iterator does not have a next is not valid", "Function expected");
- a = function() {}
- assert.throws(function () { var b = [...a]; }, TypeError, "Spread when the iterator is not a function", "Function expected");
- a = {}
- assert.throws(function () { var b = [...a]; }, TypeError, "Spread when the iterator is not a function", "Function expected");
- a = /r/g;
- assert.throws(function () { var b = [...a]; }, TypeError, "Spread when the iterator is not a function", "Function expected");
- }
- },
- {
- name: "Kangax Tests",
- body: function ()
- {
- assert.areEqual("𠮷", Array(..."𠮷")[0]);
- assert.areEqual("a", Array(..."a")[0]);
- assert.areEqual("𠮷", [..."𠮷"][0]);
- assert.areEqual("a", [..."a" ][0]);
- var iterableNum = __createIterableObject(1, 2, 3);
- //assert.areEqual(3, Math.max(...Object.create(iterableNum))); //TODO look into why this doesn't work
- assert.areEqual(3, Math.max(...iterableNum));
- var iterableStr = __createIterableObject("b", "c", "d");
- assert.areEqual("d", ["a", ...iterableStr, "e"][3]);
- //assert.areEqual("d", ["a", ...Object.create(iterableStr), "e"][3]);
- }
- },
- {
- name: "Spread TypeError: Object expected",
- body: function ()
- {
- var a = [1, 2];
- a[Symbol.iterator] = function() {};
- assert.throws(function () { var b = [...a]; }, TypeError, "the @@iterator function should return an Object", "Object expected");
- }
- },
- {
- name: "A spread argument's @@iterator has changed",
- body: function ()
- {
- var a = [1, 2];
- var c = [4, 5];
- count = 0;
- a[Symbol.iterator] = function() {
- return { next: function() {
- if (count < 3)
- {
- return { value: count++, done: false };
- }
- else
- {
- return { done: true };
- }
- }};};
- var result = [-1,0,1,2,3,4,5,6];
- var b = [-1,...a,3,...c,6]
- assert.areEqual(result,b, "confirm only a spreads with a counting iterator");
- assert.areEqual(3,count,"confirm side effect of incrementing count equals the number we expect");
- c[Symbol.iterator] = simpleIterator(c);
- count = 0;
- var b = [-1,...a,3,...c,6];
- assert.areEqual(result,b, "confirm both a and c spread, with c using an iterator that increments c's array");
- }
- },
- {
- name: "Array Spread Iterator causes parameter side effects",
- body: function ()
- {
- var a = [1,2];
- var b = 4
- var c = { 0 : false };
- var d = "foo";
- var e = function foo() {}
- var simpleIteratorWithParamSideEffect = function(args) {
- var iter = (function(args) {
- var j = 0;
- var length = args.length;
- return function Iterator() {
- b = 5;
- c[0] = true;
- d = "bar";
- e = function goo() {}
- return {next: function() {
- if (j < length)
- {
- return { value: args[j++], done: false };
- }
- else
- {
- j = 0;
- return { done: true };
- }
- }}}})(args)
- return iter;};
- a[Symbol.iterator] = simpleIteratorWithParamSideEffect(a);
- var result = [...a,b,c,d,e];
- assert.areEqual(1,result[0]);
- assert.areEqual(2,result[1]);
- assert.areEqual(5,result[2]);
- assert.areEqual(true,result[3][0]);
- assert.areEqual("bar",result[4]);
- assert.areEqual("goo",result[5].name);
- }
- },
- {
- name: "Spread with String iterators",
- body: function ()
- {
- var a = "foobar";
- var b = [1,2,...a,4];
- var results = [1,2,'f','o','o','b','a','r',4];
- assert.areEqual(results,b, "confirm we can spread strings");
- var aa = new String(a);
- aa[Symbol.iterator] = simpleIterator(aa);
- var b = [1,2,...aa,4];
- assert.areEqual(results,b, "override the string iterator with a custom iterator that emulates the built in iterator");
- aa[Symbol.iterator] = emptyIterator;
- var b = [1,2,...aa,4];
- assert.areEqual([1,2,4],b, "override the string iterator with an empty iterator");
- }
- },
- {
- name: "Spread with typedArray iterators",
- body: function ()
- {
- var buf = [2, 3, 4, 5];
- var typedArrays = [new Int8Array(buf), new Uint8Array(buf), new Uint8ClampedArray(buf), new Uint16Array(buf),
- new Int16Array(buf), new Int32Array(buf), new Uint32Array(buf), new Float32Array(buf),
- new Float64Array(buf)];
- for(var i = 0; i < typedArrays.length;i++)
- {
- var a = typedArrays[i];
- var b = [1,...a,6];
- var results = [1,...buf,6];
- assert.areEqual(results,b, "confirm TypedArrays still spread");
- a[Symbol.iterator] = simpleIterator(a);
- var b = [1,...a,6];
- assert.areEqual(results,b, "force typed arrays to use a user defined iterator that emulates the buitin iterator behavior");
- a[Symbol.iterator] = emptyIterator;
- var b = [1,...a,6];
- assert.areEqual([1,6],b, " make typed arrays use an empty iterator");
- }
- }
- },
- {
- name: "Spread with Maps & Sets",
- body: function ()
- {
- var kvArray = [["one", 1], ["two", 2]];
- var myMap = new Map(kvArray);
- var b = [0,...myMap];
- assert.areEqual([0,["one", 1], ["two", 2]],b);
- var mapIter = myMap.keys();
- var b = [0,...mapIter];
- assert.areEqual([0, "one", "two"],b,"should show 0 and then myMap's keys");
- var mapIter = myMap.values();
- var b = [0,...mapIter];
- assert.areEqual([0, 1, 2],b,"should show 0 and then myMap's keys");
- var aSet = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
- var b = [0,...aSet, 6];
- assert.areEqual([0,1,2,3,4,5, 6],b);
- }
- },
- {
- name: "Spread with Objects",
- body: function ()
- {
- var obj = { 0 : 1, 1: 1, 2 : 1, 3 : 1, length : 4}
- assert.throws(function () { var b = [...obj]; }, TypeError, "Spread is no longer dependent on length", "Function expected");
- obj[Symbol.iterator] = simpleIterator(obj);
- var b = [...obj];
- assert.areEqual([1,1,1,1],b);
- }
- },
- {
- name: "Spread with WeakMaps & WeakSets",
- body: function ()
- {
- var kvArray = [[{animal: "dog"},"foo" ], [{animal: "cat"},"bar" ]];
- var myMap = new WeakMap(kvArray);
- myMap[Symbol.iterator] = emptyIterator;
- var b = [0,...myMap];
- assert.areEqual([0],b, "confirm any object can spread as long as it has an iterator");
- var aSet = new WeakSet([{},{},{},[4], [5], [5], [5], [5]]);
- aSet[Symbol.iterator] = emptyIterator;
- var b = [0,...aSet, 6];
- assert.areEqual([0,6],b,"confirm any object can spread as long as it has an iterator");
- }
- },
- {
- name: "Spread with arguments",
- body: function ()
- {
- var b = [];
- function bar(a,a){b = [...arguments];}
- bar([1],[2]);
- assert.areEqual([[1],[2]], b);
- class d { constructor() {arguments[Symbol.iterator] = simpleIterator(arguments); b = [...arguments]; } };
- new d(1,2,3);
- assert.areEqual([1,2,3],b, "confirm we can override the built iterator");
- new d();
- assert.areEqual([],b);
- function foo(a, b, c, ...rest) { return [a, b, c, ...rest]; }
- b= foo(1,2,3,4,5,6)
- assert.areEqual([1,2,3,4,5,6],b);
- b = foo(1,2,3);
- assert.areEqual([1,2,3],b);
- b = foo(1,2);
- assert.areEqual([1,2,undefined],b);
- }
- },
- {
- name: "Function Spread with typedArray iterators",
- body: function ()
- {
- var buf = [2, 3, 4];
- function test1(a,b,c,d,e)
- {
- var expected = [a, ...buf, e];
- var results = [a,b,c,d,e];
- assert.areEqual(results,expected, "confirm TypedArrays still spread");
- }
- function test2(a,b,c,d,e)
- {
- assert.areEqual(1,a, "should be nonspreadable numeric primitive 1");
- assert.areEqual(5,b, "should be nonspreadable numeric primitive 5");
- assert.areEqual(undefined,c);
- assert.areEqual(undefined,d);
- assert.areEqual(undefined,e);
- }
- var typedArrays = [new Int8Array(buf), new Uint8Array(buf), new Uint8ClampedArray(buf), new Uint16Array(buf),
- new Int16Array(buf), new Int32Array(buf), new Uint32Array(buf), new Float32Array(buf),
- new Float64Array(buf)];
- for(var i = 0; i < typedArrays.length;i++)
- {
- var a = typedArrays[i];
- test1(1,...a,5);
- a[Symbol.iterator] = simpleIterator(a);
- test1(1,...a,5);
- a[Symbol.iterator] = emptyIterator;
- test2(1,...a,5);
- }
- }
- },
- {
- name: "Function Spread TypeError: Function expected",
- body: function ()
- {
- var a = [1,2,3];
- a[Symbol.iterator] = 0;
- function f(z,...v) {}
- assert.throws(function () { f(0,...a); }, TypeError, "Spread when the iterator is not a function", "Function expected");
- var noNextIterator = function(){ return {done: true, value: 0};}
- a[Symbol.iterator] = noNextIterator;
- assert.throws(function () { f(0,...a); }, TypeError, "Spread when the iterator does not have a next is not valid", "Function expected");
- a = function() {}
- assert.throws(function () { f(0,...a); }, TypeError, "Spread when the iterator is not a function", "Function expected");
- a = {}
- assert.throws(function () { f(0,...a); }, TypeError, "Spread when the iterator is not a function", "Function expected");
- a = /r/g;
- assert.throws(function () { f(0,...a); }, TypeError, "Spread when the iterator is not a function", "Function expected");
- var b = 11;
- assert.throws(function () { f(0,...b); }, TypeError, "b is a primitive and thus is not iterable", "Function expected");
- }
- },
- {
- name: "Function Spread TypeError: Object expected",
- body: function ()
- {
- var a = [1, 2];
- a[Symbol.iterator] = function() {};
- function f(z,v) {}
- assert.throws(function () { f(0,...a); }, TypeError, "the @@iterator function should return an Object", "Object expected");
- }
- },
- {
- name: "Function Spread Iterator with Arguments",
- body: function ()
- {
- // constructor() { super(...arguments); } (equivalent to constructor(...args) { super(...args); } )
- class base {}
- class child extends base {}
- assert.doesNotThrow(function () { var o = new child(); }, "we should not, get a type Error, arguments has an iterator");
- var a = [1];
- var b = 'a';
- var c = new Set([1,1,1,1]);
- function test(a,b,c)
- {
- assert.areEqual([1], a);
- assert.areEqual('a', b);
- assert.areEqual([1], [...c]);
- }
- class child2 extends base {
- constructor(a,b,c) {
- super(...arguments);
- test(...arguments);
- }};
- var o = new child2(a, b, c);
- class child3 extends base {
- constructor(a,b,c) {
- arguments[Symbol.iterator] = simpleIterator(arguments);
- super(...arguments);
- test(...arguments);
- }};
- var o = new child3(a, b, c);
- }
- },
- {
- name: "Function Spread Iterator override for all objects",
- body: function ()
- {
- var a = new String("fox");
- var b = [1,2,3];
- var c = {0 : 1, 1 : 2, 2 : 3, length : 3};
- a[Symbol.iterator] = simpleIterator(a);
- b[Symbol.iterator] = simpleIterator(b);
- c[Symbol.iterator] = simpleIterator(c);
- function f(a, b, c, d, e, f, w, x, y, z)
- {
- assert.areEqual('f',a, "should be value at global string a[0]");
- assert.areEqual('o',b, "should be value at global string a[1]");
- assert.areEqual('x',c, "should be value at global string a[2]");
- assert.areEqual(1,d, "should be value at global array b[0]");
- assert.areEqual(2,e, "should be value at global array b[1]");
- assert.areEqual(3,f, "should be value at global array b[2]");
- assert.areEqual(1,w, "should be value at global object c[0]");
- assert.areEqual(2,x, "should be value at global object c[1]");
- assert.areEqual(3,y, "should be value at global object c[2]");
- assert.areEqual(4,z, "should be nonspreadable numeric primitive 4");
- }
- f(...a, ...b, ...c, 4);
- function d(a, b, c, d, e, f, w, x, y, z)
- {
- assert.areEqual(4,a, "should be nonspreadable numeric primitive 4");
- assert.areEqual(undefined,b);
- assert.areEqual(undefined,c);
- assert.areEqual(undefined,d);
- assert.areEqual(undefined,e);
- assert.areEqual(undefined,f);
- assert.areEqual(undefined,w);
- assert.areEqual(undefined,x);
- assert.areEqual(undefined,y);
- assert.areEqual(undefined,z);
- }
- a[Symbol.iterator] = emptyIterator;
- b[Symbol.iterator] = emptyIterator;
- c[Symbol.iterator] = emptyIterator;
- d(...a, ...b, ...c, 4);
- }
- },
- {
- name: "Function Spread Iterator causes parameter side effects",
- body: function ()
- {
- var a = [1,2];
- var b = [4,5];
- var c = [7,8];
- var simpleIteratorWithParamSideEffect = function(args) {
- var iter = (function(args) {
- var j = 0;
- var length = args.length;
- return function Iterator() {
- c[Symbol.iterator] = emptyIterator;
- a[Symbol.iterator] = emptyIterator;
- return {next: function() {
- if (j < length)
- {
- return { value: args[j++], done: false };
- }
- else
- {
- j = 0;
- return { done: true };
- }
- }}}})(args)
- return iter;};
- b[Symbol.iterator] = simpleIteratorWithParamSideEffect(b);
- function test(a,b,c,d,e,f)
- {
- assert.areEqual(1,a, "iterator side effect on array 'a' happens after spreading 'a'");
- assert.areEqual(2,b, "iterator side effect on array 'a' happens after spreading 'a'");
- assert.areEqual(4,c);
- assert.areEqual(5,d);
- assert.areEqual(undefined,e,"iterator side effect on array 'c' happens before spreading 'c'");
- assert.areEqual(undefined,f,"iterator side effect on array 'c' happens before spreading 'c'");
- }
- test(...a,...b,...c);
- }
- },
- {
- name: "Function Spread Iterator causes parameter side effects",
- body: function ()
- {
- var a = [1,2];
- var b = 4
- var c = { 0 : false };
- var d = "foo";
- var e = function foo() {}
- var simpleIteratorWithParamSideEffect = function(args) {
- var iter = (function(args) {
- var j = 0;
- var length = args.length;
- return function Iterator() {
- b = 5;
- c[0] = true;
- d = "bar";
- e = function goo() {}
- return {next: function() {
- if (j < length)
- {
- return { value: args[j++], done: false };
- }
- else
- {
- j = 0;
- return { done: true };
- }
- }}}})(args)
- return iter;};
- a[Symbol.iterator] = simpleIteratorWithParamSideEffect(a);
- function test(a,b,c,d,e,f)
- {
- assert.areEqual(1,a, "iterator side effect on array 'a' happens after spreading 'a'");
- assert.areEqual(2,b, "iterator side effect on array 'a' happens after spreading 'a'");
- assert.areEqual(5,c);
- assert.areEqual(true,d[0]);
- assert.areEqual("bar",e);
- assert.areEqual("goo",f.name);
- }
- test(...a,b,c,d,e);
- }
- },
- {
- name: "Function Spread Iterator override for some objects",
- body: function ()
- {
- var a = new String("fox");
- var b = [1,2,3];
- var c = {0 : 1, 1 : 2, 2 : 3, length : 3};
- a[Symbol.iterator] = simpleIterator(a);
- c[Symbol.iterator] = simpleIterator(c);
- function f(a, b, c, d, e, f, w, x, y, z)
- {
- assert.areEqual('f',a, "should be value at global string a[0]");
- assert.areEqual('o',b, "should be value at global string a[1]");
- assert.areEqual('x',c, "should be value at global string a[2]");
- assert.areEqual(1,d, "should be value at global array b[0]");
- assert.areEqual(2,e, "should be value at global array b[1]");
- assert.areEqual(3,f, "should be value at global array b[2]");
- assert.areEqual(1,w, "should be value at global object c[0]");
- assert.areEqual(2,x, "should be value at global object c[1]");
- assert.areEqual(3,y, "should be value at global object c[2]");
- assert.areEqual(4,z, "should be nonspreadable numeric primitive 4");
- }
- f(...a, ...b, ...c, 4);
- function d(a, b, c, d, e, f, w, x, y, z)
- {
- assert.areEqual(1,a, "should be value at global array b[0]");
- assert.areEqual(2,b, "should be value at global array b[1]");
- assert.areEqual(3,c, "should be value at global array b[2]");
- assert.areEqual(4,d, "should be nonspreadable numeric primitive 4");
- assert.areEqual(undefined,e);
- assert.areEqual(undefined,f);
- assert.areEqual(undefined,w);
- assert.areEqual(undefined,x);
- assert.areEqual(undefined,y);
- assert.areEqual(undefined,z);
- }
- a[Symbol.iterator] = emptyIterator;
- c[Symbol.iterator] = emptyIterator;
- d(...a, ...b, ...c, 4);
- }
- }
- ];
- testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });
|