@lvce-editor/process-explorer 2.4.0 → 3.1.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/bin/processExplorer.js +0 -0
- package/dist/index.js +177 -506
- package/package.json +6 -51
package/bin/processExplorer.js
CHANGED
|
File without changes
|
package/dist/index.js
CHANGED
|
@@ -1,384 +1,90 @@
|
|
|
1
|
-
import {
|
|
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$1 } from '@lvce-editor/rpc-registry';
|
|
3
4
|
import { VError } from '@lvce-editor/verror';
|
|
4
5
|
import { readFile } from 'node:fs/promises';
|
|
5
6
|
import { join } from 'node:path';
|
|
6
7
|
import { execFile as execFile$1 } from 'node:child_process';
|
|
7
8
|
import { promisify } from 'node:util';
|
|
8
9
|
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
const set = (id, fn) => {
|
|
12
|
-
callbacks[id] = fn;
|
|
13
|
-
};
|
|
14
|
-
const get = id => {
|
|
15
|
-
return callbacks[id];
|
|
16
|
-
};
|
|
17
|
-
const remove = id => {
|
|
18
|
-
delete callbacks[id];
|
|
19
|
-
};
|
|
20
|
-
let id = 0;
|
|
21
|
-
const create$3 = () => {
|
|
22
|
-
return ++id;
|
|
23
|
-
};
|
|
24
|
-
const registerPromise = () => {
|
|
25
|
-
const id = create$3();
|
|
26
|
-
const {
|
|
27
|
-
resolve,
|
|
28
|
-
promise
|
|
29
|
-
} = Promise.withResolvers();
|
|
30
|
-
set(id, resolve);
|
|
31
|
-
return {
|
|
32
|
-
id,
|
|
33
|
-
promise
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
const create$2 = (method, params) => {
|
|
37
|
-
const {
|
|
38
|
-
id,
|
|
39
|
-
promise
|
|
40
|
-
} = registerPromise();
|
|
41
|
-
const message = {
|
|
42
|
-
jsonrpc: Two,
|
|
43
|
-
method,
|
|
44
|
-
params,
|
|
45
|
-
id
|
|
46
|
-
};
|
|
47
|
-
return {
|
|
48
|
-
message,
|
|
49
|
-
promise
|
|
50
|
-
};
|
|
51
|
-
};
|
|
52
|
-
class JsonRpcError extends Error {
|
|
53
|
-
constructor(message) {
|
|
54
|
-
super(message);
|
|
55
|
-
this.name = 'JsonRpcError';
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
const NewLine$1 = '\n';
|
|
59
|
-
const DomException = 'DOMException';
|
|
60
|
-
const ReferenceError$1 = 'ReferenceError';
|
|
61
|
-
const SyntaxError$1 = 'SyntaxError';
|
|
62
|
-
const TypeError$1 = 'TypeError';
|
|
63
|
-
const getErrorConstructor = (message, type) => {
|
|
64
|
-
if (type) {
|
|
65
|
-
switch (type) {
|
|
66
|
-
case DomException:
|
|
67
|
-
return DOMException;
|
|
68
|
-
case TypeError$1:
|
|
69
|
-
return TypeError;
|
|
70
|
-
case SyntaxError$1:
|
|
71
|
-
return SyntaxError;
|
|
72
|
-
case ReferenceError$1:
|
|
73
|
-
return ReferenceError;
|
|
74
|
-
default:
|
|
75
|
-
return Error;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
if (message.startsWith('TypeError: ')) {
|
|
79
|
-
return TypeError;
|
|
80
|
-
}
|
|
81
|
-
if (message.startsWith('SyntaxError: ')) {
|
|
82
|
-
return SyntaxError;
|
|
83
|
-
}
|
|
84
|
-
if (message.startsWith('ReferenceError: ')) {
|
|
85
|
-
return ReferenceError;
|
|
86
|
-
}
|
|
87
|
-
return Error;
|
|
88
|
-
};
|
|
89
|
-
const constructError = (message, type, name) => {
|
|
90
|
-
const ErrorConstructor = getErrorConstructor(message, type);
|
|
91
|
-
if (ErrorConstructor === DOMException && name) {
|
|
92
|
-
return new ErrorConstructor(message, name);
|
|
93
|
-
}
|
|
94
|
-
if (ErrorConstructor === Error) {
|
|
95
|
-
const error = new Error(message);
|
|
96
|
-
if (name && name !== 'VError') {
|
|
97
|
-
error.name = name;
|
|
98
|
-
}
|
|
99
|
-
return error;
|
|
100
|
-
}
|
|
101
|
-
return new ErrorConstructor(message);
|
|
102
|
-
};
|
|
103
|
-
const getNewLineIndex = (string, startIndex = undefined) => {
|
|
104
|
-
return string.indexOf(NewLine$1, startIndex);
|
|
105
|
-
};
|
|
106
|
-
const getParentStack = error => {
|
|
107
|
-
let parentStack = error.stack || error.data || error.message || '';
|
|
108
|
-
if (parentStack.startsWith(' at')) {
|
|
109
|
-
parentStack = error.message + NewLine$1 + parentStack;
|
|
110
|
-
}
|
|
111
|
-
return parentStack;
|
|
112
|
-
};
|
|
113
|
-
const joinLines = lines => {
|
|
114
|
-
return lines.join(NewLine$1);
|
|
115
|
-
};
|
|
116
|
-
const MethodNotFound = -32601;
|
|
117
|
-
const Custom = -32001;
|
|
118
|
-
const splitLines$1 = lines => {
|
|
119
|
-
return lines.split(NewLine$1);
|
|
120
|
-
};
|
|
121
|
-
const restoreJsonRpcError = error => {
|
|
122
|
-
if (error && error instanceof Error) {
|
|
123
|
-
return error;
|
|
124
|
-
}
|
|
125
|
-
const currentStack = joinLines(splitLines$1(new Error().stack || '').slice(1));
|
|
126
|
-
if (error && error.code && error.code === MethodNotFound) {
|
|
127
|
-
const restoredError = new JsonRpcError(error.message);
|
|
128
|
-
const parentStack = getParentStack(error);
|
|
129
|
-
restoredError.stack = parentStack + NewLine$1 + currentStack;
|
|
130
|
-
return restoredError;
|
|
131
|
-
}
|
|
132
|
-
if (error && error.message) {
|
|
133
|
-
const restoredError = constructError(error.message, error.type, error.name);
|
|
134
|
-
if (error.data) {
|
|
135
|
-
if (error.data.stack && error.data.type && error.message) {
|
|
136
|
-
restoredError.stack = error.data.type + ': ' + error.message + NewLine$1 + error.data.stack + NewLine$1 + currentStack;
|
|
137
|
-
} else if (error.data.stack) {
|
|
138
|
-
restoredError.stack = error.data.stack;
|
|
139
|
-
}
|
|
140
|
-
if (error.data.codeFrame) {
|
|
141
|
-
// @ts-ignore
|
|
142
|
-
restoredError.codeFrame = error.data.codeFrame;
|
|
143
|
-
}
|
|
144
|
-
if (error.data.code) {
|
|
145
|
-
// @ts-ignore
|
|
146
|
-
restoredError.code = error.data.code;
|
|
147
|
-
}
|
|
148
|
-
if (error.data.type) {
|
|
149
|
-
// @ts-ignore
|
|
150
|
-
restoredError.name = error.data.type;
|
|
151
|
-
}
|
|
152
|
-
} else {
|
|
153
|
-
if (error.stack) {
|
|
154
|
-
const lowerStack = restoredError.stack || '';
|
|
155
|
-
// @ts-ignore
|
|
156
|
-
const indexNewLine = getNewLineIndex(lowerStack);
|
|
157
|
-
const parentStack = getParentStack(error);
|
|
158
|
-
// @ts-ignore
|
|
159
|
-
restoredError.stack = parentStack + lowerStack.slice(indexNewLine);
|
|
160
|
-
}
|
|
161
|
-
if (error.codeFrame) {
|
|
162
|
-
// @ts-ignore
|
|
163
|
-
restoredError.codeFrame = error.codeFrame;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
return restoredError;
|
|
167
|
-
}
|
|
168
|
-
if (typeof error === 'string') {
|
|
169
|
-
return new Error(`JsonRpc Error: ${error}`);
|
|
170
|
-
}
|
|
171
|
-
return new Error(`JsonRpc Error: ${error}`);
|
|
172
|
-
};
|
|
173
|
-
const unwrapJsonRpcResult = responseMessage => {
|
|
174
|
-
if ('error' in responseMessage) {
|
|
175
|
-
const restoredError = restoreJsonRpcError(responseMessage.error);
|
|
176
|
-
throw restoredError;
|
|
177
|
-
}
|
|
178
|
-
if ('result' in responseMessage) {
|
|
179
|
-
return responseMessage.result;
|
|
180
|
-
}
|
|
181
|
-
throw new JsonRpcError('unexpected response message');
|
|
182
|
-
};
|
|
183
|
-
const warn = (...args) => {
|
|
184
|
-
console.warn(...args);
|
|
185
|
-
};
|
|
186
|
-
const resolve = (id, response) => {
|
|
187
|
-
const fn = get(id);
|
|
188
|
-
if (!fn) {
|
|
189
|
-
console.log(response);
|
|
190
|
-
warn(`callback ${id} may already be disposed`);
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
fn(response);
|
|
194
|
-
remove(id);
|
|
195
|
-
};
|
|
196
|
-
const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND';
|
|
197
|
-
const getErrorType = prettyError => {
|
|
198
|
-
if (prettyError && prettyError.type) {
|
|
199
|
-
return prettyError.type;
|
|
200
|
-
}
|
|
201
|
-
if (prettyError && prettyError.constructor && prettyError.constructor.name) {
|
|
202
|
-
return prettyError.constructor.name;
|
|
203
|
-
}
|
|
204
|
-
return undefined;
|
|
205
|
-
};
|
|
206
|
-
const getErrorProperty = (error, prettyError) => {
|
|
207
|
-
if (error && error.code === E_COMMAND_NOT_FOUND) {
|
|
208
|
-
return {
|
|
209
|
-
code: MethodNotFound,
|
|
210
|
-
message: error.message,
|
|
211
|
-
data: error.stack
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
return {
|
|
215
|
-
code: Custom,
|
|
216
|
-
message: prettyError.message,
|
|
217
|
-
data: {
|
|
218
|
-
stack: prettyError.stack,
|
|
219
|
-
codeFrame: prettyError.codeFrame,
|
|
220
|
-
type: getErrorType(prettyError),
|
|
221
|
-
code: prettyError.code,
|
|
222
|
-
name: prettyError.name
|
|
223
|
-
}
|
|
224
|
-
};
|
|
225
|
-
};
|
|
226
|
-
const create$1 = (message, error) => {
|
|
227
|
-
return {
|
|
228
|
-
jsonrpc: Two,
|
|
229
|
-
id: message.id,
|
|
230
|
-
error
|
|
231
|
-
};
|
|
232
|
-
};
|
|
233
|
-
const getErrorResponse = (message, error, preparePrettyError, logError) => {
|
|
234
|
-
const prettyError = preparePrettyError(error);
|
|
235
|
-
logError(error, prettyError);
|
|
236
|
-
const errorProperty = getErrorProperty(error, prettyError);
|
|
237
|
-
return create$1(message, errorProperty);
|
|
238
|
-
};
|
|
239
|
-
const create = (message, result) => {
|
|
240
|
-
return {
|
|
241
|
-
jsonrpc: Two,
|
|
242
|
-
id: message.id,
|
|
243
|
-
result: result ?? null
|
|
244
|
-
};
|
|
245
|
-
};
|
|
246
|
-
const getSuccessResponse = (message, result) => {
|
|
247
|
-
const resultProperty = result ?? null;
|
|
248
|
-
return create(message, resultProperty);
|
|
249
|
-
};
|
|
250
|
-
const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
|
|
251
|
-
try {
|
|
252
|
-
const result = requiresSocket(message.method) ? await execute(message.method, ipc, ...message.params) : await execute(message.method, ...message.params);
|
|
253
|
-
return getSuccessResponse(message, result);
|
|
254
|
-
} catch (error) {
|
|
255
|
-
return getErrorResponse(message, error, preparePrettyError, logError);
|
|
256
|
-
}
|
|
10
|
+
const state = {
|
|
11
|
+
commandMap: {}
|
|
257
12
|
};
|
|
258
|
-
const
|
|
259
|
-
|
|
13
|
+
const set = commandMap => {
|
|
14
|
+
state.commandMap = commandMap;
|
|
260
15
|
};
|
|
261
|
-
const
|
|
262
|
-
|
|
16
|
+
const get = () => {
|
|
17
|
+
return state.commandMap;
|
|
263
18
|
};
|
|
264
|
-
|
|
19
|
+
|
|
20
|
+
const requiresSocket = () => {
|
|
265
21
|
return false;
|
|
266
22
|
};
|
|
267
|
-
const defaultResolve = resolve;
|
|
268
23
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
if (args.length === 1) {
|
|
272
|
-
const options = args[0];
|
|
273
|
-
return {
|
|
274
|
-
ipc: options.ipc,
|
|
275
|
-
message: options.message,
|
|
276
|
-
execute: options.execute,
|
|
277
|
-
resolve: options.resolve || defaultResolve,
|
|
278
|
-
preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
|
|
279
|
-
logError: options.logError || defaultLogError,
|
|
280
|
-
requiresSocket: options.requiresSocket || defaultRequiresSocket
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
return {
|
|
284
|
-
ipc: args[0],
|
|
285
|
-
message: args[1],
|
|
286
|
-
execute: args[2],
|
|
287
|
-
resolve: args[3],
|
|
288
|
-
preparePrettyError: args[4],
|
|
289
|
-
logError: args[5],
|
|
290
|
-
requiresSocket: args[6]
|
|
291
|
-
};
|
|
292
|
-
};
|
|
293
|
-
const handleJsonRpcMessage = async (...args) => {
|
|
294
|
-
const options = normalizeParams(args);
|
|
295
|
-
const {
|
|
296
|
-
message,
|
|
297
|
-
ipc,
|
|
298
|
-
execute,
|
|
299
|
-
resolve,
|
|
300
|
-
preparePrettyError,
|
|
301
|
-
logError,
|
|
302
|
-
requiresSocket
|
|
303
|
-
} = options;
|
|
304
|
-
if ('id' in message) {
|
|
305
|
-
if ('method' in message) {
|
|
306
|
-
const response = await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
|
|
307
|
-
try {
|
|
308
|
-
ipc.send(response);
|
|
309
|
-
} catch (error) {
|
|
310
|
-
const errorResponse = getErrorResponse(message, error, preparePrettyError, logError);
|
|
311
|
-
ipc.send(errorResponse);
|
|
312
|
-
}
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
resolve(message.id, message);
|
|
24
|
+
const setRpc = (rpc, rpcId) => {
|
|
25
|
+
if (typeof rpcId !== 'number') {
|
|
316
26
|
return;
|
|
317
27
|
}
|
|
318
|
-
if (
|
|
319
|
-
|
|
28
|
+
if (rpcId === RpcId.MainProcess) {
|
|
29
|
+
MainProcess.set(rpc);
|
|
320
30
|
return;
|
|
321
31
|
}
|
|
322
|
-
|
|
32
|
+
set$1(rpcId, rpc);
|
|
323
33
|
};
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
}
|
|
332
|
-
const responseMessage = await promise;
|
|
333
|
-
return unwrapJsonRpcResult(responseMessage);
|
|
34
|
+
|
|
35
|
+
const createMessagePortRpc = async (create, messagePort) => {
|
|
36
|
+
return create({
|
|
37
|
+
commandMap: get(),
|
|
38
|
+
messagePort,
|
|
39
|
+
requiresSocket: requiresSocket
|
|
40
|
+
});
|
|
334
41
|
};
|
|
335
|
-
const
|
|
336
|
-
|
|
42
|
+
const handleMessagePort = async (messagePort, rpcId) => {
|
|
43
|
+
object(messagePort);
|
|
44
|
+
const rpc = await createMessagePortRpc(ElectronMessagePortRpcClient.create, messagePort);
|
|
45
|
+
setRpc(rpc, rpcId);
|
|
337
46
|
};
|
|
338
47
|
|
|
339
|
-
const
|
|
340
|
-
|
|
48
|
+
const handleElectronMessagePort = async (messagePort, rpcId) => {
|
|
49
|
+
await handleMessagePort(messagePort, rpcId);
|
|
341
50
|
};
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
}
|
|
51
|
+
|
|
52
|
+
const createSocketRpc = async (create, webSocket) => {
|
|
53
|
+
return create({
|
|
54
|
+
commandMap: get(),
|
|
55
|
+
webSocket
|
|
56
|
+
});
|
|
349
57
|
};
|
|
350
|
-
const
|
|
351
|
-
|
|
58
|
+
const handleSocket = async (webSocket, rpcId) => {
|
|
59
|
+
object(webSocket);
|
|
60
|
+
const rpc = await createSocketRpc(WebSocketRpcParent.create, webSocket);
|
|
61
|
+
setRpc(rpc, rpcId);
|
|
352
62
|
};
|
|
353
63
|
|
|
354
|
-
const
|
|
355
|
-
const fn = getCommand(command);
|
|
356
|
-
if (!fn) {
|
|
357
|
-
throw new Error(`Command not found ${command}`);
|
|
358
|
-
}
|
|
359
|
-
return fn(...args);
|
|
360
|
-
};
|
|
64
|
+
const isWindows = process.platform === 'win32';
|
|
361
65
|
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
};
|
|
365
|
-
|
|
366
|
-
|
|
66
|
+
const getModule$1 = async () => {
|
|
67
|
+
if (isWindows) {
|
|
68
|
+
return Promise.resolve().then(function () { return ListProcessesWithMemoryUsageWindows; });
|
|
69
|
+
}
|
|
70
|
+
return Promise.resolve().then(function () { return ListProcessesWithMemoryUsageUnix; });
|
|
367
71
|
};
|
|
368
|
-
const
|
|
369
|
-
|
|
72
|
+
const listProcessesWithMemoryUsage$2 = async rootPid => {
|
|
73
|
+
const module = await getModule$1();
|
|
74
|
+
return module.listProcessesWithMemoryUsage(rootPid);
|
|
370
75
|
};
|
|
371
|
-
|
|
372
|
-
|
|
76
|
+
|
|
77
|
+
const getMainProcessId = () => {
|
|
78
|
+
return process.ppid;
|
|
373
79
|
};
|
|
374
80
|
|
|
375
|
-
const
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
81
|
+
const commandMap = {
|
|
82
|
+
'HandleElectronMessagePort.handleElectronMessagePort': handleElectronMessagePort,
|
|
83
|
+
'HandleMessagePort.handleMessagePort': handleMessagePort,
|
|
84
|
+
'HandleSocket.handleSocket': handleSocket,
|
|
85
|
+
'ListProcessesWithMemoryUsage.listProcessesWithMemoryUsage': listProcessesWithMemoryUsage$2,
|
|
86
|
+
'ProcessId.getMainProcessId': getMainProcessId
|
|
87
|
+
// 'ElectronContextMenu.openContextMenu': ElectronWebContentsView.handleContextMenu,
|
|
382
88
|
};
|
|
383
89
|
|
|
384
90
|
const NodeWorker = 1;
|
|
@@ -402,18 +108,18 @@ const Auto = () => {
|
|
|
402
108
|
throw new Error(`[shared-process] unknown ipc type`);
|
|
403
109
|
};
|
|
404
110
|
|
|
405
|
-
const getModule
|
|
111
|
+
const getModule = method => {
|
|
406
112
|
switch (method) {
|
|
113
|
+
case ElectronMessagePort:
|
|
114
|
+
return ElectronMessagePortRpcClient.create;
|
|
115
|
+
case ElectronUtilityProcess:
|
|
116
|
+
return ElectronUtilityProcessRpcClient.create;
|
|
407
117
|
case NodeForkedProcess:
|
|
408
|
-
return
|
|
118
|
+
return NodeForkedProcessRpcClient.create;
|
|
409
119
|
case NodeWorker:
|
|
410
|
-
return
|
|
411
|
-
case ElectronUtilityProcess:
|
|
412
|
-
return IpcChildWithElectronUtilityProcess;
|
|
413
|
-
case ElectronMessagePort:
|
|
414
|
-
return IpcChildWithElectronMessagePort;
|
|
120
|
+
return NodeWorkerRpcClient.create;
|
|
415
121
|
case WebSocket:
|
|
416
|
-
return
|
|
122
|
+
return NodeWebSocketRpcClient.create;
|
|
417
123
|
default:
|
|
418
124
|
throw new Error('unexpected ipc type');
|
|
419
125
|
}
|
|
@@ -423,79 +129,79 @@ const listen$1 = async ({
|
|
|
423
129
|
method,
|
|
424
130
|
...params
|
|
425
131
|
}) => {
|
|
426
|
-
const
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
// @ts-ignore
|
|
430
|
-
if (module.signal) {
|
|
431
|
-
// @ts-ignore
|
|
432
|
-
module.signal(rawIpc);
|
|
433
|
-
}
|
|
434
|
-
// @ts-ignore
|
|
435
|
-
const ipc = module.wrap(rawIpc);
|
|
436
|
-
return ipc;
|
|
132
|
+
const create = getModule(method);
|
|
133
|
+
const rpc = await create(params);
|
|
134
|
+
return rpc;
|
|
437
135
|
};
|
|
438
136
|
|
|
439
137
|
const listen = async () => {
|
|
440
|
-
|
|
138
|
+
set(commandMap);
|
|
139
|
+
await listen$1({
|
|
140
|
+
commandMap: commandMap,
|
|
441
141
|
method: Auto()
|
|
442
142
|
});
|
|
443
|
-
handleIpc(ipc);
|
|
444
|
-
};
|
|
445
|
-
|
|
446
|
-
const MainProcess = -5;
|
|
447
|
-
|
|
448
|
-
const state = {
|
|
449
|
-
ipc: undefined
|
|
450
|
-
};
|
|
451
|
-
const invoke = (method, ...params) => {
|
|
452
|
-
return invoke$1(state.ipc, method, ...params);
|
|
453
|
-
};
|
|
454
|
-
|
|
455
|
-
const handleElectronMessagePort = async (messagePort, ipcId) => {
|
|
456
|
-
object(messagePort);
|
|
457
|
-
// Assert.number(ipcId)
|
|
458
|
-
const ipc = await listen$1({
|
|
459
|
-
method: ElectronMessagePort,
|
|
460
|
-
messagePort
|
|
461
|
-
});
|
|
462
|
-
handleIpc(ipc);
|
|
463
|
-
if (ipcId === MainProcess) {
|
|
464
|
-
state.ipc = ipc;
|
|
465
|
-
}
|
|
466
|
-
};
|
|
467
|
-
|
|
468
|
-
const getMainProcessId = () => {
|
|
469
|
-
return process.ppid;
|
|
470
|
-
};
|
|
471
|
-
|
|
472
|
-
const isWindows = process.platform === 'win32';
|
|
473
|
-
|
|
474
|
-
const getModule = () => {
|
|
475
|
-
if (isWindows) {
|
|
476
|
-
return Promise.resolve().then(function () { return ListProcessesWithMemoryUsageWindows; });
|
|
477
|
-
}
|
|
478
|
-
return Promise.resolve().then(function () { return ListProcessesWithMemoryUsageUnix; });
|
|
479
|
-
};
|
|
480
|
-
const listProcessesWithMemoryUsage$2 = async rootPid => {
|
|
481
|
-
const module = await getModule();
|
|
482
|
-
return module.listProcessesWithMemoryUsage(rootPid);
|
|
483
|
-
};
|
|
484
|
-
|
|
485
|
-
const commandMap = {
|
|
486
|
-
'HandleElectronMessagePort.handleElectronMessagePort': handleElectronMessagePort,
|
|
487
|
-
'ProcessId.getMainProcessId': getMainProcessId,
|
|
488
|
-
'ListProcessesWithMemoryUsage.listProcessesWithMemoryUsage': listProcessesWithMemoryUsage$2
|
|
489
|
-
// 'ElectronContextMenu.openContextMenu': ElectronWebContentsView.handleContextMenu,
|
|
490
143
|
};
|
|
491
144
|
|
|
492
145
|
const main = async () => {
|
|
493
|
-
registerCommands(commandMap);
|
|
494
146
|
await listen();
|
|
495
147
|
};
|
|
496
148
|
|
|
497
149
|
main();
|
|
498
150
|
|
|
151
|
+
const createPidMap = async () => {
|
|
152
|
+
return MainProcess.invoke('CreatePidMap.createPidMap');
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const processNamePatterns = [{
|
|
156
|
+
matches: cmd => cmd.includes('--type=zygote'),
|
|
157
|
+
name: 'zygote'
|
|
158
|
+
}, {
|
|
159
|
+
matches: cmd => cmd.includes('--type=gpu-process'),
|
|
160
|
+
name: 'gpu-process'
|
|
161
|
+
}, {
|
|
162
|
+
matches: cmd => cmd.includes('extensionHostMain.js'),
|
|
163
|
+
name: 'extension-host'
|
|
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
|
+
}];
|
|
171
|
+
const fallbackProcessNamePatterns = [{
|
|
172
|
+
matches: cmd => cmd.includes('--type=renderer'),
|
|
173
|
+
name: 'renderer'
|
|
174
|
+
}, {
|
|
175
|
+
matches: cmd => cmd.includes('--type=utility'),
|
|
176
|
+
name: 'utility'
|
|
177
|
+
}, {
|
|
178
|
+
matches: cmd => cmd.includes('tsserver.js'),
|
|
179
|
+
name: 'tsserver.js'
|
|
180
|
+
}, {
|
|
181
|
+
matches: cmd => cmd.includes('typingsInstaller.js'),
|
|
182
|
+
name: 'typingsInstaller.js'
|
|
183
|
+
}, {
|
|
184
|
+
matches: cmd => cmd.includes('extensionHostHelperProcessMain.js'),
|
|
185
|
+
name: 'extension-host-helper-process'
|
|
186
|
+
}, {
|
|
187
|
+
matches: cmd => cmd.includes('/bin/rg') || cmd.includes('rg.exe'),
|
|
188
|
+
name: 'ripgrep'
|
|
189
|
+
}, {
|
|
190
|
+
matches: cmd => cmd.startsWith('bash'),
|
|
191
|
+
name: 'bash'
|
|
192
|
+
}, {
|
|
193
|
+
matches: cmd => cmd.startsWith('/opt/sublime_text/sublime_text '),
|
|
194
|
+
name: 'sublime-text'
|
|
195
|
+
}, {
|
|
196
|
+
matches: cmd => cmd.includes('\\conhost.exe'),
|
|
197
|
+
name: 'conhost.exe'
|
|
198
|
+
}];
|
|
199
|
+
const getPatternName = cmd => {
|
|
200
|
+
return processNamePatterns.find(pattern => pattern.matches(cmd))?.name || '';
|
|
201
|
+
};
|
|
202
|
+
const getFallbackPatternName = cmd => {
|
|
203
|
+
return fallbackProcessNamePatterns.find(pattern => pattern.matches(cmd))?.name || '';
|
|
204
|
+
};
|
|
499
205
|
const getName = (pid, cmd, rootPid, pidMap) => {
|
|
500
206
|
number(pid);
|
|
501
207
|
string(cmd);
|
|
@@ -504,52 +210,18 @@ const getName = (pid, cmd, rootPid, pidMap) => {
|
|
|
504
210
|
if (pid === rootPid) {
|
|
505
211
|
return 'main';
|
|
506
212
|
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
if (cmd.includes('--type=gpu-process')) {
|
|
511
|
-
return 'gpu-process';
|
|
512
|
-
}
|
|
513
|
-
if (cmd.includes('extensionHostMain.js')) {
|
|
514
|
-
return 'extension-host';
|
|
515
|
-
}
|
|
516
|
-
if (cmd.includes('ptyHostMain.js')) {
|
|
517
|
-
return 'pty-host';
|
|
518
|
-
}
|
|
519
|
-
if (cmd.includes('--lvce-window-kind=process-explorer')) {
|
|
520
|
-
return 'process-explorer';
|
|
213
|
+
const patternName = getPatternName(cmd);
|
|
214
|
+
if (patternName) {
|
|
215
|
+
return patternName;
|
|
521
216
|
}
|
|
522
217
|
if (pid in pidMap) {
|
|
523
|
-
return pidMap[pid] ||
|
|
524
|
-
}
|
|
525
|
-
if (cmd.includes('--type=renderer')) {
|
|
526
|
-
return `renderer`;
|
|
527
|
-
}
|
|
528
|
-
if (cmd.includes('--type=utility')) {
|
|
529
|
-
return 'utility';
|
|
530
|
-
}
|
|
531
|
-
if (cmd.includes('tsserver.js')) {
|
|
532
|
-
return 'tsserver.js';
|
|
218
|
+
return pidMap[pid] || '<unknown>';
|
|
533
219
|
}
|
|
534
|
-
|
|
535
|
-
|
|
220
|
+
const fallbackPatternName = getFallbackPatternName(cmd);
|
|
221
|
+
if (fallbackPatternName) {
|
|
222
|
+
return fallbackPatternName;
|
|
536
223
|
}
|
|
537
|
-
|
|
538
|
-
return 'extension-host-helper-process';
|
|
539
|
-
}
|
|
540
|
-
if (cmd.includes('/bin/rg') || cmd.includes('rg.exe')) {
|
|
541
|
-
return 'ripgrep';
|
|
542
|
-
}
|
|
543
|
-
if (cmd.startsWith('bash')) {
|
|
544
|
-
return 'bash';
|
|
545
|
-
}
|
|
546
|
-
if (cmd.startsWith(`/opt/sublime_text/sublime_text `)) {
|
|
547
|
-
return 'sublime-text';
|
|
548
|
-
}
|
|
549
|
-
if (cmd.includes('\\conhost.exe')) {
|
|
550
|
-
return 'conhost.exe';
|
|
551
|
-
}
|
|
552
|
-
return `${cmd}`;
|
|
224
|
+
return cmd;
|
|
553
225
|
};
|
|
554
226
|
|
|
555
227
|
const ENOENT = 'ENOENT';
|
|
@@ -557,7 +229,7 @@ const ERR_DLOPEN_FAILED = 'ERR_DLOPEN_FAILED';
|
|
|
557
229
|
const ESRCH = 'ESRCH';
|
|
558
230
|
|
|
559
231
|
const isDlOpenError = error => {
|
|
560
|
-
return error
|
|
232
|
+
return error instanceof Error && 'code' in error && error.code === ERR_DLOPEN_FAILED;
|
|
561
233
|
};
|
|
562
234
|
|
|
563
235
|
const loadWindowProcessTree = async () => {
|
|
@@ -572,30 +244,14 @@ const loadWindowProcessTree = async () => {
|
|
|
572
244
|
};
|
|
573
245
|
|
|
574
246
|
const withResolvers = () => {
|
|
575
|
-
|
|
576
|
-
* @type {any}
|
|
577
|
-
*/
|
|
578
|
-
let _resolve;
|
|
579
|
-
/**
|
|
580
|
-
* @type {any}
|
|
581
|
-
*/
|
|
582
|
-
let _reject;
|
|
583
|
-
const promise = new Promise((resolve, reject) => {
|
|
584
|
-
_resolve = resolve;
|
|
585
|
-
_reject = reject;
|
|
586
|
-
});
|
|
587
|
-
return {
|
|
588
|
-
resolve: _resolve,
|
|
589
|
-
reject: _reject,
|
|
590
|
-
promise
|
|
591
|
-
};
|
|
247
|
+
return Promise.withResolvers();
|
|
592
248
|
};
|
|
593
249
|
|
|
594
250
|
const getProcessList = async (rootPid, flags) => {
|
|
595
251
|
const WindowsProcessTree = await loadWindowProcessTree();
|
|
596
252
|
const {
|
|
597
|
-
|
|
598
|
-
|
|
253
|
+
promise,
|
|
254
|
+
resolve
|
|
599
255
|
} = withResolvers();
|
|
600
256
|
WindowsProcessTree.getProcessList(rootPid, resolve, flags);
|
|
601
257
|
return promise;
|
|
@@ -603,20 +259,19 @@ const getProcessList = async (rootPid, flags) => {
|
|
|
603
259
|
const addCpuUsage = async processList => {
|
|
604
260
|
const WindowsProcessTree = await loadWindowProcessTree();
|
|
605
261
|
const {
|
|
606
|
-
|
|
607
|
-
|
|
262
|
+
promise,
|
|
263
|
+
resolve
|
|
608
264
|
} = withResolvers();
|
|
609
|
-
|
|
265
|
+
const mutableProcessList = processList.map(process => ({
|
|
266
|
+
...process
|
|
267
|
+
}));
|
|
268
|
+
WindowsProcessTree.getProcessCpuUsage(mutableProcessList, resolve);
|
|
610
269
|
return promise;
|
|
611
270
|
};
|
|
612
271
|
|
|
613
272
|
const Memory = 1;
|
|
614
273
|
const CommandLine = 2;
|
|
615
274
|
|
|
616
|
-
const createPidMap = async () => {
|
|
617
|
-
return invoke('CreatePidMap.createPidMap');
|
|
618
|
-
};
|
|
619
|
-
|
|
620
275
|
// listProcesses windows implementation based on https://github.com/microsoft/vscode/blob/c0769274fa136b45799edeccc0d0a2f645b75caf/src/vs/base/node/ps.ts (License MIT)
|
|
621
276
|
|
|
622
277
|
/**
|
|
@@ -626,18 +281,15 @@ const createPidMap = async () => {
|
|
|
626
281
|
*/
|
|
627
282
|
const toResultItem = (item, rootPid, pidMap) => {
|
|
628
283
|
return {
|
|
284
|
+
cmd: item.commandLine,
|
|
285
|
+
memory: item.memory,
|
|
629
286
|
name: getName(item.pid, item.commandLine, rootPid, pidMap),
|
|
630
287
|
pid: item.pid,
|
|
631
|
-
ppid: item.ppid
|
|
632
|
-
memory: item.memory,
|
|
633
|
-
cmd: item.commandLine
|
|
288
|
+
ppid: item.ppid
|
|
634
289
|
};
|
|
635
290
|
};
|
|
636
291
|
const toResult = (completeProcessList, rootPid, pidMap) => {
|
|
637
|
-
const results =
|
|
638
|
-
for (const item of completeProcessList) {
|
|
639
|
-
results.push(toResultItem(item, rootPid, pidMap));
|
|
640
|
-
}
|
|
292
|
+
const results = Array.from(completeProcessList, item => toResultItem(item, rootPid, pidMap));
|
|
641
293
|
return results;
|
|
642
294
|
};
|
|
643
295
|
const listProcessesWithMemoryUsage$1 = async rootPid => {
|
|
@@ -699,7 +351,7 @@ const parseMemory = content => {
|
|
|
699
351
|
|
|
700
352
|
const getContent = async pid => {
|
|
701
353
|
try {
|
|
702
|
-
const filePath = join('/proc',
|
|
354
|
+
const filePath = join('/proc', String(pid), 'statm');
|
|
703
355
|
const content = await readFile(filePath, Utf8);
|
|
704
356
|
return content;
|
|
705
357
|
} catch (error) {
|
|
@@ -762,17 +414,36 @@ const splitLines = lines => {
|
|
|
762
414
|
|
|
763
415
|
// parse ps output based on vscode https://github.com/microsoft/vscode/blob/c0769274fa136b45799edeccc0d0a2f645b75caf/src/vs/base/node/ps.ts (License MIT)
|
|
764
416
|
|
|
765
|
-
const
|
|
417
|
+
const isSpace = character => {
|
|
418
|
+
return character === ' ' || character === '\t';
|
|
419
|
+
};
|
|
420
|
+
const readField = (line, startIndex) => {
|
|
421
|
+
let start = startIndex;
|
|
422
|
+
while (start < line.length && isSpace(line[start])) {
|
|
423
|
+
start++;
|
|
424
|
+
}
|
|
425
|
+
let end = start;
|
|
426
|
+
while (end < line.length && !isSpace(line[end])) {
|
|
427
|
+
end++;
|
|
428
|
+
}
|
|
429
|
+
return {
|
|
430
|
+
nextIndex: end,
|
|
431
|
+
value: line.slice(start, end)
|
|
432
|
+
};
|
|
433
|
+
};
|
|
766
434
|
const parsePsOutputLine = line => {
|
|
767
435
|
string(line);
|
|
768
|
-
const
|
|
769
|
-
|
|
436
|
+
const trimmedLine = line.trim();
|
|
437
|
+
const pidField = readField(trimmedLine, 0);
|
|
438
|
+
const ppidField = readField(trimmedLine, pidField.nextIndex);
|
|
439
|
+
const loadField = readField(trimmedLine, ppidField.nextIndex);
|
|
440
|
+
const memoryField = readField(trimmedLine, loadField.nextIndex);
|
|
441
|
+
const cmd = trimmedLine.slice(memoryField.nextIndex).trim();
|
|
442
|
+
if (pidField.value && ppidField.value && loadField.value && memoryField.value && cmd) {
|
|
770
443
|
return {
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
// load: parseInt(matches[3]),
|
|
775
|
-
// mem: parseInt(matches[4]),
|
|
444
|
+
cmd,
|
|
445
|
+
pid: Number.parseInt(pidField.value),
|
|
446
|
+
ppid: Number.parseInt(ppidField.value)
|
|
776
447
|
};
|
|
777
448
|
}
|
|
778
449
|
throw new Error(`line could not be parsed: ${line}`);
|
|
@@ -791,9 +462,9 @@ const parsePsOutput = (stdout, rootPid, pidMap) => {
|
|
|
791
462
|
const parsedLines = lines.map(parsePsOutputLine);
|
|
792
463
|
for (const parsedLine of parsedLines) {
|
|
793
464
|
const {
|
|
465
|
+
cmd,
|
|
794
466
|
pid,
|
|
795
|
-
ppid
|
|
796
|
-
cmd
|
|
467
|
+
ppid
|
|
797
468
|
} = parsedLine;
|
|
798
469
|
const depth = pid === rootPid ? 1 : depthMap[ppid];
|
|
799
470
|
if (!depth) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lvce-editor/process-explorer",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Process Explorer",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": "bin/processExplorer.js",
|
|
@@ -18,57 +18,12 @@
|
|
|
18
18
|
"node": ">=18"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@lvce-editor/assert": "^1.
|
|
22
|
-
"@lvce-editor/
|
|
23
|
-
"@lvce-editor/
|
|
24
|
-
"@lvce-editor/verror": "^1.
|
|
21
|
+
"@lvce-editor/assert": "^1.5.1",
|
|
22
|
+
"@lvce-editor/rpc": "^6.4.0",
|
|
23
|
+
"@lvce-editor/rpc-registry": "^9.27.0",
|
|
24
|
+
"@lvce-editor/verror": "^1.7.0"
|
|
25
25
|
},
|
|
26
26
|
"optionalDependencies": {
|
|
27
|
-
"@vscode/windows-process-tree": "^0.
|
|
28
|
-
},
|
|
29
|
-
"xo": {
|
|
30
|
-
"rules": {
|
|
31
|
-
"unicorn/filename-case": "off",
|
|
32
|
-
"indent": "off",
|
|
33
|
-
"semi": "off",
|
|
34
|
-
"no-unused-vars": "off",
|
|
35
|
-
"unicorn/numeric-separators-style": "off",
|
|
36
|
-
"no-extra-semi": "off",
|
|
37
|
-
"arrow-body-style": "off",
|
|
38
|
-
"padded-blocks": "off",
|
|
39
|
-
"capitalized-comments": "off",
|
|
40
|
-
"padding-line-between-statements": "off",
|
|
41
|
-
"arrow-parens": "off",
|
|
42
|
-
"no-warning-comments": "off",
|
|
43
|
-
"array-bracket-spacing": "off",
|
|
44
|
-
"comma-spacing": "off",
|
|
45
|
-
"unicorn/no-array-callback-reference": "off",
|
|
46
|
-
"comma-dangle": "off",
|
|
47
|
-
"operator-linebreak": "off",
|
|
48
|
-
"no-case-declarations": "off",
|
|
49
|
-
"no-undef": "off",
|
|
50
|
-
"object-curly-spacing": "off",
|
|
51
|
-
"object-shorthand": "off",
|
|
52
|
-
"complexity": "off",
|
|
53
|
-
"no-labels": "off",
|
|
54
|
-
"no-multi-assign": "off",
|
|
55
|
-
"max-params": "off",
|
|
56
|
-
"no-bitwise": "off",
|
|
57
|
-
"unicorn/prefer-math-trunc": "off",
|
|
58
|
-
"no-await-in-loop": "off",
|
|
59
|
-
"unicorn/prefer-add-event-listener": "off",
|
|
60
|
-
"no-unused-expressions": "off",
|
|
61
|
-
"node/prefer-global/process": "off",
|
|
62
|
-
"unicorn/prevent-abbreviations": "off",
|
|
63
|
-
"unicorn/no-process-exit": "off",
|
|
64
|
-
"quotes": "off",
|
|
65
|
-
"n/prefer-global/process": [
|
|
66
|
-
"error",
|
|
67
|
-
"always"
|
|
68
|
-
]
|
|
69
|
-
},
|
|
70
|
-
"ignores": [
|
|
71
|
-
"distmin"
|
|
72
|
-
]
|
|
27
|
+
"@vscode/windows-process-tree": "^0.7.0"
|
|
73
28
|
}
|
|
74
29
|
}
|