From bd132d1f747f66de142f53d50bc9d06596575bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Sun, 4 Aug 2019 15:04:40 +0200 Subject: [PATCH 01/78] implement left/right scroll --- src/InputHandler.ts | 62 ++++++++++++++++++++++++++++++++++++++------- src/Types.d.ts | 2 ++ 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 83019c18..86bedffb 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -177,7 +177,9 @@ export class InputHandler extends Disposable implements IInputHandler { * CSI handler */ this._parser.setCsiHandler({final: '@'}, params => this.insertChars(params)); + this._parser.setCsiHandler({intermediates: ' ', final: '@'}, params => this.scrollLeft(params)); this._parser.setCsiHandler({final: 'A'}, params => this.cursorUp(params)); + this._parser.setCsiHandler({intermediates: ' ', final: 'A'}, params => this.scrollRight(params)); this._parser.setCsiHandler({final: 'B'}, params => this.cursorDown(params)); this._parser.setCsiHandler({final: 'C'}, params => this.cursorForward(params)); this._parser.setCsiHandler({final: 'D'}, params => this.cursorBackward(params)); @@ -1036,17 +1038,59 @@ export class InputHandler extends Disposable implements IInputHandler { * CSI Ps T Scroll down Ps lines (default = 1) (SD). */ public scrollDown(params: IParams): void { - if (params.length < 2) { - let param = params.params[0] || 1; + let param = params.params[0] || 1; - // make buffer local for faster access - const buffer = this._bufferService.buffer; + // make buffer local for faster access + const buffer = this._bufferService.buffer; - while (param--) { - buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 1); - buffer.lines.splice(buffer.ybase + buffer.scrollTop, 0, buffer.getBlankLine(DEFAULT_ATTR_DATA)); - } - this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom); + while (param--) { + buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 1); + buffer.lines.splice(buffer.ybase + buffer.scrollTop, 0, buffer.getBlankLine(DEFAULT_ATTR_DATA)); + } + this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom); + } + + /** + * CSI Ps SP @ Scroll left Ps columns (default = 1) (SL) ECMA-48 + * + * Notation: (Pn) + * Representation: CSI Pn 02/00 04/00 + * Parameter default value: Pn = 1 + * SL causes the data in the presentation component to be moved by n character positions + * if the line orientation is horizontal, or by n line positions if the line orientation + * is vertical, such that the data appear to move to the left; where n equals the value of Pn. + * The active presentation position is not affected by this control function. + * + * Supported: + * - always left shift (no line orientation setting respected) + */ + public scrollLeft(params: IParams): void { + const param = params.params[0] || 1; + for (let y = 0; y < this._bufferService.rows; ++y) { + const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y); + line.deleteCells(0, param, this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())); + } + } + + /** + * CSI Ps SP A Scroll right Ps columns (default = 1) (SL) ECMA-48 + * + * Notation: (Pn) + * Representation: CSI Pn 02/00 04/01 + * Parameter default value: Pn = 1 + * SR causes the data in the presentation component to be moved by n character positions + * if the line orientation is horizontal, or by n line positions if the line orientation + * is vertical, such that the data appear to move to the right; where n equals the value of Pn. + * The active presentation position is not affected by this control function. + * + * Supported: + * - always right shift (no line orientation setting respected) + */ + public scrollRight(params: IParams): void { + const param = params.params[0] || 1; + for (let y = 0; y < this._bufferService.rows; ++y) { + const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y); + line.insertCells(0, param, this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())); } } diff --git a/src/Types.d.ts b/src/Types.d.ts index e3a9771d..25824818 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -92,7 +92,9 @@ export interface IInputHandler { /** C0 SI */ shiftIn(): void; /** CSI @ */ insertChars(params: IParams): void; + /** CSI SP @ */ scrollLeft(params: IParams): void; /** CSI A */ cursorUp(params: IParams): void; + /** CSI SP A */ scrollRight(params: IParams): void; /** CSI B */ cursorDown(params: IParams): void; /** CSI C */ cursorForward(params: IParams): void; /** CSI D */ cursorBackward(params: IParams): void; From 5483a052cc4bb8ed55316ae5f617a7eeb12d0c79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Sun, 4 Aug 2019 15:15:59 +0200 Subject: [PATCH 02/78] always reset wrapped flag --- src/InputHandler.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 86bedffb..71cf0b36 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -1069,6 +1069,7 @@ export class InputHandler extends Disposable implements IInputHandler { for (let y = 0; y < this._bufferService.rows; ++y) { const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y); line.deleteCells(0, param, this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())); + line.isWrapped = false; } } @@ -1091,6 +1092,7 @@ export class InputHandler extends Disposable implements IInputHandler { for (let y = 0; y < this._bufferService.rows; ++y) { const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y); line.insertCells(0, param, this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())); + line.isWrapped = false; } } From 9a903ca1c5554209aea0f5582a6dbe945dd3efd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Sun, 4 Aug 2019 15:32:32 +0200 Subject: [PATCH 03/78] add DECIC/DECDC --- src/InputHandler.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 71cf0b36..a15a7213 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -220,6 +220,8 @@ export class InputHandler extends Disposable implements IInputHandler { this._parser.setCsiHandler({final: 'r'}, params => this.setScrollRegion(params)); this._parser.setCsiHandler({final: 's'}, params => this.saveCursor(params)); this._parser.setCsiHandler({final: 'u'}, params => this.restoreCursor(params)); + this._parser.setCsiHandler({intermediates: "'", final: '}'}, params => this.insertColumns(params)); + this._parser.setCsiHandler({intermediates: "'", final: '~'}, params => this.deleteColumns(params)); /** * execute handler @@ -1096,6 +1098,32 @@ export class InputHandler extends Disposable implements IInputHandler { } } + /** + * CSI Pm ' } + * Insert Ps Column(s) (default = 1) (DECIC), VT420 and up. + */ + public insertColumns(params: IParams): void { + const param = params.params[0] || 1; + for (let y = 0; y < this._bufferService.rows; ++y) { + const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y); + line.insertCells(this._bufferService.buffer.x, param, this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())); + line.isWrapped = false; + } + } + + /** + * CSI Pm ' ~ + * Delete Ps Column(s) (default = 1) (DECDC), VT420 and up. + */ + public deleteColumns(params: IParams): void { + const param = params.params[0] || 1; + for (let y = 0; y < this._bufferService.rows; ++y) { + const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y); + line.deleteCells(this._bufferService.buffer.x, param, this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())); + line.isWrapped = false; + } + } + /** * CSI Ps X * Erase Ps Character(s) (default = 1) (ECH). From 8bc009943455112557cadb8e68f517b67ff6549d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Sun, 4 Aug 2019 15:37:47 +0200 Subject: [PATCH 04/78] linter nonsense --- src/InputHandler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index a15a7213..e533b709 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -220,8 +220,8 @@ export class InputHandler extends Disposable implements IInputHandler { this._parser.setCsiHandler({final: 'r'}, params => this.setScrollRegion(params)); this._parser.setCsiHandler({final: 's'}, params => this.saveCursor(params)); this._parser.setCsiHandler({final: 'u'}, params => this.restoreCursor(params)); - this._parser.setCsiHandler({intermediates: "'", final: '}'}, params => this.insertColumns(params)); - this._parser.setCsiHandler({intermediates: "'", final: '~'}, params => this.deleteColumns(params)); + this._parser.setCsiHandler({intermediates: '\'', final: '}'}, params => this.insertColumns(params)); + this._parser.setCsiHandler({intermediates: '\'', final: '~'}, params => this.deleteColumns(params)); /** * execute handler From 4b5709c68dae134a91bbec436d75805e58ce834a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Sat, 17 Aug 2019 18:13:56 +0200 Subject: [PATCH 05/78] add DECIC/DECDC to interface --- src/Types.d.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Types.d.ts b/src/Types.d.ts index f591fa4f..1d7a621a 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -130,6 +130,8 @@ export interface IInputHandler { /** CSI r */ setScrollRegion(params: IParams, collect?: string): void; /** CSI s */ saveCursor(params: IParams): void; /** CSI u */ restoreCursor(params: IParams): void; + /** CSI ' } */ insertColumns(params: IParams): void; + /** CSI ' ~ */ deleteColumns(params: IParams): void; /** OSC 0 OSC 2 */ setTitle(data: string): void; /** ESC E */ nextLine(): void; From f7827c4df88f9326eb103aa183174f888bbb3ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Sat, 17 Aug 2019 18:52:11 +0200 Subject: [PATCH 06/78] add basic tests for commands --- src/InputHandler.test.ts | 71 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 7 deletions(-) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index 8752e0a3..ad41d27b 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -25,6 +25,14 @@ function getCursor(term: TestTerminal): number[] { ]; } +function getLines(term: TestTerminal, limit: number = term.rows): string[] { + const res: string[] = []; + for (let i = 0; i < limit; ++i) { + res.push(term.buffer.lines.get(i).translateToString(true)); + } + return res; +} + describe('InputHandler', () => { describe('save and restore cursor', () => { const terminal = new MockInputHandlingTerminal(); @@ -1125,13 +1133,6 @@ describe('InputHandler', () => { beforeEach(() => { term = new TestTerminal({cols: 10, rows: 10}); }); - function getLines(term: TestTerminal, limit: number = term.rows): string[] { - const res: string[] = []; - for (let i = 0; i < limit; ++i) { - res.push(term.buffer.lines.get(i).translateToString(true)); - } - return res; - } it('scrollUp', () => { term.writeSync('0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\x1b[2;4r\x1b[2Sm'); assert.deepEqual(getLines(term), ['m', '3', '', '', '4', '5', '6', '7', '8', '9']); @@ -1191,4 +1192,60 @@ describe('InputHandler', () => { assert.deepEqual(getLines(term), ['0', '1', 'n', 'm', '', '', '6', '7', '8', '9']); }); }); + describe('SL/SR/DECIC/DECDC', () => { + let term: TestTerminal; + beforeEach(() => { + term = new TestTerminal({cols: 5, rows: 5, scrollback: 1}); + }); + it('SL (scrollLeft)', () => { + term.writeSync('12345'.repeat(6)); + term.writeSync('\x1b[ @'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '2345', '2345', '2345', '2345', '2345']); + term.writeSync('\x1b[0 @'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '345', '345', '345', '345', '345']); + term.writeSync('\x1b[2 @'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '5', '5', '5', '5', '5']); + }); + it('SR (scrollRight)', () => { + term.writeSync('12345'.repeat(6)); + term.writeSync('\x1b[ A'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', ' 1234', ' 1234', ' 1234', ' 1234', ' 1234']); + term.writeSync('\x1b[0 A'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', ' 123', ' 123', ' 123', ' 123', ' 123']); + term.writeSync('\x1b[2 A'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', ' 1', ' 1', ' 1', ' 1', ' 1']); + }); + it('insertColumns (DECIC)', () => { + term.writeSync('12345'.repeat(6)); + term.writeSync('\x1b[3;3H'); + term.writeSync('\x1b[\'}'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']); + term.reset(); + term.writeSync('12345'.repeat(6)); + term.writeSync('\x1b[3;3H'); + term.writeSync('\x1b[1\'}'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']); + term.reset(); + term.writeSync('12345'.repeat(6)); + term.writeSync('\x1b[3;3H'); + term.writeSync('\x1b[2\'}'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '12 3', '12 3', '12 3', '12 3', '12 3']); + }); + it('deleteColumns (DECDC)', () => { + term.writeSync('12345'.repeat(6)); + term.writeSync('\x1b[3;3H'); + term.writeSync('\x1b[\'~'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '1245', '1245', '1245', '1245', '1245']); + term.reset(); + term.writeSync('12345'.repeat(6)); + term.writeSync('\x1b[3;3H'); + term.writeSync('\x1b[1\'~'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '1245', '1245', '1245', '1245', '1245']); + term.reset(); + term.writeSync('12345'.repeat(6)); + term.writeSync('\x1b[3;3H'); + term.writeSync('\x1b[2\'~'); + assert.deepEqual(getLines(term, term.rows + 1), ['12345', '125', '125', '125', '125', '125']); + }); + }); }); From 040f9f49d91251735e0dc2a78cad1b6d783ba7c4 Mon Sep 17 00:00:00 2001 From: Jon Bockhorst Date: Mon, 14 Oct 2019 14:25:02 -0500 Subject: [PATCH 07/78] Support link position in hover tooltip callback --- src/browser/Linkifier.ts | 2 +- src/browser/Types.d.ts | 12 ++++++++++-- typings/xterm.d.ts | 27 ++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/browser/Linkifier.ts b/src/browser/Linkifier.ts index 53a32aa7..d17de1ca 100644 --- a/src/browser/Linkifier.ts +++ b/src/browser/Linkifier.ts @@ -306,7 +306,7 @@ export class Linkifier implements ILinkifier { e => { this._onLinkTooltip.fire(this._createLinkHoverEvent(x1, y1, x2, y2, fg)); if (matcher.hoverTooltipCallback) { - matcher.hoverTooltipCallback(e, uri); + matcher.hoverTooltipCallback(e, uri, { startRow: y1, startColumn: x1, endRow: y2, endColumn: x2 }); } }, () => { diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index 894beb36..bd3d8722 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -43,14 +43,22 @@ export interface IViewport extends IDisposable { onThemeChange(colors: IColorSet): void; } +export interface ILinkLocation { + startColumn: number; + startRow: number; + endColumn: number; + endRow: number; +} + export type LinkMatcherHandler = (event: MouseEvent, uri: string) => void; +export type LinkMatcherHoverTooltipCallback = (event: MouseEvent, uri: string, position: ILinkLocation) => void; export type LinkMatcherValidationCallback = (uri: string, callback: (isValid: boolean) => void) => void; export interface ILinkMatcher { id: number; regex: RegExp; handler: LinkMatcherHandler; - hoverTooltipCallback?: LinkMatcherHandler; + hoverTooltipCallback?: LinkMatcherHoverTooltipCallback; hoverLeaveCallback?: () => void; matchIndex?: number; validationCallback?: LinkMatcherValidationCallback; @@ -96,7 +104,7 @@ export interface ILinkMatcherOptions { /** * A callback that fires when the mouse hovers over a link. */ - tooltipCallback?: LinkMatcherHandler; + tooltipCallback?: LinkMatcherHoverTooltipCallback; /** * A callback that fires when the mouse leaves a link that was hovered. */ diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 44ef66bd..2ea8706a 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -269,7 +269,7 @@ declare module 'xterm' { /** * A callback that fires when the mouse hovers over a link for a moment. */ - tooltipCallback?: (event: MouseEvent, uri: string) => boolean | void; + tooltipCallback?: (event: MouseEvent, uri: string, location: ILinkLocation) => boolean | void; /** * A callback that fires when the mouse leaves a link. Note that this can @@ -842,6 +842,31 @@ declare module 'xterm' { endRow: number; } + /** + * An object representing a link location within the terminal. + */ + interface ILinkLocation { + /** + * The start column of the link. + */ + startColumn: number; + + /** + * The start row of the link. + */ + startRow: number; + + /** + * The end column of the link. + */ + endColumn: number; + + /** + * The end row of the link. + */ + endRow: number; + } + /** * Represents a terminal buffer. */ From 843ea1b61084e2402453a5e81b161e9dc15bef11 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 16 Oct 2019 15:41:47 -0700 Subject: [PATCH 08/78] Fix scrollback going missing when increase size on Windows This also forces the scroll bar to sync after a resize early, this may fix other bugs. Fixes #2459 --- src/Terminal.ts | 4 ++++ src/browser/Types.d.ts | 2 +- src/browser/Viewport.ts | 22 ++++++++++++++-------- src/common/buffer/Buffer.ts | 30 ++++++++++++++++++------------ 4 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 3a2a1eb3..852d424d 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -1469,6 +1469,10 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp this._charSizeService.measure(); } + // Sync the scroll area to make sure scroll events don't fire and scroll the viewport to an + // invalid location + this.viewport.syncScrollArea(true); + this.refresh(0, this.rows - 1); this._onResize.fire({ cols: x, rows: y }); } diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index 894beb36..692d6b03 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -35,7 +35,7 @@ export interface IPartialColorSet { export interface IViewport extends IDisposable { scrollBarWidth: number; - syncScrollArea(): void; + syncScrollArea(immediate?: boolean): void; getLinesScrolled(ev: WheelEvent): number; onWheel(ev: WheelEvent): boolean; onTouchStart(ev: TouchEvent): void; diff --git a/src/browser/Viewport.ts b/src/browser/Viewport.ts index d200ef8c..4817ab3b 100644 --- a/src/browser/Viewport.ts +++ b/src/browser/Viewport.ts @@ -61,7 +61,14 @@ export class Viewport extends Disposable implements IViewport { * Refreshes row height, setting line-height, viewport height and scroll area height if * necessary. */ - private _refresh(): void { + private _refresh(immediate: boolean): void { + if (immediate) { + this._innerRefresh(); + if (this._refreshAnimationFrame !== null) { + cancelAnimationFrame(this._refreshAnimationFrame); + } + return; + } if (this._refreshAnimationFrame === null) { this._refreshAnimationFrame = requestAnimationFrame(() => this._innerRefresh()); } @@ -89,40 +96,39 @@ export class Viewport extends Disposable implements IViewport { this._refreshAnimationFrame = null; } - /** * Updates dimensions and synchronizes the scroll area if necessary. */ - public syncScrollArea(): void { + public syncScrollArea(immediate: boolean = false): void { // If buffer height changed if (this._lastRecordedBufferLength !== this._bufferService.buffer.lines.length) { this._lastRecordedBufferLength = this._bufferService.buffer.lines.length; - this._refresh(); + this._refresh(immediate); return; } // If viewport height changed if (this._lastRecordedViewportHeight !== this._renderService.dimensions.canvasHeight) { - this._refresh(); + this._refresh(immediate); return; } // If the buffer position doesn't match last scroll top const newScrollTop = this._bufferService.buffer.ydisp * this._currentRowHeight; if (this._lastScrollTop !== newScrollTop) { - this._refresh(); + this._refresh(immediate); return; } // If element's scroll top changed, this can happen when hiding the element if (this._lastScrollTop !== this._viewportElement.scrollTop) { - this._refresh(); + this._refresh(immediate); return; } // If row height changed if (this._renderService.dimensions.scaledCellHeight / window.devicePixelRatio !== this._currentRowHeight) { - this._refresh(); + this._refresh(immediate); return; } } diff --git a/src/common/buffer/Buffer.ts b/src/common/buffer/Buffer.ts index 1b3e5d86..152bab7a 100644 --- a/src/common/buffer/Buffer.ts +++ b/src/common/buffer/Buffer.ts @@ -167,19 +167,25 @@ export class Buffer implements IBuffer { if (this._rows < newRows) { for (let y = this._rows; y < newRows; y++) { if (this.lines.length < newRows + this.ybase) { - if (this.ybase > 0 && this.lines.length <= this.ybase + this.y + addToY + 1) { - // There is room above the buffer and there are no empty elements below the line, - // scroll up - this.ybase--; - addToY++; - if (this.ydisp > 0) { - // Viewport is at the top of the buffer, must increase downwards - this.ydisp--; - } - } else { - // Add a blank line if there is no buffer left at the top to scroll to, or if there - // are blank lines after the cursor + if (this._optionsService.options.windowsMode) { + // Just add the new missing rows on Windows as conpty reprints the screen with it's + // view of the world. Once a line enters scrollback for conpty it remains there this.lines.push(new BufferLine(newCols, nullCell)); + } else { + if (this.ybase > 0 && this.lines.length <= this.ybase + this.y + addToY + 1) { + // There is room above the buffer and there are no empty elements below the line, + // scroll up + this.ybase--; + addToY++; + if (this.ydisp > 0) { + // Viewport is at the top of the buffer, must increase downwards + this.ydisp--; + } + } else { + // Add a blank line if there is no buffer left at the top to scroll to, or if there + // are blank lines after the cursor + this.lines.push(new BufferLine(newCols, nullCell)); + } } } } From e8dc563ccfd3caeb0d8da9d7e605517799c4eb06 Mon Sep 17 00:00:00 2001 From: Leonardo Bressan Motyczka Date: Wed, 16 Oct 2019 20:05:45 -0300 Subject: [PATCH 09/78] Include puppeteer deps on devcontainer --- .devcontainer/Dockerfile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 4d4e605b..e5736562 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -8,12 +8,19 @@ RUN apt-get update \ # Verify git and process tools are installed RUN apt-get install -y git procps -# Install yarn +# Install yarn, puppeteer deps RUN apt-get install -y curl apt-transport-https lsb-release \ && curl -sS https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/pubkey.gpg | apt-key add - 2>/dev/null \ && echo "deb https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ && apt-get update \ - && apt-get -y install --no-install-recommends yarn + && apt-get -y install --no-install-recommends \ + yarn fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst ttf-freefont \ + # https://github.com/Googlechrome/puppeteer/issues/290#issuecomment-322921352 + gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \ + libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 \ + libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 \ + libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 \ + ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget # Clean up RUN apt-get autoremove -y \ From 3d500ba802343153060c7e9405855378bbb91f15 Mon Sep 17 00:00:00 2001 From: Leonardo Bressan Motyczka Date: Wed, 16 Oct 2019 20:07:56 -0300 Subject: [PATCH 10/78] Launch puppeteer without sandbox --- addons/xterm-addon-attach/src/AttachAddon.api.ts | 2 +- addons/xterm-addon-search/src/SearchAddon.api.ts | 2 +- addons/xterm-addon-web-links/src/WebLinksAddon.api.ts | 2 +- addons/xterm-addon-webgl/src/WebglRenderer.api.ts | 2 +- test/api/CharWidth.api.ts | 2 +- test/api/InputHandler.api.ts | 2 +- test/api/MouseTracking.api.ts | 2 +- test/api/Parser.api.ts | 2 +- test/api/Terminal.api.ts | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/addons/xterm-addon-attach/src/AttachAddon.api.ts b/addons/xterm-addon-attach/src/AttachAddon.api.ts index c5b2d858..94d11139 100644 --- a/addons/xterm-addon-attach/src/AttachAddon.api.ts +++ b/addons/xterm-addon-attach/src/AttachAddon.api.ts @@ -21,7 +21,7 @@ describe('AttachAddon', () => { browser = await puppeteer.launch({ headless: process.argv.indexOf('--headless') !== -1, slowMo: 80, - args: [`--window-size=${width},${height}`] + args: [`--window-size=${width},${height}`, `--no-sandbox`] }); page = (await browser.pages())[0]; await page.setViewport({ width, height }); diff --git a/addons/xterm-addon-search/src/SearchAddon.api.ts b/addons/xterm-addon-search/src/SearchAddon.api.ts index 14e12a8c..cb5a02b8 100644 --- a/addons/xterm-addon-search/src/SearchAddon.api.ts +++ b/addons/xterm-addon-search/src/SearchAddon.api.ts @@ -21,7 +21,7 @@ describe('Search Tests', function (): void { browser = await puppeteer.launch({ headless: process.argv.indexOf('--headless') !== -1, slowMo: 80, - args: [`--window-size=${width},${height}`] + args: [`--window-size=${width},${height}`, `--no-sandbox`] }); page = (await browser.pages())[0]; await page.setViewport({ width, height }); diff --git a/addons/xterm-addon-web-links/src/WebLinksAddon.api.ts b/addons/xterm-addon-web-links/src/WebLinksAddon.api.ts index 2c0044be..3fb1a536 100644 --- a/addons/xterm-addon-web-links/src/WebLinksAddon.api.ts +++ b/addons/xterm-addon-web-links/src/WebLinksAddon.api.ts @@ -20,7 +20,7 @@ describe('WebLinksAddon', () => { browser = await puppeteer.launch({ headless: process.argv.indexOf('--headless') !== -1, slowMo: 80, - args: [`--window-size=${width},${height}`] + args: [`--window-size=${width},${height}`, `--no-sandbox`] }); page = (await browser.pages())[0]; await page.setViewport({ width, height }); diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.api.ts b/addons/xterm-addon-webgl/src/WebglRenderer.api.ts index 66be22d9..9303782d 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.api.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.api.ts @@ -22,7 +22,7 @@ describe('WebGL Renderer Integration Tests', function(): void { browser = await puppeteer.launch({ headless: process.argv.indexOf('--headless') !== -1, slowMo: 80, - args: [`--window-size=${width},${height}`] + args: [`--window-size=${width},${height}`, `--no-sandbox`] }); page = (await browser.pages())[0]; await page.setViewport({ width, height }); diff --git a/test/api/CharWidth.api.ts b/test/api/CharWidth.api.ts index 035208cc..0561bf07 100644 --- a/test/api/CharWidth.api.ts +++ b/test/api/CharWidth.api.ts @@ -21,7 +21,7 @@ describe('CharWidth Integration Tests', function(): void { browser = await puppeteer.launch({ headless: process.argv.indexOf('--headless') !== -1, slowMo: 80, - args: [`--window-size=${width},${height}`] + args: [`--window-size=${width},${height}`, `--no-sandbox`] }); page = (await browser.pages())[0]; await page.setViewport({ width, height }); diff --git a/test/api/InputHandler.api.ts b/test/api/InputHandler.api.ts index 05b16010..fe068610 100644 --- a/test/api/InputHandler.api.ts +++ b/test/api/InputHandler.api.ts @@ -21,7 +21,7 @@ describe('InputHandler Integration Tests', function(): void { browser = await puppeteer.launch({ headless: process.argv.indexOf('--headless') !== -1, slowMo: 80, - args: [`--window-size=${width},${height}`] + args: [`--window-size=${width},${height}`, `--no-sandbox`] }); page = (await browser.pages())[0]; await page.setViewport({ width, height }); diff --git a/test/api/MouseTracking.api.ts b/test/api/MouseTracking.api.ts index 90c18f75..602d630c 100644 --- a/test/api/MouseTracking.api.ts +++ b/test/api/MouseTracking.api.ts @@ -216,7 +216,7 @@ describe('Mouse Tracking Tests', function(): void { browser = await puppeteer.launch({ headless: process.argv.indexOf('--headless') !== -1, slowMo: 80, - args: [`--window-size=${width},${height}`] + args: [`--window-size=${width},${height}`, `--no-sandbox`] }); page = (await browser.pages())[0]; await page.setViewport({ width, height }); diff --git a/test/api/Parser.api.ts b/test/api/Parser.api.ts index 28f7d8b3..e46242ab 100644 --- a/test/api/Parser.api.ts +++ b/test/api/Parser.api.ts @@ -21,7 +21,7 @@ describe('Parser Integration Tests', function(): void { browser = await puppeteer.launch({ headless: process.argv.indexOf('--headless') !== -1, slowMo: 80, - args: [`--window-size=${width},${height}`] + args: [`--window-size=${width},${height}`, `--no-sandbox`] }); page = (await browser.pages())[0]; await page.setViewport({ width, height }); diff --git a/test/api/Terminal.api.ts b/test/api/Terminal.api.ts index edbdf8a3..08963d9c 100644 --- a/test/api/Terminal.api.ts +++ b/test/api/Terminal.api.ts @@ -21,7 +21,7 @@ describe('API Integration Tests', function(): void { browser = await puppeteer.launch({ headless: process.argv.indexOf('--headless') !== -1, slowMo: 80, - args: [`--window-size=${width},${height}`] + args: [`--window-size=${width},${height}`, `--no-sandbox`] }); page = (await browser.pages())[0]; await page.setViewport({ width, height }); From 07308485a4957896ad942987b4750dbaecfa6e97 Mon Sep 17 00:00:00 2001 From: Leonardo Bressan Motyczka Date: Wed, 16 Oct 2019 20:08:57 -0300 Subject: [PATCH 11/78] Update MouseTracking puppeteer window size This allows all tests to successfully run in devcontainer --- test/api/MouseTracking.api.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/api/MouseTracking.api.ts b/test/api/MouseTracking.api.ts index 602d630c..1372b567 100644 --- a/test/api/MouseTracking.api.ts +++ b/test/api/MouseTracking.api.ts @@ -11,8 +11,10 @@ const APP = 'http://127.0.0.1:3000/test'; let browser: puppeteer.Browser; let page: puppeteer.Page; -const width = 1024; -const height = 768; +// adjusted to work inside devcontainer +// see https://github.com/xtermjs/xterm.js/issues/2379 +const width = 1280; +const height = 960; // adjust terminal row/col size so we can test // >80 up to 223 and >255 From 990be060f2d4124bfa2e50b56d7f7194a8119951 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 17 Oct 2019 10:00:45 -0700 Subject: [PATCH 12/78] Allow builds to specify a force release var This will let us automate patch releases by queuing a manual build Fixes #2154 --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 26f0ca73..b1ccdbf0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -107,7 +107,7 @@ jobs: - Windows - Linux_IntegrationTests - macOS_IntegrationTests - condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq(variables['Build.SourceBranch'], 'refs/heads/release/*'))) + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq(variables['FORCE_RELEASE'], 'true'))) pool: vmImage: 'ubuntu-16.04' steps: From 08475eb4954c1fff67ea0ab79bb21cd798d7ddfd Mon Sep 17 00:00:00 2001 From: Jon Bockhorst Date: Thu, 17 Oct 2019 12:25:42 -0500 Subject: [PATCH 13/78] Update API to use IViewportRange and IViewportCellPosition --- src/browser/Linkifier.ts | 2 +- src/browser/Types.d.ts | 15 +++++++++------ typings/xterm.d.ts | 33 +++++++++++++++++++-------------- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/browser/Linkifier.ts b/src/browser/Linkifier.ts index d17de1ca..0b51d43f 100644 --- a/src/browser/Linkifier.ts +++ b/src/browser/Linkifier.ts @@ -306,7 +306,7 @@ export class Linkifier implements ILinkifier { e => { this._onLinkTooltip.fire(this._createLinkHoverEvent(x1, y1, x2, y2, fg)); if (matcher.hoverTooltipCallback) { - matcher.hoverTooltipCallback(e, uri, { startRow: y1, startColumn: x1, endRow: y2, endColumn: x2 }); + matcher.hoverTooltipCallback(e, uri, { start: { row: y1, col: x1 }, end: { row: y2, col: x2 } }); } }, () => { diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index bd3d8722..2b9a4a9b 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -43,15 +43,18 @@ export interface IViewport extends IDisposable { onThemeChange(colors: IColorSet): void; } -export interface ILinkLocation { - startColumn: number; - startRow: number; - endColumn: number; - endRow: number; +export interface IViewportRange { + start: IViewportCellPosition; + end: IViewportCellPosition; +} + +export interface IViewportCellPosition { + col: number; + row: number; } export type LinkMatcherHandler = (event: MouseEvent, uri: string) => void; -export type LinkMatcherHoverTooltipCallback = (event: MouseEvent, uri: string, position: ILinkLocation) => void; +export type LinkMatcherHoverTooltipCallback = (event: MouseEvent, uri: string, position: IViewportRange) => void; export type LinkMatcherValidationCallback = (uri: string, callback: (isValid: boolean) => void) => void; export interface ILinkMatcher { diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 2ea8706a..32dce910 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -269,7 +269,7 @@ declare module 'xterm' { /** * A callback that fires when the mouse hovers over a link for a moment. */ - tooltipCallback?: (event: MouseEvent, uri: string, location: ILinkLocation) => boolean | void; + tooltipCallback?: (event: MouseEvent, uri: string, location: IViewportRange) => boolean | void; /** * A callback that fires when the mouse leaves a link. Note that this can @@ -843,28 +843,33 @@ declare module 'xterm' { } /** - * An object representing a link location within the terminal. + * An object representing a range within the viewport of the terminal. */ - interface ILinkLocation { + interface IViewportRange { /** - * The start column of the link. + * The start cell of the range. */ - startColumn: number; + start: IViewportCellPosition; /** - * The start row of the link. + * The end cell of the range. */ - startRow: number; + end: IViewportCellPosition; + } + + /** + * An object representing a cell within the viewport of the terminal. + */ + interface IViewportCellPosition { + /** + * The column of the cell. + */ + col: number; /** - * The end column of the link. + * The row of the cell. */ - endColumn: number; - - /** - * The end row of the link. - */ - endRow: number; + row: number; } /** From 57581ca4ef4b80794eeed996c2b016e954429687 Mon Sep 17 00:00:00 2001 From: Jon Bockhorst Date: Thu, 17 Oct 2019 12:40:32 -0500 Subject: [PATCH 14/78] Updated IViewportCellPosition wording --- typings/xterm.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 32dce910..e7b2247e 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -858,7 +858,7 @@ declare module 'xterm' { } /** - * An object representing a cell within the viewport of the terminal. + * An object representing a cell position within the viewport of the terminal. */ interface IViewportCellPosition { /** From caf075dcb00f7a785fe763bcabd461e374cd741c Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 17 Oct 2019 11:54:32 -0700 Subject: [PATCH 15/78] Create a PR for website update after a release --- bin/publish.js | 20 +++++++++++++++++++- bin/update-website.sh | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 bin/update-website.sh diff --git a/bin/publish.js b/bin/publish.js index d95ecc57..9d58ed15 100644 --- a/bin/publish.js +++ b/bin/publish.js @@ -5,6 +5,7 @@ const cp = require('child_process'); const fs = require('fs'); +const os = require('os'); const path = require('path'); // Setup auth @@ -18,8 +19,9 @@ if (isDryRun) { const changedFiles = getChangedFilesInCommit('HEAD'); // Publish xterm if any files were changed outside of the addons directory +let isStableRelease = false; if (changedFiles.some(e => e.search(/^addons\//) === -1)) { - checkAndPublishPackage(path.resolve(__dirname, '..')); + isStableRelease = checkAndPublishPackage(path.resolve(__dirname, '..')); } // Publish addons if any files were changed inside of the addon @@ -39,6 +41,11 @@ addonPackageDirs.forEach(p => { } }); +// Publish website if it's a stable release +if (isStableRelease) { + updateWebsite(); +} + function checkAndPublishPackage(packageDir) { const packageJson = require(path.join(packageDir, 'package.json')); @@ -76,6 +83,8 @@ function checkAndPublishPackage(packageDir) { } console.groupEnd(); + + return isStableRelease; } function getNextBetaVersion(packageJson) { @@ -115,3 +124,12 @@ function getChangedFilesInCommit(commit) { const changedFiles = output.split('\n').filter(e => e.length > 0); return changedFiles; } + +function updateWebsite() { + console.log('Updating website'); + const cwd = fs.mkdtempSync(path.join(os.tmpdir(), 'website-')); + const packageJson = require(path.join(path.resolve(__dirname, '..'), 'package.json')); + if (!isDryRun) { + cp.spawnSync('sh', [path.join(__dirname, 'update-website.sh'), packageJson.version], { cwd, stdio: [process.stdin, process.stdout, process.stderr] }); + } +} diff --git a/bin/update-website.sh b/bin/update-website.sh new file mode 100644 index 00000000..4379d915 --- /dev/null +++ b/bin/update-website.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# Name the arguments +VERSION=$1 + +# Clone docs repo and update the documentation +git clone https://github.com/xtermjs/xtermjs.org +cd xtermjs.org +yarn +./bin/update-docs + +# Add changes to index and only proceed if there are changes to commit +touch test-file +git add . +if ! git diff-index --quiet HEAD --; then + + # Delete the upstream branch if it exists for some reason + export BRANCH_NAME=update-$VERSION + git branch -D $BRANCH_NAME || true + git push origin :$BRANCH_NAME || true + + # Create commit and push it to update-x.y.z + git checkout -b $BRANCH_NAME + git config --global user.name Daniel Imms + git config --global user.email tyriar@tyriar.com + git commit -m 'Update docs for v$VERSION' + git push --set-upstream origin update-4.2.0 + git push -f + + # Create a PR in the GitHub repo + curl \ + -H "Authorization: token $GITHUB_TOKEN" \ + -X POST \ + -d "{\"title\":\"Update docs for v$VERSION\",\"base\":\"master\",\"head\":\"xtermjs:$BRANCH_NAME\"}" \ + https://api.github.com/repos/xtermjs/xtermjs.org/pulls + +else + + echo "No changes to commit" + +fi From 83508048585ec5c7d5322c27d9d2c9f7d3949d86 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 17 Oct 2019 12:36:03 -0700 Subject: [PATCH 16/78] Adjust to use 1-based, note in API --- src/browser/Linkifier.ts | 4 +++- typings/xterm.d.ts | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/browser/Linkifier.ts b/src/browser/Linkifier.ts index 0b51d43f..ecaf8af9 100644 --- a/src/browser/Linkifier.ts +++ b/src/browser/Linkifier.ts @@ -306,7 +306,9 @@ export class Linkifier implements ILinkifier { e => { this._onLinkTooltip.fire(this._createLinkHoverEvent(x1, y1, x2, y2, fg)); if (matcher.hoverTooltipCallback) { - matcher.hoverTooltipCallback(e, uri, { start: { row: y1, col: x1 }, end: { row: y2, col: x2 } }); + // Note that IViewportRange use 1-based coordinates to align with escape sequences such + // as CUP which use 1,1 as the default for row/col + matcher.hoverTooltipCallback(e, uri, { start: { row: y1 + 1, col: x1 + 1 }, end: { row: y2 + 1, col: x2 } }); } }, () => { diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index e7b2247e..c1f5eab9 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -862,12 +862,12 @@ declare module 'xterm' { */ interface IViewportCellPosition { /** - * The column of the cell. + * The column of the cell. Note that this is 1-based; the first column is column 1. */ col: number; /** - * The row of the cell. + * The row of the cell. Note that this is 1-based; the first row is row 1. */ row: number; } From 44a4bd788f83338891265d133a30de915fc65938 Mon Sep 17 00:00:00 2001 From: Leonardo Bressan Motyczka Date: Fri, 18 Oct 2019 14:48:56 -0300 Subject: [PATCH 17/78] Adjust proposeDimensions to behave like resize --- addons/xterm-addon-fit/src/FitAddon.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/addons/xterm-addon-fit/src/FitAddon.ts b/addons/xterm-addon-fit/src/FitAddon.ts index e25a4783..ca7e24b1 100644 --- a/addons/xterm-addon-fit/src/FitAddon.ts +++ b/addons/xterm-addon-fit/src/FitAddon.ts @@ -17,6 +17,9 @@ interface ITerminalDimensions { cols: number; } +const MINIMUM_COLS = 2; +const MINIMUM_ROWS = 1; + export class FitAddon implements ITerminalAddon { private _terminal: Terminal | undefined; @@ -71,8 +74,8 @@ export class FitAddon implements ITerminalAddon { const availableHeight = parentElementHeight - elementPaddingVer; const availableWidth = parentElementWidth - elementPaddingHor - core.viewport.scrollBarWidth; const geometry = { - cols: Math.floor(availableWidth / core._renderService.dimensions.actualCellWidth), - rows: Math.floor(availableHeight / core._renderService.dimensions.actualCellHeight) + cols: Math.max(MINIMUM_COLS, Math.floor(availableWidth / core._renderService.dimensions.actualCellWidth)), + rows: Math.max(MINIMUM_ROWS, Math.floor(availableHeight / core._renderService.dimensions.actualCellHeight)) }; return geometry; } From a92635b22c82eda268b2b555131acb10ca99c506 Mon Sep 17 00:00:00 2001 From: Leonardo Bressan Motyczka Date: Fri, 18 Oct 2019 14:49:09 -0300 Subject: [PATCH 18/78] Introduce FitAddon tests --- addons/xterm-addon-fit/src/FitAddon.api.ts | 116 +++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 addons/xterm-addon-fit/src/FitAddon.api.ts diff --git a/addons/xterm-addon-fit/src/FitAddon.api.ts b/addons/xterm-addon-fit/src/FitAddon.api.ts new file mode 100644 index 00000000..49d274bc --- /dev/null +++ b/addons/xterm-addon-fit/src/FitAddon.api.ts @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2019 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import * as puppeteer from 'puppeteer'; +import { assert } from 'chai'; +import { ITerminalOptions } from 'xterm'; + +const APP = 'http://127.0.0.1:3000/test'; + +let browser: puppeteer.Browser; +let page: puppeteer.Page; +const width = 1024; +const height = 768; + +describe('FitAddon', () => { + before(async function(): Promise { + this.timeout(20000); + browser = await puppeteer.launch({ + headless: process.argv.indexOf('--headless') !== -1, + slowMo: 80, + args: [`--window-size=${width},${height}`, `--no-sandbox`] + }); + page = (await browser.pages())[0]; + await page.setViewport({ width, height }); + }); + + after(async () => { + await browser.close(); + }); + + beforeEach(async function(): Promise { + this.timeout(20000); + await page.goto(APP); + }); + + describe('proposeDimensions', () => { + it('no terminal', async function(): Promise { + await page.evaluate(`window.fit = new FitAddon();`); + assert.equal(await page.evaluate(`window.fit.proposeDimensions()`), undefined); + }); + + it('default', async function(): Promise { + await openTerminal(); + await loadFit(); + assert.deepEqual(await page.evaluate(`window.fit.proposeDimensions()`), { + cols: 87, + rows: 26 + }); + }); + + it('width', async function(): Promise { + await openTerminal(); + await loadFit(1008); + assert.deepEqual(await page.evaluate(`window.fit.proposeDimensions()`), { + cols: 110, + rows: 26 + }); + }); + + it('small', async function(): Promise { + await openTerminal(); + await loadFit(1, 1); + assert.deepEqual(await page.evaluate(`window.fit.proposeDimensions()`), { + cols: 2, + rows: 1 + }); + }); + }); + + describe('fit', () => { + it('default', async function(): Promise { + await openTerminal(); + await loadFit(); + await page.evaluate(`window.fit.fit()`); + assert.equal(await page.evaluate(`window.term.cols`), 87); + assert.equal(await page.evaluate(`window.term.rows`), 26); + }); + + it('width', async function(): Promise { + await openTerminal(); + await loadFit(1008); + await page.evaluate(`window.fit.fit()`); + assert.equal(await page.evaluate(`window.term.cols`), 110); + assert.equal(await page.evaluate(`window.term.rows`), 26); + }); + + it('small', async function(): Promise { + await openTerminal(); + await loadFit(1, 1); + await page.evaluate(`window.fit.fit()`); + assert.equal(await page.evaluate(`window.term.cols`), 2); + assert.equal(await page.evaluate(`window.term.rows`), 1); + }); + }); +}); + +async function loadFit(width: number = 800, height: number = 450): Promise { + await page.evaluate(` + window.fit = new FitAddon(); + window.term.loadAddon(window.fit); + document.querySelector('#terminal-container').style.width='${width}px'; + document.querySelector('#terminal-container').style.height='${height}px'; + `); +} + +async function openTerminal(options: ITerminalOptions = {}): Promise { + await page.evaluate(`window.term = new Terminal(${JSON.stringify(options)})`); + await page.evaluate(`window.term.open(document.querySelector('#terminal-container'))`); + if (options.rendererType === 'dom') { + await page.waitForSelector('.xterm-rows'); + } else { + await page.waitForSelector('.xterm-text-layer'); + } +} From f8a62a23e59d8a186b5f7cfc1389b1e3d2a2dccb Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 18 Oct 2019 11:23:11 -0700 Subject: [PATCH 19/78] Speed tests up by avoiding page loads --- addons/xterm-addon-fit/src/FitAddon.api.ts | 29 ++++++++++++---------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/addons/xterm-addon-fit/src/FitAddon.api.ts b/addons/xterm-addon-fit/src/FitAddon.api.ts index 49d274bc..f9972aef 100644 --- a/addons/xterm-addon-fit/src/FitAddon.api.ts +++ b/addons/xterm-addon-fit/src/FitAddon.api.ts @@ -14,7 +14,7 @@ let page: puppeteer.Page; const width = 1024; const height = 768; -describe('FitAddon', () => { +describe.only('FitAddon', () => { before(async function(): Promise { this.timeout(20000); browser = await puppeteer.launch({ @@ -24,25 +24,25 @@ describe('FitAddon', () => { }); page = (await browser.pages())[0]; await page.setViewport({ width, height }); + await page.goto(APP); + await openTerminal(); }); after(async () => { await browser.close(); }); - beforeEach(async function(): Promise { - this.timeout(20000); - await page.goto(APP); + it('no terminal', async function(): Promise { + await page.evaluate(`window.fit = new FitAddon();`); + assert.equal(await page.evaluate(`window.fit.proposeDimensions()`), undefined); }); describe('proposeDimensions', () => { - it('no terminal', async function(): Promise { - await page.evaluate(`window.fit = new FitAddon();`); - assert.equal(await page.evaluate(`window.fit.proposeDimensions()`), undefined); + afterEach(async () => { + return unloadFit(); }); it('default', async function(): Promise { - await openTerminal(); await loadFit(); assert.deepEqual(await page.evaluate(`window.fit.proposeDimensions()`), { cols: 87, @@ -51,7 +51,6 @@ describe('FitAddon', () => { }); it('width', async function(): Promise { - await openTerminal(); await loadFit(1008); assert.deepEqual(await page.evaluate(`window.fit.proposeDimensions()`), { cols: 110, @@ -60,7 +59,6 @@ describe('FitAddon', () => { }); it('small', async function(): Promise { - await openTerminal(); await loadFit(1, 1); assert.deepEqual(await page.evaluate(`window.fit.proposeDimensions()`), { cols: 2, @@ -70,8 +68,11 @@ describe('FitAddon', () => { }); describe('fit', () => { + afterEach(async () => { + return unloadFit(); + }); + it('default', async function(): Promise { - await openTerminal(); await loadFit(); await page.evaluate(`window.fit.fit()`); assert.equal(await page.evaluate(`window.term.cols`), 87); @@ -79,7 +80,6 @@ describe('FitAddon', () => { }); it('width', async function(): Promise { - await openTerminal(); await loadFit(1008); await page.evaluate(`window.fit.fit()`); assert.equal(await page.evaluate(`window.term.cols`), 110); @@ -87,7 +87,6 @@ describe('FitAddon', () => { }); it('small', async function(): Promise { - await openTerminal(); await loadFit(1, 1); await page.evaluate(`window.fit.fit()`); assert.equal(await page.evaluate(`window.term.cols`), 2); @@ -105,6 +104,10 @@ async function loadFit(width: number = 800, height: number = 450): Promise `); } +async function unloadFit(): Promise { + await page.evaluate(`window.fit.dispose();`); +} + async function openTerminal(options: ITerminalOptions = {}): Promise { await page.evaluate(`window.term = new Terminal(${JSON.stringify(options)})`); await page.evaluate(`window.term.open(document.querySelector('#terminal-container'))`); From f445bc763b2584f74e46d47fcac496114a838bba Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Fri, 18 Oct 2019 13:51:17 -0400 Subject: [PATCH 20/78] Adds scrollSensitivity option for scrolling speed --- demo/client.ts | 4 ++-- src/browser/Viewport.ts | 11 ++++++----- src/common/services/OptionsService.ts | 7 +++++++ src/common/services/Services.ts | 2 ++ typings/xterm.d.ts | 5 +++++ 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/demo/client.ts b/demo/client.ts index e05a7105..7942cffe 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -254,7 +254,7 @@ function initOptions(term: TerminalType): void { }); html += '
'; numberOptions.forEach(o => { - html += `
`; + html += `
`; }); html += '
'; Object.keys(stringOptions).forEach(o => { @@ -283,7 +283,7 @@ function initOptions(term: TerminalType): void { console.log('change', o, input.value); if (o === 'cols' || o === 'rows') { updateTerminalSize(); - } else if (o === 'lineHeight') { + } else if (o === 'lineHeight' || o === 'scrollSensitivity') { term.setOption(o, parseFloat(input.value)); updateTerminalSize(); } else { diff --git a/src/browser/Viewport.ts b/src/browser/Viewport.ts index 4817ab3b..5edd7b80 100644 --- a/src/browser/Viewport.ts +++ b/src/browser/Viewport.ts @@ -198,7 +198,7 @@ export class Viewport extends Disposable implements IViewport { } // Fallback to WheelEvent.DOM_DELTA_PIXEL - let amount = this._applyFastScrollModifier(ev.deltaY, ev); + let amount = this._applyScrollModifier(ev.deltaY, ev); if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) { amount *= this._currentRowHeight; } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) { @@ -219,7 +219,7 @@ export class Viewport extends Disposable implements IViewport { } // Fallback to WheelEvent.DOM_DELTA_LINE - let amount = this._applyFastScrollModifier(ev.deltaY, ev); + let amount = this._applyScrollModifier(ev.deltaY, ev); if (ev.deltaMode === WheelEvent.DOM_DELTA_PIXEL) { amount /= this._currentRowHeight + 0.0; // Prevent integer division this._wheelPartialScroll += amount; @@ -231,15 +231,16 @@ export class Viewport extends Disposable implements IViewport { return amount; } - private _applyFastScrollModifier(amount: number, ev: WheelEvent): number { + private _applyScrollModifier(amount: number, ev: WheelEvent): number { const modifier = this._optionsService.options.fastScrollModifier; // Multiply the scroll speed when the modifier is down if ((modifier === 'alt' && ev.altKey) || (modifier === 'ctrl' && ev.ctrlKey) || (modifier === 'shift' && ev.shiftKey)) { - return amount * Math.max(1, this._optionsService.options.fastScrollSensitivity); + return amount * this._optionsService.options.fastScrollSensitivity; } - return amount; + + return amount * this._optionsService.options.scrollSensitivity; } /** diff --git a/src/common/services/OptionsService.ts b/src/common/services/OptionsService.ts index 9230421c..ccfca6d9 100644 --- a/src/common/services/OptionsService.ts +++ b/src/common/services/OptionsService.ts @@ -33,6 +33,7 @@ export const DEFAULT_OPTIONS: ITerminalOptions = Object.freeze({ letterSpacing: 0, logLevel: 'info', scrollback: 1000, + scrollSensitivity: 1, screenReaderMode: false, macOptionIsMeta: false, macOptionClickForcesSelection: false, @@ -121,6 +122,12 @@ export class OptionsService implements IOptionsService { throw new Error(`${key} cannot be less than 0, value: ${value}`); } break; + case 'fastScrollSensitivity': + case 'scrollSensitivity': + if (value <= 0) { + throw new Error(`${key} cannot be less than or equal to 0, value: ${value}`); + } + break; } return value; } diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index 1df59f84..0872d3db 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -196,6 +196,7 @@ export interface IPartialTerminalOptions { rows?: number; screenReaderMode?: boolean; scrollback?: number; + scrollSensitivity?: number; tabStopWidth?: number; theme?: ITheme; windowsMode?: boolean; @@ -227,6 +228,7 @@ export interface ITerminalOptions { rows: number; screenReaderMode: boolean; scrollback: number; + scrollSensitivity: number; tabStopWidth: number; theme: ITheme; windowsMode: boolean; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index af7d5ca8..361bafde 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -183,6 +183,11 @@ declare module 'xterm' { */ scrollback?: number; + /** + * The scrolling speed multiplier used for adjusting normal scrolling speed. + */ + scrollSensitivity?: number; + /** * The size of tab stops in the terminal. */ From fc1081661537c0e698dea2cccce5f6c20440a8cf Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 21 Oct 2019 11:27:01 -0700 Subject: [PATCH 21/78] Remove .only from fit test --- addons/xterm-addon-fit/src/FitAddon.api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/xterm-addon-fit/src/FitAddon.api.ts b/addons/xterm-addon-fit/src/FitAddon.api.ts index f9972aef..4f955868 100644 --- a/addons/xterm-addon-fit/src/FitAddon.api.ts +++ b/addons/xterm-addon-fit/src/FitAddon.api.ts @@ -14,7 +14,7 @@ let page: puppeteer.Page; const width = 1024; const height = 768; -describe.only('FitAddon', () => { +describe('FitAddon', () => { before(async function(): Promise { this.timeout(20000); browser = await puppeteer.launch({ From 449ede1d576a72ed36be2e8f19de99be10c36bad Mon Sep 17 00:00:00 2001 From: miguel Date: Mon, 21 Oct 2019 14:55:22 -0400 Subject: [PATCH 22/78] Prevent search result from being deselected if it is the only result remove leading whitespace prevent single search term deselection in findPrevious --- addons/xterm-addon-search/src/SearchAddon.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/addons/xterm-addon-search/src/SearchAddon.ts b/addons/xterm-addon-search/src/SearchAddon.ts index 5893f79f..3c12e4f1 100644 --- a/addons/xterm-addon-search/src/SearchAddon.ts +++ b/addons/xterm-addon-search/src/SearchAddon.ts @@ -59,12 +59,12 @@ export class SearchAddon implements ITerminalAddon { let startCol = 0; let startRow = 0; - + let currentSelection = null; if (this._terminal.hasSelection()) { const incremental = searchOptions ? searchOptions.incremental : false; // Start from the selection end if there is a selection // For incremental search, use existing row - const currentSelection = this._terminal.getSelectionPosition()!; + currentSelection = this._terminal.getSelectionPosition()!; startRow = incremental ? currentSelection.startRow : currentSelection.endRow; startCol = incremental ? currentSelection.startColumn : currentSelection.endColumn; } @@ -97,6 +97,9 @@ export class SearchAddon implements ITerminalAddon { } } + // If there is only one result, return false. + if (!result && currentSelection) return false; + // Set selection and scroll if a result was found return this._selectResult(result); } @@ -123,8 +126,9 @@ export class SearchAddon implements ITerminalAddon { let startCol = this._terminal.cols; let result: ISearchResult | undefined = undefined; const incremental = searchOptions ? searchOptions.incremental : false; + let currentSelection = null; if (this._terminal.hasSelection()) { - const currentSelection = this._terminal.getSelectionPosition()!; + currentSelection = this._terminal.getSelectionPosition()!; // Start from selection start if there is a selection startRow = currentSelection.startRow; startCol = currentSelection.startColumn; @@ -161,6 +165,9 @@ export class SearchAddon implements ITerminalAddon { } } + // If there is only one result, return false. + if (!result && currentSelection) return false; + // Set selection and scroll if a result was found return this._selectResult(result); } From d02086e5c66bcdbf07998e4dcf2a6211dd7481d7 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 21 Oct 2019 14:42:56 -0700 Subject: [PATCH 23/78] Add test to cover search multiple times --- addons/xterm-addon-search/src/SearchAddon.api.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/addons/xterm-addon-search/src/SearchAddon.api.ts b/addons/xterm-addon-search/src/SearchAddon.api.ts index cb5a02b8..e3520116 100644 --- a/addons/xterm-addon-search/src/SearchAddon.api.ts +++ b/addons/xterm-addon-search/src/SearchAddon.api.ts @@ -15,7 +15,7 @@ const width = 800; const height = 600; describe('Search Tests', function (): void { - this.timeout(200000); + this.timeout(20000); before(async function (): Promise { browser = await puppeteer.launch({ @@ -98,6 +98,14 @@ describe('Search Tests', function (): void { await page.evaluate(`window.search.findNext('[A-Z]+', {regex: true, caseSensitive: true})`); assert.deepEqual(await page.evaluate(`window.term.getSelection()`), 'ABCD'); }); + + it('Search for single result twice should not unselect it', async () => { + await writeSync('abc def'); + assert.deepEqual(await page.evaluate(`window.search.findNext('abc')`), true); + assert.deepEqual(await page.evaluate(`window.term.getSelection()`), 'abc'); + assert.deepEqual(await page.evaluate(`window.search.findNext('abc')`), true); + assert.deepEqual(await page.evaluate(`window.term.getSelection()`), 'abc'); + }); }); async function openTerminal(options: ITerminalOptions = {}): Promise { From 7b752be68a7eb9ae1376ca0eab52bfe539295530 Mon Sep 17 00:00:00 2001 From: Jon Bockhorst Date: Mon, 21 Oct 2019 20:24:03 -0500 Subject: [PATCH 24/78] Expose IViewportRange in the public API --- typings/xterm.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 361bafde..8ed3caa2 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -860,7 +860,7 @@ declare module 'xterm' { /** * An object representing a range within the viewport of the terminal. */ - interface IViewportRange { + export interface IViewportRange { /** * The start cell of the range. */ From 7576e8c20226bb799fb451ba802f90c8909304db Mon Sep 17 00:00:00 2001 From: Leonardo Bressan Motyczka Date: Mon, 21 Oct 2019 22:27:25 -0300 Subject: [PATCH 25/78] test-api: Fail fast if .only is used --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index b1ccdbf0..6f4a83af 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -80,7 +80,7 @@ jobs: - script: | yarn start & sleep 10 - yarn test-api --headless + yarn test-api --headless --forbid-only displayName: 'Linux Integration tests' - job: macOS_IntegrationTests @@ -97,7 +97,7 @@ jobs: - script: | yarn start & sleep 10 - yarn test-api --headless + yarn test-api --headless --forbid-only displayName: 'MacOS Integration tests' - job: Release From 09b244ed2fcc69a51de934117c249921c0af6a18 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 21 Oct 2019 18:44:03 -0700 Subject: [PATCH 26/78] Fix NaN comparison --- src/public/Terminal.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/public/Terminal.ts b/src/public/Terminal.ts index b72a4cff..fe34cb36 100644 --- a/src/public/Terminal.ts +++ b/src/public/Terminal.ts @@ -181,7 +181,7 @@ export class Terminal implements ITerminalApi { private _verifyIntegers(...values: number[]): void { values.forEach(value => { - if (value === Infinity || value === NaN || value % 1 !== 0) { + if (value === Infinity || isNaN(value) || value % 1 !== 0) { throw new Error('This API only accepts integers'); } }); From bcdebe7648b50975d28e7cf2ad7c2625f63df700 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 21 Oct 2019 18:46:26 -0700 Subject: [PATCH 27/78] Remove duplicate switch case Guessing this one was the result of a bad merge? --- src/Terminal.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 852d424d..597c14cd 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -383,18 +383,6 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp case 'theme': this._setTheme(this.optionsService.options.theme); break; - case 'scrollback': - const newBufferLength = this.rows + this.optionsService.options.scrollback; - if (this.buffer.lines.length > newBufferLength) { - const amountToTrim = this.buffer.lines.length - newBufferLength; - const needsRefresh = (this.buffer.ydisp - amountToTrim < 0); - this.buffer.lines.trimStart(amountToTrim); - this.buffer.ybase = Math.max(this.buffer.ybase - amountToTrim, 0); - this.buffer.ydisp = Math.max(this.buffer.ydisp - amountToTrim, 0); - if (needsRefresh) { - this.refresh(0, this.rows - 1); - } - } case 'windowsMode': if (this.optionsService.options.windowsMode) { if (!this._windowsMode) { From 6f7c91d0cd3eb4cd4abeb08212fa1373eb06b601 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 21 Oct 2019 18:47:18 -0700 Subject: [PATCH 28/78] Remove useless local var assignment --- src/browser/renderer/CharacterJoinerRegistry.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/browser/renderer/CharacterJoinerRegistry.ts b/src/browser/renderer/CharacterJoinerRegistry.ts index a5abe80f..5385b76b 100644 --- a/src/browser/renderer/CharacterJoinerRegistry.ts +++ b/src/browser/renderer/CharacterJoinerRegistry.ts @@ -303,7 +303,6 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry { // current range ranges[i - 1][1] = Math.max(newRange[1], range[1]); ranges.splice(i, 1); - inRange = false; return ranges; } From 9826f3a14c67ea430fffb269984a72796c65de8a Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 21 Oct 2019 18:47:43 -0700 Subject: [PATCH 29/78] Remove unneeded defensive check --- addons/xterm-addon-webgl/src/GlyphRenderer.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/addons/xterm-addon-webgl/src/GlyphRenderer.ts b/addons/xterm-addon-webgl/src/GlyphRenderer.ts index 186cb2c1..bd4488dc 100644 --- a/addons/xterm-addon-webgl/src/GlyphRenderer.ts +++ b/addons/xterm-addon-webgl/src/GlyphRenderer.ts @@ -105,9 +105,6 @@ export class GlyphRenderer { const gl = this._gl; const program = throwIfFalsy(createProgram(gl, vertexShaderSource, fragmentShaderSource)); - if (program === undefined) { - throw new Error('Could not create WebGL program'); - } this._program = program; // Uniform locations From cfd158cbff8edae45bbb9aadc48e0275a85f5aef Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 21 Oct 2019 18:48:49 -0700 Subject: [PATCH 30/78] Remove unused imports --- addons/xterm-addon-webgl/src/WebglRenderer.ts | 2 +- src/browser/renderer/dom/DomRendererRowFactory.ts | 2 +- src/common/buffer/BufferLine.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts index 3d41e1b5..3f8163ba 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -14,7 +14,7 @@ import { IWebGL2RenderingContext } from './Types'; import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants'; import { RenderModel, COMBINED_CHAR_BIT_MASK } from './RenderModel'; import { Disposable } from 'common/Lifecycle'; -import { DEFAULT_COLOR, CHAR_DATA_CHAR_INDEX, CHAR_DATA_CODE_INDEX, CHAR_DATA_ATTR_INDEX, NULL_CELL_CODE } from 'common/buffer/Constants'; +import { DEFAULT_COLOR, CHAR_DATA_CHAR_INDEX, CHAR_DATA_CODE_INDEX, NULL_CELL_CODE } from 'common/buffer/Constants'; import { Terminal } from 'xterm'; import { getLuminance } from './ColorUtils'; import { IRenderLayer } from './renderLayer/Types'; diff --git a/src/browser/renderer/dom/DomRendererRowFactory.ts b/src/browser/renderer/dom/DomRendererRowFactory.ts index 316645f8..3e3b5df0 100644 --- a/src/browser/renderer/dom/DomRendererRowFactory.ts +++ b/src/browser/renderer/dom/DomRendererRowFactory.ts @@ -8,7 +8,7 @@ import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants'; import { AttributeData } from 'common/buffer/AttributeData'; import { NULL_CELL_CODE, WHITESPACE_CELL_CHAR } from 'common/buffer/Constants'; import { CellData } from 'common/buffer/CellData'; -import { ITerminalOptions, IOptionsService } from 'common/services/Services'; +import { IOptionsService } from 'common/services/Services'; export const BOLD_CLASS = 'xterm-bold'; export const DIM_CLASS = 'xterm-dim'; diff --git a/src/common/buffer/BufferLine.ts b/src/common/buffer/BufferLine.ts index 8e742be3..1e95e004 100644 --- a/src/common/buffer/BufferLine.ts +++ b/src/common/buffer/BufferLine.ts @@ -5,7 +5,7 @@ import { CharData, IBufferLine, ICellData } from 'common/Types'; import { stringFromCodePoint } from 'common/input/TextDecoder'; -import { DEFAULT_COLOR, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_ATTR_INDEX, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, WHITESPACE_CELL_CHAR, Content } from 'common/buffer/Constants'; +import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_ATTR_INDEX, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, WHITESPACE_CELL_CHAR, Content } from 'common/buffer/Constants'; import { CellData } from 'common/buffer/CellData'; import { AttributeData } from 'common/buffer/AttributeData'; From 1dbe482fcb7dbf66320ab593c3f299bca2f2407c Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 21 Oct 2019 19:03:53 -0700 Subject: [PATCH 31/78] Suppress server alerts --- demo/server.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/demo/server.js b/demo/server.js index 9a45d06f..f04705aa 100644 --- a/demo/server.js +++ b/demo/server.js @@ -14,24 +14,26 @@ function startServer() { logs = {}; app.use('/xterm.css', express.static(__dirname + '/../css/xterm.css')); - app.get('/logo.png', (req, res) => res.sendFile(__dirname + '/logo.png')); - - app.get('/', function(req, res){ - res.sendFile(__dirname + '/index.html'); + app.get('/logo.png', (req, res) => { + res.sendFile(__dirname + '/logo.png'); // lgtm [js/missing-rate-limiting] }); - app.get('/test', function(req, res){ - res.sendFile(__dirname + '/test.html'); + app.get('/', (req, res) => { + res.sendFile(__dirname + '/index.html'); // lgtm [js/missing-rate-limiting] }); - app.get('/style.css', function(req, res){ - res.sendFile(__dirname + '/style.css'); + app.get('/test', (req, res) => { + res.sendFile(__dirname + '/test.html'); // lgtm [js/missing-rate-limiting] + }); + + app.get('/style.css', (req, res) => { + res.sendFile(__dirname + '/style.css'); // lgtm [js/missing-rate-limiting] }); app.use('/dist', express.static(__dirname + '/dist')); app.use('/src', express.static(__dirname + '/src')); - app.post('/terminals', function (req, res) { + app.post('/terminals', (req, res) => { const env = Object.assign({}, process.env); env['COLORTERM'] = 'truecolor'; var cols = parseInt(req.query.cols), @@ -55,7 +57,7 @@ function startServer() { res.end(); }); - app.post('/terminals/:pid/size', function (req, res) { + app.post('/terminals/:pid/size', (req, res) => { var pid = parseInt(req.params.pid), cols = parseInt(req.query.cols), rows = parseInt(req.query.rows), From 51ef0d0680e53d61836bf85e14acea322df312fa Mon Sep 17 00:00:00 2001 From: Leonardo Bressan Motyczka Date: Tue, 22 Oct 2019 03:00:18 +0000 Subject: [PATCH 32/78] Update test-unit to allow double dash args --- bin/test.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/bin/test.js b/bin/test.js index 775ec004..760908a3 100644 --- a/bin/test.js +++ b/bin/test.js @@ -15,15 +15,22 @@ let testFiles = [ './out/**/*test.js' ]; -// ability to inject particular test files via -// yarn test [testFileA testFileB ...] +let flagArgs = []; + if (process.argv.length > 2) { - testFiles = process.argv.slice(2); + const args = process.argv.slice(2); + flagArgs = args.filter(e => e.startsWith('--')); + // ability to inject particular test files via + // yarn test [testFileA testFileB ...] + files = args.filter(e => !e.startsWith('--')); + if(files.length){ + testFiles = files; + } } const run = cp.spawnSync( path.resolve(__dirname, '../node_modules/.bin/mocha'), - testFiles, + [...testFiles, ...flagArgs], { cwd: path.resolve(__dirname, '..'), env, @@ -31,4 +38,4 @@ const run = cp.spawnSync( } ); -process.exit(run.status); \ No newline at end of file +process.exit(run.status); From 5c2479944ec865f4df2bb33935f32af4ba395563 Mon Sep 17 00:00:00 2001 From: Leonardo Bressan Motyczka Date: Tue, 22 Oct 2019 03:00:40 +0000 Subject: [PATCH 33/78] Ensure test-unit fails fast if .only present --- azure-pipelines.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 6f4a83af..a58f7fe0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -20,7 +20,7 @@ jobs: yarn displayName: 'Install dependencies and build' - script: | - yarn test-unit + yarn test-unit --forbid-only displayName: 'Unit tests' - script: | yarn lint @@ -38,7 +38,7 @@ jobs: yarn displayName: 'Install dependencies and build' - script: | - yarn test-unit + yarn test-unit --forbid-only displayName: 'Unit tests' - script: | yarn lint @@ -56,7 +56,7 @@ jobs: yarn displayName: 'Install dependencies and build' - script: | - yarn test-unit + yarn test-unit --forbid-only displayName: 'Unit tests' - script: | yarn lint From 495f97cf95034f36166e3b32978ade076752e096 Mon Sep 17 00:00:00 2001 From: Miguel Roncancio Date: Mon, 21 Oct 2019 23:39:01 -0400 Subject: [PATCH 34/78] change return value, import ISelectionPosition --- addons/xterm-addon-search/src/SearchAddon.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/xterm-addon-search/src/SearchAddon.ts b/addons/xterm-addon-search/src/SearchAddon.ts index 3c12e4f1..5f85ebbf 100644 --- a/addons/xterm-addon-search/src/SearchAddon.ts +++ b/addons/xterm-addon-search/src/SearchAddon.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { Terminal, IDisposable, ITerminalAddon } from 'xterm'; +import { Terminal, IDisposable, ITerminalAddon, ISelectionPosition } from 'xterm'; export interface ISearchOptions { regex?: boolean; @@ -59,7 +59,7 @@ export class SearchAddon implements ITerminalAddon { let startCol = 0; let startRow = 0; - let currentSelection = null; + let currentSelection: ISelectionPosition | undefined = undefined; if (this._terminal.hasSelection()) { const incremental = searchOptions ? searchOptions.incremental : false; // Start from the selection end if there is a selection @@ -98,7 +98,7 @@ export class SearchAddon implements ITerminalAddon { } // If there is only one result, return false. - if (!result && currentSelection) return false; + if (!result && currentSelection) return true; // Set selection and scroll if a result was found return this._selectResult(result); @@ -126,7 +126,7 @@ export class SearchAddon implements ITerminalAddon { let startCol = this._terminal.cols; let result: ISearchResult | undefined = undefined; const incremental = searchOptions ? searchOptions.incremental : false; - let currentSelection = null; + let currentSelection: ISelectionPosition | undefined = undefined; if (this._terminal.hasSelection()) { currentSelection = this._terminal.getSelectionPosition()!; // Start from selection start if there is a selection @@ -166,7 +166,7 @@ export class SearchAddon implements ITerminalAddon { } // If there is only one result, return false. - if (!result && currentSelection) return false; + if (!result && currentSelection) return true; // Set selection and scroll if a result was found return this._selectResult(result); From 5d547bffb0fe277ace5be2deb96e12fce2500aa8 Mon Sep 17 00:00:00 2001 From: Miguel Roncancio Date: Mon, 21 Oct 2019 23:39:01 -0400 Subject: [PATCH 35/78] change return value, import ISelectionPosition --- addons/xterm-addon-search/src/SearchAddon.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/addons/xterm-addon-search/src/SearchAddon.ts b/addons/xterm-addon-search/src/SearchAddon.ts index 3c12e4f1..cfee3cb9 100644 --- a/addons/xterm-addon-search/src/SearchAddon.ts +++ b/addons/xterm-addon-search/src/SearchAddon.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { Terminal, IDisposable, ITerminalAddon } from 'xterm'; +import { Terminal, IDisposable, ITerminalAddon, ISelectionPosition } from 'xterm'; export interface ISearchOptions { regex?: boolean; @@ -59,7 +59,7 @@ export class SearchAddon implements ITerminalAddon { let startCol = 0; let startRow = 0; - let currentSelection = null; + let currentSelection: ISelectionPosition | undefined = undefined; if (this._terminal.hasSelection()) { const incremental = searchOptions ? searchOptions.incremental : false; // Start from the selection end if there is a selection @@ -97,8 +97,8 @@ export class SearchAddon implements ITerminalAddon { } } - // If there is only one result, return false. - if (!result && currentSelection) return false; + // If there is only one result, return true. + if (!result && currentSelection) return true; // Set selection and scroll if a result was found return this._selectResult(result); @@ -126,7 +126,7 @@ export class SearchAddon implements ITerminalAddon { let startCol = this._terminal.cols; let result: ISearchResult | undefined = undefined; const incremental = searchOptions ? searchOptions.incremental : false; - let currentSelection = null; + let currentSelection: ISelectionPosition | undefined = undefined; if (this._terminal.hasSelection()) { currentSelection = this._terminal.getSelectionPosition()!; // Start from selection start if there is a selection @@ -165,8 +165,8 @@ export class SearchAddon implements ITerminalAddon { } } - // If there is only one result, return false. - if (!result && currentSelection) return false; + // If there is only one result, return true. + if (!result && currentSelection) return true; // Set selection and scroll if a result was found return this._selectResult(result); From 3ce552cdec206e5e6ee7e5782740e9e90861698c Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 22 Oct 2019 06:33:07 -0700 Subject: [PATCH 36/78] Warn don't throw when open is called on unattached element Related microsoft/vscode#83016 --- src/Terminal.ts | 4 ++++ src/public/Terminal.ts | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 597c14cd..3e7e55ca 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -508,6 +508,10 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp throw new Error('Terminal requires a parent element.'); } + if (!document.body.contains(parent)) { + this._logService.warn('Terminal.open was called on an element that was not attached to the DOM'); + } + this._document = this._parent.ownerDocument; // Create main element container diff --git a/src/public/Terminal.ts b/src/public/Terminal.ts index fe34cb36..c167bed8 100644 --- a/src/public/Terminal.ts +++ b/src/public/Terminal.ts @@ -56,9 +56,6 @@ export class Terminal implements ITerminalApi { this._core.resize(columns, rows); } public open(parent: HTMLElement): void { - if (!document.body.contains(parent)) { - throw new Error('open must be called on an element that is attached to the DOM'); - } this._core.open(parent); } public attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void { From 5e2001f4b57393475d171b2b802e300782cfb7d6 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 22 Oct 2019 07:14:32 -0700 Subject: [PATCH 37/78] Space out if --- bin/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/test.js b/bin/test.js index 760908a3..3b08d4a1 100644 --- a/bin/test.js +++ b/bin/test.js @@ -23,7 +23,7 @@ if (process.argv.length > 2) { // ability to inject particular test files via // yarn test [testFileA testFileB ...] files = args.filter(e => !e.startsWith('--')); - if(files.length){ + if (files.length) { testFiles = files; } } From 616d341e8ce6cd1f4b9c59157414882b9c825a5d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 22 Oct 2019 07:17:37 -0700 Subject: [PATCH 38/78] Avoid initializing to undefined --- addons/xterm-addon-search/src/SearchAddon.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/xterm-addon-search/src/SearchAddon.ts b/addons/xterm-addon-search/src/SearchAddon.ts index cfee3cb9..91fd3977 100644 --- a/addons/xterm-addon-search/src/SearchAddon.ts +++ b/addons/xterm-addon-search/src/SearchAddon.ts @@ -59,7 +59,7 @@ export class SearchAddon implements ITerminalAddon { let startCol = 0; let startRow = 0; - let currentSelection: ISelectionPosition | undefined = undefined; + let currentSelection: ISelectionPosition | undefined; if (this._terminal.hasSelection()) { const incremental = searchOptions ? searchOptions.incremental : false; // Start from the selection end if there is a selection @@ -124,9 +124,9 @@ export class SearchAddon implements ITerminalAddon { const isReverseSearch = true; let startRow = this._terminal.buffer.baseY + this._terminal.rows; let startCol = this._terminal.cols; - let result: ISearchResult | undefined = undefined; + let result: ISearchResult | undefined; const incremental = searchOptions ? searchOptions.incremental : false; - let currentSelection: ISelectionPosition | undefined = undefined; + let currentSelection: ISelectionPosition | undefined; if (this._terminal.hasSelection()) { currentSelection = this._terminal.getSelectionPosition()!; // Start from selection start if there is a selection From 84e4cf7e9c84f8d28dd6418ae9d91f27dfdb449c Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 23 Oct 2019 11:37:17 -0700 Subject: [PATCH 39/78] Remove double space in dts --- typings/xterm.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 8ed3caa2..62670f3d 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -449,7 +449,7 @@ declare module 'xterm' { onLineFeed: IEvent; /** - * Adds an event listener for when a scroll occurs. The event value is the + * Adds an event listener for when a scroll occurs. The event value is the * new position of the viewport. * @returns an `IDisposable` to stop listening. */ From 6d620166b40c8565845b7459f6c4947ba30737ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 24 Oct 2019 17:52:03 +0200 Subject: [PATCH 40/78] fix typo in decoder and add a test case --- src/common/input/TextDecoder.test.ts | 12 ++++++++++++ src/common/input/TextDecoder.ts | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/common/input/TextDecoder.test.ts b/src/common/input/TextDecoder.test.ts index cda74a18..ed42ce05 100644 --- a/src/common/input/TextDecoder.test.ts +++ b/src/common/input/TextDecoder.test.ts @@ -7,6 +7,8 @@ import { assert } from 'chai'; import { StringToUtf32, stringFromCodePoint, Utf8ToUtf32, utf32ToString } from 'common/input/TextDecoder'; import { encode } from 'utf8'; +declare const console: any; + // convert UTF32 codepoints to string function toString(data: Uint32Array, length: number): string { if ((String as any).fromCodePoint) { @@ -214,6 +216,16 @@ describe('text encodings', () => { } assert(decoded, 'Ä€𝄞Ö𝄞€Ü𝄞€'); }); + it('test break after 3 bytes - issue #2495', () => { + const decoder = new Utf8ToUtf32(); + const target = new Uint32Array(5); + const utf8Data = fromByteString('\xf0\xa0\x9c\x8e'); + let written = decoder.decode(utf8Data.slice(0, 3), target); + assert.equal(written, 0); + written = decoder.decode(utf8Data.slice(3), target); + assert.equal(written, 1); + assert(toString(target, written), '𠜎'); + }); }); }); }); diff --git a/src/common/input/TextDecoder.ts b/src/common/input/TextDecoder.ts index 7e141e02..397d25a7 100644 --- a/src/common/input/TextDecoder.ts +++ b/src/common/input/TextDecoder.ts @@ -194,7 +194,7 @@ export class Utf8ToUtf32 { target[size++] = cp; } } else { - if (codepoint < 0x010000 || codepoint > 0x10FFFF) { + if (cp < 0x010000 || cp > 0x10FFFF) { // illegal codepoint } else { target[size++] = cp; From 30d3d4602707f2382572436706fa012e8e8d8115 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 24 Oct 2019 18:04:44 +0200 Subject: [PATCH 41/78] make linter happy --- src/common/input/TextDecoder.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common/input/TextDecoder.test.ts b/src/common/input/TextDecoder.test.ts index ed42ce05..92b0e03a 100644 --- a/src/common/input/TextDecoder.test.ts +++ b/src/common/input/TextDecoder.test.ts @@ -7,7 +7,6 @@ import { assert } from 'chai'; import { StringToUtf32, stringFromCodePoint, Utf8ToUtf32, utf32ToString } from 'common/input/TextDecoder'; import { encode } from 'utf8'; -declare const console: any; // convert UTF32 codepoints to string function toString(data: Uint32Array, length: number): string { From f8fa962ec7d376a9799d60bc76db6ab2537aea83 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 24 Oct 2019 09:35:12 -0700 Subject: [PATCH 42/78] Fix lgtm suppression comment line --- demo/server.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/demo/server.js b/demo/server.js index f04705aa..85e1aca7 100644 --- a/demo/server.js +++ b/demo/server.js @@ -14,20 +14,20 @@ function startServer() { logs = {}; app.use('/xterm.css', express.static(__dirname + '/../css/xterm.css')); - app.get('/logo.png', (req, res) => { - res.sendFile(__dirname + '/logo.png'); // lgtm [js/missing-rate-limiting] + app.get('/logo.png', (req, res) => { // lgtm [js/missing-rate-limiting] + res.sendFile(__dirname + '/logo.png'); }); - app.get('/', (req, res) => { - res.sendFile(__dirname + '/index.html'); // lgtm [js/missing-rate-limiting] + app.get('/', (req, res) => { // lgtm [js/missing-rate-limiting] + res.sendFile(__dirname + '/index.html'); }); - app.get('/test', (req, res) => { - res.sendFile(__dirname + '/test.html'); // lgtm [js/missing-rate-limiting] + app.get('/test', (req, res) => { // lgtm [js/missing-rate-limiting] + res.sendFile(__dirname + '/test.html'); }); - app.get('/style.css', (req, res) => { - res.sendFile(__dirname + '/style.css'); // lgtm [js/missing-rate-limiting] + app.get('/style.css', (req, res) => { // lgtm [js/missing-rate-limiting] + res.sendFile(__dirname + '/style.css'); }); app.use('/dist', express.static(__dirname + '/dist')); From c223524f77b3cb8b91196a1afbd161f20e7f09a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 24 Oct 2019 19:27:35 +0200 Subject: [PATCH 43/78] respect DECSTBM --- src/InputHandler.ts | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index d38fe103..2ffcd5f8 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -1064,10 +1064,14 @@ export class InputHandler extends Disposable implements IInputHandler { * - always left shift (no line orientation setting respected) */ public scrollLeft(params: IParams): void { + const buffer = this._bufferService.buffer; + if (buffer.y > buffer.scrollBottom || buffer.y < buffer.scrollTop) { + return; + } const param = params.params[0] || 1; - for (let y = 0; y < this._bufferService.rows; ++y) { - const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y); - line.deleteCells(0, param, this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())); + for (let y = buffer.scrollTop; y <= buffer.scrollBottom; ++y) { + const line = buffer.lines.get(buffer.ybase + y); + line.deleteCells(0, param, buffer.getNullCell(this._terminal.eraseAttrData())); line.isWrapped = false; } } @@ -1087,10 +1091,14 @@ export class InputHandler extends Disposable implements IInputHandler { * - always right shift (no line orientation setting respected) */ public scrollRight(params: IParams): void { + const buffer = this._bufferService.buffer; + if (buffer.y > buffer.scrollBottom || buffer.y < buffer.scrollTop) { + return; + } const param = params.params[0] || 1; - for (let y = 0; y < this._bufferService.rows; ++y) { - const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y); - line.insertCells(0, param, this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())); + for (let y = buffer.scrollTop; y <= buffer.scrollBottom; ++y) { + const line = buffer.lines.get(buffer.ybase + y); + line.insertCells(0, param, buffer.getNullCell(this._terminal.eraseAttrData())); line.isWrapped = false; } } @@ -1100,10 +1108,14 @@ export class InputHandler extends Disposable implements IInputHandler { * Insert Ps Column(s) (default = 1) (DECIC), VT420 and up. */ public insertColumns(params: IParams): void { + const buffer = this._bufferService.buffer; + if (buffer.y > buffer.scrollBottom || buffer.y < buffer.scrollTop) { + return; + } const param = params.params[0] || 1; - for (let y = 0; y < this._bufferService.rows; ++y) { - const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y); - line.insertCells(this._bufferService.buffer.x, param, this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())); + for (let y = buffer.scrollTop; y <= buffer.scrollBottom; ++y) { + const line = this._bufferService.buffer.lines.get(buffer.ybase + y); + line.insertCells(buffer.x, param, buffer.getNullCell(this._terminal.eraseAttrData())); line.isWrapped = false; } } @@ -1113,10 +1125,14 @@ export class InputHandler extends Disposable implements IInputHandler { * Delete Ps Column(s) (default = 1) (DECDC), VT420 and up. */ public deleteColumns(params: IParams): void { + const buffer = this._bufferService.buffer; + if (buffer.y > buffer.scrollBottom || buffer.y < buffer.scrollTop) { + return; + } const param = params.params[0] || 1; - for (let y = 0; y < this._bufferService.rows; ++y) { - const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y); - line.deleteCells(this._bufferService.buffer.x, param, this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())); + for (let y = buffer.scrollTop; y <= buffer.scrollBottom; ++y) { + const line = buffer.lines.get(buffer.ybase + y); + line.deleteCells(buffer.x, param, buffer.getNullCell(this._terminal.eraseAttrData())); line.isWrapped = false; } } From a4d561d3b9b0acb244afde04b5b01abcd785f31b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 24 Oct 2019 20:36:01 +0200 Subject: [PATCH 44/78] xterm testfiles for SL/SR/DECIC/DECDC with DECSTBM --- .../escape_sequence_files/t600-DECSTBM_SR.in | 25 +++++++++++++++++++ .../t600-DECSTBM_SR.text | 25 +++++++++++++++++++ .../escape_sequence_files/t601-DECSTBM_SL.in | 25 +++++++++++++++++++ .../t601-DECSTBM_SL.text | 25 +++++++++++++++++++ .../t602-DECSTBM_DECIC.in | 25 +++++++++++++++++++ .../t602-DECSTBM_DECIC.text | 25 +++++++++++++++++++ .../t603-DECSTBM_DECDC.in | 25 +++++++++++++++++++ .../t603-DECSTBM_DECDC.text | 25 +++++++++++++++++++ src/InputHandler.ts | 2 +- 9 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 fixtures/escape_sequence_files/t600-DECSTBM_SR.in create mode 100644 fixtures/escape_sequence_files/t600-DECSTBM_SR.text create mode 100644 fixtures/escape_sequence_files/t601-DECSTBM_SL.in create mode 100644 fixtures/escape_sequence_files/t601-DECSTBM_SL.text create mode 100644 fixtures/escape_sequence_files/t602-DECSTBM_DECIC.in create mode 100644 fixtures/escape_sequence_files/t602-DECSTBM_DECIC.text create mode 100644 fixtures/escape_sequence_files/t603-DECSTBM_DECDC.in create mode 100644 fixtures/escape_sequence_files/t603-DECSTBM_DECDC.text diff --git a/fixtures/escape_sequence_files/t600-DECSTBM_SR.in b/fixtures/escape_sequence_files/t600-DECSTBM_SR.in new file mode 100644 index 00000000..9fa002fc --- /dev/null +++ b/fixtures/escape_sequence_files/t600-DECSTBM_SR.in @@ -0,0 +1,25 @@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB[5 A[5 A[5 A \ No newline at end of file diff --git a/fixtures/escape_sequence_files/t600-DECSTBM_SR.text b/fixtures/escape_sequence_files/t600-DECSTBM_SR.text new file mode 100644 index 00000000..8592dd1b --- /dev/null +++ b/fixtures/escape_sequence_files/t600-DECSTBM_SR.text @@ -0,0 +1,25 @@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB diff --git a/fixtures/escape_sequence_files/t601-DECSTBM_SL.in b/fixtures/escape_sequence_files/t601-DECSTBM_SL.in new file mode 100644 index 00000000..e99f5190 --- /dev/null +++ b/fixtures/escape_sequence_files/t601-DECSTBM_SL.in @@ -0,0 +1,25 @@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB[5 @[5 @[5 @ \ No newline at end of file diff --git a/fixtures/escape_sequence_files/t601-DECSTBM_SL.text b/fixtures/escape_sequence_files/t601-DECSTBM_SL.text new file mode 100644 index 00000000..1912cb56 --- /dev/null +++ b/fixtures/escape_sequence_files/t601-DECSTBM_SL.text @@ -0,0 +1,25 @@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +fghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +fghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +fghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +fghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +fghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +fghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB diff --git a/fixtures/escape_sequence_files/t602-DECSTBM_DECIC.in b/fixtures/escape_sequence_files/t602-DECSTBM_DECIC.in new file mode 100644 index 00000000..e31f4e12 --- /dev/null +++ b/fixtures/escape_sequence_files/t602-DECSTBM_DECIC.in @@ -0,0 +1,25 @@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB[5'}[5'}[5'} \ No newline at end of file diff --git a/fixtures/escape_sequence_files/t602-DECSTBM_DECIC.text b/fixtures/escape_sequence_files/t602-DECSTBM_DECIC.text new file mode 100644 index 00000000..f3fa17bc --- /dev/null +++ b/fixtures/escape_sequence_files/t602-DECSTBM_DECIC.text @@ -0,0 +1,25 @@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijk lmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw +abcdefghijk lmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw +abcdefghijk lmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw +abcdefghijk lmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw +abcdefghijk lmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw +abcdefghijk lmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB diff --git a/fixtures/escape_sequence_files/t603-DECSTBM_DECDC.in b/fixtures/escape_sequence_files/t603-DECSTBM_DECDC.in new file mode 100644 index 00000000..ecb966d9 --- /dev/null +++ b/fixtures/escape_sequence_files/t603-DECSTBM_DECDC.in @@ -0,0 +1,25 @@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB[5'~[5'~[5'~ \ No newline at end of file diff --git a/fixtures/escape_sequence_files/t603-DECSTBM_DECDC.text b/fixtures/escape_sequence_files/t603-DECSTBM_DECDC.text new file mode 100644 index 00000000..b98db23c --- /dev/null +++ b/fixtures/escape_sequence_files/t603-DECSTBM_DECDC.text @@ -0,0 +1,25 @@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijkqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijkqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijkqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijkqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijkqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijkqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzAB diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 2ffcd5f8..85d540b3 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -1077,7 +1077,7 @@ export class InputHandler extends Disposable implements IInputHandler { } /** - * CSI Ps SP A Scroll right Ps columns (default = 1) (SL) ECMA-48 + * CSI Ps SP A Scroll right Ps columns (default = 1) (SR) ECMA-48 * * Notation: (Pn) * Representation: CSI Pn 02/00 04/01 From 68d6d5576c2be67091a3a02f44302daa5be0ef88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 24 Oct 2019 21:01:59 +0200 Subject: [PATCH 45/78] force screen update for altered lines --- src/InputHandler.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 85d540b3..21ad8ea0 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -1074,6 +1074,7 @@ export class InputHandler extends Disposable implements IInputHandler { line.deleteCells(0, param, buffer.getNullCell(this._terminal.eraseAttrData())); line.isWrapped = false; } + this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom); } /** @@ -1101,6 +1102,7 @@ export class InputHandler extends Disposable implements IInputHandler { line.insertCells(0, param, buffer.getNullCell(this._terminal.eraseAttrData())); line.isWrapped = false; } + this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom); } /** @@ -1118,6 +1120,7 @@ export class InputHandler extends Disposable implements IInputHandler { line.insertCells(buffer.x, param, buffer.getNullCell(this._terminal.eraseAttrData())); line.isWrapped = false; } + this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom); } /** @@ -1135,6 +1138,7 @@ export class InputHandler extends Disposable implements IInputHandler { line.deleteCells(buffer.x, param, buffer.getNullCell(this._terminal.eraseAttrData())); line.isWrapped = false; } + this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom); } /** From fe08f349184c1b86f55f7cb180f7dee75dae4c2c Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 24 Oct 2019 12:03:18 -0700 Subject: [PATCH 46/78] Use mp3 audio instead of wav wav needs ffmpeg which vscode does not ship with, mp3 is best for compat --- src/common/services/OptionsService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/services/OptionsService.ts b/src/common/services/OptionsService.ts index ccfca6d9..d9ea60d5 100644 --- a/src/common/services/OptionsService.ts +++ b/src/common/services/OptionsService.ts @@ -12,7 +12,7 @@ import { clone } from 'common/Clone'; // This sound is released under the Creative Commons Attribution 3.0 Unported // (CC BY 3.0) license. It was created by 'altemark'. No modifications have been // made, apart from the conversion to base64. -export const DEFAULT_BELL_SOUND = 'data:audio/wav;base64,UklGRigBAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQQBAADpAFgCwAMlBZoG/wdmCcoKRAypDQ8PbRDBEQQTOxRtFYcWlBePGIUZXhoiG88bcBz7HHIdzh0WHlMeZx51HmkeUx4WHs8dah0AHXwc3hs9G4saxRnyGBIYGBcQFv8U4RPAEoYRQBACD70NWwwHC6gJOwjWBloF7gOBAhABkf8b/qv8R/ve+Xf4Ife79W/0JfPZ8Z/wde9N7ijtE+wU6xvqM+lb6H7nw+YX5mrlxuQz5Mzje+Ma49fioeKD4nXiYeJy4pHitOL04j/jn+MN5IPkFOWs5U3mDefM55/ogOl36m7rdOyE7abuyu8D8Unyj/Pg9D/2qfcb+Yn6/vuK/Qj/lAAlAg=='; +export const DEFAULT_BELL_SOUND = 'data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4LjMyLjEwNAAAAAAAAAAAAAAA//tQxAADB8AhSmxhIIEVCSiJrDCQBTcu3UrAIwUdkRgQbFAZC1CQEwTJ9mjRvBA4UOLD8nKVOWfh+UlK3z/177OXrfOdKl7pyn3Xf//WreyTRUoAWgBgkOAGbZHBgG1OF6zM82DWbZaUmMBptgQhGjsyYqc9ae9XFz280948NMBWInljyzsNRFLPWdnZGWrddDsjK1unuSrVN9jJsK8KuQtQCtMBjCEtImISdNKJOopIpBFpNSMbIHCSRpRR5iakjTiyzLhchUUBwCgyKiweBv/7UsQbg8isVNoMPMjAAAA0gAAABEVFGmgqK////9bP/6XCykxBTUUzLjEwMKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq'; // TODO: Freeze? export const DEFAULT_OPTIONS: ITerminalOptions = Object.freeze({ From 5ea016d537130bcadfdf39c1a39a4dd6f8a9bcbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 24 Oct 2019 21:57:22 +0200 Subject: [PATCH 47/78] remove URXVT and UTF8 encoding from codebase --- src/common/services/CoreMouseService.test.ts | 18 +- src/common/services/CoreMouseService.ts | 19 - test/api/MouseTracking.api.ts | 1184 ------------------ 3 files changed, 1 insertion(+), 1220 deletions(-) diff --git a/src/common/services/CoreMouseService.test.ts b/src/common/services/CoreMouseService.test.ts index 2063a496..71d06da5 100644 --- a/src/common/services/CoreMouseService.test.ts +++ b/src/common/services/CoreMouseService.test.ts @@ -34,7 +34,7 @@ describe('CoreMouseService', () => { }); it('default encodings - DEFAULT, UTF8, SGR, URXVT', () => { const cms = new CoreMouseService(bufferService, coreService); - assert.deepEqual(Object.keys((cms as any)._encodings), ['DEFAULT', 'UTF8', 'SGR', 'URXVT']); + assert.deepEqual(Object.keys((cms as any)._encodings), ['DEFAULT', 'SGR']); }); it('protocol/encoding setter, reset', () => { const cms = new CoreMouseService(bufferService, coreService); @@ -151,14 +151,6 @@ describe('CoreMouseService', () => { } } }); - it('UTF8 encoding', () => { - cms.activeProtocol = 'ANY'; - cms.activeEncoding = 'UTF8'; - for (let i = 0; i < bufferService.cols; ++i) { - assert.equal(cms.triggerMouseEvent({ col: i, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), true); - assert.deepEqual(toBytes(reports.pop()), [0x1b, 0x5b, 0x4d, 0x20, i + 33, 0x21]); - } - }); it('SGR encoding', () => { cms.activeProtocol = 'ANY'; cms.activeEncoding = 'SGR'; @@ -167,14 +159,6 @@ describe('CoreMouseService', () => { assert.deepEqual(reports.pop(), `\x1b[<0;${i + 1};1M`); } }); - it('URXVT', () => { - cms.activeProtocol = 'ANY'; - cms.activeEncoding = 'URXVT'; - for (let i = 0; i < bufferService.cols; ++i) { - assert.equal(cms.triggerMouseEvent({ col: i, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), true); - assert.deepEqual(reports.pop(), `\x1b[32;${i + 1};1M`); - } - }); }); it('eventCodes with modifiers (DEFAULT encoding)', () => { // TODO: implement AUX button tests diff --git a/src/common/services/CoreMouseService.ts b/src/common/services/CoreMouseService.ts index 0c846519..19852d16 100644 --- a/src/common/services/CoreMouseService.ts +++ b/src/common/services/CoreMouseService.ts @@ -132,17 +132,6 @@ const DEFAULT_ENCODINGS: {[key: string]: CoreMouseEncoding} = { // FIXED: params = params.map(v => (v > 255) ? 0 : value); return `\x1b[M${S(params[0])}${S(params[1])}${S(params[2])}`; }, - /** - * UTF8 - CSI M Pb Px Py - * Same as DEFAULT, but with optional 2-byte UTF8 - * encoding for values > 223 (can encode up to 2015). - */ - UTF8: (e: ICoreMouseEvent) => { - let params = [eventCode(e, false) + 32, e.col + 32, e.row + 32]; - // limit to 2-byte UTF8 - params = params.map(v => (v > 2047) ? 0 : v); - return `\x1b[M${S(params[0])}${S(params[1])}${S(params[2])}`; - }, /** * SGR - CSI < Pb ; Px ; Py M|m * No encoding limitation. @@ -151,14 +140,6 @@ const DEFAULT_ENCODINGS: {[key: string]: CoreMouseEncoding} = { SGR: (e: ICoreMouseEvent) => { const final = (e.action === CoreMouseAction.UP && e.button !== CoreMouseButton.WHEEL) ? 'm' : 'M'; return `\x1b[<${eventCode(e, true)};${e.col};${e.row}${final}`; - }, - /** - * URXVT - CSI Pb ; Px ; Py M - * Same button encoding as default, decimal encoding for coords. - * Ambiguity with other sequences, should not be used. - */ - URXVT: (e: ICoreMouseEvent) => { - return `\x1b[${eventCode(e, false) + 32};${e.col};${e.row}M`; } }; diff --git a/test/api/MouseTracking.api.ts b/test/api/MouseTracking.api.ts index 1372b567..37d46f74 100644 --- a/test/api/MouseTracking.api.ts +++ b/test/api/MouseTracking.api.ts @@ -167,7 +167,6 @@ function parseReport(encoding: string, msg: number[]): {state: any; row: number; let col: number; // unpack msg const report = String.fromCharCode.apply(null, msg); - // console.log([report]); // skip non mouse reports if (!report || report[0] !== '\x1b') { return report; @@ -179,14 +178,6 @@ function parseReport(encoding: string, msg: number[]): {state: any; row: number; col: report.charCodeAt(4) - 32, row: report.charCodeAt(5) - 32 }; - case 'UTF8': - // TODO: once the binary patch is in place, - // use UTF8 byte check here - return { - state: evalButtonCode(report.charCodeAt(3) - 32), - col: report.charCodeAt(4) - 32, - row: report.charCodeAt(5) - 32 - }; case 'SGR': sReport = report.slice(3, -1); [buttonCode, col, row] = sReport.split(';').map(el => parseInt(el)); @@ -195,10 +186,6 @@ function parseReport(encoding: string, msg: number[]): {state: any; row: number; state.action = 'release'; } return {state, row, col}; - case 'URXVT': - sReport = report.slice(2, -1); - [buttonCode, col, row] = sReport.split(';').map(el => parseInt(el)); - return {state: evalButtonCode(buttonCode - 32), row, col}; default: return { state: evalButtonCode(report.charCodeAt(3) - 32), @@ -373,124 +360,6 @@ describe('Mouse Tracking Tests', function(): void { // await page.keyboard.up('Shift'); assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}]); }); - it.skip('UTF8 encoding', async () => { - const encoding = 'UTF8'; - await resetMouseModes(); - await mouseMove(0, 0); - await page.evaluate(`window.term.write('\x1b[?9h\x1b[?1005h');`); - - // test at 0,0 - await mouseDown('left'); - assert.deepEqual(await getReports(encoding), [{col: 1, row: 1, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}]); - - // mouseup should not report - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), []); - - // mousemove should not report - await mouseMove(50, 10); - assert.deepEqual(await getReports(encoding), []); - await mouseDown('left'); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [{col: 51, row: 11, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}]); - - // test at max rows/cols - await mouseMove(cols - 1, rows - 1); - await mouseDown('left'); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [{col: cols, row: rows, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}]); - - // button press/move/release tests - // left button - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}]); - // middle button - // bug: default action not cancelled (adds data to getReports from clipboard under X11) - // await mouseMove(43, 24); - // await getReports(encoding); // clear reports - // await mouseDown('middle'); - // await mouseMove(44, 24); - // await mouseUp('middle'); - // assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'middle', modifier: {control: false, shift: false, meta: false}}}]); - // right button - // bug: default action not cancelled (popup shown) - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await mouseDown('right'); - await mouseMove(44, 24); - await mouseUp('right'); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'right', modifier: {control: false, shift: false, meta: false}}}]); - - // wheel - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await wheelUp(); - assert.deepEqual(await getReports(encoding), []); - await wheelDown(); - assert.deepEqual(await getReports(encoding), []); - - // modifiers - // CTRL - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Control'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Control'); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}]); - - - // ALT - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Alt'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Alt'); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}]); - - // SHIFT - // note: caught by selection manager - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Shift'); // defaults to ShiftLeft - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Shift'); - if (noShift) { - assert.deepEqual(await getReports(encoding), []); - } else { - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}} - ]); - } - - // all modifiers - // bug: Shift not working - reporting totally wrong coords and modifiers - selection manager again? - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Control'); - await page.keyboard.down('Alt'); - // await page.keyboard.down('Shift'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Control'); - await page.keyboard.up('Alt'); - // await page.keyboard.up('Shift'); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}]); - }); it('SGR encoding', async () => { const encoding = 'SGR'; await resetMouseModes(); @@ -564,125 +433,6 @@ describe('Mouse Tracking Tests', function(): void { assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}]); - // ALT - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Alt'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Alt'); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}]); - - // SHIFT - // note: caught by selection manager - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Shift'); // defaults to ShiftLeft - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Shift'); - if (noShift) { - assert.deepEqual(await getReports(encoding), []); - } else { - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}} - ]); - } - - // all modifiers - // bug: Shift not working - reporting totally wrong coords and modifiers - selection manager again? - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Control'); - await page.keyboard.down('Alt'); - // await page.keyboard.down('Shift'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Control'); - await page.keyboard.up('Alt'); - // await page.keyboard.up('Shift'); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}]); - }); - it.skip('URXVT encoding', async () => { - // bug: always reports +1 for row/col (temp. fixed in parseReport to pass tests) - const encoding = 'URXVT'; - await resetMouseModes(); - await mouseMove(0, 0); - await page.evaluate(`window.term.write('\x1b[?9h\x1b[?1015h');`); - - // test at 0,0 - await mouseDown('left'); - assert.deepEqual(await getReports(encoding), [{col: 1, row: 1, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}]); - - // mouseup should not report - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), []); - - // mousemove should not report - await mouseMove(50, 10); - assert.deepEqual(await getReports(encoding), []); - await mouseDown('left'); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [{col: 51, row: 11, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}]); - - // test at max rows/cols - await mouseMove(cols - 1, rows - 1); - await mouseDown('left'); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [{col: cols, row: rows, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}]); - - // button press/move/release tests - // left button - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}]); - // middle button - // bug: default action not cancelled (adds data to getReports from clipboard under X11) - // await mouseMove(43, 24); - // await getReports(encoding); // clear reports - // await mouseDown('middle'); - // await mouseMove(44, 24); - // await mouseUp('middle'); - // assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'middle', modifier: {control: false, shift: false, meta: false}}}]); - // right button - // bug: default action not cancelled (popup shown) - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await mouseDown('right'); - await mouseMove(44, 24); - await mouseUp('right'); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'right', modifier: {control: false, shift: false, meta: false}}}]); - - // wheel - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await wheelUp(); - assert.deepEqual(await getReports(encoding), []); - await wheelDown(); - assert.deepEqual(await getReports(encoding), []); - - // modifiers - // CTRL - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Control'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Control'); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}]); - - // ALT await mouseMove(43, 24); await getReports(encoding); // clear reports @@ -889,155 +639,6 @@ describe('Mouse Tracking Tests', function(): void { {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: true}}} ]); }); - it.skip('UTF8 encoding', async () => { - const encoding = 'UTF8'; - await resetMouseModes(); - await mouseMove(0, 0); - await page.evaluate(`window.term.write('\x1b[?1000h\x1b[?1005h');`); - - // test at 0,0 - await mouseDown('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 1, row: 1, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}} - ]); - - // mouseup should report, encoding cannot report released button - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 1, row: 1, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // mousemove should not report - await mouseMove(50, 10); - assert.deepEqual(await getReports(encoding), []); - await mouseDown('left'); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 51, row: 11, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: 51, row: 11, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // test at max rows/cols - await mouseMove(cols - 1, rows - 1); - await mouseDown('left'); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: cols, row: rows, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: cols, row: rows, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // button press/move/release tests - // left button - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - // middle button - // bug: default action not cancelled (adds data to getReports from clipboard under X11) - // await mouseMove(43, 24); - // await getReports(encoding); // clear reports - // await mouseDown('middle'); - // await mouseMove(44, 24); - // await mouseUp('middle'); - // assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'middle', modifier: {control: false, shift: false, meta: false}}}]); - // right button - // bug: default action not cancelled (popup shown) - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await mouseDown('right'); - await mouseMove(44, 24); - await mouseUp('right'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'right', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // wheel - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await wheelUp(); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'up', button: 'wheel', modifier: {control: false, shift: false, meta: false}}}]); - await wheelDown(); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: false, meta: false}}}]); - - // modifiers - // CTRL - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Control'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Control'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: true, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: true, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: false}}} - ]); - - // ALT - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Alt'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Alt'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: false, meta: true}}} - ]); - - // SHIFT - // note: press/release caught by selection manager - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Shift'); // defaults to ShiftLeft - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Shift'); - if (noShift) { - assert.deepEqual(await getReports(encoding), [ - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: true, meta: false}}} - ]); - } else { - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: true, meta: false}}} - ]); - } - - // all modifiers - // bug: Shift not working - selection manager? - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Control'); - await page.keyboard.down('Alt'); - // await page.keyboard.down('Shift'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Control'); - await page.keyboard.up('Alt'); - // await page.keyboard.up('Shift'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: true, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: true, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: true}}} - ]); - }); it('SGR encoding', async () => { const encoding = 'SGR'; await resetMouseModes(); @@ -1187,155 +788,6 @@ describe('Mouse Tracking Tests', function(): void { {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: true}}} ]); }); - it.skip('URXVT encoding', async () => { - const encoding = 'URXVT'; - await resetMouseModes(); - await mouseMove(0, 0); - await page.evaluate(`window.term.write('\x1b[?1000h\x1b[?1015h');`); - - // test at 0,0 - await mouseDown('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 1, row: 1, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}} - ]); - - // mouseup should report, encoding cannot report released button - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 1, row: 1, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // mousemove should not report - await mouseMove(50, 10); - assert.deepEqual(await getReports(encoding), []); - await mouseDown('left'); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 51, row: 11, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: 51, row: 11, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // test at max rows/cols - await mouseMove(cols - 1, rows - 1); - await mouseDown('left'); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: cols, row: rows, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: cols, row: rows, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // button press/move/release tests - // left button - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - // middle button - // bug: default action not cancelled (adds data to getReports from clipboard under X11) - // await mouseMove(43, 24); - // await getReports(encoding); // clear reports - // await mouseDown('middle'); - // await mouseMove(44, 24); - // await mouseUp('middle'); - // assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'middle', modifier: {control: false, shift: false, meta: false}}}]); - // right button - // bug: default action not cancelled (popup shown) - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await mouseDown('right'); - await mouseMove(44, 24); - await mouseUp('right'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'right', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // wheel - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await wheelUp(); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'up', button: 'wheel', modifier: {control: false, shift: false, meta: false}}}]); - await wheelDown(); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: false, meta: false}}}]); - - // modifiers - // CTRL - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Control'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Control'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: true, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: true, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: false}}} - ]); - - // ALT - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Alt'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Alt'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: false, meta: true}}} - ]); - - // SHIFT - // note: press/release caught by selection manager - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Shift'); // defaults to ShiftLeft - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Shift'); - if (noShift) { - assert.deepEqual(await getReports(encoding), [ - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: true, meta: false}}} - ]); - } else { - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: true, meta: false}}} - ]); - } - - // all modifiers - // bug: Shift not working - selection manager? - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Control'); - await page.keyboard.down('Alt'); - // await page.keyboard.down('Shift'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Control'); - await page.keyboard.up('Alt'); - // await page.keyboard.up('Shift'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: true, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: true, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: true}}} - ]); - }); }); describe('DECSET 1002 (xterm with drag)', () => { /** @@ -1502,164 +954,6 @@ describe('Mouse Tracking Tests', function(): void { {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: true}}} ]); }); - it.skip('UTF8 encoding', async () => { - const encoding = 'UTF8'; - await resetMouseModes(); - await mouseMove(0, 0); - await page.evaluate(`window.term.write('\x1b[?1002h\x1b[?1005h');`); - - // test at 0,0 - // bug: release is fired immediately - await mouseDown('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 1, row: 1, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}} - ]); - - // mouseup should report, encoding cannot report released button - // bug: release already fired thus no event here - expected: release event - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 1, row: 1, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // mousemove should not report - await mouseMove(50, 10); - assert.deepEqual(await getReports(encoding), []); - await mouseDown('left'); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 51, row: 11, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: 51, row: 11, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // test at max rows/cols - await mouseMove(cols - 1, rows - 1); - await mouseDown('left'); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: cols, row: rows, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: cols, row: rows, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // button press/move/release tests - // left button - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - // middle button - // bug: default action not cancelled (adds data to getReports from clipboard under X11) - // await mouseMove(43, 24); - // await getReports(encoding); // clear reports - // await mouseDown('middle'); - // await mouseMove(44, 24); - // await mouseUp('middle'); - // assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'middle', modifier: {control: false, shift: false, meta: false}}}]); - // right button - // bug: default action not cancelled (popup shown) - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await mouseDown('right'); - await mouseMove(44, 24); - await mouseUp('right'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'right', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'move', button: 'right', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // wheel - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await wheelUp(); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'up', button: 'wheel', modifier: {control: false, shift: false, meta: false}}}]); - await wheelDown(); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: false, meta: false}}}]); - - // modifiers - // CTRL - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Control'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Control'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: true, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: true, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: true, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: false}}} - ]); - - // ALT - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Alt'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Alt'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: false, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: false, meta: true}}} - ]); - - // SHIFT - // note: press/release/drag caught by selection manager - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Shift'); // defaults to ShiftLeft - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Shift'); - if (noShift) { - assert.deepEqual(await getReports(encoding), [ - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: true, meta: false}}} - ]); - } else { - // bug: completely messed up - wrong modifier, only partially reported - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: true, meta: false}}} - ]); - } - - // all modifiers - // bug: Shift not working - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Control'); - await page.keyboard.down('Alt'); - // await page.keyboard.down('Shift'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Control'); - await page.keyboard.up('Alt'); - // await page.keyboard.up('Shift'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: true, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: true, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: true, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: true}}} - ]); - }); it('SGR encoding', async () => { const encoding = 'SGR'; await resetMouseModes(); @@ -1816,162 +1110,6 @@ describe('Mouse Tracking Tests', function(): void { {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: true}}} ]); }); - it.skip('URXVT encoding', async () => { - const encoding = 'URXVT'; - await resetMouseModes(); - await mouseMove(0, 0); - await page.evaluate(`window.term.write('\x1b[?1002h\x1b[?1015h');`); - - // test at 0,0 - // bug: release is fired immediately - await mouseDown('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 1, row: 1, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}} - ]); - - // mouseup should report, encoding cannot report released button - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 1, row: 1, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // mousemove should not report - await mouseMove(50, 10); - assert.deepEqual(await getReports(encoding), []); - await mouseDown('left'); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 51, row: 11, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: 51, row: 11, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // test at max rows/cols - await mouseMove(cols - 1, rows - 1); - await mouseDown('left'); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: cols, row: rows, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: cols, row: rows, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // button press/move/release tests - // left button - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - // middle button - // bug: default action not cancelled (adds data to getReports from clipboard under X11) - // await mouseMove(43, 24); - // await getReports(encoding); // clear reports - // await mouseDown('middle'); - // await mouseMove(44, 24); - // await mouseUp('middle'); - // assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'middle', modifier: {control: false, shift: false, meta: false}}}]); - // right button - // bug: default action not cancelled (popup shown) - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await mouseDown('right'); - await mouseMove(44, 24); - await mouseUp('right'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'right', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'move', button: 'right', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // wheel - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await wheelUp(); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'up', button: 'wheel', modifier: {control: false, shift: false, meta: false}}}]); - await wheelDown(); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: false, meta: false}}}]); - - // modifiers - // CTRL - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Control'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Control'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: true, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: true, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: true, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: false}}} - ]); - - // ALT - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Alt'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Alt'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: false, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: false, meta: true}}} - ]); - - // SHIFT - // note: press/release/drag caught by selection manager - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Shift'); // defaults to ShiftLeft - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Shift'); - if (noShift) { - assert.deepEqual(await getReports(encoding), [ - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: true, meta: false}}} - ]); - } else { - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: true, meta: false}}} - ]); - } - - // all modifiers - // bug: Shift not working - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await page.keyboard.down('Control'); - await page.keyboard.down('Alt'); - // await page.keyboard.down('Shift'); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Control'); - await page.keyboard.up('Alt'); - // await page.keyboard.up('Shift'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: true, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: true, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: true, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: true}}} - ]); - }); }); describe('DECSET 1003 (xterm any event)', () => { /** @@ -2139,167 +1277,6 @@ describe('Mouse Tracking Tests', function(): void { {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: true}}} ]); }); - it.skip('UTF8 encoding', async () => { - const encoding = 'UTF8'; - await resetMouseModes(); - await mouseMove(0, 0); - await page.evaluate(`window.term.write('\x1b[?1003h\x1b[?1005h');`); - - // test at 0,0 - await mouseDown('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 1, row: 1, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}} - ]); - - // mouseup should report, encoding cannot report released button - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 1, row: 1, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // mousemove should report - await mouseMove(50, 10); - assert.deepEqual(await getReports(encoding), [ - {col: 51, row: 11, state: {action: 'move', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - await mouseDown('left'); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 51, row: 11, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: 51, row: 11, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // test at max rows/cols - // bug: we are capped at col 95 currently - // fix: allow values up to 223, any bigger should drop to 0 - await mouseMove(cols - 1, rows - 1); - await mouseDown('left'); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: cols, row: rows, state: {action: 'move', button: '', modifier: {control: false, shift: false, meta: false}}}, - {col: cols, row: rows, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: cols, row: rows, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // button press/move/release tests - // left button - await mouseMove(43, 24); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'move', button: '', modifier: {control: false, shift: false, meta: false}}}, - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - // middle button - // bug: default action not cancelled (adds data to getReports from clipboard under X11) - // await mouseMove(43, 24); - // await getReports(encoding); // clear reports - // await mouseDown('middle'); - // await mouseMove(44, 24); - // await mouseUp('middle'); - // assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'middle', modifier: {control: false, shift: false, meta: false}}}]); - // right button - // bug: default action not cancelled (popup shown) - await mouseMove(43, 24); - await mouseDown('right'); - await mouseMove(44, 24); - await mouseUp('right'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'move', button: '', modifier: {control: false, shift: false, meta: false}}}, - {col: 44, row: 25, state: {action: 'press', button: 'right', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'move', button: 'right', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // wheel - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await wheelUp(); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'up', button: 'wheel', modifier: {control: false, shift: false, meta: false}}}]); - await wheelDown(); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: false, meta: false}}}]); - - // modifiers - // CTRL - await page.keyboard.down('Control'); - await mouseMove(43, 24); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Control'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'move', button: '', modifier: {control: true, shift: false, meta: false}}}, - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: true, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: true, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: true, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: false}}} - ]); - - // ALT - await page.keyboard.down('Alt'); - await mouseMove(43, 24); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Alt'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'move', button: '', modifier: {control: false, shift: false, meta: true}}}, - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: false, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: false, meta: true}}} - ]); - - // SHIFT - // note: press/release/drag caught by selection manager - await page.keyboard.down('Shift'); - await mouseMove(43, 24); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Shift'); - if (noShift) { - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'move', button: '', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: true, meta: false}}} - ]); - } else { - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'move', button: '', modifier: {control: false, shift: true, meta: false}}}, - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: true, meta: false}}} - ]); - } - - // all modifiers - // bug: Shift not working - await page.keyboard.down('Control'); - await page.keyboard.down('Alt'); - // await page.keyboard.down('Shift'); - await mouseMove(43, 24); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Control'); - await page.keyboard.up('Alt'); - // await page.keyboard.up('Shift'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'move', button: '', modifier: {control: true, shift: false, meta: true}}}, - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: true, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: true, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: true, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: true}}} - ]); - }); it('SGR encoding', async () => { const encoding = 'SGR'; await resetMouseModes(); @@ -2461,167 +1438,6 @@ describe('Mouse Tracking Tests', function(): void { {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: true}}} ]); }); - it.skip('URXVT encoding', async () => { - const encoding = 'URXVT'; - await resetMouseModes(); - await mouseMove(0, 0); - await page.evaluate(`window.term.write('\x1b[?1003h\x1b[?1015h');`); - - // test at 0,0 - await mouseDown('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 1, row: 1, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}} - ]); - - // mouseup should report, encoding cannot report released button - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 1, row: 1, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // mousemove should report - await mouseMove(50, 10); - assert.deepEqual(await getReports(encoding), [ - {col: 51, row: 11, state: {action: 'move', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - await mouseDown('left'); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 51, row: 11, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: 51, row: 11, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // test at max rows/cols - // bug: we are capped at col 95 currently - // fix: allow values up to 223, any bigger should drop to 0 - await mouseMove(cols - 1, rows - 1); - await mouseDown('left'); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: cols, row: rows, state: {action: 'move', button: '', modifier: {control: false, shift: false, meta: false}}}, - {col: cols, row: rows, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: cols, row: rows, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // button press/move/release tests - // left button - await mouseMove(43, 24); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'move', button: '', modifier: {control: false, shift: false, meta: false}}}, - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - // middle button - // bug: default action not cancelled (adds data to getReports from clipboard under X11) - // await mouseMove(43, 24); - // await getReports(encoding); // clear reports - // await mouseDown('middle'); - // await mouseMove(44, 24); - // await mouseUp('middle'); - // assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'press', button: 'middle', modifier: {control: false, shift: false, meta: false}}}]); - // right button - // bug: default action not cancelled (popup shown) - await mouseMove(43, 24); - await mouseDown('right'); - await mouseMove(44, 24); - await mouseUp('right'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'move', button: '', modifier: {control: false, shift: false, meta: false}}}, - {col: 44, row: 25, state: {action: 'press', button: 'right', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'move', button: 'right', modifier: {control: false, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: false}}} - ]); - - // wheel - await mouseMove(43, 24); - await getReports(encoding); // clear reports - await wheelUp(); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'up', button: 'wheel', modifier: {control: false, shift: false, meta: false}}}]); - await wheelDown(); - assert.deepEqual(await getReports(encoding), [{col: 44, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: false, meta: false}}}]); - - // modifiers - // CTRL - await page.keyboard.down('Control'); - await mouseMove(43, 24); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Control'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'move', button: '', modifier: {control: true, shift: false, meta: false}}}, - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: true, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: true, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: true, shift: false, meta: false}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: false}}} - ]); - - // ALT - await page.keyboard.down('Alt'); - await mouseMove(43, 24); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Alt'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'move', button: '', modifier: {control: false, shift: false, meta: true}}}, - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: false, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: false, meta: true}}} - ]); - - // SHIFT - // note: press/release/drag caught by selection manager - await page.keyboard.down('Shift'); - await mouseMove(43, 24); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Shift'); - if (noShift) { - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'move', button: '', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: true, meta: false}}} - ]); - } else { - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'move', button: '', modifier: {control: false, shift: true, meta: false}}}, - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: false, shift: true, meta: false}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: false, shift: true, meta: false}}} - ]); - } - - // all modifiers - // bug: Shift not working - await page.keyboard.down('Control'); - await page.keyboard.down('Alt'); - // await page.keyboard.down('Shift'); - await mouseMove(43, 24); - await mouseDown('left'); - await mouseMove(44, 24); - await mouseUp('left'); - await wheelDown(); - await page.keyboard.up('Control'); - await page.keyboard.up('Alt'); - // await page.keyboard.up('Shift'); - assert.deepEqual(await getReports(encoding), [ - {col: 44, row: 25, state: {action: 'move', button: '', modifier: {control: true, shift: false, meta: true}}}, - {col: 44, row: 25, state: {action: 'press', button: 'left', modifier: {control: true, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'move', button: 'left', modifier: {control: true, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'release', button: '', modifier: {control: true, shift: false, meta: true}}}, - {col: 45, row: 25, state: {action: 'down', button: 'wheel', modifier: {control: true, shift: false, meta: true}}} - ]); - }); }); /** * move tests with multiple buttons pressed: From 13ddaf8f988a5332d7f828d2c76c50837e193844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 24 Oct 2019 22:32:10 +0200 Subject: [PATCH 48/78] limit parse buffer size --- src/InputHandler.test.ts | 18 ++++++++++++++++++ src/InputHandler.ts | 29 ++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index ca63bdae..d8defa1c 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -1248,4 +1248,22 @@ describe('InputHandler', () => { assert.deepEqual(getLines(term, term.rows + 1), ['12345', '125', '125', '125', '125', '125']); }); }); + it('should parse big chunks in smaller subchunks', () => { + // max single chunk size is hardcoded as 131072 + const calls: any[] = []; + const term = new TestTerminal({cols: 10, rows: 10}); + (term as any)._inputHandler._parser.parse = (data: Uint32Array, length: number) => { + calls.push([data.length, length]); + }; + term.writeSync('12345'); + term.writeSync('a'.repeat(10000)); + term.writeSync('a'.repeat(200000)); + term.writeSync('a'.repeat(300000)); + assert.deepEqual(calls, [ + [4096, 5], + [10000, 10000], + [131072, 131072], [131072, 200000 - 131072], + [131072, 131072], [131072, 131072], [131072, 300000 - 131072 - 131072] + ]); + }); }); diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 21ad8ea0..f0f8d147 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -28,6 +28,11 @@ import { DcsHandler } from 'common/parser/DcsParser'; */ const GLEVEL: {[key: string]: number} = {'(': 0, ')': 1, '*': 2, '+': 3, '-': 1, '.': 2}; +/** + * Max length of the UTF32 input buffer. Real memory consumption is 4 times higher. + */ +const MAX_PARSEBUFFER_LENGTH = 131072; + /** * DCS subparser implementations @@ -335,14 +340,28 @@ export class InputHandler extends Disposable implements IInputHandler { this._logService.debug('parsing data', data); + // resize input buffer if needed if (this._parseBuffer.length < data.length) { - this._parseBuffer = new Uint32Array(data.length); + if (this._parseBuffer.length < MAX_PARSEBUFFER_LENGTH) { + this._parseBuffer = new Uint32Array(Math.min(data.length, MAX_PARSEBUFFER_LENGTH)); + } } - this._parser.parse(this._parseBuffer, - (typeof data === 'string') + + // process big data in smaller chunks + if (data.length > MAX_PARSEBUFFER_LENGTH) { + for (let i = 0; i < data.length; i += MAX_PARSEBUFFER_LENGTH) { + const end = i + MAX_PARSEBUFFER_LENGTH < data.length ? i + MAX_PARSEBUFFER_LENGTH : data.length; + const len = (typeof data === 'string') + ? this._stringDecoder.decode(data.substring(i, end), this._parseBuffer) + : this._utf8Decoder.decode(data.subarray(i, end), this._parseBuffer); + this._parser.parse(this._parseBuffer, len); + } + } else { + const len = (typeof data === 'string') ? this._stringDecoder.decode(data, this._parseBuffer) - : this._utf8Decoder.decode(data, this._parseBuffer) - ); + : this._utf8Decoder.decode(data, this._parseBuffer); + this._parser.parse(this._parseBuffer, len); + } buffer = this._bufferService.buffer; if (buffer.x !== cursorStartX || buffer.y !== cursorStartY) { From 31be1ebc533ad2fdf807e0a5e2218d049fad1cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Fri, 25 Oct 2019 12:41:31 +0200 Subject: [PATCH 49/78] remove DECSET 1005 and 1015 from InputHandler --- src/InputHandler.ts | 18 ++++++++---------- src/common/services/CoreMouseService.test.ts | 2 +- src/common/services/CoreMouseService.ts | 2 +- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 74358583..1b384660 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -1321,16 +1321,14 @@ export class InputHandler extends Disposable implements IInputHandler { // focusout: ^[[O this._terminal.sendFocus = true; break; - case 1005: // utf8 ext mode mouse - // for wide terminals - // simply encodes large values as utf8 characters - this._coreMouseService.activeEncoding = 'UTF8'; + case 1005: // utf8 ext mode mouse - removed in #2507 + this._logService.debug('DECSET 1005 not supported (see #2507)'); break; case 1006: // sgr ext mode mouse this._coreMouseService.activeEncoding = 'SGR'; break; - case 1015: // urxvt ext mode mouse - this._coreMouseService.activeEncoding = 'URXVT'; + case 1015: // urxvt ext mode mouse - removed in #2507 + this._logService.debug('DECSET 1005 not supported (see #2507)'); break; case 25: // show cursor this._terminal.cursorHidden = false; @@ -1494,14 +1492,14 @@ export class InputHandler extends Disposable implements IInputHandler { case 1004: // send focusin/focusout events this._terminal.sendFocus = false; break; - case 1005: // utf8 ext mode mouse - this._coreMouseService.activeEncoding = 'DEFAULT'; + case 1005: // utf8 ext mode mouse - removed in #2507 + this._logService.debug('DECRST 1005 not supported (see #2507)'); break; case 1006: // sgr ext mode mouse this._coreMouseService.activeEncoding = 'DEFAULT'; break; - case 1015: // urxvt ext mode mouse - this._coreMouseService.activeEncoding = 'DEFAULT'; + case 1015: // urxvt ext mode mouse - removed in #2507 + this._logService.debug('DECRST 1015 not supported (see #2507)'); break; case 25: // hide cursor this._terminal.cursorHidden = true; diff --git a/src/common/services/CoreMouseService.test.ts b/src/common/services/CoreMouseService.test.ts index 71d06da5..f7d3bf83 100644 --- a/src/common/services/CoreMouseService.test.ts +++ b/src/common/services/CoreMouseService.test.ts @@ -32,7 +32,7 @@ describe('CoreMouseService', () => { const cms = new CoreMouseService(bufferService, coreService); assert.deepEqual(Object.keys((cms as any)._protocols), ['NONE', 'X10', 'VT200', 'DRAG', 'ANY']); }); - it('default encodings - DEFAULT, UTF8, SGR, URXVT', () => { + it('default encodings - DEFAULT, SGR', () => { const cms = new CoreMouseService(bufferService, coreService); assert.deepEqual(Object.keys((cms as any)._encodings), ['DEFAULT', 'SGR']); }); diff --git a/src/common/services/CoreMouseService.ts b/src/common/services/CoreMouseService.ts index 19852d16..500655b9 100644 --- a/src/common/services/CoreMouseService.ts +++ b/src/common/services/CoreMouseService.ts @@ -148,7 +148,7 @@ const DEFAULT_ENCODINGS: {[key: string]: CoreMouseEncoding} = { * * Provides mouse tracking reports with different protocols and encodings. * - protocols: NONE (default), X10, VT200, DRAG, ANY - * - encodings: DEFAULT, SGR, UTF8, URXVT + * - encodings: DEFAULT, SGR (UTF8, URXVT removed in #2507) * * Custom protocols/encodings can be added by `addProtocol` / `addEncoding`. * To activate a protocol/encoding, set `activeProtocol` / `activeEncoding`. From ee2c1f71ef2180111d9df4d3d2c3ed6ff44094ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Fri, 25 Oct 2019 12:43:34 +0200 Subject: [PATCH 50/78] fix typo in debug msg --- src/InputHandler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 3ede2bed..7b6ea1fe 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -1441,7 +1441,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._coreMouseService.activeEncoding = 'SGR'; break; case 1015: // urxvt ext mode mouse - removed in #2507 - this._logService.debug('DECSET 1005 not supported (see #2507)'); + this._logService.debug('DECSET 1015 not supported (see #2507)'); break; case 25: // show cursor this._terminal.cursorHidden = false; From 67e5974eee035d338b4135ac1fdde298460906d6 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 25 Oct 2019 04:04:17 -0700 Subject: [PATCH 51/78] Set disposed marker line to -1 Another indicator that it's disposed/invalid --- src/common/buffer/Marker.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/buffer/Marker.ts b/src/common/buffer/Marker.ts index 7f52ac99..9a4256d3 100644 --- a/src/common/buffer/Marker.ts +++ b/src/common/buffer/Marker.ts @@ -29,6 +29,7 @@ export class Marker extends Disposable implements IMarker { return; } this.isDisposed = true; + this.line = -1; // Emit before super.dispose such that dispose listeners get a change to react this._onDispose.fire(); } From dac2da05bf1d3ccdc19f17296e49d6c53ff612d7 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 25 Oct 2019 04:13:03 -0700 Subject: [PATCH 52/78] Clarify marker API docs --- typings/xterm.d.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 62670f3d..7d19283f 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -325,7 +325,8 @@ declare module 'xterm' { /** * Represents a specific line in the terminal that is tracked when scrollback - * is trimmed and lines are added or removed. + * is trimmed and lines are added or removed. This is a single line that may + * be part of a larger wrapped line. */ export interface IMarker extends IDisposable { /** @@ -339,7 +340,8 @@ declare module 'xterm' { readonly isDisposed: boolean; /** - * The actual line index in the buffer at this point in time. + * The actual line index in the buffer at this point in time. This is set to + * -1 if the marker has been disposed. */ readonly line: number; } From 851fb7ae381eac879af89bdc5c2a705867d4dae1 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 25 Oct 2019 04:43:34 -0700 Subject: [PATCH 53/78] Refine IViewportRange API to use 'cursor positions' for x value Fixes #2484 --- src/browser/Linkifier.ts | 2 +- src/browser/Types.d.ts | 10 +++++----- typings/xterm.d.ts | 23 ++++++++++++++--------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/browser/Linkifier.ts b/src/browser/Linkifier.ts index ecaf8af9..58aca70e 100644 --- a/src/browser/Linkifier.ts +++ b/src/browser/Linkifier.ts @@ -308,7 +308,7 @@ export class Linkifier implements ILinkifier { if (matcher.hoverTooltipCallback) { // Note that IViewportRange use 1-based coordinates to align with escape sequences such // as CUP which use 1,1 as the default for row/col - matcher.hoverTooltipCallback(e, uri, { start: { row: y1 + 1, col: x1 + 1 }, end: { row: y2 + 1, col: x2 } }); + matcher.hoverTooltipCallback(e, uri, { start: { x: x1, y: y1 }, end: { x: x2, y: y2 } }); } }, () => { diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index 274fc16f..aa7a4c86 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -44,13 +44,13 @@ export interface IViewport extends IDisposable { } export interface IViewportRange { - start: IViewportCellPosition; - end: IViewportCellPosition; + start: IViewportRangePosition; + end: IViewportRangePosition; } -export interface IViewportCellPosition { - col: number; - row: number; +export interface IViewportRangePosition { + x: number; + y: number; } export type LinkMatcherHandler = (event: MouseEvent, uri: string) => void; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 62670f3d..f5435cca 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -862,29 +862,34 @@ declare module 'xterm' { */ export interface IViewportRange { /** - * The start cell of the range. + * The start of the range. */ - start: IViewportCellPosition; + start: IViewportRangePosition; /** - * The end cell of the range. + * The end of the range. */ - end: IViewportCellPosition; + end: IViewportRangePosition; } /** * An object representing a cell position within the viewport of the terminal. */ - interface IViewportCellPosition { + interface IViewportRangePosition { /** - * The column of the cell. Note that this is 1-based; the first column is column 1. + * The x position of the cell. This is a 0-based index that refers to the + * space in between columns, not the column itself. Index 0 refers to the + * left side of the viewport, index `Terminal.cols` refers to the right side + * of the viewport. This can be thought of as how a cursor is positioned in + * a text editor. */ - col: number; + x: number; /** - * The row of the cell. Note that this is 1-based; the first row is row 1. + * The y position of the cell. This is a 0-based index that refers to a + * specific row. */ - row: number; + y: number; } /** From a5a0779aa9a1badc0ee837db95a1ac84c48b39a2 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 25 Oct 2019 05:22:03 -0700 Subject: [PATCH 54/78] Apply scrollSensitivity on fast scroll too Fixes #2513 --- src/browser/Viewport.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/Viewport.ts b/src/browser/Viewport.ts index 5edd7b80..b88f381d 100644 --- a/src/browser/Viewport.ts +++ b/src/browser/Viewport.ts @@ -237,7 +237,7 @@ export class Viewport extends Disposable implements IViewport { if ((modifier === 'alt' && ev.altKey) || (modifier === 'ctrl' && ev.ctrlKey) || (modifier === 'shift' && ev.shiftKey)) { - return amount * this._optionsService.options.fastScrollSensitivity; + return amount * this._optionsService.options.fastScrollSensitivity * this._optionsService.options.scrollSensitivity; } return amount * this._optionsService.options.scrollSensitivity; From bfe11b708100c6a8cda5fcddec2f6c853c8b5bfe Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 25 Oct 2019 05:38:17 -0700 Subject: [PATCH 55/78] v4.2.0 --- addons/xterm-addon-fit/package.json | 2 +- addons/xterm-addon-search/package.json | 2 +- addons/xterm-addon-webgl/package.json | 2 +- package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/xterm-addon-fit/package.json b/addons/xterm-addon-fit/package.json index fa1bf852..4bceb258 100644 --- a/addons/xterm-addon-fit/package.json +++ b/addons/xterm-addon-fit/package.json @@ -1,6 +1,6 @@ { "name": "xterm-addon-fit", - "version": "0.2.1", + "version": "0.3.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" diff --git a/addons/xterm-addon-search/package.json b/addons/xterm-addon-search/package.json index c2e14032..c426ee3b 100644 --- a/addons/xterm-addon-search/package.json +++ b/addons/xterm-addon-search/package.json @@ -1,6 +1,6 @@ { "name": "xterm-addon-search", - "version": "0.2.1", + "version": "0.3.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" diff --git a/addons/xterm-addon-webgl/package.json b/addons/xterm-addon-webgl/package.json index 9a01aea0..a6befe08 100644 --- a/addons/xterm-addon-webgl/package.json +++ b/addons/xterm-addon-webgl/package.json @@ -1,6 +1,6 @@ { "name": "xterm-addon-webgl", - "version": "0.2.1", + "version": "0.3.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" diff --git a/package.json b/package.json index 709a1415..8174bbf5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "xterm", "description": "Full xterm terminal, in your browser", - "version": "4.1.0", + "version": "4.2.0", "main": "lib/xterm.js", "style": "css/xterm.css", "types": "typings/xterm.d.ts", From 25c18e8e07d4d08f8ea2178e1e730799d655149f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Fri, 25 Oct 2019 17:29:38 +0200 Subject: [PATCH 56/78] conditional build for addons --- bin/install-addons.js | 40 ++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 41 insertions(+) create mode 100644 bin/install-addons.js diff --git a/bin/install-addons.js b/bin/install-addons.js new file mode 100644 index 00000000..b042552a --- /dev/null +++ b/bin/install-addons.js @@ -0,0 +1,40 @@ +const path = require('path'); +const cp = require('child_process'); +const fs = require('fs'); + +const PACKAGE_ROOT = path.join(__dirname, '..'); + +// install addon deps +const addonsPath = path.join(PACKAGE_ROOT, 'addons'); +if (fs.existsSync(addonsPath)) { + console.log('pulling addon dependencies...'); + + // whether to use yarn or npm + let hasYarn = false; + try { + cp.execSync('yarn --version').toString(); + hasYarn = true; + } catch(e) {} + + // walk all addon folders + fs.readdir(addonsPath, (err, files) => { + files.forEach(folder => { + const addonPath = path.join(addonsPath, folder); + + // install only if there are dependencies listed + const packageJson = require(path.join(addonPath, 'package.json')); + if ((packageJson.devDependencies && Object.keys(packageJson.devDependencies).length) + || (packageJson.dependencies && Object.keys(packageJson.dependencies).length)) + { + console.log('Preparing', folder); + if (hasYarn) { + cp.execSync('yarn', {cwd: addonPath}); + } else { + cp.execSync('npm install', {cwd: addonPath}); + } + } else { + console.log('Skipped', folder); + } + }); + }); +} diff --git a/package.json b/package.json index 8174bbf5..773d954a 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "repository": "https://github.com/xtermjs/xterm.js", "license": "MIT", "scripts": { + "postinstall": "node -e \"try { require('./bin/install-addons'); } catch(e) {}\"", "prepackage": "npm run build", "package": "webpack", "start": "node demo/start", From 6f8cbc56ebfd7e53c7e611244fe04017c13ccf86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Fri, 25 Oct 2019 18:07:32 +0200 Subject: [PATCH 57/78] skip folder w'o package.json; restrict linter to src folders --- bin/install-addons.js | 15 ++++++++++++--- package.json | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/bin/install-addons.js b/bin/install-addons.js index b042552a..0a3ebe0c 100644 --- a/bin/install-addons.js +++ b/bin/install-addons.js @@ -22,9 +22,18 @@ if (fs.existsSync(addonsPath)) { const addonPath = path.join(addonsPath, folder); // install only if there are dependencies listed - const packageJson = require(path.join(addonPath, 'package.json')); - if ((packageJson.devDependencies && Object.keys(packageJson.devDependencies).length) - || (packageJson.dependencies && Object.keys(packageJson.dependencies).length)) + // also skip addon if it does not contain any package.json + // (might happen after branch switches) + let packageJson; + try { + packageJson = require(path.join(addonPath, 'package.json')); + } catch (e) {} + if (packageJson + && ( + (packageJson.devDependencies && Object.keys(packageJson.devDependencies).length) + || (packageJson.dependencies && Object.keys(packageJson.dependencies).length) + ) + ) { console.log('Preparing', folder); if (hasYarn) { diff --git a/package.json b/package.json index 773d954a..7762cd84 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "prepackage": "npm run build", "package": "webpack", "start": "node demo/start", - "lint": "tslint 'src/**/*.ts' 'addons/**/*.ts'", + "lint": "tslint 'src/**/*.ts' 'addons/*/src/**/*.ts'", "test": "npm run test-unit", "posttest": "npm run lint", "test-api": "mocha \"**/*.api.js\"", From d733ce3e63d74a0ec4f02630fb241d7c2dab8569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Fri, 25 Oct 2019 19:27:29 +0200 Subject: [PATCH 58/78] add copyright note --- bin/install-addons.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bin/install-addons.js b/bin/install-addons.js index 0a3ebe0c..bba0a9ea 100644 --- a/bin/install-addons.js +++ b/bin/install-addons.js @@ -1,3 +1,10 @@ +/** + * Copyright (c) 2019 The xterm.js authors. All rights reserved. + * @license MIT + * + * Script to initialize addon packages under "addons/" with outer deps. + */ + const path = require('path'); const cp = require('child_process'); const fs = require('fs'); From 04f828bc1aa1bf463bf325fd22d8442f75052d44 Mon Sep 17 00:00:00 2001 From: jerch Date: Fri, 25 Oct 2019 21:46:49 +0200 Subject: [PATCH 59/78] Update bin/install-addons.js Co-Authored-By: Daniel Imms --- bin/install-addons.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bin/install-addons.js b/bin/install-addons.js index bba0a9ea..23ae445a 100644 --- a/bin/install-addons.js +++ b/bin/install-addons.js @@ -34,7 +34,9 @@ if (fs.existsSync(addonsPath)) { let packageJson; try { packageJson = require(path.join(addonPath, 'package.json')); - } catch (e) {} + } catch (e) { + // swallow as changing branches can leave folders around + } if (packageJson && ( (packageJson.devDependencies && Object.keys(packageJson.devDependencies).length) From 03435a9f4d8542a0f05884f983875758bb4fc68a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Fri, 25 Oct 2019 22:11:51 +0200 Subject: [PATCH 60/78] use prebuild instead of postinstall --- bin/install-addons.js | 2 -- package.json | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/bin/install-addons.js b/bin/install-addons.js index 23ae445a..83adea1f 100644 --- a/bin/install-addons.js +++ b/bin/install-addons.js @@ -29,8 +29,6 @@ if (fs.existsSync(addonsPath)) { const addonPath = path.join(addonsPath, folder); // install only if there are dependencies listed - // also skip addon if it does not contain any package.json - // (might happen after branch switches) let packageJson; try { packageJson = require(path.join(addonPath, 'package.json')); diff --git a/package.json b/package.json index 7762cd84..1bc7861e 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,6 @@ "repository": "https://github.com/xtermjs/xterm.js", "license": "MIT", "scripts": { - "postinstall": "node -e \"try { require('./bin/install-addons'); } catch(e) {}\"", "prepackage": "npm run build", "package": "webpack", "start": "node demo/start", @@ -17,6 +16,7 @@ "posttest": "npm run lint", "test-api": "mocha \"**/*.api.js\"", "test-unit": "node ./bin/test.js", + "prebuild": "node ./bin/install-addons.js", "build": "tsc -b ./tsconfig.all.json", "prepare": "npm run build", "prepublishOnly": "npm run package", From 5b3a093f13aded3d5165634fd109088b17dd303d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Sat, 26 Oct 2019 17:20:35 +0200 Subject: [PATCH 61/78] stick to prepare to avoid re-running yarn for addons everytime during build --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 1bc7861e..fb9592c7 100644 --- a/package.json +++ b/package.json @@ -16,9 +16,10 @@ "posttest": "npm run lint", "test-api": "mocha \"**/*.api.js\"", "test-unit": "node ./bin/test.js", - "prebuild": "node ./bin/install-addons.js", "build": "tsc -b ./tsconfig.all.json", - "prepare": "npm run build", + "prepare": "npm run setup", + "setup": "npm run build", + "presetup": "node ./bin/install-addons.js", "prepublishOnly": "npm run package", "watch": "tsc -b -w ./tsconfig.all.json --preserveWatchOutput", "benchmark": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json", From 486fc714b3c647e962bf4ba82ced60f01a87ac13 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 26 Oct 2019 18:12:17 -0700 Subject: [PATCH 62/78] Support checkboxes in demo to toggle addons Fixes #2407 --- demo/client.ts | 88 ++++++++++++++++++++++++++++++++++++++++++------- demo/index.html | 5 +++ 2 files changed, 81 insertions(+), 12 deletions(-) diff --git a/demo/client.ts b/demo/client.ts index 7942cffe..b32d6c6a 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -39,13 +39,39 @@ export interface IWindowWithTerminal extends Window { declare let window: IWindowWithTerminal; let term; -let fitAddon: FitAddon; -let searchAddon: SearchAddon; let protocol; let socketURL; let socket; let pid; +type AddonType = 'attach' | 'fit' | 'search' | 'web-links' | 'webgl'; + +interface IDemoAddon { + name: T; + canChange: boolean; + ctor: + T extends 'attach' ? typeof AttachAddon : + T extends 'fit' ? typeof FitAddon : + T extends 'search' ? typeof SearchAddon : + T extends 'web-links' ? typeof WebLinksAddon : + typeof WebglAddon; + instance?: + T extends 'attach' ? AttachAddon : + T extends 'fit' ? FitAddon : + T extends 'search' ? SearchAddon : + T extends 'web-links' ? WebLinksAddon : + T extends 'webgl' ? WebglAddon : + never; +} + +const addons: { [T in AddonType]: IDemoAddon} = { + attach: { name: 'attach', ctor: AttachAddon, canChange: false }, + fit: { name: 'fit', ctor: FitAddon, canChange: false }, + search: { name: 'search', ctor: SearchAddon, canChange: true }, + 'web-links': { name: 'web-links', ctor: WebLinksAddon, canChange: true }, + webgl: { name: 'webgl', ctor: WebglAddon, canChange: true } +}; + const terminalContainer = document.getElementById('terminal-container'); const actionElements = { findNext: document.querySelector('#find-next'), @@ -108,11 +134,12 @@ function createTerminal(): void { // Load addons const typedTerm = term as TerminalType; - typedTerm.loadAddon(new WebLinksAddon()); - searchAddon = new SearchAddon(); - typedTerm.loadAddon(searchAddon); - fitAddon = new FitAddon(); - typedTerm.loadAddon(fitAddon); + addons['web-links'].instance = new WebLinksAddon(); + addons.search.instance = new SearchAddon(); + addons.fit.instance = new FitAddon(); + typedTerm.loadAddon(addons['web-links'].instance); + typedTerm.loadAddon(addons.search.instance); + typedTerm.loadAddon(addons.fit.instance); window.term = term; // Expose `term` to window for debugging purposes term.onResize((size: { cols: number, rows: number }) => { @@ -129,17 +156,17 @@ function createTerminal(): void { socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + '/terminals/'; term.open(terminalContainer); - fitAddon.fit(); + addons.fit.instance!.fit(); term.focus(); addDomListener(paddingElement, 'change', setPadding); addDomListener(actionElements.findNext, 'keyup', (e) => { - searchAddon.findNext(actionElements.findNext.value, getSearchOptions(e)); + addons.search.instance.findNext(actionElements.findNext.value, getSearchOptions(e)); }); addDomListener(actionElements.findPrevious, 'keyup', (e) => { - searchAddon.findPrevious(actionElements.findPrevious.value, getSearchOptions(e)); + addons.search.instance.findPrevious(actionElements.findPrevious.value, getSearchOptions(e)); }); // fit is called within a setTimeout, cols and rows need this. @@ -167,8 +194,10 @@ function createTerminal(): void { } function runRealTerminal(): void { - term.loadAddon(new AttachAddon(socket)); + addons.attach.instance = new AttachAddon(socket); + term.loadAddon(addons.attach.instance); term._initialized = true; + initAddons(term); } function runFakeTerminal(): void { @@ -177,6 +206,7 @@ function runFakeTerminal(): void { } term._initialized = true; + initAddons(term); term.prompt = () => { term.write('\r\n$ '); @@ -300,6 +330,40 @@ function initOptions(term: TerminalType): void { }); } +function initAddons(term: TerminalType): void { + const fragment = document.createDocumentFragment(); + Object.keys(addons).forEach((name: AddonType) => { + const addon = addons[name]; + const checkbox = document.createElement('input') as HTMLInputElement; + checkbox.type = 'checkbox'; + checkbox.checked = !!addon.instance; + if (!addon.canChange) { + checkbox.disabled = true; + } + checkbox.addEventListener('change', () => { + if (checkbox.checked) { + addon.instance = new addon.ctor(); + term.loadAddon(addon.instance); + } else { + addon.instance!.dispose(); + addon.instance = undefined; + } + }); + const label = document.createElement('label'); + label.classList.add('addon'); + if (!addon.canChange) { + label.title = 'This addon is needed for the demo to operate'; + } + label.appendChild(checkbox); + label.appendChild(document.createTextNode(name)); + const wrapper = document.createElement('div'); + wrapper.classList.add('addon'); + wrapper.appendChild(label); + fragment.appendChild(wrapper); + }); + document.getElementById('addons-container').appendChild(fragment); +} + function addDomListener(element: HTMLElement, type: string, handler: (...args: any[]) => any): void { element.addEventListener(type, handler); term._core.register({ dispose: () => element.removeEventListener(type, handler) }); @@ -312,5 +376,5 @@ function updateTerminalSize(): void { const height = (rows * term._core._renderService.dimensions.actualCellHeight).toString() + 'px'; terminalContainer.style.width = width; terminalContainer.style.height = height; - fitAddon.fit(); + addons.fit.instance.fit(); } diff --git a/demo/index.html b/demo/index.html index ef8f3891..83ea6815 100644 --- a/demo/index.html +++ b/demo/index.html @@ -26,6 +26,11 @@

These options can be set in the Terminal constructor or using the Terminal.setOption function.

+
+

Addons

+

Addons can be loaded and unloaded on a particular terminal to extend its functionality.

+
+

Style

From 2f18edbcac8a42522ebd692a726dee860642d01d Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 26 Oct 2019 18:12:56 -0700 Subject: [PATCH 63/78] Remove old webgl enable button --- demo/client.ts | 1 - demo/index.html | 1 - 2 files changed, 2 deletions(-) diff --git a/demo/client.ts b/demo/client.ts index b32d6c6a..5b76700e 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -118,7 +118,6 @@ if (document.location.pathname === '/test') { } else { createTerminal(); document.getElementById('dispose').addEventListener('click', disposeRecreateButtonHandler); - document.getElementById('webgl').addEventListener('click', () => term.loadAddon(new WebglAddon())); } function createTerminal(): void { diff --git a/demo/index.html b/demo/index.html index 83ea6815..88c6bc4c 100644 --- a/demo/index.html +++ b/demo/index.html @@ -41,7 +41,6 @@

Attention: The demo is a barebones implementation and is designed for the development and evaluation of xterm.js only. Exposing the demo to the public as is would introduce security risks for the host.

- From d0e05eb795c6ab4a22b3dc00ffb3f2e6e8de3e80 Mon Sep 17 00:00:00 2001 From: Revanth Mahesh Date: Sun, 27 Oct 2019 10:11:43 +0530 Subject: [PATCH 64/78] Support disposing of EventEmitters --- src/common/EventEmitter.ts | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/common/EventEmitter.ts b/src/common/EventEmitter.ts index 34ac190f..ea9df48b 100644 --- a/src/common/EventEmitter.ts +++ b/src/common/EventEmitter.ts @@ -16,11 +16,13 @@ export interface IEvent { export interface IEventEmitter { event: IEvent; fire(data: T): void; + dispose(): void; } export class EventEmitter implements IEventEmitter { private _listeners: IListener[] = []; private _event?: IEvent; + private _disposed: boolean = false; public get event(): IEvent { if (!this._event) { @@ -28,10 +30,12 @@ export class EventEmitter implements IEventEmitter { this._listeners.push(listener); const disposable = { dispose: () => { - for (let i = 0; i < this._listeners.length; i++) { - if (this._listeners[i] === listener) { - this._listeners.splice(i, 1); - return; + if (!this._disposed) { + for (let i = 0; i < this._listeners.length; i++) { + if (this._listeners[i] === listener) { + this._listeners.splice(i, 1); + return; + } } } } @@ -51,4 +55,12 @@ export class EventEmitter implements IEventEmitter { queue[i].call(undefined, data); } } + +public dispose(): void { + if (this._listeners) { + this._listeners.splice(0, this._listeners.length); + } + this._disposed = true; +} + } From f3bbcb35e4421c112d81f66f0ea1f3286e8e5ed4 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 26 Oct 2019 21:52:11 -0700 Subject: [PATCH 65/78] Clean up --- src/common/EventEmitter.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/common/EventEmitter.ts b/src/common/EventEmitter.ts index ea9df48b..5991e338 100644 --- a/src/common/EventEmitter.ts +++ b/src/common/EventEmitter.ts @@ -56,11 +56,10 @@ export class EventEmitter implements IEventEmitter { } } -public dispose(): void { - if (this._listeners) { - this._listeners.splice(0, this._listeners.length); + public dispose(): void { + if (this._listeners) { + this._listeners.length = 0; + } + this._disposed = true; } - this._disposed = true; -} - } From 56d33668310397948dcfeb6324ac1d518ebb11bf Mon Sep 17 00:00:00 2001 From: alberto Date: Sun, 27 Oct 2019 22:08:42 +0100 Subject: [PATCH 66/78] Fix typo --- addons/xterm-addon-search/typings/xterm-addon-search.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/xterm-addon-search/typings/xterm-addon-search.d.ts b/addons/xterm-addon-search/typings/xterm-addon-search.d.ts index 94bc5297..913f33df 100644 --- a/addons/xterm-addon-search/typings/xterm-addon-search.d.ts +++ b/addons/xterm-addon-search/typings/xterm-addon-search.d.ts @@ -27,7 +27,7 @@ declare module 'xterm-addon-search' { caseSensitive?: boolean; /** - * Whether to do an indcremental search, this will expand the selection if it + * Whether to do an incremental search, this will expand the selection if it * still matches the term the user typed. Note that this only affects * `findNext`, not `findPrevious`. */ From dca1e0b93549a155fef5b6e82532f6be6552957f Mon Sep 17 00:00:00 2001 From: alberto Date: Sun, 27 Oct 2019 22:18:11 +0100 Subject: [PATCH 67/78] Fix another typo --- addons/xterm-addon-search/typings/xterm-addon-search.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/xterm-addon-search/typings/xterm-addon-search.d.ts b/addons/xterm-addon-search/typings/xterm-addon-search.d.ts index 913f33df..f27aba78 100644 --- a/addons/xterm-addon-search/typings/xterm-addon-search.d.ts +++ b/addons/xterm-addon-search/typings/xterm-addon-search.d.ts @@ -17,7 +17,7 @@ declare module 'xterm-addon-search' { /** * Whether to search for a whole word, the result is only valid if it's - * suppounded in "non-word" characters such as `_`, `(`, `)` or space. + * surrounded in "non-word" characters such as `_`, `(`, `)` or space. */ wholeWord?: boolean; From 8d0fdc8731b823968e991eb8b98588f5577407ab Mon Sep 17 00:00:00 2001 From: alberto Date: Sun, 27 Oct 2019 22:29:36 +0100 Subject: [PATCH 68/78] Fix grammar --- typings/xterm.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 295a03b2..27f39177 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -49,7 +49,7 @@ declare module 'xterm' { /** * When enabled the cursor will be set to the beginning of the next line - * with every new line. This equivalent to sending '\r\n' for each '\n'. + * with every new line. This is equivalent to sending '\r\n' for each '\n'. * Normally the termios settings of the underlying PTY deals with the * translation of '\n' to '\r\n' and this setting should not be used. If you * deal with data from a non-PTY related source, this settings might be From fe2ac04b857e730f62780e55ebf1d672890510b7 Mon Sep 17 00:00:00 2001 From: alberto Date: Sun, 27 Oct 2019 22:34:54 +0100 Subject: [PATCH 69/78] Fix grammar --- typings/xterm.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 27f39177..eb9904e8 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -437,7 +437,7 @@ declare module 'xterm' { onData: IEvent; /** - * Adds an event listener for a key is pressed. The event value contains the + * Adds an event listener for when a key is pressed. The event value contains the * string that will be sent in the data event as well as the DOM event that * triggered it. * @returns an `IDisposable` to stop listening. From ffe2d66affe663c5bb861a92c28517f19e90c5be Mon Sep 17 00:00:00 2001 From: alberto Date: Sun, 27 Oct 2019 22:38:55 +0100 Subject: [PATCH 70/78] Remove duplicated punctuation --- typings/xterm.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index eb9904e8..9ec407c7 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -609,7 +609,7 @@ declare module 'xterm' { /** * Selects text within the terminal. - * @param column The column the selection starts at.. + * @param column The column the selection starts at. * @param row The row the selection starts at. * @param length The length of the selection. */ From b880cd3ad3d171023bcb11caf708f6ec7d7c1f6c Mon Sep 17 00:00:00 2001 From: alberto Date: Sun, 27 Oct 2019 22:43:26 +0100 Subject: [PATCH 71/78] Fix punctuation mark --- typings/xterm.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 9ec407c7..eb2b3a7f 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -918,7 +918,7 @@ declare module 'xterm' { /** * The line within the buffer where the top of the bottom page is (when - * fully scrolled down); + * fully scrolled down). */ readonly baseY: number; From cb1cf3cd119d500d5ac099548a5d5394fc061e03 Mon Sep 17 00:00:00 2001 From: alberto Date: Sun, 27 Oct 2019 22:50:22 +0100 Subject: [PATCH 72/78] Fix grammar --- typings/xterm.d.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index eb2b3a7f..9728a72c 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1047,7 +1047,7 @@ declare module 'xterm' { * array will contain subarrays with their numercial values. * Return true if the sequence was handled; false if we should try * a previous handler (set by addCsiHandler or setCsiHandler). - * The most recently-added handler is tried first. + * The most recently added handler is tried first. * @return An IDisposable you can call to remove this handler. */ addCsiHandler(id: IFunctionIdentifier, callback: (params: (number | number[])[]) => boolean): IDisposable; @@ -1066,7 +1066,7 @@ declare module 'xterm' { * The function gets the payload and numerical parameters as arguments. * Return true if the sequence was handled; false if we should try * a previous handler (set by addDcsHandler or setDcsHandler). - * The most recently-added handler is tried first. + * The most recently added handler is tried first. * @return An IDisposable you can call to remove this handler. */ addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: (number | number[])[]) => boolean): IDisposable; @@ -1079,7 +1079,7 @@ declare module 'xterm' { * @param callback The function to handle the sequence. * Return true if the sequence was handled; false if we should try * a previous handler (set by addEscHandler or setEscHandler). - * The most recently-added handler is tried first. + * The most recently added handler is tried first. * @return An IDisposable you can call to remove this handler. */ addEscHandler(id: IFunctionIdentifier, handler: () => boolean): IDisposable; @@ -1097,7 +1097,7 @@ declare module 'xterm' { * The callback is called with OSC data string. * Return true if the sequence was handled; false if we should try * a previous handler (set by addOscHandler or setOscHandler). - * The most recently-added handler is tried first. + * The most recently added handler is tried first. * @return An IDisposable you can call to remove this handler. */ addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable; From 6c2b34a5c8b421f3b29aeddac07108ea4bcf8404 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 30 Oct 2019 20:03:53 -0700 Subject: [PATCH 73/78] Use YarnInstaller --- azure-pipelines.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a58f7fe0..cec85ba5 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -12,9 +12,9 @@ jobs: inputs: versionSpec: '8.x' displayName: 'Install Node.js' - - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + - task: YarnInstaller@3 inputs: - versionSpec: "1.9.4" + versionSpec: '1.x' displayName: 'Install Yarn' - script: | yarn @@ -70,9 +70,9 @@ jobs: inputs: versionSpec: '8.x' displayName: 'Install Node.js' - - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + - task: YarnInstaller@3 inputs: - versionSpec: "1.9.4" + versionSpec: '1.x' displayName: 'Install Yarn' - script: | yarn @@ -115,9 +115,9 @@ jobs: inputs: versionSpec: '8.x' displayName: 'Install Node.js' - - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + - task: YarnInstaller@3 inputs: - versionSpec: "1.9.4" + versionSpec: '1.x' displayName: 'Install Yarn' - script: | yarn From 79f3a7343cf71de92e18157ab6f7a90931181d9b Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 30 Oct 2019 20:07:41 -0700 Subject: [PATCH 74/78] Don't wrap for single line scripts --- azure-pipelines.yml | 39 +++++++++++++-------------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index cec85ba5..c6ee9ac0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -16,14 +16,11 @@ jobs: inputs: versionSpec: '1.x' displayName: 'Install Yarn' - - script: | - yarn + - script: yarn displayName: 'Install dependencies and build' - - script: | - yarn test-unit --forbid-only + - script: yarn test-unit --forbid-only displayName: 'Unit tests' - - script: | - yarn lint + - script: yarn lint displayName: 'Lint' - job: macOS @@ -34,14 +31,11 @@ jobs: inputs: versionSpec: '8.x' displayName: 'Install Node.js' - - script: | - yarn + - script: yarn displayName: 'Install dependencies and build' - - script: | - yarn test-unit --forbid-only + - script: yarn test-unit --forbid-only displayName: 'Unit tests' - - script: | - yarn lint + - script: yarn lint displayName: 'Lint' - job: Windows @@ -52,14 +46,11 @@ jobs: inputs: versionSpec: '8.x' displayName: 'Install Node.js' - - script: | - yarn + - script: yarn displayName: 'Install dependencies and build' - - script: | - yarn test-unit --forbid-only + - script: yarn test-unit --forbid-only displayName: 'Unit tests' - - script: | - yarn lint + - script: yarn lint displayName: 'Lint' - job: Linux_IntegrationTests @@ -74,8 +65,7 @@ jobs: inputs: versionSpec: '1.x' displayName: 'Install Yarn' - - script: | - yarn + - script: yarn displayName: 'Install dependencies and build' - script: | yarn start & @@ -91,8 +81,7 @@ jobs: inputs: versionSpec: '8.x' displayName: 'Install Node.js' - - script: | - yarn + - script: yarn displayName: 'Install dependencies and build' - script: | yarn start & @@ -119,9 +108,7 @@ jobs: inputs: versionSpec: '1.x' displayName: 'Install Yarn' - - script: | - yarn + - script: yarn displayName: 'Install dependencies and build' - - script: | - NPM_AUTH_TOKEN="$(NPM_AUTH_TOKEN)" node ./bin/publish.js + - script: NPM_AUTH_TOKEN="$(NPM_AUTH_TOKEN)" node ./bin/publish.js displayName: 'Package and publish to npm' From a450bd52d7a5c12e9ce6767774c653c0b0f0547b Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 30 Oct 2019 20:18:32 -0700 Subject: [PATCH 75/78] Generate and publish coverage report to pipelines --- .gitignore | 1 + azure-pipelines.yml | 17 ++ package.json | 1 + yarn.lock | 522 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 530 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 64273dda..8aea04b2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ node_modules/ lib/ out/ out-test/ +.nyc_output/ Makefile.gyp *.Makefile *.target.gyp.mk diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c6ee9ac0..cab8fa51 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -22,6 +22,23 @@ jobs: displayName: 'Unit tests' - script: yarn lint displayName: 'Lint' + - script: | + NODE_PATH=$(pwd)/out ./node_modules/.bin/nyc ./node_modules/.bin/mocha './out/*test.js' './out/**/*test.js' + ./node_modules/.bin/nyc report --reporter=cobertura + displayName: 'Coverage report' + - task: PublishCodeCoverageResults@1 + inputs: + codeCoverageTool: Cobertura + summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/*coverage.xml' + reportDirectory: '$(System.DefaultWorkingDirectory)/**/coverage' + displayName: 'Publish coverage' + - task: mspremier.BuildQualityChecks.QualityChecks-task.BuildQualityChecks@6 + displayName: 'Check build quality' + inputs: + checkCoverage: true + coverageType: branches + coverageThreshold: 55 + coverageFailOption: fixed - job: macOS pool: diff --git a/package.json b/package.json index fb9592c7..fa29486a 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "jsdom": "^11.11.0", "mocha": "^6.1.4", "node-pty": "0.7.6", + "nyc": "13", "puppeteer": "^1.15.0", "source-map-loader": "^0.2.4", "ts-loader": "^6.0.4", diff --git a/yarn.lock b/yarn.lock index 0019809a..c96c390c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,6 +9,46 @@ dependencies: "@babel/highlight" "^7.0.0" +"@babel/code-frame@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== + dependencies: + "@babel/highlight" "^7.0.0" + +"@babel/generator@^7.4.0", "@babel/generator@^7.6.3": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.4.tgz#a4f8437287bf9671b07f483b76e3bb731bc97671" + integrity sha512-jsBuXkFoZxk0yWLyGI9llT9oiQ2FeTASmRFE32U+aaDTfoE92t78eroO7PTpU/OrYq38hlcDM6vbfLDaOLy+7w== + dependencies: + "@babel/types" "^7.6.3" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + +"@babel/helper-function-name@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" + integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== + dependencies: + "@babel/helper-get-function-arity" "^7.0.0" + "@babel/template" "^7.1.0" + "@babel/types" "^7.0.0" + +"@babel/helper-get-function-arity@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" + integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== + dependencies: + "@babel/types" "^7.0.0" + +"@babel/helper-split-export-declaration@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" + integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== + dependencies: + "@babel/types" "^7.4.4" + "@babel/highlight@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" @@ -18,6 +58,44 @@ esutils "^2.0.2" js-tokens "^4.0.0" +"@babel/parser@^7.4.3", "@babel/parser@^7.6.0", "@babel/parser@^7.6.3": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.4.tgz#cb9b36a7482110282d5cb6dd424ec9262b473d81" + integrity sha512-D8RHPW5qd0Vbyo3qb+YjO5nvUVRTXFLQ/FsDxJU2Nqz4uB5EnUN0ZQSEYpvTIbRuttig1XbHWU5oMeQwQSAA+A== + +"@babel/template@^7.1.0", "@babel/template@^7.4.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.6.0.tgz#7f0159c7f5012230dad64cca42ec9bdb5c9536e6" + integrity sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.6.0" + "@babel/types" "^7.6.0" + +"@babel/traverse@^7.4.3": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.3.tgz#66d7dba146b086703c0fb10dd588b7364cec47f9" + integrity sha512-unn7P4LGsijIxaAJo/wpoU11zN+2IaClkQAxcJWBNCMS6cmVh802IyLHNkAjQ0iYnRS3nnxk5O3fuXW28IMxTw== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.6.3" + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/parser" "^7.6.3" + "@babel/types" "^7.6.3" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/types@^7.0.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.6.0", "@babel/types@^7.6.3": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.3.tgz#3f07d96f854f98e2fbd45c64b0cb942d11e8ba09" + integrity sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + "@fimbul/bifrost@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@fimbul/bifrost/-/bifrost-0.11.0.tgz#83cacc21464198b12e3cc1c2204ae6c6d7afd158" @@ -439,11 +517,23 @@ app-root-path@^2.2.1: resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.2.1.tgz#d0df4a682ee408273583d43f6f79e9892624bc9a" integrity sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA== +append-transform@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab" + integrity sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw== + dependencies: + default-require-extensions "^2.0.0" + aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= + are-we-there-yet@~1.1.2: version "1.1.5" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" @@ -489,6 +579,11 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -816,6 +911,16 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +caching-transform@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-3.0.2.tgz#601d46b91eca87687a281e71cef99791b0efca70" + integrity sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w== + dependencies: + hasha "^3.0.0" + make-dir "^2.0.0" + package-hash "^3.0.0" + write-file-atomic "^2.4.2" + camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" @@ -1075,6 +1180,11 @@ commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== +commander@~2.20.3: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -1134,6 +1244,13 @@ content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== +convert-source-map@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" + integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== + dependencies: + safe-buffer "~5.1.1" + cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" @@ -1197,6 +1314,14 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" +cross-spawn@^4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" + integrity sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE= + dependencies: + lru-cache "^4.0.1" + which "^1.2.9" + cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" @@ -1293,7 +1418,7 @@ debug@^3.1.0: dependencies: ms "2.0.0" -debug@^4.0.1, debug@^4.1.0: +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== @@ -1339,6 +1464,13 @@ deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= +default-require-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7" + integrity sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc= + dependencies: + strip-bom "^3.0.0" + defaults@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" @@ -1536,6 +1668,13 @@ errno@^0.1.3, errno@~0.1.7: dependencies: prr "~1.0.1" +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + es-abstract@^1.5.1: version "1.13.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" @@ -1557,6 +1696,11 @@ es-to-primitive@^1.2.0: is-date-object "^1.0.1" is-symbol "^1.0.2" +es6-error@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== + es6-promise@^4.0.3: version "4.2.6" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.6.tgz#b685edd8258886365ea62b57d30de28fadcd974f" @@ -1878,7 +2022,7 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-cache-dir@^2.1.0: +find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== @@ -1921,6 +2065,14 @@ for-in@^1.0.2: resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= +foreground-child@^1.5.6: + version "1.5.6" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" + integrity sha1-T9ca0t/elnibmApcCilZN8svXOk= + dependencies: + cross-spawn "^4" + signal-exit "^3.0.0" + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -2097,6 +2249,11 @@ global-modules-path@^2.1.0: resolved "https://registry.yarnpkg.com/global-modules-path/-/global-modules-path-2.3.0.tgz#b0e2bac6beac39745f7db5c59d26a36a0b94f7dc" integrity sha512-HchvMJNYh9dGSCy8pOQ2O8u/hoXaL+0XhnrwH0RyLiSXMMTl9W3N6KUU73+JFOg5PGjtzl6VZzUQsnrpm7Szag== +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2: version "4.2.2" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" @@ -2107,6 +2264,17 @@ growl@1.10.5: resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== +handlebars@^4.1.2: + version "4.5.1" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.1.tgz#8a01c382c180272260d07f2d1aa3ae745715c7ba" + integrity sha512-C29UoFzHe9yM61lOsIlCE5/mQVGrnIOrOq7maQl76L7tYPCgC1og0Ajt6uWnX4ZTxBPnjw+CUvawphwCfJgUnA== + dependencies: + neo-async "^2.6.0" + optimist "^0.6.1" + source-map "^0.6.1" + optionalDependencies: + uglify-js "^3.1.4" + har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -2189,6 +2357,13 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasha@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-3.0.0.tgz#52a32fab8569d41ca69a61ff1a214f8eb7c8bd39" + integrity sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk= + dependencies: + is-stream "^1.0.1" + he@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -2203,6 +2378,11 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +hosted-git-info@^2.1.4: + version "2.8.5" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" + integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg== + html-encoding-sniffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" @@ -2387,6 +2567,11 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + is-arrayish@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" @@ -2525,7 +2710,7 @@ is-regex@^1.0.4: dependencies: has "^1.0.1" -is-stream@^1.1.0: +is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= @@ -2579,6 +2764,58 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +istanbul-lib-coverage@^2.0.3, istanbul-lib-coverage@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" + integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== + +istanbul-lib-hook@^2.0.3: + version "2.0.7" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz#c95695f383d4f8f60df1f04252a9550e15b5b133" + integrity sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA== + dependencies: + append-transform "^1.0.0" + +istanbul-lib-instrument@^3.1.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630" + integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA== + dependencies: + "@babel/generator" "^7.4.0" + "@babel/parser" "^7.4.3" + "@babel/template" "^7.4.0" + "@babel/traverse" "^7.4.3" + "@babel/types" "^7.4.0" + istanbul-lib-coverage "^2.0.5" + semver "^6.0.0" + +istanbul-lib-report@^2.0.4: + version "2.0.8" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33" + integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ== + dependencies: + istanbul-lib-coverage "^2.0.5" + make-dir "^2.1.0" + supports-color "^6.1.0" + +istanbul-lib-source-maps@^3.0.2: + version "3.0.6" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8" + integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^2.0.5" + make-dir "^2.1.0" + rimraf "^2.6.3" + source-map "^0.6.1" + +istanbul-reports@^2.1.1: + version "2.2.6" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af" + integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA== + dependencies: + handlebars "^4.1.2" + javascript-natural-sort@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59" @@ -2634,7 +2871,12 @@ jsdom@^11.11.0: ws "^4.0.0" xml-name-validator "^3.0.0" -json-parse-better-errors@^1.0.2: +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== @@ -2739,6 +2981,16 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +load-json-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" + integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= + dependencies: + graceful-fs "^4.1.2" + parse-json "^4.0.0" + pify "^3.0.0" + strip-bom "^3.0.0" + loader-runner@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" @@ -2778,6 +3030,11 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +lodash.flattendeep@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" + integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -2788,6 +3045,11 @@ lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== +lodash@^4.17.13: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + log-symbols@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" @@ -2821,7 +3083,14 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" -make-dir@^2.0.0: +make-dir@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== + dependencies: + pify "^3.0.0" + +make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== @@ -2910,6 +3179,13 @@ merge-descriptors@1.0.1: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= +merge-source-map@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" + integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw== + dependencies: + source-map "^0.6.1" + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -3021,6 +3297,11 @@ minimist@^1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= + minipass@^2.2.1, minipass@^2.3.5: version "2.5.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.5.0.tgz#dddb1d001976978158a05badfcbef4a771612857" @@ -3164,7 +3445,7 @@ negotiator@0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -neo-async@^2.5.0, neo-async@^2.6.1: +neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== @@ -3242,6 +3523,16 @@ nopt@^4.0.1: abbrev "1" osenv "^0.1.4" +normalize-package-data@^2.3.2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" @@ -3294,6 +3585,36 @@ nwsapi@^2.0.0: resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.0.4.tgz#dc79040a5f77b97716dc79565fc7fc3ef7d50570" integrity sha512-Zt6HRR6RcJkuj5/N9zeE7FN6YitRW//hK2wTOwX274IBphbY3Zf5+yn5mZ9v/SzAOTMjQNxZf9KkmPLWn0cV4g== +nyc@13: + version "13.3.0" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-13.3.0.tgz#da4dbe91a9c8b9ead3f4f3344c76f353e3c78c75" + integrity sha512-P+FwIuro2aFG6B0Esd9ZDWUd51uZrAEoGutqZxzrVmYl3qSfkLgcQpBPBjtDFsUQLFY1dvTQJPOyeqr8S9GF8w== + dependencies: + archy "^1.0.0" + arrify "^1.0.1" + caching-transform "^3.0.1" + convert-source-map "^1.6.0" + find-cache-dir "^2.0.0" + find-up "^3.0.0" + foreground-child "^1.5.6" + glob "^7.1.3" + istanbul-lib-coverage "^2.0.3" + istanbul-lib-hook "^2.0.3" + istanbul-lib-instrument "^3.1.0" + istanbul-lib-report "^2.0.4" + istanbul-lib-source-maps "^3.0.2" + istanbul-reports "^2.1.1" + make-dir "^1.3.0" + merge-source-map "^1.1.0" + resolve-from "^4.0.0" + rimraf "^2.6.3" + signal-exit "^3.0.2" + spawn-wrap "^1.4.2" + test-exclude "^5.1.0" + uuid "^3.3.2" + yargs "^12.0.5" + yargs-parser "^11.1.1" + oauth-sign@~0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" @@ -3376,6 +3697,14 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" +optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + optionator@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" @@ -3393,7 +3722,7 @@ os-browserify@^0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= -os-homedir@^1.0.0: +os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= @@ -3482,6 +3811,16 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +package-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-3.0.0.tgz#50183f2d36c9e3e528ea0a8605dff57ce976f88e" + integrity sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA== + dependencies: + graceful-fs "^4.1.15" + hasha "^3.0.0" + lodash.flattendeep "^4.4.0" + release-zalgo "^1.0.0" + pako@~1.0.5: version "1.0.10" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" @@ -3508,6 +3847,14 @@ parse-asn1@^5.0.0: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + parse5@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" @@ -3560,11 +3907,23 @@ path-parse@^1.0.5: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" integrity sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME= +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== + dependencies: + pify "^3.0.0" + pbkdf2@^3.0.3: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" @@ -3591,6 +3950,11 @@ picomatch@^2.0.5: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6" integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA== +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + pify@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" @@ -3813,6 +4177,23 @@ rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +read-pkg-up@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" + integrity sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA== + dependencies: + find-up "^3.0.0" + read-pkg "^3.0.0" + +read-pkg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" + integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= + dependencies: + load-json-file "^4.0.0" + normalize-package-data "^2.3.2" + path-type "^3.0.0" + "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" @@ -3857,6 +4238,13 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +release-zalgo@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" + integrity sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA= + dependencies: + es6-error "^4.0.1" + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -3941,6 +4329,11 @@ resolve-from@^3.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" integrity sha1-six699nWiBvItuZTM17rywoYh0g= +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -3951,6 +4344,13 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= +resolve@^1.10.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" + integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== + dependencies: + path-parse "^1.0.6" + resolve@^1.3.2: version "1.8.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" @@ -3971,7 +4371,7 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== -rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: +rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -4048,7 +4448,7 @@ seed-random@2.2.0: resolved "https://registry.yarnpkg.com/seed-random/-/seed-random-2.2.0.tgz#2a9b19e250a817099231a5b99a4daf80b7fbed54" integrity sha1-KpsZ4lCoFwmSMaW5mk2vgLf77VQ= -semver@^5.3.0, semver@^5.6.0: +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -4233,7 +4633,7 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@^0.5.6: +source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -4243,6 +4643,44 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +spawn-wrap@^1.4.2: + version "1.4.3" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.4.3.tgz#81b7670e170cca247d80bf5faf0cfb713bdcf848" + integrity sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw== + dependencies: + foreground-child "^1.5.6" + mkdirp "^0.5.0" + os-homedir "^1.0.1" + rimraf "^2.6.2" + signal-exit "^3.0.2" + which "^1.3.0" + +spdx-correct@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" + integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" + integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" @@ -4401,6 +4839,11 @@ strip-ansi@^5.1.0: dependencies: ansi-regex "^4.1.0" +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -4432,6 +4875,13 @@ supports-color@^5.4.0: dependencies: has-flag "^3.0.0" +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + symbol-tree@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" @@ -4479,6 +4929,16 @@ terser@^4.1.2: source-map "~0.6.1" source-map-support "~0.5.12" +test-exclude@^5.1.0: + version "5.2.3" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0" + integrity sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g== + dependencies: + glob "^7.1.3" + minimatch "^3.0.4" + read-pkg-up "^4.0.0" + require-main-filename "^2.0.0" + text-hex@1.0.x: version "1.0.0" resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" @@ -4521,6 +4981,11 @@ to-arraybuffer@^1.0.0: resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" @@ -4729,6 +5194,14 @@ typescript@^3.5.1: resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.1.tgz#ba72a6a600b2158139c5dd8850f700e231464202" integrity sha512-64HkdiRv1yYZsSe4xC1WVgamNigVYjlssIoaH2HcZF0+ijsk5YK2g0G34w9wJkze8+5ow4STd22AynfO6ZYYLw== +uglify-js@^3.1.4: + version "3.6.5" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.5.tgz#b0ee796d2ae7e25672e04f65629b997cd4b30bd6" + integrity sha512-7L3W+Npia1OCr5Blp4/Vw83tK1mu5gnoIURtT1fUVfQ3Kf8WStWV6NJz0fdoBJZls0KlweruRTLVe6XLafmy5g== + dependencies: + commander "~2.20.3" + source-map "~0.6.1" + union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -4830,11 +5303,24 @@ uuid@^3.1.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== +uuid@^3.3.2: + version "3.3.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" + integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== + v8-compile-cache@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz#a428b28bb26790734c4fc8bc9fa106fccebf6a6c" integrity sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw== +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -4962,7 +5448,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@1.3.1, which@^1.2.9: +which@1.3.1, which@^1.2.9, which@^1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -4999,6 +5485,11 @@ winston@^3.2.1: triple-beam "^1.3.0" winston-transport "^4.3.0" +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= + wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" @@ -5024,6 +5515,15 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +write-file-atomic@^2.4.2: + version "2.4.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" + integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + ws@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ws/-/ws-4.1.0.tgz#a979b5d7d4da68bf54efe0408967c324869a7289" From 39c0fdb54ad530466ed8bd72a75c387a7bde6fdf Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 30 Oct 2019 20:31:40 -0700 Subject: [PATCH 76/78] Remove report directory --- azure-pipelines.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index cab8fa51..8c35196a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -30,7 +30,6 @@ jobs: inputs: codeCoverageTool: Cobertura summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/*coverage.xml' - reportDirectory: '$(System.DefaultWorkingDirectory)/**/coverage' displayName: 'Publish coverage' - task: mspremier.BuildQualityChecks.QualityChecks-task.BuildQualityChecks@6 displayName: 'Check build quality' From 08b10ba65160aae9af802a2c6fea1d694ff5c64f Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 30 Oct 2019 21:13:09 -0700 Subject: [PATCH 77/78] Add note about unit test coverage in contributing --- CONTRIBUTING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e8102a2e..d5efe9d2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -52,3 +52,7 @@ By contributing code to xterm.js you: holder has explicitly granted the right to use it like this, through a compatible open source license or through a direct agreement with you.) + +### Test coverage + +One area that always needs attention is improving out unit test coverage, you can view the code coverage report on [Azure Pipelines](https://dev.azure.com/xtermjs/xterm.js/_build/latest?definitionId=3) by clicking the Code Coverage tab. From fbb9ef9f7f5f9b5cfa7e4fbfa419f0d0bbeabe54 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 31 Oct 2019 11:59:04 -0700 Subject: [PATCH 78/78] Change to tracking lines in code coverage --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 8c35196a..177f581f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -35,8 +35,8 @@ jobs: displayName: 'Check build quality' inputs: checkCoverage: true - coverageType: branches - coverageThreshold: 55 + coverageType: lines + coverageThreshold: 60 coverageFailOption: fixed - job: macOS