fix: throw TypeError for non-integral Infinity chunk/window size in Iterator.prototype.chunks/windows

The Iterator Chunking proposal requires a TypeError when the size is not
an integral Number before the [1, 2^32-1] RangeError check. ECMA-262
defines an integral Number as finite, so +/-Infinity is not integral and
must throw TypeError. The previous guard used Math.floor(size) !== size,
which is false for Infinity (Math.floor(Infinity) === Infinity), letting
+/-Infinity fall through to the range check and throw RangeError instead.

Use the finite-aware isIntegralNumber helper so +/-Infinity yields
TypeError, while -0/0/-1/2^32/2^53 keep throwing RangeError and valid
sizes in [1, 2^32-1] still pass.
This commit is contained in:
Yarchik
2026-07-01 23:42:39 +01:00
parent 6349b6aa7d
commit 852f979165
5 changed files with 10 additions and 2 deletions
@@ -1,14 +1,14 @@
'use strict';
var isIntegralNumber = require('../internals/is-integral-number');
var iteratorClose = require('../internals/iterator-close');
var $RangeError = RangeError;
var $TypeError = TypeError;
var floor = Math.floor;
var CHUNK_SIZE_VALIDATION_ERROR = 'Chunk size must be an integer in [1, 2^32-1]';
module.exports = function (chunkSize, iterator) {
if (typeof chunkSize != 'number' || floor(chunkSize) !== chunkSize) {
if (typeof chunkSize != 'number' || !isIntegralNumber(chunkSize)) {
return iteratorClose(iterator, 'throw', new $TypeError(CHUNK_SIZE_VALIDATION_ERROR));
}
if (chunkSize === 0 || chunkSize >>> 0 !== chunkSize) {
@@ -35,6 +35,8 @@ QUnit.test('Iterator#chunks', assert => {
assert.throws(() => chunks.call(it), TypeError, 'throws on empty argument');
assert.throws(() => chunks.call(it, '2'), TypeError, 'throws on empty argument');
assert.throws(() => chunks.call(it, 2.1), TypeError, 'throws on empty argument');
assert.throws(() => chunks.call(it, Infinity), TypeError, 'throws a TypeError on non-integral Infinity argument');
assert.throws(() => chunks.call(it, -Infinity), TypeError, 'throws a TypeError on non-integral -Infinity argument');
assert.throws(() => chunks.call(it, -1), RangeError, 'throws on negative argument');
assert.throws(() => chunks.call(it, 2 ** 32), RangeError, 'throws on negative argument');
@@ -39,6 +39,8 @@ QUnit.test('Iterator#windows', assert => {
assert.throws(() => windows.call(it), TypeError, 'throws on empty argument');
assert.throws(() => windows.call(it, '2'), TypeError, 'throws on empty argument');
assert.throws(() => windows.call(it, 2.1), TypeError, 'throws on empty argument');
assert.throws(() => windows.call(it, Infinity), TypeError, 'throws a TypeError on non-integral Infinity argument');
assert.throws(() => windows.call(it, -Infinity), TypeError, 'throws a TypeError on non-integral -Infinity argument');
assert.throws(() => windows.call(it, -1), RangeError, 'throws on negative argument');
assert.throws(() => windows.call(it, 2 ** 32), RangeError, 'throws on negative argument');
@@ -34,6 +34,8 @@ QUnit.test('Iterator#chunks', assert => {
assert.throws(() => chunks.call(it), TypeError, 'throws on empty argument');
assert.throws(() => chunks.call(it, '2'), TypeError, 'throws on empty argument');
assert.throws(() => chunks.call(it, 2.1), TypeError, 'throws on empty argument');
assert.throws(() => chunks.call(it, Infinity), TypeError, 'throws a TypeError on non-integral Infinity argument');
assert.throws(() => chunks.call(it, -Infinity), TypeError, 'throws a TypeError on non-integral -Infinity argument');
assert.throws(() => chunks.call(it, -1), RangeError, 'throws on negative argument');
assert.throws(() => chunks.call(it, 2 ** 32), RangeError, 'throws on negative argument');
@@ -38,6 +38,8 @@ QUnit.test('Iterator#windows', assert => {
assert.throws(() => windows.call(it), TypeError, 'throws on empty argument');
assert.throws(() => windows.call(it, '2'), TypeError, 'throws on empty argument');
assert.throws(() => windows.call(it, 2.1), TypeError, 'throws on empty argument');
assert.throws(() => windows.call(it, Infinity), TypeError, 'throws a TypeError on non-integral Infinity argument');
assert.throws(() => windows.call(it, -Infinity), TypeError, 'throws a TypeError on non-integral -Infinity argument');
assert.throws(() => windows.call(it, -1), RangeError, 'throws on negative argument');
assert.throws(() => windows.call(it, 2 ** 32), RangeError, 'throws on negative argument');