@lvce-editor/shared-process 0.15.27 → 0.15.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/mocks/windows-process-tree.js +1 -0
  2. package/package.json +5 -5
  3. package/src/parts/CreatePidMap/CreatePidMap.js +6 -0
  4. package/src/parts/ErrorCodes/ErrorCodes.js +1 -0
  5. package/src/parts/ErrorType/ErrorType.js +4 -0
  6. package/src/parts/GetAccurateMemoryUsage/GetAccurateMemoryUsage.js +38 -0
  7. package/src/parts/GetElectronRebuildPath/GetElectronRebuildPath.js +6 -0
  8. package/src/parts/GetErrorConstructor/GetErrorConstructor.js +28 -0
  9. package/src/parts/GetPsOutput/GetPsOutput.js +20 -0
  10. package/src/parts/JsonRpc/JsonRpc.js +9 -4
  11. package/src/parts/ListProcessGetName/ListProcessGetName.js +54 -0
  12. package/src/parts/ListProcessesWithMemoryUsage/ListProcessesWithMemoryUsage.ipc.js +7 -0
  13. package/src/parts/ListProcessesWithMemoryUsage/ListProcessesWithMemoryUsage.js +13 -0
  14. package/src/parts/ListProcessesWithMemoryUsageUnix/ListProcessesWithMemoryUsageUnix.js +32 -0
  15. package/src/parts/ListProcessesWithMemoryUsageWindows/ListProcessesWithMemoryUsageWindows.js +51 -0
  16. package/src/parts/LoadWindowsProcessTree/LoadWindowsProcessTree.js +16 -0
  17. package/src/parts/Module/Module.js +2 -0
  18. package/src/parts/ModuleId/ModuleId.js +1 -0
  19. package/src/parts/ModuleMap/ModuleMap.js +3 -0
  20. package/src/parts/ParentIpc/ParentIpc.js +8 -0
  21. package/src/parts/ParsePsOutput/ParsePsOutput.js +50 -0
  22. package/src/parts/Process/Process.ipc.js +1 -0
  23. package/src/parts/RebuildNodePty/RebuildNodePty.js +11 -10
  24. package/src/parts/RestoreJsonRpcError/RestoreJsonRpcError.js +79 -0
  25. package/src/parts/UnwrapJsonRpcResult/UnwrapJsonRpcResult.js +13 -0
  26. package/src/parts/WindowsProcessTree/WindowsProcessTree.js +26 -0
  27. package/src/parts/WindowsProcessTreeDataFlag/WindowsProcessTreeDataFlag.js +3 -0
@@ -0,0 +1 @@
1
+ export {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/shared-process",
3
- "version": "0.15.27",
3
+ "version": "0.15.28",
4
4
  "description": "Utility package for @lvce-editor/server",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -16,10 +16,10 @@
16
16
  "node": ">=16"
17
17
  },
18
18
  "dependencies": {
19
- "@babel/code-frame": "^7.21.4",
20
- "@lvce-editor/extension-host": "0.15.27",
21
- "@lvce-editor/extension-host-helper-process": "0.15.27",
22
- "@lvce-editor/pty-host": "0.15.27",
19
+ "@babel/code-frame": "^7.22.5",
20
+ "@lvce-editor/extension-host": "0.15.28",
21
+ "@lvce-editor/extension-host-helper-process": "0.15.28",
22
+ "@lvce-editor/pty-host": "0.15.28",
23
23
  "debug": "^4.3.4",
24
24
  "execa": "^7.1.1",
25
25
  "exit-hook": "^3.2.0",
@@ -0,0 +1,6 @@
1
+ import * as ParentIpc from '../ParentIpc/ParentIpc.js'
2
+
3
+ export const createPidMap = async () => {
4
+ const pidMap = await ParentIpc.invoke('CreatePidMap.createPidMap')
5
+ return pidMap
6
+ }
@@ -18,3 +18,4 @@ export const ERR_IPC_CHANNEL_CLOSED = 'ERR_IPC_CHANNEL_CLOSED'
18
18
  export const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND'
19
19
  export const EXDEV = 'EXDEV'
20
20
  export const ERR_DLOPEN_FAILED = 'ERR_DLOPEN_FAILED'
21
+ export const ESRCH = 'ESRCH'
@@ -0,0 +1,4 @@
1
+ export const DomException = 'DOMException'
2
+ export const ReferenceError = 'ReferenceError'
3
+ export const SyntaxError = 'SyntaxError'
4
+ export const TypeError = 'TypeError'
@@ -0,0 +1,38 @@
1
+ import { join } from 'node:path'
2
+ import { readFile } from 'node:fs/promises'
3
+ import { VError } from '../VError/VError.js'
4
+ import * as Assert from '../Assert/Assert.js'
5
+ import * as EncodingType from '../EncodingType/EncodingType.js'
6
+ import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
7
+
8
+ export const getAccurateMemoryUsage = async (pid) => {
9
+ Assert.number(pid)
10
+ try {
11
+ const filePath = join('/proc', `${pid}`, 'statm')
12
+ let content
13
+ try {
14
+ content = await readFile(filePath, EncodingType.Utf8)
15
+ } catch (error) {
16
+ if (
17
+ error &&
18
+ // @ts-ignore
19
+ (error.code === ErrorCodes.ENOENT ||
20
+ // @ts-ignore
21
+ error.code === ErrorCodes.ESRCH)
22
+ ) {
23
+ return -1
24
+ }
25
+ throw error
26
+ }
27
+ const trimmedContent = content.trim()
28
+ const numberBlocks = trimmedContent.split(' ')
29
+ const pageSize = 4096
30
+ const rss = Number.parseInt(numberBlocks[1]) * pageSize
31
+ const shared = Number.parseInt(numberBlocks[2]) * pageSize
32
+ const memory = rss - shared
33
+ return memory
34
+ } catch (error) {
35
+ // @ts-ignore
36
+ throw new VError(error, 'Failed to get accurate memory usage')
37
+ }
38
+ }
@@ -0,0 +1,6 @@
1
+ import * as Path from '../Path/Path.js'
2
+ import * as Root from '../Root/Root.js'
3
+
4
+ export const getElectronRebuildPath = () => {
5
+ return Path.join(Root.root, 'packages', 'main-process', 'node_modules', '.bin', 'electron-rebuild')
6
+ }
@@ -0,0 +1,28 @@
1
+ import * as ErrorType from '../ErrorType/ErrorType.js'
2
+
3
+ export const getErrorConstructor = (message, type) => {
4
+ if (type) {
5
+ switch (type) {
6
+ case ErrorType.DomException:
7
+ return DOMException
8
+ case ErrorType.TypeError:
9
+ return TypeError
10
+ case ErrorType.SyntaxError:
11
+ return SyntaxError
12
+ case ErrorType.ReferenceError:
13
+ return ReferenceError
14
+ default:
15
+ return Error
16
+ }
17
+ }
18
+ if (message.startsWith('TypeError: ')) {
19
+ return TypeError
20
+ }
21
+ if (message.startsWith('SyntaxError: ')) {
22
+ return SyntaxError
23
+ }
24
+ if (message.startsWith('ReferenceError: ')) {
25
+ return ReferenceError
26
+ }
27
+ return Error
28
+ }
@@ -0,0 +1,20 @@
1
+ import { VError } from '../VError/VError.js'
2
+ import { execFile as _execFile } from 'node:child_process'
3
+ import * as Signal from '../Signal/Signal.js'
4
+ import { promisify } from 'node:util'
5
+
6
+ const execFile = promisify(_execFile)
7
+
8
+ export const getPsOutput = async () => {
9
+ try {
10
+ const { stdout } = await execFile('ps', ['-ax', '-o', 'pid=,ppid=,pcpu=,pmem=,command='])
11
+ return stdout.trim()
12
+ } catch (error) {
13
+ // @ts-ignore
14
+ if (error && error.signal === Signal.SIGINT) {
15
+ return ''
16
+ }
17
+ // @ts-ignore
18
+ throw new VError(error, `Failed to execute ps`)
19
+ }
20
+ }
@@ -1,5 +1,6 @@
1
1
  import * as Callback from '../Callback/Callback.js'
2
2
  import * as JsonRpcVersion from '../JsonRpcVersion/JsonRpcVersion.js'
3
+ import * as UnwrapJsonRpcResult from '../UnwrapJsonRpcResult/UnwrapJsonRpcResult.js'
3
4
 
4
5
  export const send = (transport, method, ...params) => {
5
6
  transport.send({
@@ -9,7 +10,7 @@ export const send = (transport, method, ...params) => {
9
10
  })
10
11
  }
11
12
 
12
- export const invoke = (ipc, method, ...params) => {
13
+ export const invoke = async (ipc, method, ...params) => {
13
14
  const { id, promise } = Callback.registerPromise()
14
15
  ipc.send({
15
16
  jsonrpc: JsonRpcVersion.Two,
@@ -17,10 +18,12 @@ export const invoke = (ipc, method, ...params) => {
17
18
  params,
18
19
  id,
19
20
  })
20
- return promise
21
+ const responseMessage = await promise
22
+ const result = UnwrapJsonRpcResult.unwrapJsonRpcResult(responseMessage)
23
+ return result
21
24
  }
22
25
 
23
- export const invokeAndTransfer = (ipc, handle, method, ...params) => {
26
+ export const invokeAndTransfer = async (ipc, handle, method, ...params) => {
24
27
  const { id, promise } = Callback.registerPromise()
25
28
  ipc.sendAndTransfer(
26
29
  {
@@ -31,5 +34,7 @@ export const invokeAndTransfer = (ipc, handle, method, ...params) => {
31
34
  },
32
35
  handle
33
36
  )
34
- return promise
37
+ const responseMessage = await promise
38
+ const result = UnwrapJsonRpcResult.unwrapJsonRpcResult(responseMessage)
39
+ return result
35
40
  }
@@ -0,0 +1,54 @@
1
+ import * as Assert from '../Assert/Assert.js'
2
+
3
+ export const getName = (pid, cmd, rootPid, pidMap) => {
4
+ Assert.number(pid)
5
+ Assert.string(cmd)
6
+ Assert.number(rootPid)
7
+ Assert.object(pidMap)
8
+ if (pid === rootPid) {
9
+ return 'main'
10
+ }
11
+ if (cmd.includes('--type=zygote')) {
12
+ return 'zygote'
13
+ }
14
+ if (cmd.includes('--type=gpu-process')) {
15
+ return 'gpu-process'
16
+ }
17
+ if (cmd.includes('extensionHostMain.js')) {
18
+ return 'extension-host'
19
+ }
20
+ if (cmd.includes('ptyHostMain.js')) {
21
+ return 'pty-host'
22
+ }
23
+ if (cmd.includes('--lvce-window-kind=process-explorer')) {
24
+ return 'process-explorer'
25
+ }
26
+ if (pid in pidMap) {
27
+ return pidMap[pid] || `<unknown>`
28
+ }
29
+ if (cmd.includes('--type=renderer')) {
30
+ return `renderer`
31
+ }
32
+ if (cmd.includes('--type=utility')) {
33
+ return 'utility'
34
+ }
35
+ if (cmd.includes('typescript/lib/tsserver.js')) {
36
+ return 'tsserver.js'
37
+ }
38
+ if (cmd.includes('typescript/lib/typingsInstaller.js')) {
39
+ return 'typingsInstaller.js'
40
+ }
41
+ if (cmd.includes('extensionHostHelperProcessMain.js')) {
42
+ return 'extension-host-helper-process'
43
+ }
44
+ if (cmd.includes('/bin/rg')) {
45
+ return 'ripgrep'
46
+ }
47
+ if (cmd.startsWith('bash')) {
48
+ return 'bash'
49
+ }
50
+ if (cmd.startsWith(`/opt/sublime_text/sublime_text `)) {
51
+ return 'sublime-text'
52
+ }
53
+ return `${cmd}`
54
+ }
@@ -0,0 +1,7 @@
1
+ import * as ListProcessesWithMemoryUsage from './ListProcessesWithMemoryUsage.js'
2
+
3
+ export const name = 'ListProcessesWithMemoryUsage'
4
+
5
+ export const Commands = {
6
+ listProcessesWithMemoryUsage: ListProcessesWithMemoryUsage.listProcessesWithMemoryUsage,
7
+ }
@@ -0,0 +1,13 @@
1
+ import * as Platform from '../Platform/Platform.js'
2
+
3
+ const getModule = () => {
4
+ if (Platform.isWindows) {
5
+ return import('../ListProcessesWithMemoryUsageWindows/ListProcessesWithMemoryUsageWindows.js')
6
+ }
7
+ return import('../ListProcessesWithMemoryUsageUnix/ListProcessesWithMemoryUsageUnix.js')
8
+ }
9
+
10
+ export const listProcessesWithMemoryUsage = async (rootPid) => {
11
+ const module = await getModule()
12
+ return module.listProcessesWithMemoryUsage(rootPid)
13
+ }
@@ -0,0 +1,32 @@
1
+ import * as CreatePidMap from '../CreatePidMap/CreatePidMap.js'
2
+ import * as GetAccurateMemoryUsage from '../GetAccurateMemoryUsage/GetAccurateMemoryUsage.js'
3
+ import * as GetPsOutput from '../GetPsOutput/GetPsOutput.js'
4
+ import * as ParsePsOutput from '../ParsePsOutput/ParsePsOutput.js'
5
+
6
+ const addAccurateMemoryUsage = async (process) => {
7
+ const accurateMemoryUsage = await GetAccurateMemoryUsage.getAccurateMemoryUsage(process.pid)
8
+ return {
9
+ ...process,
10
+ memory: accurateMemoryUsage,
11
+ }
12
+ }
13
+
14
+ const hasPositiveMemoryUsage = (process) => {
15
+ return process.memory >= 0
16
+ }
17
+
18
+ export const listProcessesWithMemoryUsage = async (rootPid) => {
19
+ // console.time('getPsOutput')
20
+ const stdout = await GetPsOutput.getPsOutput()
21
+ const pidMap = await CreatePidMap.createPidMap()
22
+ // console.log({ stdout })
23
+ // console.timeEnd('getPsOutput')
24
+ // console.time('parsePsOutput')
25
+ const parsed = ParsePsOutput.parsePsOutput(stdout, rootPid, pidMap)
26
+ // console.timeEnd('parsePsOutput')
27
+ // console.time('addAccurateMemoryUsage')
28
+ const parsedWithAccurateMemoryUsage = await Promise.all(parsed.map(addAccurateMemoryUsage))
29
+ // console.timeEnd('addAccurateMemoryUsage')
30
+ const filtered = parsedWithAccurateMemoryUsage.filter(hasPositiveMemoryUsage)
31
+ return filtered
32
+ }
@@ -0,0 +1,51 @@
1
+ // listProcesses windows implementation based on https://github.com/microsoft/vscode/blob/c0769274fa136b45799edeccc0d0a2f645b75caf/src/vs/base/node/ps.ts (License MIT)
2
+
3
+ import { VError } from '../VError/VError.js'
4
+ import * as ListProcessGetName from '../ListProcessGetName/ListProcessGetName.js'
5
+ import * as WindowsProcessTree from '../WindowsProcessTree/WindowsProcessTree.js'
6
+ import * as WindowsProcessTreeDataFlag from '../WindowsProcessTreeDataFlag/WindowsProcessTreeDataFlag.js'
7
+ import * as CreatePidMap from '../CreatePidMap/CreatePidMap.js'
8
+
9
+ /**
10
+ * @param {import('@vscode/windows-process-tree').IProcessCpuInfo} item
11
+ * @param {number} rootPid
12
+ * @param {object} pidMap
13
+ */
14
+ const toResultItem = (item, rootPid, pidMap) => {
15
+ return {
16
+ name: ListProcessGetName.getName(item.pid, item.commandLine, rootPid, pidMap),
17
+ pid: item.pid,
18
+ ppid: item.ppid,
19
+ memory: item.memory,
20
+ cmd: item.commandLine,
21
+ }
22
+ }
23
+
24
+ /**
25
+ *
26
+ * @param {import('@vscode/windows-process-tree').IProcessCpuInfo[]} completeProcessList
27
+ * @param {number} rootPid
28
+ */
29
+ const toResult = (completeProcessList, rootPid, pidMap) => {
30
+ const results = []
31
+ for (const item of completeProcessList) {
32
+ results.push(toResultItem(item, rootPid, pidMap))
33
+ }
34
+ return results
35
+ }
36
+
37
+ export const listProcessesWithMemoryUsage = async (rootPid) => {
38
+ try {
39
+ const processList = await WindowsProcessTree.getProcessList(rootPid, WindowsProcessTreeDataFlag.CommandLine | WindowsProcessTreeDataFlag.Memory)
40
+ if (!processList) {
41
+ throw new VError(`Root process ${rootPid} not found`)
42
+ }
43
+ const pidMap = await CreatePidMap.createPidMap()
44
+ const completeProcessList = await WindowsProcessTree.addCpuUsage(processList)
45
+ const result = toResult(completeProcessList, rootPid, pidMap)
46
+ return result
47
+ } catch (error) {
48
+ // @ts-ignore
49
+ throw new VError(error, `Failed to list processes`)
50
+ }
51
+ }
@@ -0,0 +1,16 @@
1
+ import { VError } from '../VError/VError.js'
2
+ import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
3
+
4
+ export const loadWindowProcessTree = async () => {
5
+ try {
6
+ // @ts-ignore
7
+ return await import('@vscode/windows-process-tree')
8
+ } catch (error) {
9
+ if (error && error instanceof Error && 'code' in error && error.code === ErrorCodes.ERR_DLOPEN_FAILED) {
10
+ throw new VError(
11
+ `Failed to load windows process tree: The native module "@vscode/windows-process-tree" is not compatible with this node version and must be compiled against a matching electron version using electron-rebuild`
12
+ )
13
+ }
14
+ throw new VError(error, `Failed to load windows process tree`)
15
+ }
16
+ }
@@ -70,6 +70,8 @@ export const load = (moduleId) => {
70
70
  return import('../GetTerminalSpawnOptions/GetTerminalSpawnOptions.ipc.js')
71
71
  case ModuleId.HandleCliArgs:
72
72
  return import('../HandleCliArgs/HandleCliArgs.ipc.js')
73
+ case ModuleId.ListProcessesWithMemoryUsage:
74
+ return import('../ListProcessesWithMemoryUsage/ListProcessesWithMemoryUsage.ipc.js')
73
75
  default:
74
76
  throw new Error(`module ${moduleId} not found`)
75
77
  }
@@ -32,3 +32,4 @@ export const HandleElectronMessagePort = 31
32
32
  export const HandleNodeMessagePort = 32
33
33
  export const GetTerminalSpawnOptions = 33
34
34
  export const HandleCliArgs = 34
35
+ export const ListProcessesWithMemoryUsage = 35
@@ -168,6 +168,7 @@ export const getModuleId = (commandId) => {
168
168
  case 'RebuildNodePty.rebuildNodePty':
169
169
  return ModuleId.RebuildNodePty
170
170
  case 'Process.getPid':
171
+ case 'Process.kill':
171
172
  return ModuleId.Process
172
173
  case 'HandleNodeMessagePort.handleNodeMessagePort':
173
174
  return ModuleId.HandleNodeMessagePort
@@ -177,6 +178,8 @@ export const getModuleId = (commandId) => {
177
178
  return ModuleId.GetTerminalSpawnOptions
178
179
  case 'HandleCliArgs.handleCliArgs':
179
180
  return ModuleId.HandleCliArgs
181
+ case 'ListProcessesWithMemoryUsage.listProcessesWithMemoryUsage':
182
+ return ModuleId.ListProcessesWithMemoryUsage
180
183
  default:
181
184
  throw new CommandNotFoundError(commandId)
182
185
  }
@@ -1,6 +1,7 @@
1
1
  import * as HandleIpc from '../HandleIpc/HandleIpc.js'
2
2
  import * as IpcChild from '../IpcChild/IpcChild.js'
3
3
  import * as IpcChildType from '../IpcChildType/IpcChildType.js'
4
+ import * as JsonRpc from '../JsonRpc/JsonRpc.js'
4
5
 
5
6
  // TODO add tests for this
6
7
 
@@ -10,6 +11,7 @@ import * as IpcChildType from '../IpcChildType/IpcChildType.js'
10
11
 
11
12
  export const state = {
12
13
  electronPortMap: new Map(),
14
+ ipc: undefined,
13
15
  }
14
16
 
15
17
  // TODO maybe rename to hydrate
@@ -19,4 +21,10 @@ export const listen = async () => {
19
21
  method,
20
22
  })
21
23
  HandleIpc.handleIpc(ipc)
24
+ // @ts-ignore
25
+ state.ipc = ipc
26
+ }
27
+
28
+ export const invoke = (method, ...params) => {
29
+ return JsonRpc.invoke(state.ipc, method, ...params)
22
30
  }
@@ -0,0 +1,50 @@
1
+ // parse ps output based on vscode https://github.com/microsoft/vscode/blob/c0769274fa136b45799edeccc0d0a2f645b75caf/src/vs/base/node/ps.ts (License MIT)
2
+
3
+ import * as Assert from '../Assert/Assert.js'
4
+ import * as ListProcessGetName from '../ListProcessGetName/ListProcessGetName.js'
5
+ import * as SplitLines from '../SplitLines/SplitLines.js'
6
+
7
+ const PID_CMD = /^\s*(\d+)\s+(\d+)\s+([\d.]+)\s+([\d.]+)\s+(.+)$/s
8
+
9
+ const parsePsOutputLine = (line) => {
10
+ Assert.string(line)
11
+ const matches = PID_CMD.exec(line.trim())
12
+ if (matches && matches.length === 6) {
13
+ return {
14
+ pid: Number.parseInt(matches[1]),
15
+ ppid: Number.parseInt(matches[2]),
16
+ cmd: matches[5],
17
+ // load: parseInt(matches[3]),
18
+ // mem: parseInt(matches[4]),
19
+ }
20
+ }
21
+ throw new Error(`line could not be parsed: ${line}`)
22
+ }
23
+
24
+ export const parsePsOutput = (stdout, rootPid, pidMap) => {
25
+ Assert.string(stdout)
26
+ Assert.number(rootPid)
27
+ Assert.object(pidMap)
28
+ if (stdout === '') {
29
+ return []
30
+ }
31
+ const lines = SplitLines.splitLines(stdout)
32
+ const result = []
33
+ const depthMap = Object.create(null)
34
+ depthMap[rootPid] = 1
35
+ const parsedLines = lines.map(parsePsOutputLine)
36
+ for (const parsedLine of parsedLines) {
37
+ const { pid, ppid, cmd } = parsedLine
38
+ const depth = pid === rootPid ? 1 : depthMap[ppid]
39
+ if (!depth) {
40
+ continue
41
+ }
42
+ result.push({
43
+ ...parsedLine,
44
+ depth,
45
+ name: ListProcessGetName.getName(pid, cmd, rootPid, pidMap),
46
+ })
47
+ depthMap[pid] = depth + 1
48
+ }
49
+ return result
50
+ }
@@ -6,4 +6,5 @@ export const Commands = {
6
6
  crash: Process.crash,
7
7
  crashAsync: Process.crashAsync,
8
8
  getPid: Process.getPid,
9
+ kill: Process.kill,
9
10
  }
@@ -1,13 +1,10 @@
1
1
  import { spawn } from 'node:child_process'
2
+ import * as GetElectronRebuildPath from '../GetElectronRebuildPath/GetElectronRebuildPath.js'
2
3
  import * as IsElectron from '../IsElectron/IsElectron.js'
3
4
  import * as Path from '../Path/Path.js'
4
5
  import * as Root from '../Root/Root.js'
5
6
  import { VError } from '../VError/VError.js'
6
7
 
7
- const getElectronRebuildPath = () => {
8
- return Path.join(Root.root, 'packages', 'main-process', 'node_modules', '.bin', 'electron-rebuild')
9
- }
10
-
11
8
  const getPtyHostPath = () => {
12
9
  return Path.join(Root.root, 'packages', 'pty-host')
13
10
  }
@@ -16,7 +13,7 @@ const getPtyHostPath = () => {
16
13
  * @param {string} cwd
17
14
  */
18
15
  const rebuildNodePtyElectron = async (cwd) => {
19
- const electronRebuildPath = getElectronRebuildPath()
16
+ const electronRebuildPath = GetElectronRebuildPath.getElectronRebuildPath()
20
17
  const childProcess = spawn(electronRebuildPath, [], {
21
18
  cwd,
22
19
  stdio: 'inherit',
@@ -34,14 +31,18 @@ const rebuildNodePtyNode = async (cwd) => {
34
31
  })
35
32
  }
36
33
 
34
+ const getFn = () => {
35
+ if (IsElectron.isElectron()) {
36
+ return rebuildNodePtyElectron
37
+ }
38
+ return rebuildNodePtyNode
39
+ }
40
+
37
41
  export const rebuildNodePty = async () => {
38
42
  try {
39
43
  const ptyHostPath = getPtyHostPath()
40
- if (IsElectron.isElectron()) {
41
- await rebuildNodePtyElectron(ptyHostPath)
42
- } else {
43
- await rebuildNodePtyNode(ptyHostPath)
44
- }
44
+ const rebuild = getFn()
45
+ await rebuild(ptyHostPath)
45
46
  } catch (error) {
46
47
  throw new VError(error, `Failed to rebuild node-pty`)
47
48
  }
@@ -0,0 +1,79 @@
1
+ import * as Character from '../Character/Character.js'
2
+ import * as GetErrorConstructor from '../GetErrorConstructor/GetErrorConstructor.js'
3
+ import * as JoinLines from '../JoinLines/JoinLines.js'
4
+ import { JsonRpcError } from '../JsonRpcError/JsonRpcError.js'
5
+ import * as JsonRpcErrorCode from '../JsonRpcErrorCode/JsonRpcErrorCode.js'
6
+ import * as SplitLines from '../SplitLines/SplitLines.js'
7
+
8
+ const constructError = (message, type, name) => {
9
+ const ErrorConstructor = GetErrorConstructor.getErrorConstructor(message, type)
10
+ // @ts-ignore
11
+ if (ErrorConstructor === DOMException && name) {
12
+ return new ErrorConstructor(message, name)
13
+ }
14
+ if (ErrorConstructor === Error) {
15
+ const error = new Error(message)
16
+ if (name && name !== 'VError') {
17
+ error.name = name
18
+ }
19
+ return error
20
+ }
21
+ return new ErrorConstructor(message)
22
+ }
23
+
24
+ const recreateStack = (message, stack) => {
25
+ if (message && !stack.includes(message)) {
26
+ return message + Character.NewLine + stack
27
+ }
28
+ return stack
29
+ }
30
+
31
+ const getErrorType = (error) => {
32
+ if (error && error.type) {
33
+ return error.type
34
+ }
35
+ if (error && error.data && error.data.type) {
36
+ return error.data.type
37
+ }
38
+ return ''
39
+ }
40
+
41
+ export const restoreJsonRpcError = (error) => {
42
+ if (error && error instanceof Error) {
43
+ return error
44
+ }
45
+ if (error && error.code && error.code === JsonRpcErrorCode.MethodNotFound) {
46
+ const restoredError = new JsonRpcError(error.message)
47
+ restoredError.stack = error.stack || error.data || ''
48
+ return restoredError
49
+ }
50
+ if (error && error.message) {
51
+ const type = getErrorType(error)
52
+ const restoredError = constructError(error.message, type, error.name)
53
+ const currentStack = JoinLines.joinLines(SplitLines.splitLines(new Error().stack).slice(1))
54
+ if (error.data) {
55
+ if (error.data.stack && type && error.message) {
56
+ restoredError.stack = type + ': ' + error.message + Character.NewLine + error.data.stack + Character.NewLine + currentStack
57
+ } else if (error.data.stack) {
58
+ restoredError.stack = recreateStack(error.message, error.data.stack) + Character.NewLine + currentStack
59
+ }
60
+ if (error.data.codeFrame) {
61
+ // @ts-ignore
62
+ restoredError.codeFrame = error.data.codeFrame
63
+ }
64
+ if (error.data.code) {
65
+ // @ts-ignore
66
+ restoredError.code = error.data.code
67
+ }
68
+ } else if (error.stack) {
69
+ // @ts-ignore
70
+ restoredError.stack = recreateStack(error.message, error.stack) + Character.NewLine + currentStack
71
+ }
72
+ return restoredError
73
+ }
74
+ if (typeof error === 'string') {
75
+ return new Error(`JsonRpc Error: ${error}`)
76
+ }
77
+ console.log({ error })
78
+ return new Error(`JsonRpc Error: Unknown Error`)
79
+ }
@@ -0,0 +1,13 @@
1
+ import { JsonRpcError } from '../JsonRpcError/JsonRpcError.js'
2
+ import * as RestoreJsonRpcError from '../RestoreJsonRpcError/RestoreJsonRpcError.js'
3
+
4
+ export const unwrapJsonRpcResult = (responseMessage) => {
5
+ if ('error' in responseMessage) {
6
+ const restoredError = RestoreJsonRpcError.restoreJsonRpcError(responseMessage.error)
7
+ throw restoredError
8
+ }
9
+ if ('result' in responseMessage) {
10
+ return responseMessage.result
11
+ }
12
+ throw new JsonRpcError('unexpected response message')
13
+ }
@@ -0,0 +1,26 @@
1
+ import * as LoadWindowsProcessTree from '../LoadWindowsProcessTree/LoadWindowsProcessTree.js'
2
+
3
+ /**
4
+ *
5
+ * @param {number} rootPid
6
+ * @param {WindowsProcessTree.ProcessDataFlag} flags
7
+ * @returns {Promise<WindowsProcessTree.IProcessInfo[] | undefined>}
8
+ */
9
+ export const getProcessList = async (rootPid, flags) => {
10
+ const WindowsProcessTree = await LoadWindowsProcessTree.loadWindowProcessTree()
11
+ return new Promise((resolve, reject) => {
12
+ WindowsProcessTree.getProcessList(rootPid, resolve, flags)
13
+ })
14
+ }
15
+
16
+ /**
17
+ *
18
+ * @param {WindowsProcessTree.IProcessInfo[]} processList
19
+ * @returns Promise< WindowsProcessTree.IProcessCpuInfo[]>
20
+ */
21
+ export const addCpuUsage = async (processList) => {
22
+ const WindowsProcessTree = await LoadWindowsProcessTree.loadWindowProcessTree()
23
+ return new Promise((resolve) => {
24
+ WindowsProcessTree.getProcessCpuUsage(processList, resolve)
25
+ })
26
+ }
@@ -0,0 +1,3 @@
1
+ export const None = 0
2
+ export const Memory = 1
3
+ export const CommandLine = 2