From 663b16bc12bf33f5462006c3573e4fbe64360002 Mon Sep 17 00:00:00 2001 From: CHaBou Date: Sun, 10 Feb 2019 22:31:52 +0100 Subject: [PATCH] Add Session class and Session options decoration by plugins (#3464) * Add Session class and options plugin decoration * add init() method * Add warning for non-overrided session methods --- app/plugins.js | 22 ++++++++++++++++--- app/plugins/extensions.js | 2 ++ app/session.js | 45 +++++++++++++++++++++++++++++---------- app/ui/window.js | 8 ++++--- 4 files changed, 60 insertions(+), 17 deletions(-) diff --git a/app/plugins.js b/app/plugins.js index 5c64dde7..7f7d5652 100644 --- a/app/plugins.js +++ b/app/plugins.js @@ -332,9 +332,9 @@ exports.onWindow = win => { }); }; -// decorates the base object by calling plugin[key] +// decorates the base entity by calling plugin[key] // for all the available plugins -function decorateObject(base, key) { +function decorateEntity(base, key, type) { let decorated = base; modules.forEach(plugin => { if (plugin[key]) { @@ -345,7 +345,7 @@ function decorateObject(base, key) { notify('Plugin error!', `"${plugin._name}" when decorating ${key}`, {error: e}); return; } - if (res && typeof res === 'object') { + if (res && (!type || typeof res === type)) { decorated = res; } else { notify('Plugin error!', `"${plugin._name}": invalid return type for \`${key}\``); @@ -356,6 +356,14 @@ function decorateObject(base, key) { return decorated; } +function decorateObject(base, key) { + return decorateEntity(base, key, 'object'); +} + +function decorateClass(base, key) { + return decorateEntity(base, key, 'function'); +} + exports.getDeprecatedConfig = () => { const deprecated = {}; const baseConfig = config.getConfig(); @@ -409,4 +417,12 @@ exports.getDecoratedBrowserOptions = defaults => { return decorateObject(defaults, 'decorateBrowserOptions'); }; +exports.decorateSessionOptions = defaults => { + return decorateObject(defaults, 'decorateSessionOptions'); +}; + +exports.decorateSessionClass = Session => { + return decorateClass(Session, 'decorateSessionClass'); +}; + exports._toDependencies = toDependencies; diff --git a/app/plugins/extensions.js b/app/plugins/extensions.js index 102bb6c5..f6179e7d 100644 --- a/app/plugins/extensions.js +++ b/app/plugins/extensions.js @@ -4,6 +4,8 @@ module.exports = { 'onWindow', 'onRendererWindow', 'onUnload', + 'decorateSessionClass', + 'decorateSessionOptions', 'middleware', 'reduceUI', 'reduceSessions', diff --git a/app/session.js b/app/session.js index 30ff0778..1f84fd42 100644 --- a/app/session.js +++ b/app/session.js @@ -74,9 +74,17 @@ class DataBatcher extends EventEmitter { } module.exports = class Session extends EventEmitter { - constructor({uid, rows, cols: columns, cwd, shell, shellArgs}) { - const osLocale = require('os-locale'); + constructor(options) { super(); + this.pty = null; + this.batcher = null; + this.shell = null; + this.ended = false; + this.init(options); + } + + init({uid, rows, cols: columns, cwd, shell, shellArgs}) { + const osLocale = require('os-locale'); const baseEnv = Object.assign( {}, process.env, @@ -141,24 +149,39 @@ module.exports = class Session extends EventEmitter { } write(data) { - this.pty.write(data); + if (this.pty) { + this.pty.write(data); + } else { + //eslint-disable-next-line no-console + console.warn('Warning: Attempted to write to a session with no pty'); + } } resize({cols, rows}) { - try { - this.pty.resize(cols, rows); - } catch (err) { + if (this.pty) { + try { + this.pty.resize(cols, rows); + } catch (err) { + //eslint-disable-next-line no-console + console.error(err.stack); + } + } else { //eslint-disable-next-line no-console - console.error(err.stack); + console.warn('Warning: Attempted to resize a session with no pty'); } } destroy() { - try { - this.pty.kill(); - } catch (err) { + if (this.pty) { + try { + this.pty.kill(); + } catch (err) { + //eslint-disable-next-line no-console + console.error('exit error', err.stack); + } + } else { //eslint-disable-next-line no-console - console.error('exit error', err.stack); + console.warn('Warning: Attempted to destroy a session with no pty'); } this.emit('exit'); this.ended = true; diff --git a/app/ui/window.js b/app/ui/window.js index cab68303..caf6d29c 100644 --- a/app/ui/window.js +++ b/app/ui/window.js @@ -14,6 +14,7 @@ const Session = require('../session'); const contextMenuTemplate = require('./contextmenu'); const {execCommand} = require('../commands'); const {setRendererType, unsetRendererType} = require('../utils/renderer-utils'); +const {decorateSessionOptions, decorateSessionClass} = require('../plugins'); module.exports = class Window { constructor(options_, cfg, fn) { @@ -89,7 +90,7 @@ module.exports = class Window { function createSession(extraOptions = {}) { const uid = uuid.v4(); - const options = Object.assign( + const defaultOptions = Object.assign( { rows: 40, cols: 100, @@ -101,8 +102,9 @@ module.exports = class Window { extraOptions, {uid} ); - - const session = new Session(options); + const options = decorateSessionOptions(defaultOptions); + const DecoratedSession = decorateSessionClass(Session); + const session = new DecoratedSession(options); sessions.set(uid, session); return {session, options}; }