From 16e73d147d68db8299b07dda1431e8f4fe36fdfa Mon Sep 17 00:00:00 2001 From: speedytwenty Date: Tue, 12 Apr 2022 20:01:57 -0600 Subject: [PATCH 1/3] Failing (non-completing) tests for infinite loop in Cell.drawEmpty() --- test/issues/296-test.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 test/issues/296-test.js diff --git a/test/issues/296-test.js b/test/issues/296-test.js new file mode 100644 index 0000000..965055c --- /dev/null +++ b/test/issues/296-test.js @@ -0,0 +1,31 @@ +const Table = require('../..'); + +/** + * This test doesn't actually fail it never completes. I could not find a method + * to get the infinite loop to timeout within the test. Not sure how GHA will + * handle this. + */ +test('it should not loop infinitely with invalid table data', async () => { + const table = new Table(); + table.push( + [ + { content: 'A', colSpan: 2 }, + { content: 'B', rowSpan: 3 }, + ], + [], + [{ content: 'C', colSpan: 3 }] + ); + expect(() => table.toString()).not.toThrow(); +}); + +test('it should not error on invalid table data', () => { + const table = new Table(); + table.push( + [ + { content: 'A', colSpan: 2 }, + { content: 'B', rowSpan: 3 }, + ], + [{ content: 'C', colSpan: 3 }] + ); + expect(() => table.toString()).not.toThrow(); +}); From 74092549dbf5834aa2efc1223a510f57820a2f74 Mon Sep 17 00:00:00 2001 From: speedytwenty Date: Wed, 13 Apr 2022 00:34:58 -0600 Subject: [PATCH 2/3] Avoid infinite loop with invalid table data --- src/layout-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/layout-manager.js b/src/layout-manager.js index 3937452..654b272 100644 --- a/src/layout-manager.js +++ b/src/layout-manager.js @@ -110,7 +110,7 @@ const { ColSpanCell, RowSpanCell } = Cell; let colSpanCell = new ColSpanCell(); colSpanCell.x = cell.x + k; colSpanCell.y = cell.y; - cellColumns.splice(columnIndex + 1, 0, colSpanCell); + cellColumns.splice(colSpanCell.x, 0, colSpanCell); } } } From 7326824d27397c35cbbefc88eadc5480b7d548ba Mon Sep 17 00:00:00 2001 From: speedytwenty Date: Wed, 13 Apr 2022 01:23:57 -0600 Subject: [PATCH 3/3] Avoid fatal error with invalid table data (with optional debug output) --- src/layout-manager.js | 13 +++++++++---- test/issues/296-test.js | 4 +++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/layout-manager.js b/src/layout-manager.js index 654b272..ecafaf9 100644 --- a/src/layout-manager.js +++ b/src/layout-manager.js @@ -88,14 +88,19 @@ const { ColSpanCell, RowSpanCell } = Cell; } function addRowSpanCells(table) { - table.forEach(function (row, rowIndex) { + table.forEach(function (row) { row.forEach(function (cell) { for (let i = 1; i < cell.rowSpan; i++) { let rowSpanCell = new RowSpanCell(cell); + const line = cell.y + i; rowSpanCell.x = cell.x; - rowSpanCell.y = cell.y + i; + rowSpanCell.y = line; rowSpanCell.colSpan = cell.colSpan; - insertCell(rowSpanCell, table[rowIndex + i]); + if (!table[line]) { + const { x, y } = rowSpanCell; + warn(`${x}-${y}: Expected empty array for row ${line - 1} (line ${line}).`); + } + insertCell(rowSpanCell, table[rowSpanCell.y] || []); } }); }); @@ -146,7 +151,7 @@ const { ColSpanCell, RowSpanCell } = Cell; cell.x = opts.x; cell.y = opts.y; warn(`Missing cell at ${cell.y}-${cell.x}.`); - insertCell(cell, table[y]); + insertCell(cell, table[y] || []); } } } diff --git a/test/issues/296-test.js b/test/issues/296-test.js index 965055c..28fc71a 100644 --- a/test/issues/296-test.js +++ b/test/issues/296-test.js @@ -19,7 +19,7 @@ test('it should not loop infinitely with invalid table data', async () => { }); test('it should not error on invalid table data', () => { - const table = new Table(); + const table = new Table({ debug: true }); table.push( [ { content: 'A', colSpan: 2 }, @@ -28,4 +28,6 @@ test('it should not error on invalid table data', () => { [{ content: 'C', colSpan: 3 }] ); expect(() => table.toString()).not.toThrow(); + // This expectation can be dropped if the expectation in the code changes + expect(table.messages).toContain('2-2: Expected empty array for row 1 (line 2).'); });