From d8d8562264a9d7b88fc100d9611daf5d4fb44aed Mon Sep 17 00:00:00 2001 From: Test Date: Thu, 26 Mar 2026 07:20:56 +0100 Subject: [PATCH] fix: guard parentPort.on() in parse-worker for non-worker imports The webhook integration test imports extractWebhooks directly from parse-worker.ts. When imported outside a worker thread, parentPort is null and the top-level parentPort!.on('message', ...) crashes with "Cannot read properties of null (reading 'on')". Wrap the message handler registration in an `if (parentPort)` guard. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../core/ingestion/workers/parse-worker.ts | 116 +++++++++--------- 1 file changed, 61 insertions(+), 55 deletions(-) diff --git a/gitnexus/src/core/ingestion/workers/parse-worker.ts b/gitnexus/src/core/ingestion/workers/parse-worker.ts index 4562144bc..93dd163ec 100644 --- a/gitnexus/src/core/ingestion/workers/parse-worker.ts +++ b/gitnexus/src/core/ingestion/workers/parse-worker.ts @@ -2395,61 +2395,67 @@ const mergeResult = (target: ParseWorkerResult, src: ParseWorkerResult) => { target.fileCount += src.fileCount; }; -parentPort!.on('message', (msg: WorkerIncomingMessage) => { - try { - // Legacy single-message mode (backward compat): array of files - if (Array.isArray(msg)) { - const result = processBatch(msg, (filesProcessed) => { - parentPort!.postMessage({ type: 'progress', filesProcessed }); - }); - parentPort!.postMessage({ type: 'result', data: result }); - return; - } - - // Sub-batch mode: { type: 'sub-batch', files: [...] } - if (msg.type === 'sub-batch') { - const result = processBatch(msg.files, (filesProcessed) => { - parentPort!.postMessage({ - type: 'progress', - filesProcessed: cumulativeProcessed + filesProcessed, +// Only register message handler when running as a worker thread. +// When imported directly (e.g. tests importing extractWebhooks), +// parentPort is null and this block must be skipped. +if (parentPort) { + parentPort.on('message', (msg: WorkerIncomingMessage) => { + try { + // Legacy single-message mode (backward compat): array of files + if (Array.isArray(msg)) { + const result = processBatch(msg, (filesProcessed) => { + parentPort!.postMessage({ type: 'progress', filesProcessed }); }); - }); - cumulativeProcessed += result.fileCount; - mergeResult(accumulated, result); - // Signal ready for next sub-batch - parentPort!.postMessage({ type: 'sub-batch-done' }); - return; - } + parentPort!.postMessage({ type: 'result', data: result }); + return; + } - // Flush: send accumulated results - if (msg.type === 'flush') { - parentPort!.postMessage({ type: 'result', data: accumulated }); - // Reset for potential reuse - accumulated = { - nodes: [], - relationships: [], - symbols: [], - imports: [], - calls: [], - assignments: [], - heritage: [], - routes: [], - fetchCalls: [], - decoratorRoutes: [], - toolDefs: [], - ormQueries: [], - webhooks: [], - queuePatterns: [], - constructorBindings: [], - fileScopeBindings: [], - skippedLanguages: {}, - fileCount: 0, - }; - cumulativeProcessed = 0; - return; + // Sub-batch mode: { type: 'sub-batch', files: [...] } + if (msg.type === 'sub-batch') { + const result = processBatch(msg.files, (filesProcessed) => { + parentPort!.postMessage({ + type: 'progress', + filesProcessed: cumulativeProcessed + filesProcessed, + }); + }); + cumulativeProcessed += result.fileCount; + mergeResult(accumulated, result); + // Signal ready for next sub-batch + parentPort!.postMessage({ type: 'sub-batch-done' }); + return; + } + + // Flush: send accumulated results + if (msg.type === 'flush') { + parentPort!.postMessage({ type: 'result', data: accumulated }); + // Reset for potential reuse + accumulated = { + nodes: [], + relationships: [], + symbols: [], + imports: [], + calls: [], + assignments: [], + heritage: [], + routes: [], + fetchCalls: [], + decoratorRoutes: [], + toolDefs: [], + ormQueries: [], + webhooks: [], + queuePatterns: [], + constructorBindings: [], + fileScopeBindings: [], + typeEnvBindings: [], + skippedLanguages: {}, + fileCount: 0, + }; + cumulativeProcessed = 0; + return; + } + } catch (err) { + const message = err instanceof Error ? err.message : String(err); + parentPort!.postMessage({ type: 'error', error: message }); } - } catch (err) { - const message = err instanceof Error ? err.message : String(err); - parentPort!.postMessage({ type: 'error', error: message }); - } -}); + }); +}