12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070 |
- var runArrayTests = function (it) {
- 'use strict';
- var Sym = typeof Symbol === 'undefined' ? {} : Symbol;
- var isSymbol = function (sym) {
- return typeof Sym === 'function' && typeof sym === 'symbol';
- };
- var functionsHaveNames = (function foo() {}).name === 'foo';
- var ifFunctionsHaveNamesIt = functionsHaveNames ? it : it.skip;
- var ifSymbolIteratorIt = isSymbol(Sym.iterator) ? it : it.skip;
- var ifSymbolIteratorAndArrayValuesIt = isSymbol(Sym.iterator) && Array.prototype.values ? it : it.skip;
- var ifSymbolUnscopablesIt = isSymbol(Sym.unscopables) ? it : it.skip;
- var ifShimIt = (typeof process !== 'undefined' && process.env.NO_ES6_SHIM) ? it.skip : it;
- var ifSupportsDescriptorsIt = Object.getOwnPropertyDescriptor ? it : it.skip;
- var ifHasDunderProtoIt = [].__proto__ === Array.prototype ? it : it.skip; // eslint-disable-line no-proto
- var isNegativeZero = function (x) {
- return (1 / x) < 0;
- };
- describe('Array', function () {
- var list = [5, 10, 15, 20];
- ifShimIt('is on the exported object', function () {
- var exported = require('../');
- expect(exported.Array).to.equal(Array);
- });
- describe('@@iterator', function () {
- ifSymbolIteratorIt('uses Symbol.iterator if available', function () {
- var b = {};
- var c = {};
- var a = [b, c];
- var iteratorFn = a[Sym.iterator];
- var iterator = iteratorFn.call(a);
- expect(iterator.next()).to.eql({ done: false, value: b });
- expect(iterator.next()).to.eql({ done: false, value: c });
- expect(iterator.next()).to.eql({ done: true, value: undefined });
- });
- ifSymbolIteratorAndArrayValuesIt('has the right default iteration function', function () {
- // fixed in Webkit https://bugs.webkit.org/show_bug.cgi?id=143838
- expect(Array.prototype).to.have.property(Sym.iterator, Array.prototype.values);
- });
- });
- describe('.from()', function () {
- if (!Object.prototype.hasOwnProperty.call(Array, 'from')) {
- return it('exists', function () {
- expect(Array).to.have.property('from');
- });
- }
- ifFunctionsHaveNamesIt('has the correct name', function () {
- expect(Array.from).to.have.property('name', 'from');
- });
- it('has the right arity', function () {
- expect(Array.from).to.have.property('length', 1);
- });
- it('is not enumerable', function () {
- expect(Array).ownPropertyDescriptor('from').to.have.property('enumerable', false);
- });
- it('works with primitives', function () {
- expect(Array.from(false)).to.eql([]);
- expect(Array.from(true)).to.eql([]);
- expect(Array.from(-Infinity)).to.eql([]);
- expect(Array.from(-0)).to.eql([]);
- expect(Array.from(0)).to.eql([]);
- expect(Array.from(1)).to.eql([]);
- expect(Array.from(Infinity)).to.eql([]);
- });
- it('should create correct array from iterable', function () {
- (function () {
- expect(Array.from(arguments)).to.eql([0, 1, 2]);
- }(0, 1, 2));
- expect(Array.from([null, undefined, 0.1248, -0, 0])).to.eql([null, undefined, 0.1248, -0, 0]);
- if (Array.prototype.values) {
- expect(Array.from([null, undefined, 0.1248, -0, 0].values())).to.eql([null, undefined, 0.1248, -0, 0]);
- }
- });
- it('works with arraylike objects', function () {
- expect(Array.from({ length: 1 })).to.eql([undefined]);
- expect(Array.from({ 0: 'a', 1: 'b', length: 2 })).to.eql(['a', 'b']);
- });
- it('swallows negative lengths', function () {
- expect(Array.from({ length: -1 })).to.have.property('length', 0);
- expect(Array.from({ length: -Infinity })).to.have.property('length', 0);
- expect(Array.from({ length: -0 })).to.have.property('length', 0);
- expect(Array.from({ length: -42 })).to.have.property('length', 0);
- });
- it('works with strings', function () {
- expect(Array.from('')).to.eql([]);
- expect(Array.from('abc')).to.eql('abc'.split(''));
- });
- it('should handle empty iterables correctly', function () {
- (function () {
- expect(Array.from(arguments)).to.eql([]);
- }());
- expect(Array.from([])).to.eql([]);
- expect(Array.from({})).to.eql([]);
- expect(Array.from({ a: 1 })).to.eql([]);
- });
- it('should work with other constructors', function () {
- var Foo = function FooBar(length, args) {
- this.args = args;
- this.length = length;
- };
- var args = ['a', 'b', 'c'];
- var expected = new Foo(args.length);
- args.forEach(function (arg, index) {
- expected[index] = arg;
- });
- expect(Array.from.call(Foo, args)).to.be.an.instanceOf(Foo);
- expect(Array.from.call(Foo, args)).to.eql(expected);
- });
- describe('map functions', function () {
- it('supports a map function', function () {
- var original = [1, 2, 3];
- var mapper = function (item) {
- return item * 2;
- };
- var mapped = Array.from(original, mapper);
- expect(mapped).to.eql([2, 4, 6]);
- });
- it('passes both (and only) the item and the current index to the map function', function () {
- var original = [1, 2, 3];
- var expectedItems = [1, 2, 3];
- var expectedIndices = [0, 1, 2];
- var actualItems = [];
- var actualIndices = [];
- var mapper = function (item, index) {
- actualItems.push(item);
- actualIndices.push(index);
- expect(arguments).to.have.property('length', 2);
- return item;
- };
- var mapped = Array.from(original, mapper);
- expect(mapped).to.eql(expectedItems);
- expect(actualItems).to.eql(expectedItems);
- expect(actualIndices).to.eql(expectedIndices);
- });
- it('passes both the item and the current index to the map function with a "this" value', function () {
- var original = [1, 2, 3];
- var expectedItems = [1, 2, 3];
- var expectedIndices = [0, 1, 2];
- var expectedContext = {};
- var actualItems = [];
- var actualIndices = [];
- var mapper = function (item, index) {
- actualItems.push(item);
- actualIndices.push(index);
- expect(arguments).to.have.property('length', 2);
- expect(this).to.eql(expectedContext);
- return item;
- };
- var mapped = Array.from(original, mapper, expectedContext);
- expect(mapped).to.eql(expectedItems);
- expect(actualItems).to.eql(expectedItems);
- expect(actualIndices).to.eql(expectedIndices);
- });
- it('accepts an object thisArg', function () {
- var context = {};
- Array.from([1, 2, 3], function () {
- expect(this).to.equal(context);
- }, context);
- });
- it('accepts a primitive thisArg', function () {
- Array.from([1, 2, 3], function () {
- expect(this.valueOf()).to.equal(42);
- expect(Object.prototype.toString.call(this)).to.equal('[object Number]');
- }, 42);
- });
- it('accepts a falsy thisArg', function () {
- Array.from([1, 2, 3], function () {
- expect(this.valueOf()).to.equal(false);
- expect(Object.prototype.toString.call(this)).to.equal('[object Boolean]');
- }, false);
- });
- });
- it('does not throw when provided an undefined second arg', function () {
- expect(Array.from([], undefined)).to.eql([]);
- });
- it('throws when provided a nonfunction second arg', function () {
- expect(function () { Array.from([], null); }).to['throw'](TypeError);
- expect(function () { Array.from([], false); }).to['throw'](TypeError);
- expect(function () { Array.from([], true); }).to['throw'](TypeError);
- expect(function () { Array.from([], /a/g); }).to['throw'](TypeError);
- expect(function () { Array.from([], {}); }).to['throw'](TypeError);
- expect(function () { Array.from([], []); }).to['throw'](TypeError);
- expect(function () { Array.from([], ''); }).to['throw'](TypeError);
- expect(function () { Array.from([], 3); }).to['throw'](TypeError);
- });
- it('supports a this arg', function () {
- var original = [1, 2, 3];
- var context = {};
- var mapper = function (item) {
- expect(this).to.equal(context);
- return item * 2;
- };
- var mapped = Array.from(original, mapper, context);
- expect(mapped).to.eql([2, 4, 6]);
- });
- it('throws when provided null or undefined', function () {
- expect(function () { Array.from(); }).to['throw'](TypeError);
- expect(function () { Array.from(undefined); }).to['throw'](TypeError);
- expect(function () { Array.from(null); }).to['throw'](TypeError);
- });
- it('removes holes', function () {
- /* eslint-disable no-sparse-arrays */
- var input = [0, , 2];
- var result = Array.from([0, , 2]);
- /* eslint-enable no-sparse-arrays */
- expect(1 in input).to.equal(false);
- expect(1 in result).to.equal(true);
- expect(result).to.eql([0, undefined, 2]);
- });
- it('works with this flaky example', function () {
- expect(Array.from([1, NaN, false])).to.eql([1, NaN, false]);
- });
- ifSupportsDescriptorsIt('works when Object.prototype has a throwing setter', function () {
- // TODO: breaks in Chrome 17, IE 9, Safari 5.1-6
- var key = 10;
- /* eslint no-extend-native: 0 */
- Object.defineProperty(Object.prototype, key, {
- configurable: true,
- get: function () {}, // eslint-disable-line getter-return
- set: function (v) { throw new EvalError('boom'); }
- });
- expect(function () {
- var arr = [];
- arr[key] = 42;
- }).to['throw'](EvalError); // assert thrower
- expect(function () { Array.from({ length: key + 1 }); }).not.to['throw']();
- delete Object.prototype[key];
- expect(key in Object.prototype).to.equal(false); // assert cleanup
- });
- });
- describe('.of()', function () {
- if (!Object.prototype.hasOwnProperty.call(Array, 'of')) {
- return it('exists', function () {
- expect(Array).to.have.property('of');
- });
- }
- ifFunctionsHaveNamesIt('has the correct name', function () {
- expect(Array.of).to.have.property('name', 'of');
- });
- it('has the right arity', function () {
- expect(Array.of).to.have.property('length', 0);
- });
- it('is not enumerable', function () {
- expect(Array).ownPropertyDescriptor('of').to.have.property('enumerable', false);
- });
- it('should create correct array from arguments', function () {
- expect(Array.of(1, null, undefined)).to.eql([1, null, undefined]);
- });
- it('should work with other constructors', function () {
- var Foo = function FooBar(length) {
- this.args = Array.prototype.slice.call(arguments, 1);
- this.length = length;
- };
- var args = ['a', 'b', 'c'];
- var expected = new Foo(args.length);
- args.forEach(function (arg, index) {
- expected[index] = arg;
- });
- expect(Array.of.apply(Foo, args)).to.be.an.instanceOf(Foo);
- expect(Array.of.apply(Foo, args)).to.eql(expected);
- });
- describe('without Array.from', function () {
- var originalFrom = Array.from;
- beforeEach(function () {
- Array.from = 42;
- });
- afterEach(function () {
- Array.from = originalFrom;
- });
- it('still works', function () {
- expect(Array.of(1, 2, 3)).to.eql([1, 2, 3]);
- });
- });
- });
- describe('#copyWithin()', function () {
- if (!Object.prototype.hasOwnProperty.call(Array.prototype, 'copyWithin')) {
- return it('exists', function () {
- expect(Array.prototype).to.have.property('copyWithin');
- });
- }
- ifFunctionsHaveNamesIt('has the correct name', function () {
- expect(Array.prototype.copyWithin).to.have.property('name', 'copyWithin');
- });
- it('has the right arity', function () {
- expect(Array.prototype.copyWithin).to.have.property('length', 2);
- });
- it('is not enumerable', function () {
- expect(Array.prototype).ownPropertyDescriptor('copyWithin').to.have.property('enumerable', false);
- });
- it('modifies the object in-place', function () {
- var arr = [1, 2, 3, 4, 5];
- expect(arr.copyWithin(0, 3)).to.eql([4, 5, 3, 4, 5]);
- expect(arr).to.eql([4, 5, 3, 4, 5]);
- });
- it('works with 2 args', function () {
- expect([1, 2, 3, 4, 5].copyWithin(0, 3)).to.eql([4, 5, 3, 4, 5]);
- expect([1, 2, 3, 4, 5].copyWithin(1, 3)).to.eql([1, 4, 5, 4, 5]);
- expect([1, 2, 3, 4, 5].copyWithin(1, 2)).to.eql([1, 3, 4, 5, 5]);
- expect([1, 2, 3, 4, 5].copyWithin(2, 2)).to.eql([1, 2, 3, 4, 5]);
- });
- it('works with 3 args', function () {
- expect([1, 2, 3, 4, 5].copyWithin(0, 3, 4)).to.eql([4, 2, 3, 4, 5]);
- expect([1, 2, 3, 4, 5].copyWithin(1, 3, 4)).to.eql([1, 4, 3, 4, 5]);
- expect([1, 2, 3, 4, 5].copyWithin(1, 2, 4)).to.eql([1, 3, 4, 4, 5]);
- });
- it('works with negative args', function () {
- expect([1, 2, 3, 4, 5].copyWithin(0, -2)).to.eql([4, 5, 3, 4, 5]);
- expect([1, 2, 3, 4, 5].copyWithin(0, -2, -1)).to.eql([4, 2, 3, 4, 5]);
- expect([1, 2, 3, 4, 5].copyWithin(-4, -3, -2)).to.eql([1, 3, 3, 4, 5]);
- expect([1, 2, 3, 4, 5].copyWithin(-4, -3, -1)).to.eql([1, 3, 4, 4, 5]);
- expect([1, 2, 3, 4, 5].copyWithin(-4, -3)).to.eql([1, 3, 4, 5, 5]);
- });
- it('works with arraylike objects', function () {
- var args = (function () { return arguments; }(1, 2, 3));
- expect(Array.isArray(args)).to.equal(false);
- var argsClass = Object.prototype.toString.call(args);
- expect(Array.prototype.slice.call(args)).to.eql([1, 2, 3]);
- Array.prototype.copyWithin.call(args, -2, 0);
- expect(Array.prototype.slice.call(args)).to.eql([1, 1, 2]);
- expect(Object.prototype.toString.call(args)).to.equal(argsClass);
- });
- ifSymbolUnscopablesIt('should be unscopable if Symbols exist', function () {
- var unscopables = Array.prototype[Sym.unscopables];
- expect(!!unscopables).to.equal(true);
- expect(unscopables.copyWithin).to.equal(true);
- });
- it('should delete the target key if the source key is not present', function () {
- /* eslint-disable no-sparse-arrays */
- expect([, 1, 2].copyWithin(1, 0)).to.eql([, , 1]);
- /* eslint-enable no-sparse-arrays */
- });
- it('should check inherited properties as well', function () {
- var Parent = function Parent() {};
- Parent.prototype[0] = 'foo';
- var sparse = new Parent();
- sparse[1] = 1;
- sparse[2] = 2;
- sparse.length = 3;
- var result = Array.prototype.copyWithin.call(sparse, 1, 0);
- expect(result).to.have.property('0');
- expect(result).not.to.have.ownProperty('0');
- expect(result).to.have.ownProperty('1');
- expect(result).to.eql({ 0: 'foo', 1: 'foo', 2: 1, length: 3 });
- });
- // https://github.com/tc39/test262/pull/2443
- describe('security issues', function () {
- // make a long integer Array
- var longDenseArray = function longDenseArray() {
- var a = [0];
- for (var i = 0; i < 1024; i++) {
- a[i] = i;
- }
- return a;
- };
- describe('coerced-values-start-change-start', function () {
- var currArray;
- var shorten = function shorten() {
- currArray.length = 20;
- return 1000;
- };
- it('coercion side-effect makes start out of bounds', function () {
- currArray = longDenseArray();
- var array = [];
- array.length = 20;
- expect(currArray.copyWithin(0, { valueOf: shorten })).to.deep.equal(array);
- });
- ifHasDunderProtoIt('coercion side-effect makes start out of bounds with prototype', function () {
- currArray = longDenseArray();
- Object.setPrototypeOf(currArray, longDenseArray());
- var array2 = longDenseArray();
- array2.length = 20;
- for (var i = 0; i < 24; i++) {
- array2[i] = Object.getPrototypeOf(currArray)[i + 1000];
- }
- expect(currArray.copyWithin(0, { valueOf: shorten })).to.have.deep.members(array2);
- });
- });
- describe('coerced-values-start-change-target', function () {
- it('coercion side-effect makes target out of bounds', function () {
- var shorten = function shorten() {
- currArray.length = 20;
- return 1;
- };
- var array = longDenseArray();
- array.length = 20;
- for (var i = 0; i < 19; i++) {
- array[i + 1000] = array[i + 1];
- }
- var currArray = longDenseArray();
- expect(currArray.copyWithin(1000, { valueOf: shorten })).to.deep.equal(array);
- });
- });
- });
- });
- describe('#find()', function () {
- if (!Object.prototype.hasOwnProperty.call(Array.prototype, 'find')) {
- return it('exists', function () {
- expect(Array.prototype).to.have.property('find');
- });
- }
- ifFunctionsHaveNamesIt('has the correct name', function () {
- expect(Array.prototype.find).to.have.property('name', 'find');
- });
- it('should have the right arity', function () {
- expect(Array.prototype.find).to.have.property('length', 1);
- });
- it('is not enumerable', function () {
- expect(Array.prototype).ownPropertyDescriptor('find').to.have.property('enumerable', false);
- });
- it('should find item by predicate', function () {
- var result = list.find(function (item) { return item === 15; });
- expect(result).to.equal(15);
- });
- it('should return undefined when nothing matched', function () {
- var result = list.find(function (item) { return item === 'a'; });
- expect(result).to.equal(undefined);
- });
- it('should throw TypeError when function was not passed', function () {
- expect(function () { list.find(); }).to['throw'](TypeError);
- });
- it('should receive all three parameters', function () {
- var foundIndex = list.find(function (value, index, arr) {
- expect(list).to.have.property(index, value);
- expect(list).to.eql(arr);
- return false;
- });
- expect(foundIndex).to.equal(undefined);
- });
- it('should work with the context argument', function () {
- var context = {};
- [1].find(function () { expect(this).to.equal(context); }, context);
- });
- it('should work with an array-like object', function () {
- var obj = { 0: 1, 1: 2, 2: 3, length: 3 };
- var found = Array.prototype.find.call(obj, function (item) { return item === 2; });
- expect(found).to.equal(2);
- });
- it('should work with an array-like object with negative length', function () {
- var obj = { 0: 1, 1: 2, 2: 3, length: -3 };
- var found = Array.prototype.find.call(obj, function () {
- throw new Error('should not reach here');
- });
- expect(found).to.equal(undefined);
- });
- it('should work with a sparse array', function () {
- /* eslint-disable no-sparse-arrays */
- var obj = [1, , undefined];
- /* eslint-enable no-sparse-arrays */
- expect(1 in obj).to.equal(false);
- var seen = [];
- var found = obj.find(function (item, idx) {
- seen.push([idx, item]);
- return false;
- });
- expect(found).to.equal(undefined);
- expect(seen).to.eql([[0, 1], [1, undefined], [2, undefined]]);
- });
- it('should work with a sparse array-like object', function () {
- var obj = { 0: 1, 2: undefined, length: 3.2 };
- var seen = [];
- var found = Array.prototype.find.call(obj, function (item, idx) {
- seen.push([idx, item]);
- return false;
- });
- expect(found).to.equal(undefined);
- expect(seen).to.eql([[0, 1], [1, undefined], [2, undefined]]);
- });
- ifSymbolUnscopablesIt('should be unscopable if Symbols exist', function () {
- var unscopables = Array.prototype[Sym.unscopables];
- expect(!!unscopables).to.equal(true);
- expect(unscopables.find).to.equal(true);
- });
- });
- describe('#findIndex()', function () {
- if (!Object.prototype.hasOwnProperty.call(Array.prototype, 'findIndex')) {
- return it('exists', function () {
- expect(Array.prototype).to.have.property('findIndex');
- });
- }
- ifFunctionsHaveNamesIt('has the correct name', function () {
- expect(Array.prototype.findIndex).to.have.property('name', 'findIndex');
- });
- it('should have the right arity', function () {
- expect(Array.prototype.findIndex).to.have.property('length', 1);
- });
- it('is not enumerable', function () {
- expect(Array.prototype).ownPropertyDescriptor('findIndex').to.have.property('enumerable', false);
- });
- it('should find item key by predicate', function () {
- var result = list.findIndex(function (item) { return item === 15; });
- expect(result).to.equal(2);
- });
- it('should return -1 when nothing matched', function () {
- var result = list.findIndex(function (item) { return item === 'a'; });
- expect(result).to.equal(-1);
- });
- it('should throw TypeError when function was not passed', function () {
- expect(function () { list.findIndex(); }).to['throw'](TypeError);
- });
- it('should receive all three parameters', function () {
- var foundIndex = list.findIndex(function (value, index, arr) {
- expect(list[index]).to.equal(value);
- expect(list).to.eql(arr);
- return false;
- });
- expect(foundIndex).to.equal(-1);
- });
- it('should work with the context argument', function () {
- var context = {};
- [1].findIndex(function () { expect(this).to.equal(context); }, context);
- });
- it('should work with an array-like object', function () {
- var obj = { 0: 1, 1: 2, 2: 3, length: 3 };
- var foundIndex = Array.prototype.findIndex.call(obj, function (item) { return item === 2; });
- expect(foundIndex).to.equal(1);
- });
- it('should work with an array-like object with negative length', function () {
- var obj = { 0: 1, 1: 2, 2: 3, length: -3 };
- var foundIndex = Array.prototype.findIndex.call(obj, function () {
- throw new Error('should not reach here');
- });
- expect(foundIndex).to.equal(-1);
- });
- it('should work with a sparse array', function () {
- /* eslint-disable no-sparse-arrays */
- var obj = [1, , undefined];
- /* eslint-enable no-sparse-arrays */
- expect(1 in obj).to.equal(false);
- var seen = [];
- var foundIndex = obj.findIndex(function (item, idx) {
- seen.push([idx, item]);
- return item === undefined && idx === 2;
- });
- expect(foundIndex).to.equal(2);
- expect(seen).to.eql([[0, 1], [1, undefined], [2, undefined]]);
- });
- it('should work with a sparse array-like object', function () {
- var obj = { 0: 1, 2: undefined, length: 3.2 };
- var seen = [];
- var foundIndex = Array.prototype.findIndex.call(obj, function (item, idx) {
- seen.push([idx, item]);
- return false;
- });
- expect(foundIndex).to.equal(-1);
- expect(seen).to.eql([[0, 1], [1, undefined], [2, undefined]]);
- });
- ifSymbolUnscopablesIt('should be unscopable if Symbols exist', function () {
- var unscopables = Array.prototype[Sym.unscopables];
- expect(!!unscopables).to.equal(true);
- expect(unscopables.findIndex).to.equal(true);
- });
- });
- describe('ArrayIterator', function () {
- if (!Object.prototype.hasOwnProperty.call(Array.prototype, 'keys')) {
- return it('can be tested', function () {
- expect(Array.prototype).to.have.property('keys');
- });
- }
- var arrayIterator;
- beforeEach(function () {
- arrayIterator = [1, 2, 3].keys();
- });
- describe('#next()', function () {
- it('should work when applied to an ArrayIterator', function () {
- expect(arrayIterator.next.apply(arrayIterator)).to.eql({ value: 0, done: false });
- expect(arrayIterator.next.apply(arrayIterator)).to.eql({ value: 1, done: false });
- expect(arrayIterator.next.apply(arrayIterator)).to.eql({ value: 2, done: false });
- expect(arrayIterator.next.apply(arrayIterator)).to.eql({ value: undefined, done: true });
- });
- it('throws when not applied to an ArrayIterator', function () {
- expect(function () { arrayIterator.next.apply({}); }).to['throw'](TypeError);
- });
- });
- });
- describe('#keys()', function () {
- if (!Object.prototype.hasOwnProperty.call(Array.prototype, 'keys')) {
- return it('exists', function () {
- expect(Array.prototype).to.have.property('keys');
- });
- }
- ifFunctionsHaveNamesIt('has the correct name', function () {
- expect(Array.prototype.keys).to.have.property('name', 'keys');
- });
- it('should have the right arity ', function () {
- expect(Array.prototype.keys.length).to.equal(0);
- });
- it('is not enumerable', function () {
- expect(Array.prototype).ownPropertyDescriptor('keys').to.have.property('enumerable', false);
- });
- describe('basic keys iteration', function () {
- var mylist = [5, 10, 15, 20];
- var keys;
- beforeEach(function () {
- if (!keys) {
- keys = mylist.keys();
- }
- });
- it('should return 0 on first object', function () {
- expect(keys.next()).to.eql({ value: 0, done: false });
- });
- it('should return 1 on second object', function () {
- expect(keys.next()).to.eql({ value: 1, done: false });
- });
- it('should return 2 on third object', function () {
- expect(keys.next()).to.eql({ value: 2, done: false });
- });
- it('should return 3 on fourth object', function () {
- expect(keys.next()).to.eql({ value: 3, done: false });
- });
- it('should set done on completing iteration', function () {
- expect(keys.next()).to.eql({ value: undefined, done: true });
- });
- it('once done it should stay done', function () {
- mylist.push(4);
- expect(keys.next()).to.eql({ value: undefined, done: true });
- });
- });
- it('should not skip sparse keys', function () {
- var sparse = [1];
- sparse[2] = 3;
- var keys = sparse.keys();
- expect(keys.next()).to.eql({ value: 0, done: false });
- expect(keys.next()).to.eql({ value: 1, done: false });
- expect(keys.next()).to.eql({ value: 2, done: false });
- expect(keys.next()).to.eql({ value: undefined, done: true });
- });
- ifSymbolUnscopablesIt('should be unscopable if Symbols exist', function () {
- var unscopables = Array.prototype[Sym.unscopables];
- expect(!!unscopables).to.equal(true);
- expect(unscopables.keys).to.equal(true);
- });
- });
- describe('#values()', function () {
- if (!Object.prototype.hasOwnProperty.call(Array.prototype, 'values')) {
- return it('exists', function () {
- expect(Array.prototype).to.have.property('values');
- });
- }
- ifFunctionsHaveNamesIt('has the correct name', function () {
- expect(Array.prototype.values).to.have.property('name', 'values');
- });
- it('has the right arity', function () {
- expect(Array.prototype.values).to.have.property('length', 0);
- });
- it('is not enumerable', function () {
- expect(Array.prototype).ownPropertyDescriptor('values').to.have.property('enumerable', false);
- });
- describe('basic list iteration', function () {
- var mylist = [5, 10, 15, 20];
- var values;
- beforeEach(function () {
- if (!values) {
- values = mylist.values();
- }
- });
- it('should return 5 on first object', function () {
- expect(values.next()).to.eql({ value: 5, done: false });
- });
- it('should return 10 on second object', function () {
- expect(values.next()).to.eql({ value: 10, done: false });
- });
- it('should return 15 on third object', function () {
- expect(values.next()).to.eql({ value: 15, done: false });
- });
- it('should return 20 on fourth object', function () {
- expect(values.next()).to.eql({ value: 20, done: false });
- });
- it('should set done on completing iteration', function () {
- expect(values.next()).to.eql({ value: undefined, done: true });
- });
- it('once done it should stay done', function () {
- mylist.push(4);
- expect(values.next()).to.eql({ value: undefined, done: true });
- });
- });
- it('should not skip sparse values', function () {
- var sparse = [1];
- sparse[2] = 3;
- var values = sparse.values();
- expect(values.next()).to.eql({ value: 1, done: false });
- expect(values.next()).to.eql({ value: undefined, done: false });
- expect(values.next()).to.eql({ value: 3, done: false });
- expect(values.next()).to.eql({ value: undefined, done: true });
- });
- ifSymbolUnscopablesIt('should be unscopable if Symbols exist', function () {
- var unscopables = Array.prototype[Sym.unscopables];
- expect(!!unscopables).to.equal(true);
- expect(unscopables.values).to.equal(true);
- });
- });
- describe('#entries()', function () {
- if (!Object.prototype.hasOwnProperty.call(Array.prototype, 'entries')) {
- return it('exists', function () {
- expect(Array.prototype).to.have.property('entries');
- });
- }
- ifFunctionsHaveNamesIt('has the correct name', function () {
- expect(Array.prototype.entries).to.have.property('name', 'entries');
- });
- it('has the right arity', function () {
- expect(Array.prototype.entries).to.have.property('length', 0);
- });
- it('is not enumerable', function () {
- expect(Array.prototype).ownPropertyDescriptor('entries').to.have.property('enumerable', false);
- });
- describe('basic list iteration', function () {
- var mylist = [5, 10, 15, 20];
- var entries;
- beforeEach(function () {
- if (!entries) {
- entries = mylist.entries();
- }
- });
- it('should return [0, 5] on first object', function () {
- var val = entries.next();
- expect(val).to.eql({ value: [0, 5], done: false });
- });
- it('should return [1, 10] on second object', function () {
- var val = entries.next();
- expect(val).to.eql({ value: [1, 10], done: false });
- });
- it('should return [2, 15] on third object', function () {
- var val = entries.next();
- expect(val).to.eql({ value: [2, 15], done: false });
- });
- it('should return [3, 20] on fourth object', function () {
- var val = entries.next();
- expect(val).to.eql({ value: [3, 20], done: false });
- });
- it('should set done on completing iteration', function () {
- var val = entries.next();
- expect(val).to.eql({ value: undefined, done: true });
- });
- it('once done it should stay done', function () {
- mylist.push(4);
- var val = entries.next();
- expect(val).to.eql({ value: undefined, done: true });
- });
- });
- it('should not skip sparse entries', function () {
- var sparse = [1];
- sparse[2] = 3;
- var entries = sparse.entries();
- expect(entries.next()).to.eql({ value: [0, 1], done: false });
- expect(entries.next()).to.eql({ value: [1, undefined], done: false });
- expect(entries.next()).to.eql({ value: [2, 3], done: false });
- expect(entries.next()).to.eql({ value: undefined, done: true });
- });
- ifSymbolUnscopablesIt('should be unscopable if Symbols exist', function () {
- var unscopables = Array.prototype[Sym.unscopables];
- expect(!!unscopables).to.equal(true);
- expect(unscopables.entries).to.equal(true);
- });
- });
- describe('#fill()', function () {
- if (!Object.prototype.hasOwnProperty.call(Array.prototype, 'fill')) {
- return it('exists', function () {
- expect(Array.prototype).to.have.property('fill');
- });
- }
- ifFunctionsHaveNamesIt('has the correct name', function () {
- expect(Array.prototype.fill).to.have.property('name', 'fill');
- });
- it('has the right arity', function () {
- expect(Array.prototype.fill).to.have.property('length', 1);
- });
- it('is not enumerable', function () {
- expect(Array.prototype).ownPropertyDescriptor('fill').to.have.property('enumerable', false);
- });
- it('works with just a value', function () {
- var original = [1, 2, 3, 4, 5, 6];
- var filled = [-1, -1, -1, -1, -1, -1];
- expect(original.fill(-1)).to.eql(filled);
- });
- it('accepts a positive start index', function () {
- var original = [1, 2, 3, 4, 5, 6];
- var filled = [1, 2, 3, -1, -1, -1];
- expect(original.fill(-1, 3)).to.eql(filled);
- });
- it('accepts a negative start index', function () {
- var original = [1, 2, 3, 4, 5, 6];
- var filled = [1, 2, 3, -1, -1, -1];
- expect(original.fill(-1, -3)).to.eql(filled);
- });
- it('accepts a negative end index', function () {
- var original = [1, 2, 3];
- var filled = [4, 2, 3];
- expect(original.fill(4, -3, -2)).to.eql(filled);
- });
- it('accepts a large start index', function () {
- var original = [1, 2, 3, 4, 5, 6];
- var filled = [1, 2, 3, 4, 5, 6];
- expect(original.fill(-1, 9)).to.eql(filled);
- });
- ifSymbolUnscopablesIt('should be unscopable if Symbols exist', function () {
- var unscopables = Array.prototype[Sym.unscopables];
- expect(!!unscopables).to.equal(true);
- expect(unscopables.fill).to.equal(true);
- });
- });
- // this length converts to "1", preventing a crazy crash in older FF
- var negativeLength = { 0: 1, length: -Math.pow(2, 32) + 1 };
- var throwRangeError = function (v, i) {
- if (i === negativeLength.length >>> 0) {
- return v;
- }
- // note: in nonconforming browsers, this will be called
- // -1 >>> 0 times, which is 4294967295, so the throw matters.
- throw new RangeError('should not reach here: length of -1 should clamp to length of 0');
- };
- var throwRangeErrorReduce = function throwRangeErrorReduce(acc, v, i) {
- return throwRangeErrorReduce(v, i);
- };
- describe('#forEach()', function () {
- it('uses ToLength to clamp negative values to zero', function () {
- expect(function () {
- Array.prototype.forEach.call(negativeLength, throwRangeError);
- }).not.to['throw']();
- });
- });
- describe('#map()', function () {
- it('uses ToLength to clamp negative values to zero', function () {
- var mapped;
- expect(function () {
- mapped = Array.prototype.map.call(negativeLength, throwRangeError);
- }).not.to['throw']();
- expect(mapped).to.eql([]);
- });
- });
- describe('#filter()', function () {
- it('uses ToLength to clamp negative values to zero', function () {
- var filtered;
- expect(function () {
- filtered = Array.prototype.filter.call(negativeLength, throwRangeError);
- }).not.to['throw']();
- expect(filtered).to.eql([]);
- });
- });
- describe('#some()', function () {
- it('uses ToLength to clamp negative values to zero', function () {
- var result;
- expect(function () {
- result = Array.prototype.some.call(negativeLength, throwRangeError);
- }).not.to['throw']();
- expect(result).to.equal([].some(Object));
- });
- });
- describe('#every()', function () {
- it('uses ToLength to clamp negative values to zero', function () {
- var result;
- expect(function () {
- result = Array.prototype.every.call(negativeLength, throwRangeError);
- }).not.to['throw']();
- expect(result).to.equal([].every(Object));
- });
- });
- describe('#reduce()', function () {
- it('uses ToLength to clamp negative values to zero', function () {
- var accumulator = {};
- var reduced;
- expect(function () {
- reduced = Array.prototype.reduce.call(negativeLength, throwRangeErrorReduce, accumulator);
- }).not.to['throw']();
- expect(reduced).to.equal(accumulator);
- });
- });
- describe('#reduceRight()', function () {
- it('uses ToLength to clamp negative values to zero', function () {
- var negativeOneToUint32minusOne = (-1 >>> 0) - 1;
- var obj = { length: -1 };
- obj[negativeOneToUint32minusOne] = true;
- var accumulator = {};
- var reduced;
- expect(function () {
- reduced = Array.prototype.reduceRight.call(obj, throwRangeErrorReduce, accumulator);
- }).not.to['throw']();
- expect(reduced).to.equal(accumulator);
- });
- });
- describe('#indexOf()', function () {
- it('converts second argument from -0 to +0', function () {
- expect(isNegativeZero([true].indexOf(true, -0))).to.equal(false);
- });
- });
- });
- };
- describe('clean Object.prototype', function () {
- 'use strict';
- runArrayTests.call(this, it);
- });
- describe('polluted Object.prototype', function () {
- 'use strict';
- var shimmedIt = function () {
- /* eslint-disable no-extend-native */
- Object.prototype[1] = 42;
- /* eslint-enable no-extend-native */
- it.apply(this, arguments);
- delete Object.prototype[1];
- };
- shimmedIt.skip = it.skip;
- return runArrayTests.call(this, shimmedIt);
- });
|