Skip to content

Commit c75a73c

Browse files
authored
Merge commit from fork
fix(gantt): limit loop if excluding all dates
2 parents 91b1ccf + faafb5d commit c75a73c

3 files changed

Lines changed: 28 additions & 2 deletions

File tree

.changeset/common-parents-serve.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'mermaid': patch
3+
---
4+
5+
fix(gantt): add iteration limit for `excludes` field

packages/mermaid/src/diagrams/gantt/ganttDb.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,21 +251,28 @@ const checkTaskDates = function (task, dateFormat, excludes, includes) {
251251
* @param {dayjs.Dayjs} startTime - The start time.
252252
* @param {dayjs.Dayjs} endTime - The original end time (will return a different end time if it's invalid).
253253
* @param {string} dateFormat - Dayjs date format string.
254-
* @param {*} excludes
255-
* @param {*} includes
254+
* @param {string[]} excludes - Dates or days to exclude.
255+
* @param {string[]} includes - Dates to always include, even if they match the excludes.
256256
* @returns {[endTime: dayjs.Dayjs, renderEndTime: Date | null]} The new `endTime`, and the end time to render.
257257
* `renderEndTime` may be `null` if `startTime` is newer than `endTime`.
258+
* @throws {Error} If a valid end time cannot be found after 10,000 iterations.
258259
*/
259260
const fixTaskDates = function (startTime, endTime, dateFormat, excludes, includes) {
260261
let invalid = false;
261262
let renderEndTime = null;
263+
const maxEndTime = endTime.add(10000, 'd');
262264
while (startTime <= endTime) {
263265
if (!invalid) {
264266
renderEndTime = endTime.toDate();
265267
}
266268
invalid = isInvalidDate(startTime, dateFormat, excludes, includes);
267269
if (invalid) {
268270
endTime = endTime.add(1, 'd');
271+
if (endTime > maxEndTime) {
272+
throw new Error(
273+
'Failed to find a valid date that was not excluded by `excludes` after 10,000 iterations.'
274+
);
275+
}
269276
}
270277
startTime = startTime.add(1, 'd');
271278
}

packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,20 @@ describe('when using the ganttDb', function () {
282282
expect(tasks[0].task).toEqual('test1');
283283
});
284284

285+
it('should not infinite loop when excluding everything', function () {
286+
ganttDb.setDateFormat('YYYY-MM-DD');
287+
ganttDb.setExcludes('weekends,monday,tuesday,wednesday,thursday,friday');
288+
ganttDb.setWeekend('saturday');
289+
ganttDb.addSection('weekends skip test');
290+
ganttDb.addTask('test1', 'id1,2019-02-01,7d');
291+
292+
expect(() => ganttDb.getTasks()).toThrowError('Failed to find a valid date');
293+
294+
// Fridays are now allowed, so it should not throw an error
295+
ganttDb.setExcludes('weekends,monday,tuesday,wednesday,thursday');
296+
expect(() => ganttDb.getTasks()).not.toThrow();
297+
});
298+
285299
it('should maintain the order in which tasks are created', function () {
286300
ganttDb.setAccTitle('Project Execution');
287301
ganttDb.setDateFormat('YYYY-MM-DD');

0 commit comments

Comments
 (0)