Skip to content

Commit

Permalink
add counter argument to iterator helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
zloirock committed Oct 20, 2022
1 parent 3e18cd0 commit c8d22f6
Show file tree
Hide file tree
Showing 26 changed files with 69 additions and 40 deletions.
1 change: 1 addition & 0 deletions packages/core-js/internals/iterator-create-proxy.js
Expand Up @@ -75,6 +75,7 @@ module.exports = function (nextHandler, IS_ITERATOR) {
} else state = record;
state.type = ITERATOR_PROXY;
state.nextHandler = nextHandler;
state.counter = 0;
state.done = false;
setInternalState(this, state);
};
Expand Down
3 changes: 2 additions & 1 deletion packages/core-js/modules/esnext.iterator.every.js
Expand Up @@ -8,9 +8,10 @@ var getIteratorDirect = require('../internals/get-iterator-direct');
$({ target: 'Iterator', proto: true, real: true, forced: true }, {
every: function every(fn) {
var record = getIteratorDirect(this);
var counter = 0;
aCallable(fn);
return !iterate(record, function (value, stop) {
if (!fn(value)) return stop();
if (!fn(value, counter++)) return stop();
}, { IS_RECORD: true, INTERRUPTED: true }).stopped;
}
});
2 changes: 1 addition & 1 deletion packages/core-js/modules/esnext.iterator.filter.js
Expand Up @@ -18,7 +18,7 @@ var IteratorProxy = createIteratorProxy(function () {
done = this.done = !!result.done;
if (done) return;
value = result.value;
if (callWithSafeIterationClosing(iterator, filterer, value)) return value;
if (callWithSafeIterationClosing(iterator, filterer, [value, this.counter++], true)) return value;
}
});

Expand Down
3 changes: 2 additions & 1 deletion packages/core-js/modules/esnext.iterator.find.js
Expand Up @@ -8,9 +8,10 @@ var getIteratorDirect = require('../internals/get-iterator-direct');
$({ target: 'Iterator', proto: true, real: true, forced: true }, {
find: function find(fn) {
var record = getIteratorDirect(this);
var counter = 0;
aCallable(fn);
return iterate(record, function (value, stop) {
if (fn(value)) return stop(value);
if (fn(value, counter++)) return stop(value);
}, { IS_RECORD: true, INTERRUPTED: true }).result;
}
});
2 changes: 1 addition & 1 deletion packages/core-js/modules/esnext.iterator.flat-map.js
Expand Up @@ -28,7 +28,7 @@ var IteratorProxy = createIteratorProxy(function () {
if (this.done = !!result.done) return;

try {
mapped = mapper(result.value);
mapped = mapper(result.value, this.counter++);
iteratorMethod = getIteratorMethod(mapped);

if (!iteratorMethod) {
Expand Down
8 changes: 7 additions & 1 deletion packages/core-js/modules/esnext.iterator.for-each.js
Expand Up @@ -2,10 +2,16 @@
// https://github.com/tc39/proposal-iterator-helpers
var $ = require('../internals/export');
var iterate = require('../internals/iterate');
var aCallable = require('../internals/a-callable');
var getIteratorDirect = require('../internals/get-iterator-direct');

$({ target: 'Iterator', proto: true, real: true, forced: true }, {
forEach: function forEach(fn) {
iterate(getIteratorDirect(this), fn, { IS_RECORD: true });
var record = getIteratorDirect(this);
var counter = 0;
aCallable(fn);
iterate(record, function (value) {
fn(value, counter++);
}, { IS_RECORD: true });
}
});
1 change: 1 addition & 0 deletions packages/core-js/modules/esnext.iterator.indexed.js
@@ -1,3 +1,4 @@
// TODO: Remove from `core-js@4`
// https://github.com/tc39/proposal-iterator-helpers
var $ = require('../internals/export');
var indexed = require('../internals/iterator-indexed');
Expand Down
2 changes: 1 addition & 1 deletion packages/core-js/modules/esnext.iterator.map.js
Expand Up @@ -12,7 +12,7 @@ var IteratorProxy = createIteratorProxy(function () {
var iterator = this.iterator;
var result = anObject(call(this.next, iterator));
var done = this.done = !!result.done;
if (!done) return callWithSafeIterationClosing(iterator, this.mapper, result.value);
if (!done) return callWithSafeIterationClosing(iterator, this.mapper, [result.value, this.counter++], true);
});

$({ target: 'Iterator', proto: true, real: true, forced: true }, {
Expand Down
4 changes: 3 additions & 1 deletion packages/core-js/modules/esnext.iterator.reduce.js
Expand Up @@ -13,13 +13,15 @@ $({ target: 'Iterator', proto: true, real: true, forced: true }, {
aCallable(reducer);
var noInitial = arguments.length < 2;
var accumulator = noInitial ? undefined : arguments[1];
var counter = 0;
iterate(record, function (value) {
if (noInitial) {
noInitial = false;
accumulator = value;
} else {
accumulator = reducer(accumulator, value);
accumulator = reducer(accumulator, value, counter);
}
counter++;
}, { IS_RECORD: true });
if (noInitial) throw $TypeError('Reduce of empty iterator with no initial value');
return accumulator;
Expand Down
3 changes: 2 additions & 1 deletion packages/core-js/modules/esnext.iterator.some.js
Expand Up @@ -8,9 +8,10 @@ var getIteratorDirect = require('../internals/get-iterator-direct');
$({ target: 'Iterator', proto: true, real: true, forced: true }, {
some: function some(fn) {
var record = getIteratorDirect(this);
var counter = 0;
aCallable(fn);
return iterate(record, function (value, stop) {
if (fn(value)) return stop();
if (fn(value, counter++)) return stop();
}, { IS_RECORD: true, INTERRUPTED: true }).stopped;
}
});
5 changes: 3 additions & 2 deletions tests/pure/esnext.iterator.every.js
Expand Up @@ -12,10 +12,11 @@ QUnit.test('Iterator#every', assert => {

assert.true(every.call(createIterator([1, 2, 3]), it => typeof it == 'number'), 'basic functionality #1');
assert.false(every.call(createIterator([1, 2, 3]), it => it % 2), 'basic functionality #2');
every.call(createIterator([1]), function (arg) {
every.call(createIterator([1]), function (arg, counter) {
assert.same(this, STRICT_THIS, 'this');
assert.same(arguments.length, 1, 'arguments length');
assert.same(arguments.length, 2, 'arguments length');
assert.same(arg, 1, 'argument');
assert.same(counter, 0, 'counter');
});

assert.throws(() => every.call(undefined, () => { /* empty */ }), TypeError);
Expand Down
5 changes: 3 additions & 2 deletions tests/pure/esnext.iterator.filter.js
Expand Up @@ -11,10 +11,11 @@ QUnit.test('Iterator#filter', assert => {
assert.nonEnumerable(Iterator.prototype, 'filter');

assert.arrayEqual(filter.call(createIterator([1, 2, 3]), it => it % 2).toArray(), [1, 3], 'basic functionality');
filter.call(createIterator([1]), function (arg) {
filter.call(createIterator([1]), function (arg, counter) {
assert.same(this, STRICT_THIS, 'this');
assert.same(arguments.length, 1, 'arguments length');
assert.same(arguments.length, 2, 'arguments length');
assert.same(arg, 1, 'argument');
assert.same(counter, 0, 'counter');
}).toArray();

assert.throws(() => filter.call(undefined, () => { /* empty */ }), TypeError);
Expand Down
5 changes: 3 additions & 2 deletions tests/pure/esnext.iterator.find.js
Expand Up @@ -11,10 +11,11 @@ QUnit.test('Iterator#find', assert => {
assert.nonEnumerable(Iterator.prototype, 'find');

assert.same(find.call(createIterator([1, 2, 3]), it => !(it % 2)), 2, 'basic functionality');
find.call(createIterator([1]), function (arg) {
find.call(createIterator([1]), function (arg, counter) {
assert.same(this, STRICT_THIS, 'this');
assert.same(arguments.length, 1, 'arguments length');
assert.same(arguments.length, 2, 'arguments length');
assert.same(arg, 1, 'argument');
assert.same(counter, 0, 'counter');
});

assert.throws(() => find.call(undefined, () => { /* empty */ }), TypeError);
Expand Down
5 changes: 3 additions & 2 deletions tests/pure/esnext.iterator.flat-map.js
Expand Up @@ -15,10 +15,11 @@ QUnit.test('Iterator#flatMap', assert => {
[-1, -2, 3, 4, 5, 6, 'a', 'b'],
'basic functionality',
);
flatMap.call(createIterator([1]), function (arg) {
flatMap.call(createIterator([1]), function (arg, counter) {
assert.same(this, STRICT_THIS, 'this');
assert.same(arguments.length, 1, 'arguments length');
assert.same(arguments.length, 2, 'arguments length');
assert.same(arg, 1, 'argument');
assert.same(counter, 0, 'counter');
return [arg];
}).toArray();

Expand Down
5 changes: 3 additions & 2 deletions tests/pure/esnext.iterator.for-each.js
Expand Up @@ -16,10 +16,11 @@ QUnit.test('Iterator#forEach', assert => {

assert.arrayEqual(array, [1, 2, 3], 'basic functionality');

forEach.call(createIterator([1]), function (arg) {
forEach.call(createIterator([1]), function (arg, counter) {
assert.same(this, STRICT_THIS, 'this');
assert.same(arguments.length, 1, 'arguments length');
assert.same(arguments.length, 2, 'arguments length');
assert.same(arg, 1, 'argument');
assert.same(counter, 0, 'counter');
});

assert.throws(() => forEach.call(undefined, () => { /* empty */ }), TypeError);
Expand Down
5 changes: 3 additions & 2 deletions tests/pure/esnext.iterator.map.js
Expand Up @@ -11,10 +11,11 @@ QUnit.test('Iterator#map', assert => {
assert.nonEnumerable(Iterator.prototype, 'map');

assert.arrayEqual(map.call(createIterator([1, 2, 3]), it => it ** 2).toArray(), [1, 4, 9], 'basic functionality');
map.call(createIterator([1]), function (arg) {
map.call(createIterator([1]), function (arg, counter) {
assert.same(this, STRICT_THIS, 'this');
assert.same(arguments.length, 1, 'arguments length');
assert.same(arguments.length, 2, 'arguments length');
assert.same(arg, 1, 'argument');
assert.same(counter, 0, 'counter');
}).toArray();

assert.throws(() => map.call(undefined, () => { /* empty */ }), TypeError);
Expand Down
5 changes: 3 additions & 2 deletions tests/pure/esnext.iterator.reduce.js
Expand Up @@ -12,11 +12,12 @@ QUnit.test('Iterator#reduce', assert => {

assert.same(reduce.call(createIterator([1, 2, 3]), (a, b) => a + b, 1), 7, 'basic functionality');
assert.same(reduce.call(createIterator([1, 2, 3]), (a, b) => a + b), 6, 'basic functionality, no init');
reduce.call(createIterator([2]), function (a, b) {
reduce.call(createIterator([2]), function (a, b, counter) {
assert.same(this, STRICT_THIS, 'this');
assert.same(arguments.length, 2, 'arguments length');
assert.same(arguments.length, 3, 'arguments length');
assert.same(a, 1, 'argument 1');
assert.same(b, 2, 'argument 2');
assert.same(counter, 0, 'counter');
}, 1);

assert.throws(() => reduce.call(undefined, (a, b) => a + b, 0), TypeError);
Expand Down
5 changes: 3 additions & 2 deletions tests/pure/esnext.iterator.some.js
Expand Up @@ -12,10 +12,11 @@ QUnit.test('Iterator#some', assert => {

assert.true(some.call(createIterator([1, 2, 3]), it => it % 2), 'basic functionality #1');
assert.false(some.call(createIterator([1, 2, 3]), it => typeof it == 'string'), 'basic functionality #2');
some.call(createIterator([1]), function (arg) {
some.call(createIterator([1]), function (arg, counter) {
assert.same(this, STRICT_THIS, 'this');
assert.same(arguments.length, 1, 'arguments length');
assert.same(arguments.length, 2, 'arguments length');
assert.same(arg, 1, 'argument');
assert.same(counter, 0, 'counter');
});

assert.throws(() => some.call(undefined, () => { /* empty */ }), TypeError);
Expand Down
5 changes: 3 additions & 2 deletions tests/tests/esnext.iterator.every.js
Expand Up @@ -12,10 +12,11 @@ QUnit.test('Iterator#every', assert => {

assert.true(every.call(createIterator([1, 2, 3]), it => typeof it == 'number'), 'basic functionality #1');
assert.false(every.call(createIterator([1, 2, 3]), it => it % 2), 'basic functionality #2');
every.call(createIterator([1]), function (arg) {
every.call(createIterator([1]), function (arg, counter) {
assert.same(this, STRICT_THIS, 'this');
assert.same(arguments.length, 1, 'arguments length');
assert.same(arguments.length, 2, 'arguments length');
assert.same(arg, 1, 'argument');
assert.same(counter, 0, 'counter');
});

assert.throws(() => every.call(undefined, () => { /* empty */ }), TypeError);
Expand Down
5 changes: 3 additions & 2 deletions tests/tests/esnext.iterator.filter.js
Expand Up @@ -11,10 +11,11 @@ QUnit.test('Iterator#filter', assert => {
assert.nonEnumerable(Iterator.prototype, 'filter');

assert.arrayEqual(filter.call(createIterator([1, 2, 3]), it => it % 2).toArray(), [1, 3], 'basic functionality');
filter.call(createIterator([1]), function (arg) {
filter.call(createIterator([1]), function (arg, counter) {
assert.same(this, STRICT_THIS, 'this');
assert.same(arguments.length, 1, 'arguments length');
assert.same(arguments.length, 2, 'arguments length');
assert.same(arg, 1, 'argument');
assert.same(counter, 0, 'counter');
});

assert.throws(() => filter.call(undefined, () => { /* empty */ }), TypeError);
Expand Down
5 changes: 3 additions & 2 deletions tests/tests/esnext.iterator.find.js
Expand Up @@ -11,10 +11,11 @@ QUnit.test('Iterator#find', assert => {
assert.nonEnumerable(Iterator.prototype, 'find');

assert.same(find.call(createIterator([1, 2, 3]), it => !(it % 2)), 2, 'basic functionality');
find.call(createIterator([1]), function (arg) {
find.call(createIterator([1]), function (arg, counter) {
assert.same(this, STRICT_THIS, 'this');
assert.same(arguments.length, 1, 'arguments length');
assert.same(arguments.length, 2, 'arguments length');
assert.same(arg, 1, 'argument');
assert.same(counter, 0, 'counter');
});

assert.throws(() => find.call(undefined, () => { /* empty */ }), TypeError);
Expand Down
5 changes: 3 additions & 2 deletions tests/tests/esnext.iterator.flat-map.js
Expand Up @@ -15,10 +15,11 @@ QUnit.test('Iterator#flatMap', assert => {
[-1, -2, 3, 4, 5, 6, 'a', 'b'],
'basic functionality',
);
flatMap.call(createIterator([1]), function (arg) {
flatMap.call(createIterator([1]), function (arg, counter) {
assert.same(this, STRICT_THIS, 'this');
assert.same(arguments.length, 1, 'arguments length');
assert.same(arguments.length, 2, 'arguments length');
assert.same(arg, 1, 'argument');
assert.same(counter, 0, 'counter');
return [arg];
}).toArray();

Expand Down
5 changes: 3 additions & 2 deletions tests/tests/esnext.iterator.for-each.js
Expand Up @@ -16,10 +16,11 @@ QUnit.test('Iterator#forEach', assert => {

assert.arrayEqual(array, [1, 2, 3], 'basic functionality');

forEach.call(createIterator([1]), function (arg) {
forEach.call(createIterator([1]), function (arg, counter) {
assert.same(this, STRICT_THIS, 'this');
assert.same(arguments.length, 1, 'arguments length');
assert.same(arguments.length, 2, 'arguments length');
assert.same(arg, 1, 'argument');
assert.same(counter, 0, 'counter');
});

assert.throws(() => forEach.call(undefined, () => { /* empty */ }), TypeError);
Expand Down
5 changes: 3 additions & 2 deletions tests/tests/esnext.iterator.map.js
Expand Up @@ -11,10 +11,11 @@ QUnit.test('Iterator#map', assert => {
assert.nonEnumerable(Iterator.prototype, 'map');

assert.arrayEqual(map.call(createIterator([1, 2, 3]), it => it ** 2).toArray(), [1, 4, 9], 'basic functionality');
map.call(createIterator([1]), function (arg) {
map.call(createIterator([1]), function (arg, counter) {
assert.same(this, STRICT_THIS, 'this');
assert.same(arguments.length, 1, 'arguments length');
assert.same(arguments.length, 2, 'arguments length');
assert.same(arg, 1, 'argument');
assert.same(counter, 0, 'counter');
}).toArray();

assert.throws(() => map.call(undefined, () => { /* empty */ }), TypeError);
Expand Down
5 changes: 3 additions & 2 deletions tests/tests/esnext.iterator.reduce.js
Expand Up @@ -12,11 +12,12 @@ QUnit.test('Iterator#reduce', assert => {

assert.same(reduce.call(createIterator([1, 2, 3]), (a, b) => a + b, 1), 7, 'basic functionality');
assert.same(reduce.call(createIterator([1, 2, 3]), (a, b) => a + b), 6, 'basic functionality, no init');
reduce.call(createIterator([2]), function (a, b) {
reduce.call(createIterator([2]), function (a, b, counter) {
assert.same(this, STRICT_THIS, 'this');
assert.same(arguments.length, 2, 'arguments length');
assert.same(arguments.length, 3, 'arguments length');
assert.same(a, 1, 'argument 1');
assert.same(b, 2, 'argument 2');
assert.same(counter, 0, 'counter');
}, 1);

assert.throws(() => reduce.call(undefined, (a, b) => a + b, 0), TypeError);
Expand Down
5 changes: 3 additions & 2 deletions tests/tests/esnext.iterator.some.js
Expand Up @@ -12,10 +12,11 @@ QUnit.test('Iterator#some', assert => {

assert.true(some.call(createIterator([1, 2, 3]), it => it % 2), 'basic functionality #1');
assert.false(some.call(createIterator([1, 2, 3]), it => typeof it == 'string'), 'basic functionality #2');
some.call(createIterator([1]), function (arg) {
some.call(createIterator([1]), function (arg, counter) {
assert.same(this, STRICT_THIS, 'this');
assert.same(arguments.length, 1, 'arguments length');
assert.same(arguments.length, 2, 'arguments length');
assert.same(arg, 1, 'argument');
assert.same(counter, 0, 'counter');
});

assert.throws(() => some.call(undefined, () => { /* empty */ }), TypeError);
Expand Down

0 comments on commit c8d22f6

Please sign in to comment.