()
| 596 | } |
| 597 | |
| 598 | async function processNextBatch() { |
| 599 | if (pendingFileQueue.length === 0) { |
| 600 | // Cross-linking phase |
| 601 | self.postMessage({ type: 'PROGRESS', payload: { msg: "Building high-fidelity relationships...", percent: 95 } }); |
| 602 | await new Promise(r => setTimeout(r, 0)); |
| 603 | |
| 604 | const MAX_CALL_EDGES = 50000; |
| 605 | let callsAdded = 0; |
| 606 | for (const [callerId, calls] of fileCalls.entries()) { |
| 607 | if (callsAdded >= MAX_CALL_EDGES) break; |
| 608 | const callerFile = nodes[callerId - 1]?.file; |
| 609 | for (const calledName of calls) { |
| 610 | const targetId = resolveSymbol(`Function:${calledName}`, callerFile) || |
| 611 | resolveSymbol(`Class:${calledName}`, callerFile) || |
| 612 | resolveSymbol(calledName, callerFile); |
| 613 | if (targetId && targetId !== callerId) { |
| 614 | links.push({ source: callerId, target: targetId, type: 'CALLS' }); |
| 615 | callsAdded++; |
| 616 | if (callsAdded >= MAX_CALL_EDGES) break; |
| 617 | } |
| 618 | } |
| 619 | } |
| 620 | for (const [classId, bases] of inheritances.entries()) { |
| 621 | const classFile = nodes[classId - 1]?.file; |
| 622 | for (const baseName of bases) { |
| 623 | const targetId = resolveSymbol(`Class:${baseName}`, classFile) || resolveSymbol(baseName, classFile); |
| 624 | if (targetId) links.push({ source: classId, target: targetId, type: 'INHERITS' }); |
| 625 | } |
| 626 | } |
| 627 | |
| 628 | const pm = (performance as any).memory; |
| 629 | if (pm) { |
| 630 | console.log(`[Worker RAM Pre-PostMessage] ${(pm.usedJSHeapSize / 1048576).toFixed(1)} MB used.`); |
| 631 | } |
| 632 | |
| 633 | self.postMessage({ type: 'PROGRESS', payload: { msg: "Indexing complete! Transferring structures to UI...", percent: 100 } }); |
| 634 | const filePaths = Array.from(filePathToNodeId.keys()); |
| 635 | self.postMessage({ type: 'DONE', payload: { nodes, links, files: filePaths } }); |
| 636 | return; |
| 637 | } |
| 638 | |
| 639 | // Smaller batch = less peak memory per tick; GC gets more breathing room |
| 640 | const batch = pendingFileQueue.splice(0, 10); |
| 641 | |
| 642 | for (let i = 0; i < batch.length; i++) { |
| 643 | const f = batch[i]; |
| 644 | processedCount++; |
| 645 | |
| 646 | if (processedCount % 5 === 0) { |
| 647 | const pm = (performance as any).memory; |
| 648 | const memStr = pm ? ` [RAM: ${(pm.usedJSHeapSize / 1048576).toFixed(1)}MB]` : ""; |
| 649 | self.postMessage({ |
| 650 | type: 'PROGRESS', |
| 651 | payload: { |
| 652 | msg: `Indexing: ${f.path.split('/').pop()}${memStr}...`, |
| 653 | percent: 50 + Math.floor((processedCount / totalFiles) * 40) |
| 654 | } |
| 655 | }); |
no test coverage detected