|
4 | 4 |
|
5 | 5 | /* eslint-disable @typescript-eslint/no-explicit-any */
|
6 | 6 |
|
7 |
| -import type { Node, RetainerNode } from '@vscode/v8-heap-parser'; |
8 | 7 | import { readFile } from 'fs/promises';
|
9 | 8 | import { parentPort, workerData } from 'worker_threads';
|
10 |
| -import { |
11 |
| - EdgeType, |
12 |
| - GraphRPCCall, |
13 |
| - GraphRPCMethods, |
14 |
| - IClassGroup, |
15 |
| - INode, |
16 |
| - IRetainingNode, |
17 |
| - NodeType, |
18 |
| -} from './rpc'; |
| 9 | +import { handleMessage, prepareGraphParser } from './heapSnapshotLogic'; |
| 10 | +import { GraphRPCCall } from './rpc'; |
19 | 11 |
|
20 | 12 | if (!parentPort) {
|
21 | 13 | throw new Error('must be run in worker thread');
|
22 | 14 | }
|
23 | 15 |
|
24 | 16 | const graph = Promise.all([
|
25 | 17 | typeof workerData === 'string' ? readFile(workerData) : Promise.resolve(workerData as Uint8Array),
|
26 |
| - import('@vscode/v8-heap-parser'), |
27 |
| -]).then(async ([f, r]) => { |
28 |
| - const { decode_bytes, init_panic_hook } = await r.default; |
29 |
| - init_panic_hook(); |
30 |
| - return decode_bytes(f); |
31 |
| -}); |
32 |
| - |
33 |
| -export const isMethod = <K extends GraphRPCMethods>( |
34 |
| - method: K, |
35 |
| - t: GraphRPCCall, |
36 |
| -): t is GraphRPCCall<K> => t.method === method; |
37 |
| - |
38 |
| -const mapInto = <T extends { free(): void }, R>( |
39 |
| - arr: readonly T[], |
40 |
| - mapper: (v: T, i: number) => R, |
41 |
| -): R[] => { |
42 |
| - const transmuted = new Array<R>(arr.length); |
43 |
| - for (let i = 0; i < arr.length; i++) { |
44 |
| - const value = arr[i]; |
45 |
| - transmuted[i] = mapper(value, i); |
46 |
| - value.free(); |
47 |
| - } |
48 |
| - |
49 |
| - return transmuted; |
50 |
| -}; |
51 |
| - |
52 |
| -const processNodes = (nodes: readonly (Node | RetainerNode)[]): (INode | IRetainingNode)[] => |
53 |
| - mapInto(nodes, node => ({ |
54 |
| - name: node.name(), |
55 |
| - childrenLen: node.children_len, |
56 |
| - id: node.id, |
57 |
| - index: node.index, |
58 |
| - retainedSize: Number(node.retained_size), |
59 |
| - selfSize: Number(node.self_size), |
60 |
| - type: node.typ as unknown as NodeType, |
61 |
| - retainsIndex: (node as RetainerNode).retains_index, |
62 |
| - edgeType: (node as RetainerNode).edge_typ as unknown as EdgeType, |
63 |
| - })); |
| 18 | + prepareGraphParser(), |
| 19 | +]).then(async ([f, r]) => r(f)); |
64 | 20 |
|
65 | 21 | parentPort.on('message', (message: GraphRPCCall) => {
|
66 |
| - graph |
67 |
| - .then(g => { |
68 |
| - if (isMethod('getClassGroups', message)) { |
69 |
| - return mapInto( |
70 |
| - g.get_class_groups(...message.args, false), |
71 |
| - (group, index): IClassGroup => ({ |
72 |
| - name: group.name(), |
73 |
| - index, |
74 |
| - retainedSize: Number(group.retained_size), |
75 |
| - selfSize: Number(group.self_size), |
76 |
| - childrenLen: group.children_len, |
77 |
| - }), |
78 |
| - ); |
79 |
| - } else if (isMethod('getClassChildren', message)) { |
80 |
| - return processNodes(g.class_children(...message.args)); |
81 |
| - } else if (isMethod('getNodeChildren', message)) { |
82 |
| - return processNodes(g.node_children(...message.args)); |
83 |
| - } else if (isMethod('getRetainers', message)) { |
84 |
| - return processNodes(g.get_all_retainers(...message.args)); |
85 |
| - } else { |
86 |
| - throw new Error(`unknown method ${message.method}`); |
87 |
| - } |
88 |
| - }) |
89 |
| - .then(ok => |
90 |
| - parentPort!.postMessage({ |
91 |
| - id: message.id, |
92 |
| - result: { ok }, |
93 |
| - }), |
94 |
| - ) |
95 |
| - .catch(err => |
96 |
| - parentPort!.postMessage({ |
97 |
| - id: message.id, |
98 |
| - result: { err: err.stack || err.message || String(err) }, |
99 |
| - }), |
100 |
| - ); |
| 22 | + handleMessage(graph, message).then(m => parentPort!.postMessage(m)); |
101 | 23 | });
|
0 commit comments