KeyTable can cause stack overflow

KeyTable can cause stack overflow

sliekenssliekens Posts: 97Questions: 17Answers: 2
edited February 2017 in Bug reports

KeyTable attempts to retain focus when a table is redrawn. This behavior breaks if the table contains 0 rows after the draw.

An example scenario that breaks:
* your table contains a single row
* your table is configured to call ajax.reload() on a timer (every 10 secs)
* you select a cell using KeyTable
* someone else deletes the row that contains your selected cell

The next time the timer callback executes and the table is redrawn, KeyTable will go looking for the row and redraw the table like a mad man, eventually causing a stack overflow.

Replies

  • sliekenssliekens Posts: 97Questions: 17Answers: 2

    The offending lines of code are in this block:

    // Redraw - retain focus on the current cell
    dt.on( 'draw.keyTable', function (e) {
        if ( that.s.focusDraw ) {
            return;
        }
    
        var lastFocus = that.s.lastFocus;
    
        if ( lastFocus ) {
            var relative = that.s.lastFocus.relative;
            var info = dt.page.info();
            var row = relative.row + info.start;
    
            // Reverse if needed
            if ( row >= info.recordsDisplay ) {
                row = info.recordsDisplay - 1;
            }
    
            that._focus( row, relative.column, true, e );
        }
    } );
    

    This code results in a call to that._focus with row set to -1 causing a feedback loop in the following block:

    // Is the row on the current page? If not, we need to redraw to show the
    // page
    if ( pageInfo.length !== -1 && (row < pageInfo.start || row >= pageInfo.start+pageInfo.length) ) {
        this.s.focusDraw = true;
        this.s.waitingForDraw = true;
    
        dt
            .one( 'draw', function () {
                that.s.focusDraw = false;
                that.s.waitingForDraw = false;
                that._focus( row, column, undefined, originalEvent );
            } )
            .page( Math.floor( row / pageInfo.length ) )
            .draw( false );
    
        return;
    }
    
This discussion has been closed.