Skip to content

Commit 90e1c68

Browse files
committed
fix: ES6 iterator done flag handling
The iterator was incorrectly setting the done flag after checking hasNext(), which caused the for...of loop to skip the last value or not iterate at all. Fixes #397
1 parent b98dda1 commit 90e1c68

File tree

3 files changed

+35
-4
lines changed

3 files changed

+35
-4
lines changed

src/CronExpression.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -575,8 +575,12 @@ export class CronExpression {
575575
[Symbol.iterator](): Iterator<CronDate> {
576576
return {
577577
next: () => {
578-
const schedule = this.#findSchedule();
579-
return { value: schedule, done: !this.hasNext() };
578+
try {
579+
const schedule = this.#findSchedule();
580+
return { value: schedule, done: false };
581+
} catch {
582+
return { value: undefined as any, done: true };
583+
}
580584
},
581585
};
582586
}

tests/CronExpression.test.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,19 @@ describe('CronExpression', () => {
4545
expect(prevDate.toISOString()).toBe('2022-01-30T00:00:00.000Z');
4646
});
4747

48-
test('should check if there is a next scheduled date', () => {
48+
test('should return true if there is a next scheduled date within bounds', () => {
4949
const cronExpression = new CronExpression(fields, options);
5050
expect(cronExpression.hasNext()).toBe(true);
5151
});
5252

53+
test('should return false if there is no next scheduled date within bounds', () => {
54+
const cronExpression = new CronExpression(fields, {
55+
...options,
56+
endDate: new Date('2023-01-02T00:00:00Z'),
57+
});
58+
expect(cronExpression.hasNext()).toBe(false);
59+
});
60+
5361
test('should check if there is a previous scheduled date', () => {
5462
const cronExpression = new CronExpression(fields, options);
5563
expect(cronExpression.hasPrev()).toBe(true);

tests/CronExpressionParser.test.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,6 @@ describe('CronExpressionParser', () => {
243243
const options = {
244244
currentDate: new CronDate('Wed, 26 Dec 2012 14:38:53'),
245245
endDate: new CronDate('Wed, 26 Dec 2012 15:40:00'),
246-
iterator: true,
247246
};
248247

249248
const interval = CronExpressionParser.parse('*/25 * * * *', options);
@@ -262,9 +261,29 @@ describe('CronExpressionParser', () => {
262261
val = iterator.next();
263262
expect(val).not.toBeNull();
264263
expect(val.value).toBeTruthy();
264+
expect(val.done).toBeFalsy();
265+
266+
val = iterator.next();
267+
expect(val).not.toBeNull();
268+
expect(val.value).toBeUndefined();
265269
expect(val.done).toBeTruthy();
266270
});
267271

272+
test('valid ES6 iterator works with for..of loop', () => {
273+
const options = {
274+
currentDate: new CronDate('Wed, 26 Dec 2012 14:38:53'),
275+
endDate: new CronDate('Wed, 26 Dec 2012 15:40:00'),
276+
};
277+
const interval = CronExpressionParser.parse('*/25 * * * *', options);
278+
279+
const dates = [];
280+
for (const date of interval) {
281+
dates.push(date);
282+
}
283+
284+
expect(dates.length).toEqual(3);
285+
});
286+
268287
test('empty expression', () => {
269288
const interval = CronExpressionParser.parse('');
270289
const date = new CronDate();

0 commit comments

Comments
 (0)