From 6cd5c2b8462c0c7a4ce898125a2fc7e0507fabc6 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 31 Jan 2017 21:02:55 -0800 Subject: [PATCH 1/3] Add null checks in eraseRight and eraseLeft Fixes #519 --- src/xterm.js | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/xterm.js b/src/xterm.js index f88c9452..ec4927c7 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -2159,14 +2159,14 @@ Terminal.prototype.nextStop = function(x) { * @param {number} y The line in which to operate. */ Terminal.prototype.eraseRight = function(x, y) { - var line = this.lines.get(this.ybase + y) - , ch = [this.eraseAttr(), ' ', 1]; // xterm - - + var line = this.lines.get(this.ybase + y); + if (!line) { + return; + } + var ch = [this.eraseAttr(), ' ', 1]; // xterm for (; x < this.cols; x++) { line[x] = ch; } - this.updateRange(y); }; @@ -2178,12 +2178,15 @@ Terminal.prototype.eraseRight = function(x, y) { * @param {number} y The line in which to operate. */ Terminal.prototype.eraseLeft = function(x, y) { - var line = this.lines.get(this.ybase + y) - , ch = [this.eraseAttr(), ' ', 1]; // xterm - + var line = this.lines.get(this.ybase + y); + if (!line) { + return; + } + var ch = [this.eraseAttr(), ' ', 1]; // xterm x++; - while (x--) line[x] = ch; - + while (x--) { + line[x] = ch; + } this.updateRange(y); }; From 637a5bd9cc232bf33022d87bef484c62f0c5dfb0 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 31 Jan 2017 21:23:21 -0800 Subject: [PATCH 2/3] Don't requeue animation frame if not needed Fixes #517 --- src/xterm.js | 64 +++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/src/xterm.js b/src/xterm.js index f88c9452..fa8d6ad4 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -222,6 +222,7 @@ function Terminal(options) { this.writeBuffer = []; this.writeInProgress = false; this.refreshFramesSkipped = 0; + this.refreshAnimationFrame = null; /** * Whether _xterm.js_ sent XOFF in order to catch up with the pty process. @@ -659,7 +660,6 @@ Terminal.prototype.open = function(parent) { // Setup loop that draws to screen this.queueRefresh(0, this.rows - 1); - this.refreshLoop(); // Initialize global actions that // need to be taken on the document. @@ -1085,6 +1085,9 @@ Terminal.flags = { */ Terminal.prototype.queueRefresh = function(start, end) { this.refreshRowsQueue.push({ start: start, end: end }); + if (!this.refreshAnimationFrame) { + this.refreshAnimationFrame = window.requestAnimationFrame(this.refreshLoop.bind(this)); + } } /** @@ -1092,40 +1095,39 @@ Terminal.prototype.queueRefresh = function(start, end) { * necessary before queueing up the next one. */ Terminal.prototype.refreshLoop = function() { - // Don't refresh if there were no row changes - if (this.refreshRowsQueue.length > 0) { - // Skip MAX_REFRESH_FRAME_SKIP frames if the writeBuffer is non-empty as it - // will need to be immediately refreshed anyway. This saves a lot of - // rendering time as the viewport DOM does not need to be refreshed, no - // scroll events, no layouts, etc. - var skipFrame = this.writeBuffer.length > 0 && this.refreshFramesSkipped++ <= MAX_REFRESH_FRAME_SKIP; + // Skip MAX_REFRESH_FRAME_SKIP frames if the writeBuffer is non-empty as it + // will need to be immediately refreshed anyway. This saves a lot of + // rendering time as the viewport DOM does not need to be refreshed, no + // scroll events, no layouts, etc. + var skipFrame = this.writeBuffer.length > 0 && this.refreshFramesSkipped++ <= MAX_REFRESH_FRAME_SKIP; + if (skipFrame) { + this.refreshAnimationFrame = window.requestAnimationFrame(this.refreshLoop.bind(this)); + return; + } - if (!skipFrame) { - this.refreshFramesSkipped = 0; - var start; - var end; - if (this.refreshRowsQueue.length > 4) { - // Just do a full refresh when 5+ refreshes are queued - start = 0; - end = this.rows - 1; - } else { - // Get start and end rows that need refreshing - start = this.refreshRowsQueue[0].start; - end = this.refreshRowsQueue[0].end; - for (var i = 1; i < this.refreshRowsQueue.length; i++) { - if (this.refreshRowsQueue[i].start < start) { - start = this.refreshRowsQueue[i].start; - } - if (this.refreshRowsQueue[i].end > end) { - end = this.refreshRowsQueue[i].end; - } - } + this.refreshFramesSkipped = 0; + var start; + var end; + if (this.refreshRowsQueue.length > 4) { + // Just do a full refresh when 5+ refreshes are queued + start = 0; + end = this.rows - 1; + } else { + // Get start and end rows that need refreshing + start = this.refreshRowsQueue[0].start; + end = this.refreshRowsQueue[0].end; + for (var i = 1; i < this.refreshRowsQueue.length; i++) { + if (this.refreshRowsQueue[i].start < start) { + start = this.refreshRowsQueue[i].start; + } + if (this.refreshRowsQueue[i].end > end) { + end = this.refreshRowsQueue[i].end; } - this.refreshRowsQueue = []; - this.refresh(start, end); } } - window.requestAnimationFrame(this.refreshLoop.bind(this)); + this.refreshRowsQueue = []; + this.refreshAnimationFrame = null; + this.refresh(start, end); } /** From f9aac1bcc6f40743c58aa087f50f37e6e2435bbc Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 31 Jan 2017 23:46:58 -0800 Subject: [PATCH 3/3] Fix tests --- src/test/escape-sequences-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/escape-sequences-test.js b/src/test/escape-sequences-test.js index f35bc00a..684de079 100644 --- a/src/test/escape-sequences-test.js +++ b/src/test/escape-sequences-test.js @@ -75,7 +75,7 @@ describe('xterm output comparison', function() { beforeEach(function () { xterm = new Terminal(COLS, ROWS); - xterm.refresh = function() {}; + xterm.queueRefresh = function() {}; xterm.viewport = { syncScrollArea: function() {} };