| 368 | } |
| 369 | |
| 370 | static void extract_channels_js(CBMExtractCtx *ctx) { |
| 371 | chan_const_table_t consts = {0}; |
| 372 | scan_string_consts_js(ctx, &consts); |
| 373 | |
| 374 | /* Second pass: walk the tree looking for call_expression nodes. */ |
| 375 | TSNodeStack stack; |
| 376 | ts_nstack_init(&stack, ctx->arena, CHAN_STACK_CAP); |
| 377 | ts_nstack_push(&stack, ctx->arena, ctx->root); |
| 378 | |
| 379 | while (stack.count > 0) { |
| 380 | TSNode node = ts_nstack_pop(&stack); |
| 381 | if (strcmp(ts_node_type(node), "call_expression") == 0) { |
| 382 | js_process_call(ctx, node, &consts); |
| 383 | } |
| 384 | ts_nstack_push_children(&stack, ctx->arena, node); |
| 385 | } |
| 386 | } |
| 387 | |
| 388 | /* ══════════════════════════════════════════════════════════════════ |
| 389 | * Python — python-socketio, Django Channels, FastAPI WebSocket, Kafka |
no test coverage detected