range.js (7867B)
1 // |reftest| shell-option(--enable-iterator-range) skip-if(!Iterator.hasOwnProperty('range')) 2 3 /*--- 4 features: [Iterator.range] 5 ---*/ 6 7 // Invalid start parameter types 8 assertThrowsInstanceOf(() => Iterator.range('1'), TypeError); 9 assertThrowsInstanceOf(() => Iterator.range(null), TypeError); 10 assertThrowsInstanceOf(() => Iterator.range(undefined), TypeError); 11 assertThrowsInstanceOf(() => Iterator.range({}), TypeError); 12 assertThrowsInstanceOf(() => Iterator.range([]), TypeError); 13 assertThrowsInstanceOf(() => Iterator.range(true), TypeError); 14 assertThrowsInstanceOf(() => Iterator.range(Symbol()), TypeError); 15 16 // Invalid end parameter types 17 assertThrowsInstanceOf(() => Iterator.range(0, '1'), TypeError); 18 assertThrowsInstanceOf(() => Iterator.range(0, null), TypeError); 19 assertThrowsInstanceOf(() => Iterator.range(0, undefined), TypeError); 20 assertThrowsInstanceOf(() => Iterator.range(0, {}), TypeError); 21 assertThrowsInstanceOf(() => Iterator.range(0, []), TypeError); 22 assertThrowsInstanceOf(() => Iterator.range(0, true), TypeError); 23 assertThrowsInstanceOf(() => Iterator.range(0, Symbol()), TypeError); 24 25 // Invalid step parameter types 26 assertThrowsInstanceOf(() => Iterator.range(0, 10, '1'), TypeError); 27 assertThrowsInstanceOf(() => Iterator.range(0, 10, true), TypeError); 28 assertThrowsInstanceOf(() => Iterator.range(0, 10, Symbol()), TypeError); 29 30 // NaN and Infinity tests 31 assertThrowsInstanceOf(() => Iterator.range(NaN), RangeError); 32 assertThrowsInstanceOf(() => Iterator.range(0, NaN), RangeError); 33 assertThrowsInstanceOf(() => Iterator.range(Infinity), TypeError); 34 35 // Step type and value tests 36 assertThrowsInstanceOf(() => Iterator.range(0, 10, NaN), RangeError); 37 assertThrowsInstanceOf(() => Iterator.range(0, 10, Infinity), RangeError); 38 39 // Zero step tests 40 assertThrowsInstanceOf(() => Iterator.range(0, 10, 0), RangeError); 41 Iterator.range(0, 0, 0); 42 43 // Step configuration object tests 44 Iterator.range(0, 10, { step: 2 }); 45 Iterator.range(0, 10, { step: -1 }); 46 Iterator.range(0, 10, { inclusiveEnd: true }); 47 assertThrowsInstanceOf(() => Iterator.range(0, 10, { step: '2' }), TypeError); 48 49 // Basic number inputs 50 Iterator.range(0, 10); 51 Iterator.range(0, 10, 2); 52 53 54 // Basic sequences with increasing steps of 1 55 const result1 = Array.from(Iterator.range(0, 10)); 56 assertDeepEq(result1, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); 57 58 const result2 = Array.from(Iterator.range(2, 6)); 59 assertDeepEq(result2, [2, 3, 4, 5]); 60 61 // Test empty range 62 const result3 = Array.from(Iterator.range(0, 0)); 63 assertDeepEq(result3, []); 64 65 const result4 = Array.from(Iterator.range(5, 5)); 66 assertDeepEq(result4, []); 67 68 // testing reverse range 69 const result5 = Array.from(Iterator.range(10, 0, -2)); 70 assertDeepEq(result5, [10, 8, 6, 4, 2]); 71 72 // inclusive end 73 const result6 = Array.from(Iterator.range(0, 10, { step: 2, inclusiveEnd: true })); 74 assertDeepEq(result6, [0, 2, 4, 6, 8, 10]); 75 76 // overlapping step with range limits 77 const result7 = Array.from(Iterator.range(0, 10, 15)); 78 assertDeepEq(result7, [0]); 79 80 // negative numbers in the range 81 const result8 = Array.from(Iterator.range(-10, 0)); 82 assertDeepEq(result8, [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1]); 83 84 // floating point 85 const resultFloat1 = Array.from(Iterator.range(0.5, 3.5)); 86 assertDeepEq(resultFloat1, [0.5, 1.5, 2.5]); 87 88 const resultFloat3 = Array.from(Iterator.range(0, 0.3, 0.1)); 89 assertDeepEq(resultFloat3, [0, 0.1, 0.2]); 90 91 92 // floating point precision 93 function approximatelyEqual(a, b) { 94 // If inputs are arrays, compare each element 95 if (Array.isArray(a) && Array.isArray(b)) { 96 assertEq(a.length, b.length); 97 // Compare each element 98 for (let i = 0; i < a.length; i++) { 99 approximatelyEqual(a[i], b[i]); 100 } 101 return true; 102 } 103 104 // For single numbers 105 var r = (a != a && b != b) || Math.abs(a - b) < 0.001; 106 if (!r) { 107 print('Got', a, ', to be approximately equal to', b); 108 assertEq(false, true); 109 } 110 return true; 111 } 112 113 const resultFloat2 = Array.from(Iterator.range(0, 1, 0.2)); 114 approximatelyEqual(resultFloat2, [0, 0.2, 0.4, 0.6, 0.8]); 115 116 const resultStep2 = Array.from(Iterator.range(0, 10, 3.3)); 117 approximatelyEqual(resultStep2, [0, 3.3, 6.6, 9.9]); 118 119 // invalid mixed-type parameters 120 assertThrowsInstanceOf(() => Iterator.range(0, 10, { step: NaN, inclusiveEnd: true }), RangeError); 121 122 // bigint 123 Iterator.range(0n, 10n); 124 Iterator.range(0n, 10n, 2n); 125 126 const bigintResult1 = Array.from(Iterator.range(0n, 5n)); 127 assertDeepEq(bigintResult1, [0n, 1n, 2n, 3n, 4n]); 128 129 const bigintResult2 = Array.from(Iterator.range(0n, 10n, 2n)); 130 assertDeepEq(bigintResult2, [0n, 2n, 4n, 6n, 8n]); 131 132 // inclusive end with BigInt 133 const bigintResult3 = Array.from(Iterator.range(0n, 5n, { step: 2n, inclusiveEnd: true })); 134 assertDeepEq(bigintResult3, [0n, 2n, 4n]); 135 136 // empty BigInt range 137 const bigintResult4 = Array.from(Iterator.range(0n, 0n)); 138 assertDeepEq(bigintResult4, []); 139 140 // negative step with BigInt 141 const bigintResult5 = Array.from(Iterator.range(5n, 0n, -1n)); 142 assertDeepEq(bigintResult5, [5n, 4n, 3n, 2n, 1n]); 143 144 145 // test invalid this 146 const invalidValues = [ 147 null, 148 undefined, 149 42, 150 'string', 151 true, 152 {}, 153 Symbol('test'), 154 [], 155 new Date() 156 ]; 157 158 const iterator = Iterator.range(0, 10); 159 160 invalidValues.forEach(value => { 161 assertThrowsInstanceOf(() => { 162 iterator.next.call(value); 163 }, TypeError, `Should throw TypeError for ${typeof value}`); 164 }); 165 166 // this value is a valid iterator object from another compartment 167 const g = newGlobal({ newCompartment: true }); 168 const localIterator = Iterator.range(0, 10); 169 const otherIterator = g.eval("Iterator.range(0, 10)"); 170 171 const result = localIterator.next.call(otherIterator); 172 173 assertEq(typeof result, 'object'); 174 assertEq(result.value, 0); 175 assertEq(result.done, false); 176 177 // infinite tests for iterator sequences 178 const infiniteRange = Iterator.range(0, Infinity); 179 assertEq(typeof infiniteRange.next, 'function'); 180 181 const first = infiniteRange.next(); 182 assertEq(first.value, 0); 183 assertEq(infiniteRange.next().value, 1); 184 assertEq(first.done, false); 185 186 // negative infinity 187 const negativeInfiniteRange = Iterator.range(0, -Infinity, -1); 188 assertEq(negativeInfiniteRange.next().value, 0); 189 assertEq(negativeInfiniteRange.next().value, -1); 190 assertEq(negativeInfiniteRange.next().value, -2); 191 192 // steps 193 const stepRange = Iterator.range(0, Infinity, 2); 194 assertEq(stepRange.next().value, 0); 195 assertEq(stepRange.next().value, 2); 196 assertEq(stepRange.next().value, 4); 197 198 // test with an option object 199 const options = Iterator.range(0, Infinity, { step: 3 }); 200 assertEq(options.next().value, 0); 201 assertEq(options.next().value, 3); 202 assertEq(options.next().value, 6); 203 204 // test that inclusive end is ignored for infinite ranges 205 const infiniteRangeInclusive = Iterator.range(0, Infinity, { inclusiveEnd: true }); 206 assertEq(infiniteRangeInclusive.next().value, 0); 207 assertEq(infiniteRangeInclusive.next().value, 1); 208 209 // test negative infinity with inclusive end 210 const negativeInfiniteRangeInclusive = Iterator.range(0, -Infinity, -1, { inclusiveEnd: true }); 211 assertEq(negativeInfiniteRangeInclusive.next().value, 0); 212 assertEq(negativeInfiniteRangeInclusive.next().value, -1); 213 assertEq(negativeInfiniteRangeInclusive.next().value, -2); 214 215 // test negative infinity with step and inclusive end 216 const negativeInfiniteRangeStepInclusive = Iterator.range(0, -Infinity, -2, { inclusiveEnd: true }); 217 assertEq(negativeInfiniteRangeStepInclusive.next().value, 0); 218 assertEq(negativeInfiniteRangeStepInclusive.next().value, -2); 219 220 // bigint and infinite range 221 assertThrowsInstanceOf(() => Iterator.range(0n, Infinity), TypeError); 222 assertThrowsInstanceOf(() => Iterator.range(0n, -Infinity), TypeError); 223 assertThrowsInstanceOf(() => Iterator.range(0, Infinity, 2n), TypeError); 224 assertThrowsInstanceOf(() => Iterator.range(0, 10, Infinity), RangeError); 225 226 227 if (typeof reportCompare === 'function') 228 reportCompare(0, 0);