diff --git a/addons/xterm-addon-attach/src/AttachAddon.api.ts b/addons/xterm-addon-attach/src/AttachAddon.api.ts index 7f2ce5c1..af2c36c7 100644 --- a/addons/xterm-addon-attach/src/AttachAddon.api.ts +++ b/addons/xterm-addon-attach/src/AttachAddon.api.ts @@ -17,9 +17,8 @@ const height = 600; describe('AttachAddon', () => { before(async function(): Promise { const browserType = getBrowserType(); - browser = await browserType.launch({ - headless: process.argv.indexOf('--headless') !== -1, - args: [`--window-size=${width},${height}`, `--no-sandbox`] + browser = await browserType.launch({ dumpio: true, + headless: process.argv.indexOf('--headless') !== -1 }); page = await (await browser.newContext()).newPage(); await page.setViewportSize({ width, height }); diff --git a/addons/xterm-addon-fit/src/FitAddon.api.ts b/addons/xterm-addon-fit/src/FitAddon.api.ts index 798b2fc5..5eae6b6d 100644 --- a/addons/xterm-addon-fit/src/FitAddon.api.ts +++ b/addons/xterm-addon-fit/src/FitAddon.api.ts @@ -17,9 +17,8 @@ const height = 768; describe('FitAddon', () => { before(async function(): Promise { const browserType = getBrowserType(); - browser = await browserType.launch({ - headless: process.argv.indexOf('--headless') !== -1, - args: [`--window-size=${width},${height}`, `--no-sandbox`] + browser = await browserType.launch({ dumpio: true, + headless: process.argv.indexOf('--headless') !== -1 }); page = await (await browser.newContext()).newPage(); await page.setViewportSize({ width, height }); diff --git a/addons/xterm-addon-search/src/SearchAddon.api.ts b/addons/xterm-addon-search/src/SearchAddon.api.ts index 521e6dfe..85e5059c 100644 --- a/addons/xterm-addon-search/src/SearchAddon.api.ts +++ b/addons/xterm-addon-search/src/SearchAddon.api.ts @@ -19,9 +19,8 @@ const height = 600; describe('Search Tests', function(): void { before(async function(): Promise { const browserType = getBrowserType(); - browser = await browserType.launch({ - headless: process.argv.indexOf('--headless') !== -1, - args: [`--window-size=${width},${height}`, `--no-sandbox`] + browser = await browserType.launch({ dumpio: true, + headless: process.argv.indexOf('--headless') !== -1 }); page = await (await browser.newContext()).newPage(); await page.setViewportSize({ width, height }); diff --git a/addons/xterm-addon-serialize/src/SerializeAddon.api.ts b/addons/xterm-addon-serialize/src/SerializeAddon.api.ts index 824b4b89..9e79de3f 100644 --- a/addons/xterm-addon-serialize/src/SerializeAddon.api.ts +++ b/addons/xterm-addon-serialize/src/SerializeAddon.api.ts @@ -17,9 +17,8 @@ const height = 600; describe('SerializeAddon', () => { before(async function(): Promise { const browserType = getBrowserType(); - browser = await browserType.launch({ - headless: process.argv.indexOf('--headless') !== -1, - args: [`--window-size=${width},${height}`] + browser = await browserType.launch({ dumpio: true, + headless: process.argv.indexOf('--headless') !== -1 }); page = await (await browser.newContext()).newPage(); await page.setViewportSize({ width, height }); diff --git a/addons/xterm-addon-unicode11/src/Unicode11Addon.api.ts b/addons/xterm-addon-unicode11/src/Unicode11Addon.api.ts index 983e795f..8d521b2e 100644 --- a/addons/xterm-addon-unicode11/src/Unicode11Addon.api.ts +++ b/addons/xterm-addon-unicode11/src/Unicode11Addon.api.ts @@ -17,9 +17,8 @@ const height = 600; describe('Unicode11Addon', () => { before(async function(): Promise { const browserType = getBrowserType(); - browser = await browserType.launch({ - headless: process.argv.indexOf('--headless') !== -1, - args: [`--window-size=${width},${height}`, `--no-sandbox`] + browser = await browserType.launch({ dumpio: true, + headless: process.argv.indexOf('--headless') !== -1 }); page = await (await browser.newContext()).newPage(); await page.setViewportSize({ 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 b2516cdf..dc7317f0 100644 --- a/addons/xterm-addon-web-links/src/WebLinksAddon.api.ts +++ b/addons/xterm-addon-web-links/src/WebLinksAddon.api.ts @@ -17,9 +17,8 @@ const height = 600; describe('WebLinksAddon', () => { before(async function(): Promise { const browserType = getBrowserType(); - browser = await browserType.launch({ - headless: process.argv.indexOf('--headless') !== -1, - args: [`--window-size=${width},${height}`, `--no-sandbox`] + browser = await browserType.launch({ dumpio: true, + headless: process.argv.indexOf('--headless') !== -1 }); page = await (await browser.newContext()).newPage(); await page.setViewportSize({ width, height }); diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.api.ts b/addons/xterm-addon-webgl/src/WebglRenderer.api.ts index cd90ddd9..591d7fff 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.api.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.api.ts @@ -899,9 +899,8 @@ async function getCellColor(col: number, row: number): Promise { async function setupBrowser(options: ITerminalOptions = { rendererType: 'dom' }): Promise { const browserType = getBrowserType(); - browser = await browserType.launch({ - headless: process.argv.indexOf('--headless') !== -1, - args: [`--window-size=${width},${height}`, `--no-sandbox`] + browser = await browserType.launch({ dumpio: true, + headless: process.argv.indexOf('--headless') !== -1 }); page = await (await browser.newContext()).newPage(); await page.setViewportSize({ width, height }); diff --git a/addons/xterm-addon-webgl/src/renderLayer/CursorRenderLayer.ts b/addons/xterm-addon-webgl/src/renderLayer/CursorRenderLayer.ts index 6af2b7d7..75201f47 100644 --- a/addons/xterm-addon-webgl/src/renderLayer/CursorRenderLayer.ts +++ b/addons/xterm-addon-webgl/src/renderLayer/CursorRenderLayer.ts @@ -302,7 +302,7 @@ class CursorBlinkStateManager { // the regular interval is setup in order to support restarting the blink // animation in a lightweight way (without thrashing clearInterval and // setInterval). - this._blinkStartTimeout = setTimeout(() => { + this._blinkStartTimeout = window.setTimeout(() => { // Check if another animation restart was requested while this was being // started if (this._animationTimeRestarted) { @@ -322,7 +322,7 @@ class CursorBlinkStateManager { }); // Setup the blink interval - this._blinkInterval = setInterval(() => { + this._blinkInterval = window.setInterval(() => { // Adjust the animation time if it was restarted if (this._animationTimeRestarted) { // calc time diff @@ -360,6 +360,9 @@ class CursorBlinkStateManager { } public resume(terminal: Terminal): void { + // Clear out any existing timers just in case + this.pause(); + this._animationTimeRestarted = undefined; this._restartInterval(); this.restartBlinkAnimation(terminal); diff --git a/azure-pipelines.yml b/azure-pipelines.yml index da42d796..05c3b03d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -82,8 +82,13 @@ jobs: vmImage: 'ubuntu-18.04' steps: - script: | + # source: https://github.com/microsoft/playwright/issues/1041 sudo apt update - sudo apt install libwoff1 libopus0 libwebp6 libwebpdemux2 libenchant1c2a libgudev-1.0-0 libsecret-1-0 libhyphen0 libgdk-pixbuf2.0-0 libegl1 libgles2 libevent-2.1-6 libnotify4 libxslt1.1 + sudo apt install libwoff1 libopus0 libwebp6 libwebpdemux2 libenchant1c2a libgudev-1.0-0 libsecret-1-0 libhyphen0 libgdk-pixbuf2.0-0 libegl1 libnotify4 libxslt1.1 libevent-2.1-6 libgles2 libgl1 libegl1 libvpx5 + # for chromium + sudo apt install libnss3 libxss1 libasound2 + # for firefox + sudo apt install libdbus-glib-1-2 libxt6 displayName: Install required packages - task: NodeTool@0 inputs: diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index de43022b..9b3320b6 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -1445,4 +1445,53 @@ describe('InputHandler', () => { assert.deepEqual(getLines(term), ['¥¥ ¥¥', '¥¥ ¥', '¥¥ ¥', '¥¥¥¥¥', '']); }); }); + describe('DECSTR', () => { + let term: TestTerminal; + beforeEach(() => { + term = new TestTerminal({cols: 10, rows: 5, scrollback: 1}); + term.writeSync('01234567890123'); + }); + it('should reset IRM', () => { + term.writeSync('\x1b[4h'); + assert.equal(term.insertMode, true); + term.writeSync('\x1b[!p'); + assert.equal(term.insertMode, false); + }); + it('should reset cursor visibility', () => { + term.writeSync('\x1b[?25l'); + assert.equal((term as any)._coreService.isCursorHidden, true); + term.writeSync('\x1b[!p'); + assert.equal((term as any)._coreService.isCursorHidden, false); + }); + it('should reset scroll margins', () => { + term.writeSync('\x1b[2;4r'); + assert.equal((term as any)._bufferService.buffer.scrollTop, 1); + assert.equal((term as any)._bufferService.buffer.scrollBottom, 3); + term.writeSync('\x1b[!p'); + assert.equal((term as any)._bufferService.buffer.scrollTop, 0); + assert.equal((term as any)._bufferService.buffer.scrollBottom, term.rows - 1); + }); + it('should reset text attributes', () => { + term.writeSync('\x1b[1;2;32;43m'); + assert.equal(!!term.curAttrData.isBold(), true); + term.writeSync('\x1b[!p'); + assert.equal(!!term.curAttrData.isBold(), false); + assert.equal(term.curAttrData.fg, 0); + assert.equal(term.curAttrData.bg, 0); + }); + it('should reset DECSC data', () => { + term.writeSync('\x1b7'); + assert.equal((term as any)._bufferService.buffer.savedX, 4); + assert.equal((term as any)._bufferService.buffer.savedY, 1); + term.writeSync('\x1b[!p'); + assert.equal((term as any)._bufferService.buffer.savedX, 0); + assert.equal((term as any)._bufferService.buffer.savedY, 0); + }); + it('should reset DECOM', () => { + term.writeSync('\x1b[?6h'); + assert.equal((term as any)._coreService.decPrivateModes.origin, true); + term.writeSync('\x1b[!p'); + assert.equal((term as any)._coreService.decPrivateModes.origin, false); + }); + }); }); diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 642453b2..95738f65 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -2344,11 +2344,12 @@ export class InputHandler extends Disposable implements IInputHandler { * DECSTR only resets certain attributes. For most needs DECSTR should be sufficient. * * The following terminal attributes are reset to default values: - * - cursor is reset (default = visible, home position) * - IRM is reset (dafault = false) * - scroll margins are reset (default = viewport size) * - erase attributes are reset to default * - charsets are reset + * - DECSC data is reset to initial values + * - DECOM is reset to absolute mode * * * FIXME: there are several more attributes missing (see VT520 manual) @@ -2360,9 +2361,18 @@ export class InputHandler extends Disposable implements IInputHandler { this._bufferService.buffer.scrollTop = 0; this._bufferService.buffer.scrollBottom = this._bufferService.rows - 1; this._curAttrData = DEFAULT_ATTR_DATA.clone(); - this._bufferService.buffer.x = this._bufferService.buffer.y = 0; // ? this._coreService.reset(); this._charsetService.reset(); + + // reset DECSC data + this._bufferService.buffer.savedX = 0; + this._bufferService.buffer.savedY = this._bufferService.buffer.ybase; + this._bufferService.buffer.savedCurAttrData.fg = this._curAttrData.fg; + this._bufferService.buffer.savedCurAttrData.bg = this._curAttrData.bg; + this._bufferService.buffer.savedCharset = this._charsetService.charset; + + // reset DECOM + this._coreService.decPrivateModes.origin = false; } /** diff --git a/src/Terminal.ts b/src/Terminal.ts index 89fbf1e0..ee226115 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -476,7 +476,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp } if (!document.body.contains(parent)) { - this._logService.warn('Terminal.open was called on an element that was not attached to the DOM'); + this._logService.debug('Terminal.open was called on an element that was not attached to the DOM'); } this._document = parent.ownerDocument; diff --git a/src/browser/ColorManager.ts b/src/browser/ColorManager.ts index c8224a92..6ca4fd96 100644 --- a/src/browser/ColorManager.ts +++ b/src/browser/ColorManager.ts @@ -192,7 +192,7 @@ export class ColorManager implements IColorManager { const rgba: number = channels.toRgba(r, g, b, alpha); return { rgba, - css: channels.toCss(r, g, b, alpha) + css }; } diff --git a/src/browser/renderer/CursorRenderLayer.ts b/src/browser/renderer/CursorRenderLayer.ts index 8b25667b..607180ae 100644 --- a/src/browser/renderer/CursorRenderLayer.ts +++ b/src/browser/renderer/CursorRenderLayer.ts @@ -306,7 +306,7 @@ class CursorBlinkStateManager { // the regular interval is setup in order to support restarting the blink // animation in a lightweight way (without thrashing clearInterval and // setInterval). - this._blinkStartTimeout = setTimeout(() => { + this._blinkStartTimeout = window.setTimeout(() => { // Check if another animation restart was requested while this was being // started if (this._animationTimeRestarted) { @@ -326,7 +326,7 @@ class CursorBlinkStateManager { }); // Setup the blink interval - this._blinkInterval = setInterval(() => { + this._blinkInterval = window.setInterval(() => { // Adjust the animation time if it was restarted if (this._animationTimeRestarted) { // calc time diff @@ -364,6 +364,9 @@ class CursorBlinkStateManager { } public resume(): void { + // Clear out any existing timers just in case + this.pause(); + this._animationTimeRestarted = undefined; this._restartInterval(); this.restartBlinkAnimation(); diff --git a/test/api/CharWidth.api.ts b/test/api/CharWidth.api.ts index fbc71b46..a1c38084 100644 --- a/test/api/CharWidth.api.ts +++ b/test/api/CharWidth.api.ts @@ -16,9 +16,8 @@ const height = 600; describe('CharWidth Integration Tests', function(): void { before(async function(): Promise { const browserType = getBrowserType(); - browser = await browserType.launch({ - headless: process.argv.indexOf('--headless') !== -1, - args: [`--window-size=${width},${height}`, `--no-sandbox`] + browser = await browserType.launch({ dumpio: true, + headless: process.argv.indexOf('--headless') !== -1 }); page = await (await browser.newContext()).newPage(); await page.setViewportSize({ width, height }); diff --git a/test/api/InputHandler.api.ts b/test/api/InputHandler.api.ts index f1662112..bc845f11 100644 --- a/test/api/InputHandler.api.ts +++ b/test/api/InputHandler.api.ts @@ -21,9 +21,8 @@ describe('InputHandler Integration Tests', function(): void { before(async function(): Promise { const browserType = getBrowserType(); isChromium = browserType.name() === 'chromium'; - browser = await browserType.launch({ - headless: process.argv.indexOf('--headless') !== -1, - args: [`--window-size=${width},${height}`, `--no-sandbox`] + browser = await browserType.launch({ dumpio: true, + headless: process.argv.indexOf('--headless') !== -1 }); page = await (await browser.newContext()).newPage(); await page.setViewportSize({ width, height }); diff --git a/test/api/MouseTracking.api.ts b/test/api/MouseTracking.api.ts index 9c9a0ac5..83e98021 100644 --- a/test/api/MouseTracking.api.ts +++ b/test/api/MouseTracking.api.ts @@ -213,9 +213,8 @@ describe('Mouse Tracking Tests', async () => { const itMouse = isChromium ? it : it.skip; before(async function(): Promise { - browser = await browserType.launch({ - headless: process.argv.indexOf('--headless') !== -1, - args: [`--window-size=${width},${height}`, `--no-sandbox`] + browser = await browserType.launch({ dumpio: true, + headless: process.argv.indexOf('--headless') !== -1 }); page = await (await browser.newContext()).newPage(); await page.setViewportSize({ width, height }); diff --git a/test/api/Parser.api.ts b/test/api/Parser.api.ts index 29dcbb0b..a40fd504 100644 --- a/test/api/Parser.api.ts +++ b/test/api/Parser.api.ts @@ -17,9 +17,8 @@ const height = 600; describe('Parser Integration Tests', function(): void { before(async function(): Promise { const browserType = getBrowserType(); - browser = await browserType.launch({ - headless: process.argv.indexOf('--headless') !== -1, - args: [`--window-size=${width},${height}`, `--no-sandbox`] + browser = await browserType.launch({ dumpio: true, + headless: process.argv.indexOf('--headless') !== -1 }); page = await (await browser.newContext()).newPage(); await page.setViewportSize({ width, height }); diff --git a/test/api/Terminal.api.ts b/test/api/Terminal.api.ts index 9f16bfcd..6829fd0a 100644 --- a/test/api/Terminal.api.ts +++ b/test/api/Terminal.api.ts @@ -17,9 +17,8 @@ const height = 600; describe('API Integration Tests', function(): void { before(async () => { const browserType = getBrowserType(); - browser = await browserType.launch({ - headless: process.argv.indexOf('--headless') !== -1, - args: [`--window-size=${width},${height}`, `--no-sandbox`] + browser = await browserType.launch({ dumpio: true, + headless: process.argv.indexOf('--headless') !== -1 }); page = await (await browser.newContext()).newPage(); await page.setViewportSize({ width, height });