Bones/node_modules/es6-shim/test/array.js

1038 lines
37 KiB
JavaScript
Raw Normal View History

2017-05-17 13:45:25 -04:00
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 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 () {
/*jshint elision: true */
/* jscs:disable disallowSpaceBeforeComma */
/* jscs:disable requireSpaceAfterComma */
/* eslint-disable no-sparse-arrays */
var input = [0, , 2];
var result = Array.from([0, , 2]);
/* eslint-enable no-sparse-arrays */
/* jscs:enable requireSpaceAfterComma */
/* jscs:enable disallowSpaceBeforeComma */
/*jshint elision: false */
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 () {},
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 () {
/* jshint elision: true */
/* jscs:disable disallowSpaceBeforeComma */
/* jscs:disable requireSpaceAfterComma */
/* eslint-disable no-sparse-arrays */
expect([, 1, 2].copyWithin(1, 0)).to.eql([, , 1]);
/* jshint elision: false */
/* jscs:enable requireSpaceAfterComma */
/* jscs:enable disallowSpaceBeforeComma */
/* 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 });
});
});
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 () {
/*jshint elision: true */
/* jscs:disable disallowSpaceBeforeComma */
/* jscs:disable requireSpaceAfterComma */
/* eslint-disable no-sparse-arrays */
var obj = [1, , undefined];
/* eslint-enable no-sparse-arrays */
/* jscs:enable requireSpaceAfterComma */
/* jscs:enable disallowSpaceBeforeComma */
/*jshint elision: false */
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 () {
/*jshint elision: true */
/* jscs:disable disallowSpaceBeforeComma */
/* jscs:disable requireSpaceAfterComma */
/* eslint-disable no-sparse-arrays */
var obj = [1, , undefined];
/* eslint-enable no-sparse-arrays */
/* jscs:enable requireSpaceAfterComma */
/* jscs:enable disallowSpaceBeforeComma */
/*jshint elision: false */
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);
});