Source code

Revision control

Copy as Markdown

Other Tools

// |reftest| shell-option(--enable-iterator-range) skip-if(!Iterator.hasOwnProperty('range'))
/*---
features: [Iterator.range]
---*/
// Invalid start parameter types
assertThrowsInstanceOf(() => Iterator.range('1'), TypeError);
assertThrowsInstanceOf(() => Iterator.range(null), TypeError);
assertThrowsInstanceOf(() => Iterator.range(undefined), TypeError);
assertThrowsInstanceOf(() => Iterator.range({}), TypeError);
assertThrowsInstanceOf(() => Iterator.range([]), TypeError);
assertThrowsInstanceOf(() => Iterator.range(true), TypeError);
assertThrowsInstanceOf(() => Iterator.range(Symbol()), TypeError);
// Invalid end parameter types
assertThrowsInstanceOf(() => Iterator.range(0, '1'), TypeError);
assertThrowsInstanceOf(() => Iterator.range(0, null), TypeError);
assertThrowsInstanceOf(() => Iterator.range(0, undefined), TypeError);
assertThrowsInstanceOf(() => Iterator.range(0, {}), TypeError);
assertThrowsInstanceOf(() => Iterator.range(0, []), TypeError);
assertThrowsInstanceOf(() => Iterator.range(0, true), TypeError);
assertThrowsInstanceOf(() => Iterator.range(0, Symbol()), TypeError);
// Invalid step parameter types
assertThrowsInstanceOf(() => Iterator.range(0, 10, '1'), TypeError);
assertThrowsInstanceOf(() => Iterator.range(0, 10, true), TypeError);
assertThrowsInstanceOf(() => Iterator.range(0, 10, Symbol()), TypeError);
// NaN and Infinity tests
assertThrowsInstanceOf(() => Iterator.range(NaN), RangeError);
assertThrowsInstanceOf(() => Iterator.range(0, NaN), RangeError);
assertThrowsInstanceOf(() => Iterator.range(Infinity), TypeError);
// Step type and value tests
assertThrowsInstanceOf(() => Iterator.range(0, 10, NaN), RangeError);
assertThrowsInstanceOf(() => Iterator.range(0, 10, Infinity), RangeError);
// Zero step tests
assertThrowsInstanceOf(() => Iterator.range(0, 10, 0), RangeError);
Iterator.range(0, 0, 0);
// Step configuration object tests
Iterator.range(0, 10, { step: 2 });
Iterator.range(0, 10, { step: -1 });
Iterator.range(0, 10, { inclusiveEnd: true });
assertThrowsInstanceOf(() => Iterator.range(0, 10, { step: '2' }), TypeError);
// Basic number inputs
Iterator.range(0, 10);
Iterator.range(0, 10, 2);
// Basic sequences with increasing steps of 1
const result1 = Array.from(Iterator.range(0, 10));
assertDeepEq(result1, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
const result2 = Array.from(Iterator.range(2, 6));
assertDeepEq(result2, [2, 3, 4, 5]);
// Test empty range
const result3 = Array.from(Iterator.range(0, 0));
assertDeepEq(result3, []);
const result4 = Array.from(Iterator.range(5, 5));
assertDeepEq(result4, []);
// testing reverse range
const result5 = Array.from(Iterator.range(10, 0, -2));
assertDeepEq(result5, [10, 8, 6, 4, 2]);
// inclusive end
const result6 = Array.from(Iterator.range(0, 10, { step: 2, inclusiveEnd: true }));
assertDeepEq(result6, [0, 2, 4, 6, 8, 10]);
// overlapping step with range limits
const result7 = Array.from(Iterator.range(0, 10, 15));
assertDeepEq(result7, [0]);
// negative numbers in the range
const result8 = Array.from(Iterator.range(-10, 0));
assertDeepEq(result8, [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1]);
// floating point
const resultFloat1 = Array.from(Iterator.range(0.5, 3.5));
assertDeepEq(resultFloat1, [0.5, 1.5, 2.5]);
const resultFloat3 = Array.from(Iterator.range(0, 0.3, 0.1));
assertDeepEq(resultFloat3, [0, 0.1, 0.2]);
// floating point precision
function approximatelyEqual(a, b) {
// If inputs are arrays, compare each element
if (Array.isArray(a) && Array.isArray(b)) {
assertEq(a.length, b.length);
// Compare each element
for (let i = 0; i < a.length; i++) {
approximatelyEqual(a[i], b[i]);
}
return true;
}
// For single numbers
var r = (a != a && b != b) || Math.abs(a - b) < 0.001;
if (!r) {
print('Got', a, ', to be approximately equal to', b);
assertEq(false, true);
}
return true;
}
const resultFloat2 = Array.from(Iterator.range(0, 1, 0.2));
approximatelyEqual(resultFloat2, [0, 0.2, 0.4, 0.6, 0.8]);
const resultStep2 = Array.from(Iterator.range(0, 10, 3.3));
approximatelyEqual(resultStep2, [0, 3.3, 6.6, 9.9]);
// invalid mixed-type parameters
assertThrowsInstanceOf(() => Iterator.range(0, 10, { step: NaN, inclusiveEnd: true }), RangeError);
// bigint
Iterator.range(0n, 10n);
Iterator.range(0n, 10n, 2n);
const bigintResult1 = Array.from(Iterator.range(0n, 5n));
assertDeepEq(bigintResult1, [0n, 1n, 2n, 3n, 4n]);
const bigintResult2 = Array.from(Iterator.range(0n, 10n, 2n));
assertDeepEq(bigintResult2, [0n, 2n, 4n, 6n, 8n]);
// inclusive end with BigInt
const bigintResult3 = Array.from(Iterator.range(0n, 5n, { step: 2n, inclusiveEnd: true }));
assertDeepEq(bigintResult3, [0n, 2n, 4n]);
// empty BigInt range
const bigintResult4 = Array.from(Iterator.range(0n, 0n));
assertDeepEq(bigintResult4, []);
// negative step with BigInt
const bigintResult5 = Array.from(Iterator.range(5n, 0n, -1n));
assertDeepEq(bigintResult5, [5n, 4n, 3n, 2n, 1n]);
// test invalid this
const invalidValues = [
null,
undefined,
42,
'string',
true,
{},
Symbol('test'),
[],
new Date()
];
const iterator = Iterator.range(0, 10);
invalidValues.forEach(value => {
assertThrowsInstanceOf(() => {
iterator.next.call(value);
}, TypeError, `Should throw TypeError for ${typeof value}`);
});
// this value is a valid iterator object from another compartment
const g = newGlobal({ newCompartment: true });
const localIterator = Iterator.range(0, 10);
const otherIterator = g.eval("Iterator.range(0, 10)");
const result = localIterator.next.call(otherIterator);
assertEq(typeof result, 'object');
assertEq(result.value, 0);
assertEq(result.done, false);
// infinite tests for iterator sequences
const infiniteRange = Iterator.range(0, Infinity);
assertEq(typeof infiniteRange.next, 'function');
const first = infiniteRange.next();
assertEq(first.value, 0);
assertEq(infiniteRange.next().value, 1);
assertEq(first.done, false);
// negative infinity
const negativeInfiniteRange = Iterator.range(0, -Infinity, -1);
assertEq(negativeInfiniteRange.next().value, 0);
assertEq(negativeInfiniteRange.next().value, -1);
assertEq(negativeInfiniteRange.next().value, -2);
// steps
const stepRange = Iterator.range(0, Infinity, 2);
assertEq(stepRange.next().value, 0);
assertEq(stepRange.next().value, 2);
assertEq(stepRange.next().value, 4);
// test with an option object
const options = Iterator.range(0, Infinity, { step: 3 });
assertEq(options.next().value, 0);
assertEq(options.next().value, 3);
assertEq(options.next().value, 6);
// test that inclusive end is ignored for infinite ranges
const infiniteRangeInclusive = Iterator.range(0, Infinity, { inclusiveEnd: true });
assertEq(infiniteRangeInclusive.next().value, 0);
assertEq(infiniteRangeInclusive.next().value, 1);
// test negative infinity with inclusive end
const negativeInfiniteRangeInclusive = Iterator.range(0, -Infinity, -1, { inclusiveEnd: true });
assertEq(negativeInfiniteRangeInclusive.next().value, 0);
assertEq(negativeInfiniteRangeInclusive.next().value, -1);
assertEq(negativeInfiniteRangeInclusive.next().value, -2);
// test negative infinity with step and inclusive end
const negativeInfiniteRangeStepInclusive = Iterator.range(0, -Infinity, -2, { inclusiveEnd: true });
assertEq(negativeInfiniteRangeStepInclusive.next().value, 0);
assertEq(negativeInfiniteRangeStepInclusive.next().value, -2);
// bigint and infinite range
assertThrowsInstanceOf(() => Iterator.range(0n, Infinity), TypeError);
assertThrowsInstanceOf(() => Iterator.range(0n, -Infinity), TypeError);
assertThrowsInstanceOf(() => Iterator.range(0, Infinity, 2n), TypeError);
assertThrowsInstanceOf(() => Iterator.range(0, 10, Infinity), RangeError);
if (typeof reportCompare === 'function')
reportCompare(0, 0);