gajus / table

Formats data into a string table.
Other
904 stars 76 forks source link

Using rowSpan causing program to hang and crash #225

Open dominikwantuch opened 3 months ago

dominikwantuch commented 3 months ago

What happens?

Running code presented below hangs the program, spins up CPU to 100%, and causes memory to grow until program crashes with Node error.

Error

For versions of node < 22

#
# Fatal error in , line 0
# Fatal JavaScript invalid size error 169220804 (see crbug.com/1201626)
#
#
#
#FailureMessage Object: 0xffffe3c2ba20
----- Native stack trace -----

 1: 0xcf4864  [node]
 2: 0x1f5cc00 V8_Fatal(char const*, ...) [node]
 3: 0x104c9a0 v8::internal::FactoryBase<v8::internal::Factory>::NewArrayList(int, v8::internal::AllocationType) [node]
 4: 0x120a8f0  [node]
 5: 0x120aad0  [node]
 6: 0x145b9ac v8::internal::Runtime_GrowArrayElements(int, unsigned long*, v8::internal::Isolate*) [node]
 7: 0x186da84  [node]
Trace/breakpoint trap

Node 22.x.x

/Users/.../api/node_modules/table/dist/src/wrapString.js:21
        chunks.push((0, slice_ansi_1.default)(subjectSlice, 0, size));
               ^

RangeError: Invalid array length
    at Array.push (<anonymous>)
    at wrapString (/Users/.../api/node_modules/table/src/wrapString.ts:18:12)
    at wrapCell (/Users/.../api/node_modules/table/src/wrapCell.ts:29:30)
    at wrapRangeContent (/Users/.../api/node_modules/table/src/alignSpanningCell.ts:36:18)
    at getContainingRange (/Users/.../api/node_modules/table/src/spanningCellManager.ts:58:42)
    at Object.getContainingRange (/Users/.../api/node_modules/table/src/spanningCellManager.ts:131:14)
    at /Users/.../api/node_modules/table/src/calculateRowHeights.ts:23:59
    at Array.forEach (<anonymous>)
    at calculateRowHeights (/Users/.../api/node_modules/table/src/calculateRowHeights.ts:22:9)
    at Proxy.table (/Users/.../api/node_modules/table/src/table.ts:52:41)

Code causing issue

const data = [
    ['API xyz', '', '', ''],
    ['/users', '', '', ''],
    ['', 'GET', 'No configuration provided', 'failure'],
    ['/users/{userId}/apartments', '', '', ''],
    ['', 'GET', '', 'success'],
    ['', 'POST', 'No configuration provided', 'failure'],
]

const config: TableUserConfig = {
    spanningCells: [
        // Header
        {row: 0, col: 0, colSpan: 1, alignment: 'left'},
        {row: 0, col: 1, colSpan: 3, alignment: 'left'},

        // First endpoint
        {row: 1, col: 1, colSpan: 3},
        {row: 1, col: 0, rowSpan: 2},

        // Second endpoint
        {row: 3, col: 1, colSpan: 3},
        {row: 3, col: 0, rowSpan: 3},
    ]
}

console.log(table(data, config))

Expected output

╔════════════╤════════════════════════════════════════════╗
║ API xyz    │                                            ║
╟────────────┼────────────────────────────────────────────╢
║ /users     │                                            ║
║            ├──────┬───────────────────────────┬─────────╢
║            │ GET  │ No configuration provided │ failure ║
╟────────────┼──────┴───────────────────────────┴─────────╢
║ /users/{us │                                            ║
║ erId}/apar ├──────┬───────────────────────────┬─────────╢
║ tments     │ GET  │                           │ success ║
║            ├──────┼───────────────────────────┼─────────╢
║            │ POST │ No configuration provided │ failure ║
╚════════════╧══════╧═══════════════════════════╧═════════╝

Notes

  1. Removing {row: 3, col: 0, rowSpan: 3}, from table config makes program run again, so this is the line causing problems.
  2. I was able to run program with expected output and no crash if I set width of first column to any fixed value e.g. columns: {0: {width: 10}}