ソースを参照

moved more electron stuff out of tabby-local

Eugene Pankov 2 年 前
コミット
8cba805522

+ 2 - 3
tabby-electron/package.json

@@ -16,16 +16,15 @@
   ],
   "author": "Eugene Pankov",
   "license": "MIT",
-  "dependencies": {
-    "hasbin": "^1.2.3"
-  },
   "peerDependencies": {
     "@angular/core": "^9.1.9",
     "tabby-local": "*"
   },
   "devDependencies": {
     "electron-promise-ipc": "^2.2.4",
+    "ps-node": "^0.1.6",
     "tmp-promise": "^3.0.2",
+    "hasbin": "^1.2.3",
     "winston": "^3.3.3"
   }
 }

+ 6 - 2
tabby-electron/src/index.ts

@@ -2,7 +2,7 @@ import { NgModule } from '@angular/core'
 import { PlatformService, LogService, UpdaterService, DockingService, HostAppService, ThemesService, Platform, AppService, ConfigService, WIN_BUILD_FLUENT_BG_SUPPORTED, isWindowsBuild, HostWindowService, HotkeyProvider, ConfigProvider, FileProvider } from 'tabby-core'
 import { TerminalColorSchemeProvider } from 'tabby-terminal'
 import { SFTPContextMenuItemProvider, SSHProfileImporter, AutoPrivateKeyLocator } from 'tabby-ssh'
-import { ShellProvider, UACService } from 'tabby-local'
+import { PTYInterface, ShellProvider, UACService } from 'tabby-local'
 import { auditTime } from 'rxjs'
 
 import { HyperColorSchemes } from './colorSchemes'
@@ -16,11 +16,13 @@ import { ElectronFileProvider } from './services/fileProvider.service'
 import { ElectronHostAppService } from './services/hostApp.service'
 import { ElectronService } from './services/electron.service'
 import { DockMenuService } from './services/dockMenu.service'
+import { ElectronUACService } from './services/uac.service'
+
 import { ElectronHotkeyProvider } from './hotkeys'
 import { ElectronConfigProvider } from './config'
 import { EditSFTPContextMenu } from './sftpContextMenu'
 import { OpenSSHImporter, PrivateKeyLocator, StaticFileImporter } from './sshImporters'
-import { ElectronUACService } from './services/uac.service'
+import { ElectronPTYInterface } from './pty'
 
 import { CmderShellProvider } from './shells/cmder'
 import { Cygwin32ShellProvider } from './shells/cygwin32'
@@ -69,6 +71,8 @@ import { VSDevToolsProvider } from './shells/vs'
 
         { provide: UACService, useClass: ElectronUACService },
 
+        { provide: PTYInterface, useClass: ElectronPTYInterface },
+
         // For WindowsDefaultShellProvider
         PowerShellCoreShellProvider,
         WSLShellProvider,

+ 140 - 0
tabby-electron/src/pty.ts

@@ -0,0 +1,140 @@
+import * as psNode from 'ps-node'
+import { ipcRenderer } from 'electron'
+import { ChildProcess, PTYInterface, PTYProxy } from 'tabby-local'
+import { getWorkingDirectoryFromPID } from 'native-process-working-directory'
+
+/* eslint-disable block-scoped-var */
+
+try {
+    var macOSNativeProcessList = require('macos-native-processlist')  // eslint-disable-line @typescript-eslint/no-var-requires, no-var
+} catch { }
+
+try {
+    var windowsProcessTree = require('windows-process-tree')  // eslint-disable-line @typescript-eslint/no-var-requires, no-var
+} catch { }
+
+export class ElectronPTYInterface extends PTYInterface {
+    async spawn (...options: any[]): Promise<PTYProxy> {
+        const id = ipcRenderer.sendSync('pty:spawn', ...options)
+        return new ElectronPTYProxy(id)
+    }
+
+    async restore (id: string): Promise<ElectronPTYProxy|null> {
+        if (ipcRenderer.sendSync('pty:exists', id)) {
+            return new ElectronPTYProxy(id)
+        }
+        return null
+    }
+}
+
+// eslint-disable-next-line @typescript-eslint/no-extraneous-class
+export class ElectronPTYProxy extends PTYProxy {
+    private subscriptions: Map<string, any> = new Map()
+    private truePID: Promise<number>
+
+    constructor (
+        private id: string,
+    ) {
+        super()
+        this.truePID = new Promise(async (resolve) => {
+            let pid = await this.getPID()
+            try {
+                await new Promise(r => setTimeout(r, 2000))
+
+                // Retrieve any possible single children now that shell has fully started
+                let processes = await this.getChildProcessesInternal(pid)
+                while (pid && processes.length === 1) {
+                    if (!processes[0].pid) {
+                        break
+                    }
+                    pid = processes[0].pid
+                    processes = await this.getChildProcessesInternal(pid)
+                }
+            } finally {
+                resolve(pid)
+            }
+        })
+        this.truePID = this.truePID.catch(() => this.getPID())
+    }
+
+    getID (): string {
+        return this.id
+    }
+
+    getTruePID(): Promise<number> {
+        return this.truePID
+    }
+
+    async getPID (): Promise<number> {
+        return ipcRenderer.sendSync('pty:get-pid', this.id)
+    }
+
+    subscribe (event: string, handler: (..._: any[]) => void): void {
+        const key = `pty:${this.id}:${event}`
+        const newHandler = (_event, ...args) => handler(...args)
+        this.subscriptions.set(key, newHandler)
+        ipcRenderer.on(key, newHandler)
+    }
+
+    ackData (length: number): void {
+        ipcRenderer.send('pty:ack-data', this.id, length)
+    }
+
+    unsubscribeAll (): void {
+        for (const k of this.subscriptions.keys()) {
+            ipcRenderer.off(k, this.subscriptions.get(k))
+        }
+    }
+
+    async resize (columns: number, rows: number): Promise<void> {
+        ipcRenderer.send('pty:resize', this.id, columns, rows)
+    }
+
+    async write (data: Buffer): Promise<void> {
+        ipcRenderer.send('pty:write', this.id, data)
+    }
+
+    async kill (signal?: string): Promise<void> {
+        ipcRenderer.send('pty:kill', this.id, signal)
+    }
+
+    async getChildProcesses (): Promise<ChildProcess[]> {
+        return this.getChildProcessesInternal(await this.getTruePID())
+    }
+
+    async getChildProcessesInternal (truePID: number): Promise<ChildProcess[]> {
+        if (process.platform === 'darwin') {
+            const processes = await macOSNativeProcessList.getProcessList()
+            return processes.filter(x => x.ppid === truePID).map(p => ({
+                pid: p.pid,
+                ppid: p.ppid,
+                command: p.name,
+            }))
+        }
+        if (process.platform === 'win32') {
+            return new Promise<ChildProcess[]>(resolve => {
+                windowsProcessTree.getProcessTree(truePID, tree => {
+                    resolve(tree ? tree.children.map(child => ({
+                        pid: child.pid,
+                        ppid: tree.pid,
+                        command: child.name,
+                    })) : [])
+                })
+            })
+        }
+        return new Promise<ChildProcess[]>((resolve, reject) => {
+            psNode.lookup({ ppid: truePID }, (err, processes) => {
+                if (err) {
+                    reject(err)
+                    return
+                }
+                resolve(processes as ChildProcess[])
+            })
+        })
+    }
+
+    async getWorkingDirectory (): Promise<string|null> {
+        return getWorkingDirectoryFromPID(await this.getTruePID())
+    }
+
+}

+ 19 - 0
tabby-electron/yarn.lock

@@ -93,6 +93,11 @@ [email protected]:
   resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
   integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
 
+connected-domain@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/connected-domain/-/connected-domain-1.0.0.tgz#bfe77238c74be453a79f0cb6058deeb4f2358e93"
+  integrity sha512-lHlohUiJxlpunvDag2Y0pO20bnvarMjnrdciZeuJUqRwrf/5JHNhdpiPIr5GQ8IkqrFj5TDMQwcCjblGo1oeuA==
+
 define-properties@^1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
@@ -368,6 +373,13 @@ path-is-absolute@^1.0.0:
   resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
   integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
 
+ps-node@^0.1.6:
+  version "0.1.6"
+  resolved "https://registry.yarnpkg.com/ps-node/-/ps-node-0.1.6.tgz#9af67a99d7b1d0132e51a503099d38a8d2ace2c3"
+  integrity sha512-w7QJhUTbu70hpDso0YXDRNKCPNuchV8UTUZsAv0m7Qj5g85oHOJfr9drA1EjvK4nQK/bG8P97W4L6PJ3IQLoOA==
+  dependencies:
+    table-parser "^0.1.3"
+
 readable-stream@^3.4.0, readable-stream@^3.6.0:
   version "3.6.0"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
@@ -436,6 +448,13 @@ string_decoder@^1.1.1:
   dependencies:
     safe-buffer "~5.2.0"
 
+table-parser@^0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/table-parser/-/table-parser-0.1.3.tgz#0441cfce16a59481684c27d1b5a67ff15a43c7b0"
+  integrity sha512-LCYeuvqqoPII3lzzYaXKbC3Forb+d2u4bNwhk/9FlivuGRxPE28YEWAYcujeSlLLDlMfvy29+WPybFJZFiKMYg==
+  dependencies:
+    connected-domain "^1.0.0"
+
 [email protected]:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5"

+ 0 - 1
tabby-local/package.json

@@ -19,7 +19,6 @@
   "devDependencies": {
     "ansi-colors": "^4.1.1",
     "dataurl": "0.1.0",
-    "ps-node": "^0.1.6",
     "runes": "^0.4.2"
   },
   "peerDependencies": {

+ 19 - 0
tabby-local/src/api.ts

@@ -59,3 +59,22 @@ export abstract class UACService {
 
     abstract patchSessionOptionsForUAC (sessionOptions: SessionOptions): SessionOptions
 }
+
+export abstract class PTYProxy {
+    abstract getID (): string
+    abstract getPID (): Promise<number>
+    abstract resize (columns: number, rows: number): Promise<void>
+    abstract write (data: Buffer): Promise<void>
+    abstract kill (signal?: string): Promise<void>
+    abstract ackData (length: number): void
+    abstract subscribe (event: string, handler: (..._: any[]) => void): void
+    abstract unsubscribeAll (): void
+    abstract getChildProcesses (): Promise<ChildProcess[]>
+    abstract getTruePID (): Promise<number>
+    abstract getWorkingDirectory (): Promise<string|null>
+}
+
+export abstract class PTYInterface {
+    abstract spawn (...options: any[]): Promise<PTYProxy>
+    abstract restore (id: string): Promise<PTYProxy|null>
+}

+ 2 - 2
tabby-local/src/components/terminalTab.component.ts

@@ -51,7 +51,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent<LocalProfile>
 
     protected onFrontendReady (): void {
         this.initializeSession(this.size.columns, this.size.rows)
-        this.savedStateIsLive = this.profile.options.restoreFromPTYID === this.session?.getPTYID()
+        this.savedStateIsLive = this.profile.options.restoreFromPTYID === this.session?.getID()
         super.onFrontendReady()
     }
 
@@ -82,7 +82,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent<LocalProfile>
                 options: {
                     ...this.profile.options,
                     cwd: cwd ?? this.profile.options.cwd,
-                    restoreFromPTYID: options?.includeState && this.session?.getPTYID(),
+                    restoreFromPTYID: options?.includeState && this.session?.getID(),
                 },
             },
             savedState: options?.includeState && this.frontend?.saveState(),

+ 18 - 130
tabby-local/src/session.ts

@@ -1,87 +1,12 @@
-import * as psNode from 'ps-node'
 import * as fs from 'mz/fs'
 import * as fsSync from 'fs'
 import { Injector } from '@angular/core'
 import { HostAppService, ConfigService, WIN_BUILD_CONPTY_SUPPORTED, isWindowsBuild, Platform, BootstrapData, BOOTSTRAP_DATA, LogService } from 'tabby-core'
 import { BaseSession } from 'tabby-terminal'
-import { ipcRenderer } from 'electron'
-import { getWorkingDirectoryFromPID } from 'native-process-working-directory'
-import { SessionOptions, ChildProcess } from './api'
-
-/* eslint-disable block-scoped-var */
-
-try {
-    var macOSNativeProcessList = require('macos-native-processlist')  // eslint-disable-line @typescript-eslint/no-var-requires, no-var
-} catch { }
-
-try {
-    var windowsProcessTree = require('windows-process-tree')  // eslint-disable-line @typescript-eslint/no-var-requires, no-var
-} catch { }
+import { SessionOptions, ChildProcess, PTYInterface, PTYProxy } from './api'
 
 const windowsDirectoryRegex = /([a-zA-Z]:[^\:\[\]\?\"\<\>\|]+)/mi
 
-// eslint-disable-next-line @typescript-eslint/no-extraneous-class
-export class PTYProxy {
-    private id: string
-    private subscriptions: Map<string, any> = new Map()
-
-    static spawn (...options: any[]): PTYProxy {
-        return new PTYProxy(null, ...options)
-    }
-
-    static restore (id: string): PTYProxy|null {
-        if (ipcRenderer.sendSync('pty:exists', id)) {
-            return new PTYProxy(id)
-        }
-        return null
-    }
-
-    private constructor (id: string|null, ...options: any[]) {
-        if (id) {
-            this.id = id
-        } else {
-            this.id = ipcRenderer.sendSync('pty:spawn', ...options)
-        }
-    }
-
-    getPTYID (): string {
-        return this.id
-    }
-
-    getPID (): number {
-        return ipcRenderer.sendSync('pty:get-pid', this.id)
-    }
-
-    subscribe (event: string, handler: (..._: any[]) => void): void {
-        const key = `pty:${this.id}:${event}`
-        const newHandler = (_event, ...args) => handler(...args)
-        this.subscriptions.set(key, newHandler)
-        ipcRenderer.on(key, newHandler)
-    }
-
-    ackData (length: number): void {
-        ipcRenderer.send('pty:ack-data', this.id, length)
-    }
-
-    unsubscribeAll (): void {
-        for (const k of this.subscriptions.keys()) {
-            ipcRenderer.off(k, this.subscriptions.get(k))
-        }
-    }
-
-    resize (columns: number, rows: number): void {
-        ipcRenderer.send('pty:resize', this.id, columns, rows)
-    }
-
-    write (data: Buffer): void {
-        ipcRenderer.send('pty:write', this.id, data)
-    }
-
-    kill (signal?: string): void {
-        ipcRenderer.send('pty:kill', this.id, signal)
-    }
-}
-
 function mergeEnv (...envs) {
     const result = {}
     const keyMap = {}
@@ -121,19 +46,23 @@ export class Session extends BaseSession {
     private config: ConfigService
     private hostApp: HostAppService
     private bootstrapData: BootstrapData
+    private ptyInterface: PTYInterface
 
-    constructor (injector: Injector) {
+    constructor (
+        injector: Injector,
+    ) {
         super(injector.get(LogService).create('local'))
         this.config = injector.get(ConfigService)
         this.hostApp = injector.get(HostAppService)
+        this.ptyInterface = injector.get(PTYInterface)
         this.bootstrapData = injector.get(BOOTSTRAP_DATA)
     }
 
-    start (options: SessionOptions): void {
+    async start (options: SessionOptions): Promise<void> {
         let pty: PTYProxy|null = null
 
         if (options.restoreFromPTYID) {
-            pty = PTYProxy.restore(options.restoreFromPTYID)
+            pty = await this.ptyInterface.restore(options.restoreFromPTYID)
             options.restoreFromPTYID = undefined
         }
 
@@ -175,7 +104,7 @@ export class Session extends BaseSession {
                 cwd = undefined
             }
 
-            pty = PTYProxy.spawn(options.command, options.args ?? [], {
+            pty = await this.ptyInterface.spawn(options.command, options.args ?? [], {
                 name: 'xterm-256color',
                 cols: options.width ?? 80,
                 rows: options.height ?? 30,
@@ -191,17 +120,9 @@ export class Session extends BaseSession {
 
         this.pty = pty
 
-        this.truePID = this.pty.getPID()
-
-        setTimeout(async () => {
-            // Retrieve any possible single children now that shell has fully started
-            let processes = await this.getChildProcesses()
-            while (processes.length === 1) {
-                this.truePID = processes[0].pid
-                processes = await this.getChildProcesses()
-            }
+        pty.getTruePID().then(async () => {
             this.initialCWD = await this.getWorkingDirectory()
-        }, 2000)
+        })
 
         this.open = true
 
@@ -236,8 +157,8 @@ export class Session extends BaseSession {
         this.destroyed$.subscribe(() => this.pty!.unsubscribeAll())
     }
 
-    getPTYID (): string|null {
-        return this.pty?.getPTYID() ?? null
+    getID (): string|null {
+        return this.pty?.getID() ?? null
     }
 
     resize (columns: number, rows: number): void {
@@ -258,37 +179,7 @@ export class Session extends BaseSession {
     }
 
     async getChildProcesses (): Promise<ChildProcess[]> {
-        if (!this.truePID) {
-            return []
-        }
-        if (this.hostApp.platform === Platform.macOS) {
-            const processes = await macOSNativeProcessList.getProcessList()
-            return processes.filter(x => x.ppid === this.truePID).map(p => ({
-                pid: p.pid,
-                ppid: p.ppid,
-                command: p.name,
-            }))
-        }
-        if (this.hostApp.platform === Platform.Windows) {
-            return new Promise<ChildProcess[]>(resolve => {
-                windowsProcessTree.getProcessTree(this.truePID, tree => {
-                    resolve(tree ? tree.children.map(child => ({
-                        pid: child.pid,
-                        ppid: tree.pid,
-                        command: child.name,
-                    })) : [])
-                })
-            })
-        }
-        return new Promise<ChildProcess[]>((resolve, reject) => {
-            psNode.lookup({ ppid: this.truePID }, (err, processes) => {
-                if (err) {
-                    reject(err)
-                    return
-                }
-                resolve(processes as ChildProcess[])
-            })
-        })
+        return this.pty?.getChildProcesses() ?? []
     }
 
     async gracefullyKillProcess (): Promise<void> {
@@ -297,9 +188,9 @@ export class Session extends BaseSession {
         } else {
             await new Promise<void>((resolve) => {
                 this.kill('SIGTERM')
-                setTimeout(() => {
+                setTimeout(async () => {
                     try {
-                        process.kill(this.pty!.getPID(), 0)
+                        process.kill(await this.pty!.getPID(), 0)
                         // still alive
                         this.kill('SIGKILL')
                         resolve()
@@ -312,19 +203,16 @@ export class Session extends BaseSession {
     }
 
     supportsWorkingDirectory (): boolean {
-        return !!(this.truePID ?? this.reportedCWD ?? this.guessedCWD)
+        return !!(this.initialCWD ?? this.reportedCWD ?? this.guessedCWD)
     }
 
     async getWorkingDirectory (): Promise<string|null> {
         if (this.reportedCWD) {
             return this.reportedCWD
         }
-        if (!this.truePID) {
-            return null
-        }
         let cwd: string|null = null
         try {
-            cwd = getWorkingDirectoryFromPID(this.truePID)
+            cwd = await this.pty?.getWorkingDirectory() ?? null
         } catch (exc) {
             console.info('Could not read working directory:', exc)
         }

+ 0 - 19
tabby-local/yarn.lock

@@ -7,31 +7,12 @@ ansi-colors@^4.1.1:
   resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
   integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
 
-connected-domain@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/connected-domain/-/connected-domain-1.0.0.tgz#bfe77238c74be453a79f0cb6058deeb4f2358e93"
-  integrity sha1-v+dyOMdL5FOnnwy2BY3utPI1jpM=
-
 [email protected]:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/dataurl/-/dataurl-0.1.0.tgz#1f4734feddec05ffe445747978d86759c4b33199"
   integrity sha1-H0c0/t3sBf/kRXR5eNhnWcSzMZk=
 
-ps-node@^0.1.6:
-  version "0.1.6"
-  resolved "https://registry.yarnpkg.com/ps-node/-/ps-node-0.1.6.tgz#9af67a99d7b1d0132e51a503099d38a8d2ace2c3"
-  integrity sha1-mvZ6mdex0BMuUaUDCZ04qNKs4sM=
-  dependencies:
-    table-parser "^0.1.3"
-
 runes@^0.4.2:
   version "0.4.3"
   resolved "https://registry.yarnpkg.com/runes/-/runes-0.4.3.tgz#32f7738844bc767b65cc68171528e3373c7bb355"
   integrity sha512-K6p9y4ZyL9wPzA+PMDloNQPfoDGTiFYDvdlXznyGKgD10BJpcAosvATKrExRKOrNLgD8E7Um7WGW0lxsnOuNLg==
-
-table-parser@^0.1.3:
-  version "0.1.3"
-  resolved "https://registry.yarnpkg.com/table-parser/-/table-parser-0.1.3.tgz#0441cfce16a59481684c27d1b5a67ff15a43c7b0"
-  integrity sha1-BEHPzhallIFoTCfRtaZ/8VpDx7A=
-  dependencies:
-    connected-domain "^1.0.0"

+ 0 - 1
tabby-terminal/package.json

@@ -26,7 +26,6 @@
     "hexer": "^1.5.0",
     "ngx-colors": "^3.4.0",
     "patch-package": "^6.5.0",
-    "ps-node": "^0.1.6",
     "runes": "^0.4.2",
     "xterm": "^5.1.0",
     "xterm-addon-canvas": "^0.3.0",

+ 1 - 2
tabby-terminal/src/session.ts

@@ -10,7 +10,6 @@ import { SessionMiddlewareStack } from './api/middleware'
  */
 export abstract class BaseSession {
     open: boolean
-    truePID?: number
     readonly oscProcessor = new OSCProcessor()
     readonly middleware = new SessionMiddlewareStack()
     protected output = new Subject<string>()
@@ -85,7 +84,7 @@ export abstract class BaseSession {
         this.binaryOutput.complete()
     }
 
-    abstract start (options: unknown): void
+    abstract start (options: unknown): Promise<void>
     abstract resize (columns: number, rows: number): void
     abstract write (data: Buffer): void
     abstract kill (signal?: string): void

+ 0 - 19
tabby-terminal/yarn.lock

@@ -89,11 +89,6 @@ [email protected]:
   resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
   integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
 
-connected-domain@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/connected-domain/-/connected-domain-1.0.0.tgz#bfe77238c74be453a79f0cb6058deeb4f2358e93"
-  integrity sha1-v+dyOMdL5FOnnwy2BY3utPI1jpM=
-
 crc-32@^1.1.1:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208"
@@ -382,13 +377,6 @@ promise-stream-reader@^1.0.1:
   resolved "https://registry.yarnpkg.com/promise-stream-reader/-/promise-stream-reader-1.0.1.tgz#4e793a79c9d49a73ccd947c6da9c127f12923649"
   integrity sha512-Tnxit5trUjBAqqZCGWwjyxhmgMN4hGrtpW3Oc/tRI4bpm/O2+ej72BB08l6JBnGQgVDGCLvHFGjGgQS6vzhwXg==
 
-ps-node@^0.1.6:
-  version "0.1.6"
-  resolved "https://registry.yarnpkg.com/ps-node/-/ps-node-0.1.6.tgz#9af67a99d7b1d0132e51a503099d38a8d2ace2c3"
-  integrity sha1-mvZ6mdex0BMuUaUDCZ04qNKs4sM=
-  dependencies:
-    table-parser "^0.1.3"
-
 rimraf@^2.6.3:
   version "2.7.1"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
@@ -430,13 +418,6 @@ supports-color@^7.1.0:
   dependencies:
     has-flag "^4.0.0"
 
-table-parser@^0.1.3:
-  version "0.1.3"
-  resolved "https://registry.yarnpkg.com/table-parser/-/table-parser-0.1.3.tgz#0441cfce16a59481684c27d1b5a67ff15a43c7b0"
-  integrity sha1-BEHPzhallIFoTCfRtaZ/8VpDx7A=
-  dependencies:
-    connected-domain "^1.0.0"
-
 tiny-inflate@^1.0.2:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4"