* Phase 5: React JSX child rendering. A component that returns ` ` * mounts Child — React calls it — but JSX instantiation isn't a static call edge, * so a render tree (App.render → StaticCanvas → renderStaticScene) breaks at the * JSX hop. Link parent → each capitalized JSX child it r
(ctx: ResolutionContext, onYield: MaybeYield)
| 1231 | * (or nothing) and are dropped. |
| 1232 | */ |
| 1233 | async function reactJsxChildEdges(ctx: ResolutionContext, onYield: MaybeYield): Promise<Edge[]> { |
| 1234 | let scannedFiles = 0; |
| 1235 | const edges: Edge[] = []; |
| 1236 | const seen = new Set<string>(); |
| 1237 | const PARENT_KINDS = new Set(['method', 'function', 'component']); |
| 1238 | let scanned = 0; |
| 1239 | for (const file of ctx.getAllFiles()) { |
| 1240 | if ((++scannedFiles & 15) === 0) await onYield(); |
| 1241 | if ((++scanned & 255) === 0) await onYield(); // #1091: yield mid-scan on huge graphs |
| 1242 | const content = ctx.readFile(file); |
| 1243 | if (!content || (!content.includes('</') && !content.includes('/>'))) continue; // JSX-file gate |
| 1244 | const parents = ctx.getNodesInFile(file).filter((n) => PARENT_KINDS.has(n.kind)); |
| 1245 | for (const parent of parents) { |
| 1246 | const src = sliceLines(content, parent.startLine, parent.endLine); |
| 1247 | if (!src || (!src.includes('</') && !src.includes('/>'))) continue; |
| 1248 | const names = new Set<string>(); |
| 1249 | JSX_TAG_RE.lastIndex = 0; |
| 1250 | let m: RegExpExecArray | null; |
| 1251 | while ((m = JSX_TAG_RE.exec(src))) names.add(m[1]!); |
| 1252 | let added = 0; |
| 1253 | for (const name of names) { |
| 1254 | if (added >= MAX_JSX_CHILDREN) break; |
| 1255 | const child = ctx.getNodesByName(name).find( |
| 1256 | (n) => n.kind === 'component' || n.kind === 'function' || n.kind === 'class' |
| 1257 | ); |
| 1258 | if (!child || child.id === parent.id) continue; |
| 1259 | const key = `${parent.id}>${child.id}`; |
| 1260 | if (seen.has(key)) continue; |
| 1261 | seen.add(key); |
| 1262 | edges.push({ |
| 1263 | source: parent.id, target: child.id, kind: 'calls', line: parent.startLine, |
| 1264 | provenance: 'heuristic', |
| 1265 | metadata: { synthesizedBy: 'jsx-render', via: name }, |
| 1266 | }); |
| 1267 | added++; |
| 1268 | } |
| 1269 | } |
| 1270 | } |
| 1271 | return edges; |
| 1272 | } |
| 1273 | |
| 1274 | /** |
| 1275 | * Phase 6: Vue SFC templates. The `.vue` extractor only parses `<script>`, so |
no test coverage detected