@lvce-editor/process-explorer 3.1.0 → 3.2.0
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.
- package/dist/index.js +139 -107
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ElectronMessagePortRpcClient, WebSocketRpcParent, NodeWebSocketRpcClient, NodeWorkerRpcClient, NodeForkedProcessRpcClient, ElectronUtilityProcessRpcClient } from '@lvce-editor/rpc';
|
|
2
2
|
import { object, number, string } from '@lvce-editor/assert';
|
|
3
|
-
import { RpcId, MainProcess, set as set$
|
|
3
|
+
import { RpcId, MainProcess, set as set$2 } from '@lvce-editor/rpc-registry';
|
|
4
4
|
import { VError } from '@lvce-editor/verror';
|
|
5
5
|
import { readFile } from 'node:fs/promises';
|
|
6
6
|
import { join } from 'node:path';
|
|
@@ -10,9 +10,7 @@ import { promisify } from 'node:util';
|
|
|
10
10
|
const state = {
|
|
11
11
|
commandMap: {}
|
|
12
12
|
};
|
|
13
|
-
|
|
14
|
-
state.commandMap = commandMap;
|
|
15
|
-
};
|
|
13
|
+
|
|
16
14
|
const get = () => {
|
|
17
15
|
return state.commandMap;
|
|
18
16
|
};
|
|
@@ -21,6 +19,14 @@ const requiresSocket = () => {
|
|
|
21
19
|
return false;
|
|
22
20
|
};
|
|
23
21
|
|
|
22
|
+
const createMessagePortRpc = async (create, messagePort) => {
|
|
23
|
+
return create({
|
|
24
|
+
commandMap: get(),
|
|
25
|
+
messagePort,
|
|
26
|
+
requiresSocket: requiresSocket
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
24
30
|
const setRpc = (rpc, rpcId) => {
|
|
25
31
|
if (typeof rpcId !== 'number') {
|
|
26
32
|
return;
|
|
@@ -29,16 +35,9 @@ const setRpc = (rpc, rpcId) => {
|
|
|
29
35
|
MainProcess.set(rpc);
|
|
30
36
|
return;
|
|
31
37
|
}
|
|
32
|
-
set$
|
|
38
|
+
set$2(rpcId, rpc);
|
|
33
39
|
};
|
|
34
40
|
|
|
35
|
-
const createMessagePortRpc = async (create, messagePort) => {
|
|
36
|
-
return create({
|
|
37
|
-
commandMap: get(),
|
|
38
|
-
messagePort,
|
|
39
|
-
requiresSocket: requiresSocket
|
|
40
|
-
});
|
|
41
|
-
};
|
|
42
41
|
const handleMessagePort = async (messagePort, rpcId) => {
|
|
43
42
|
object(messagePort);
|
|
44
43
|
const rpc = await createMessagePortRpc(ElectronMessagePortRpcClient.create, messagePort);
|
|
@@ -55,12 +54,28 @@ const createSocketRpc = async (create, webSocket) => {
|
|
|
55
54
|
webSocket
|
|
56
55
|
});
|
|
57
56
|
};
|
|
57
|
+
|
|
58
58
|
const handleSocket = async (webSocket, rpcId) => {
|
|
59
59
|
object(webSocket);
|
|
60
60
|
const rpc = await createSocketRpc(WebSocketRpcParent.create, webSocket);
|
|
61
61
|
setRpc(rpc, rpcId);
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
+
const createWebSocketRpc = async (create, handle, request) => {
|
|
65
|
+
return create({
|
|
66
|
+
commandMap: get(),
|
|
67
|
+
handle,
|
|
68
|
+
request,
|
|
69
|
+
requiresSocket: requiresSocket
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
const handleWebSocket = async (handle, request, rpcId) => {
|
|
73
|
+
object(handle);
|
|
74
|
+
object(request);
|
|
75
|
+
const rpc = await createWebSocketRpc(NodeWebSocketRpcClient.create, handle, request);
|
|
76
|
+
setRpc(rpc, rpcId);
|
|
77
|
+
};
|
|
78
|
+
|
|
64
79
|
const isWindows = process.platform === 'win32';
|
|
65
80
|
|
|
66
81
|
const getModule$1 = async () => {
|
|
@@ -69,6 +84,7 @@ const getModule$1 = async () => {
|
|
|
69
84
|
}
|
|
70
85
|
return Promise.resolve().then(function () { return ListProcessesWithMemoryUsageUnix; });
|
|
71
86
|
};
|
|
87
|
+
|
|
72
88
|
const listProcessesWithMemoryUsage$2 = async rootPid => {
|
|
73
89
|
const module = await getModule$1();
|
|
74
90
|
return module.listProcessesWithMemoryUsage(rootPid);
|
|
@@ -82,11 +98,20 @@ const commandMap = {
|
|
|
82
98
|
'HandleElectronMessagePort.handleElectronMessagePort': handleElectronMessagePort,
|
|
83
99
|
'HandleMessagePort.handleMessagePort': handleMessagePort,
|
|
84
100
|
'HandleSocket.handleSocket': handleSocket,
|
|
101
|
+
'HandleWebSocket.handleWebSocket': handleWebSocket,
|
|
85
102
|
'ListProcessesWithMemoryUsage.listProcessesWithMemoryUsage': listProcessesWithMemoryUsage$2,
|
|
86
103
|
'ProcessId.getMainProcessId': getMainProcessId
|
|
87
104
|
// 'ElectronContextMenu.openContextMenu': ElectronWebContentsView.handleContextMenu,
|
|
88
105
|
};
|
|
89
106
|
|
|
107
|
+
const set$1 = commandMap => {
|
|
108
|
+
state.commandMap = commandMap;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const set = commandMap => {
|
|
112
|
+
set$1(commandMap);
|
|
113
|
+
};
|
|
114
|
+
|
|
90
115
|
const NodeWorker = 1;
|
|
91
116
|
const NodeForkedProcess = 2;
|
|
92
117
|
const ElectronUtilityProcess = 3;
|
|
@@ -148,26 +173,56 @@ const main = async () => {
|
|
|
148
173
|
|
|
149
174
|
main();
|
|
150
175
|
|
|
176
|
+
const ENOENT = 'ENOENT';
|
|
177
|
+
const ERR_DLOPEN_FAILED = 'ERR_DLOPEN_FAILED';
|
|
178
|
+
const ESRCH = 'ESRCH';
|
|
179
|
+
|
|
180
|
+
const isDlOpenError = error => {
|
|
181
|
+
return error instanceof Error && 'code' in error && error.code === ERR_DLOPEN_FAILED;
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const loadWindowProcessTree = async () => {
|
|
185
|
+
try {
|
|
186
|
+
return await import('@vscode/windows-process-tree');
|
|
187
|
+
} catch (error) {
|
|
188
|
+
if (isDlOpenError(error)) {
|
|
189
|
+
throw new VError(`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`);
|
|
190
|
+
}
|
|
191
|
+
throw new VError(error, `Failed to load windows process tree`);
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const withResolvers = () => {
|
|
196
|
+
return Promise.withResolvers();
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const addCpuUsage = async processList => {
|
|
200
|
+
const WindowsProcessTree = await loadWindowProcessTree();
|
|
201
|
+
const {
|
|
202
|
+
promise,
|
|
203
|
+
resolve
|
|
204
|
+
} = withResolvers();
|
|
205
|
+
const mutableProcessList = processList.map(process => ({
|
|
206
|
+
...process
|
|
207
|
+
}));
|
|
208
|
+
WindowsProcessTree.getProcessCpuUsage(mutableProcessList, resolve);
|
|
209
|
+
return promise;
|
|
210
|
+
};
|
|
211
|
+
|
|
151
212
|
const createPidMap = async () => {
|
|
152
213
|
return MainProcess.invoke('CreatePidMap.createPidMap');
|
|
153
214
|
};
|
|
154
215
|
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
matches: cmd => cmd.includes('ptyHostMain.js'),
|
|
166
|
-
name: 'pty-host'
|
|
167
|
-
}, {
|
|
168
|
-
matches: cmd => cmd.includes('--lvce-window-kind=process-explorer'),
|
|
169
|
-
name: 'process-explorer'
|
|
170
|
-
}];
|
|
216
|
+
const getProcessList = async (rootPid, flags) => {
|
|
217
|
+
const WindowsProcessTree = await loadWindowProcessTree();
|
|
218
|
+
const {
|
|
219
|
+
promise,
|
|
220
|
+
resolve
|
|
221
|
+
} = withResolvers();
|
|
222
|
+
WindowsProcessTree.getProcessList(rootPid, resolve, flags);
|
|
223
|
+
return promise;
|
|
224
|
+
};
|
|
225
|
+
|
|
171
226
|
const fallbackProcessNamePatterns = [{
|
|
172
227
|
matches: cmd => cmd.includes('--type=renderer'),
|
|
173
228
|
name: 'renderer'
|
|
@@ -196,12 +251,32 @@ const fallbackProcessNamePatterns = [{
|
|
|
196
251
|
matches: cmd => cmd.includes('\\conhost.exe'),
|
|
197
252
|
name: 'conhost.exe'
|
|
198
253
|
}];
|
|
199
|
-
|
|
200
|
-
return processNamePatterns.find(pattern => pattern.matches(cmd))?.name || '';
|
|
201
|
-
};
|
|
254
|
+
|
|
202
255
|
const getFallbackPatternName = cmd => {
|
|
203
256
|
return fallbackProcessNamePatterns.find(pattern => pattern.matches(cmd))?.name || '';
|
|
204
257
|
};
|
|
258
|
+
|
|
259
|
+
const processNamePatterns = [{
|
|
260
|
+
matches: cmd => cmd.includes('--type=zygote'),
|
|
261
|
+
name: 'zygote'
|
|
262
|
+
}, {
|
|
263
|
+
matches: cmd => cmd.includes('--type=gpu-process'),
|
|
264
|
+
name: 'gpu-process'
|
|
265
|
+
}, {
|
|
266
|
+
matches: cmd => cmd.includes('extensionHostMain.js'),
|
|
267
|
+
name: 'extension-host'
|
|
268
|
+
}, {
|
|
269
|
+
matches: cmd => cmd.includes('ptyHostMain.js'),
|
|
270
|
+
name: 'pty-host'
|
|
271
|
+
}, {
|
|
272
|
+
matches: cmd => cmd.includes('--lvce-window-kind=process-explorer'),
|
|
273
|
+
name: 'process-explorer'
|
|
274
|
+
}];
|
|
275
|
+
|
|
276
|
+
const getPatternName = cmd => {
|
|
277
|
+
return processNamePatterns.find(pattern => pattern.matches(cmd))?.name || '';
|
|
278
|
+
};
|
|
279
|
+
|
|
205
280
|
const getName = (pid, cmd, rootPid, pidMap) => {
|
|
206
281
|
number(pid);
|
|
207
282
|
string(cmd);
|
|
@@ -224,61 +299,6 @@ const getName = (pid, cmd, rootPid, pidMap) => {
|
|
|
224
299
|
return cmd;
|
|
225
300
|
};
|
|
226
301
|
|
|
227
|
-
const ENOENT = 'ENOENT';
|
|
228
|
-
const ERR_DLOPEN_FAILED = 'ERR_DLOPEN_FAILED';
|
|
229
|
-
const ESRCH = 'ESRCH';
|
|
230
|
-
|
|
231
|
-
const isDlOpenError = error => {
|
|
232
|
-
return error instanceof Error && 'code' in error && error.code === ERR_DLOPEN_FAILED;
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
const loadWindowProcessTree = async () => {
|
|
236
|
-
try {
|
|
237
|
-
return await import('@vscode/windows-process-tree');
|
|
238
|
-
} catch (error) {
|
|
239
|
-
if (isDlOpenError(error)) {
|
|
240
|
-
throw new VError(`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`);
|
|
241
|
-
}
|
|
242
|
-
throw new VError(error, `Failed to load windows process tree`);
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
const withResolvers = () => {
|
|
247
|
-
return Promise.withResolvers();
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
const getProcessList = async (rootPid, flags) => {
|
|
251
|
-
const WindowsProcessTree = await loadWindowProcessTree();
|
|
252
|
-
const {
|
|
253
|
-
promise,
|
|
254
|
-
resolve
|
|
255
|
-
} = withResolvers();
|
|
256
|
-
WindowsProcessTree.getProcessList(rootPid, resolve, flags);
|
|
257
|
-
return promise;
|
|
258
|
-
};
|
|
259
|
-
const addCpuUsage = async processList => {
|
|
260
|
-
const WindowsProcessTree = await loadWindowProcessTree();
|
|
261
|
-
const {
|
|
262
|
-
promise,
|
|
263
|
-
resolve
|
|
264
|
-
} = withResolvers();
|
|
265
|
-
const mutableProcessList = processList.map(process => ({
|
|
266
|
-
...process
|
|
267
|
-
}));
|
|
268
|
-
WindowsProcessTree.getProcessCpuUsage(mutableProcessList, resolve);
|
|
269
|
-
return promise;
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
const Memory = 1;
|
|
273
|
-
const CommandLine = 2;
|
|
274
|
-
|
|
275
|
-
// listProcesses windows implementation based on https://github.com/microsoft/vscode/blob/c0769274fa136b45799edeccc0d0a2f645b75caf/src/vs/base/node/ps.ts (License MIT)
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* @param {import('@vscode/windows-process-tree').IProcessCpuInfo} item
|
|
279
|
-
* @param {number} rootPid
|
|
280
|
-
* @param {object} pidMap
|
|
281
|
-
*/
|
|
282
302
|
const toResultItem = (item, rootPid, pidMap) => {
|
|
283
303
|
return {
|
|
284
304
|
cmd: item.commandLine,
|
|
@@ -288,10 +308,17 @@ const toResultItem = (item, rootPid, pidMap) => {
|
|
|
288
308
|
ppid: item.ppid
|
|
289
309
|
};
|
|
290
310
|
};
|
|
311
|
+
|
|
291
312
|
const toResult = (completeProcessList, rootPid, pidMap) => {
|
|
292
313
|
const results = Array.from(completeProcessList, item => toResultItem(item, rootPid, pidMap));
|
|
293
314
|
return results;
|
|
294
315
|
};
|
|
316
|
+
|
|
317
|
+
const Memory = 1;
|
|
318
|
+
const CommandLine = 2;
|
|
319
|
+
|
|
320
|
+
// listProcesses windows implementation based on https://github.com/microsoft/vscode/blob/c0769274fa136b45799edeccc0d0a2f645b75caf/src/vs/base/node/ps.ts (License MIT)
|
|
321
|
+
|
|
295
322
|
const listProcessesWithMemoryUsage$1 = async rootPid => {
|
|
296
323
|
try {
|
|
297
324
|
const processList = await getProcessList(rootPid, CommandLine | Memory);
|
|
@@ -315,13 +342,14 @@ const ListProcessesWithMemoryUsageWindows = {
|
|
|
315
342
|
|
|
316
343
|
const Utf8 = 'utf8';
|
|
317
344
|
|
|
345
|
+
const isEnoentErrorLinux = error => {
|
|
346
|
+
return error.code === ENOENT;
|
|
347
|
+
};
|
|
348
|
+
|
|
318
349
|
const isEnoentErrorWindows = error => {
|
|
319
350
|
return error && error.message && error.message.includes('The system cannot find the path specified.');
|
|
320
351
|
};
|
|
321
352
|
|
|
322
|
-
const isEnoentErrorLinux = error => {
|
|
323
|
-
return error.code === ENOENT;
|
|
324
|
-
};
|
|
325
353
|
const isEnoentError = error => {
|
|
326
354
|
if (!error) {
|
|
327
355
|
return false;
|
|
@@ -333,6 +361,19 @@ const isEsrchError = error => {
|
|
|
333
361
|
return error && error.code === ESRCH;
|
|
334
362
|
};
|
|
335
363
|
|
|
364
|
+
const getContent = async pid => {
|
|
365
|
+
try {
|
|
366
|
+
const filePath = join('/proc', String(pid), 'statm');
|
|
367
|
+
const content = await readFile(filePath, Utf8);
|
|
368
|
+
return content;
|
|
369
|
+
} catch (error) {
|
|
370
|
+
if (isEnoentError(error) || isEsrchError(error)) {
|
|
371
|
+
return '';
|
|
372
|
+
}
|
|
373
|
+
throw error;
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
|
|
336
377
|
const isMacOs = process.platform === 'darwin';
|
|
337
378
|
|
|
338
379
|
const EmptyString = '';
|
|
@@ -349,18 +390,6 @@ const parseMemory = content => {
|
|
|
349
390
|
return memory;
|
|
350
391
|
};
|
|
351
392
|
|
|
352
|
-
const getContent = async pid => {
|
|
353
|
-
try {
|
|
354
|
-
const filePath = join('/proc', String(pid), 'statm');
|
|
355
|
-
const content = await readFile(filePath, Utf8);
|
|
356
|
-
return content;
|
|
357
|
-
} catch (error) {
|
|
358
|
-
if (isEnoentError(error) || isEsrchError(error)) {
|
|
359
|
-
return '';
|
|
360
|
-
}
|
|
361
|
-
throw error;
|
|
362
|
-
}
|
|
363
|
-
};
|
|
364
393
|
const getAccurateMemoryUsage = async pid => {
|
|
365
394
|
try {
|
|
366
395
|
number(pid);
|
|
@@ -408,15 +437,10 @@ const hasPositiveMemoryUsage = process => {
|
|
|
408
437
|
return process.memory >= 0;
|
|
409
438
|
};
|
|
410
439
|
|
|
411
|
-
const splitLines = lines => {
|
|
412
|
-
return lines.split(NewLine);
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
// parse ps output based on vscode https://github.com/microsoft/vscode/blob/c0769274fa136b45799edeccc0d0a2f645b75caf/src/vs/base/node/ps.ts (License MIT)
|
|
416
|
-
|
|
417
440
|
const isSpace = character => {
|
|
418
441
|
return character === ' ' || character === '\t';
|
|
419
442
|
};
|
|
443
|
+
|
|
420
444
|
const readField = (line, startIndex) => {
|
|
421
445
|
let start = startIndex;
|
|
422
446
|
while (start < line.length && isSpace(line[start])) {
|
|
@@ -431,6 +455,7 @@ const readField = (line, startIndex) => {
|
|
|
431
455
|
value: line.slice(start, end)
|
|
432
456
|
};
|
|
433
457
|
};
|
|
458
|
+
|
|
434
459
|
const parsePsOutputLine = line => {
|
|
435
460
|
string(line);
|
|
436
461
|
const trimmedLine = line.trim();
|
|
@@ -448,6 +473,13 @@ const parsePsOutputLine = line => {
|
|
|
448
473
|
}
|
|
449
474
|
throw new Error(`line could not be parsed: ${line}`);
|
|
450
475
|
};
|
|
476
|
+
|
|
477
|
+
const splitLines = lines => {
|
|
478
|
+
return lines.split(NewLine);
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
// parse ps output based on vscode https://github.com/microsoft/vscode/blob/c0769274fa136b45799edeccc0d0a2f645b75caf/src/vs/base/node/ps.ts (License MIT)
|
|
482
|
+
|
|
451
483
|
const parsePsOutput = (stdout, rootPid, pidMap) => {
|
|
452
484
|
string(stdout);
|
|
453
485
|
number(rootPid);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lvce-editor/process-explorer",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "Process Explorer",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": "bin/processExplorer.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@lvce-editor/assert": "^1.5.1",
|
|
22
22
|
"@lvce-editor/rpc": "^6.4.0",
|
|
23
|
-
"@lvce-editor/rpc-registry": "^9.
|
|
23
|
+
"@lvce-editor/rpc-registry": "^9.28.0",
|
|
24
24
|
"@lvce-editor/verror": "^1.7.0"
|
|
25
25
|
},
|
|
26
26
|
"optionalDependencies": {
|