fix(javascript): yield inside semantic analysis and large projection passes (#1542)

* fix(javascript): yield inside semantic analysis and large projection passes

After #1525 the longest event-loop blocks were single stages on very large
files: semantic analysis of Obsidian's 3.7 MB app.js ran 5.8 s in one piece,
and its object projection 1.8 s.

- analyzeParsedJavaScriptSemanticsSteps yields between the analysis phases
  and between the eight derived collectors; the synchronous function drains
  it, so results are unchanged.
- Per-file analysis yields between open-receiver classification and static
  analysis and drives the semantic steps.
- Semantic node creation, definitions and references, and the object and
  frontier passes yield every 64 items. Node creation keeps source order,
  which the per-file node budget depends on.

On obsidian.asar the longest block falls from 5,355 ms to 907 ms with the
same total time (40.6 s to 39.5 s). Graph IDs and complete result digests
match main on five inputs. Remaining blocks up to about 0.9 s are single
AST traversal passes inside the analyzers.

Refs #1462

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(javascript): drop the unused synchronous derived-semantics wrapper

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kaoru0822
2026-10-10 04:20:50 -07:00
committed by GitHub
parent b9c439831d
commit ca7ef69c0c
7 changed files with 150 additions and 62 deletions
@@ -4,7 +4,7 @@ import { setImmediate } from "node:timers/promises";
import { resolveJavaScriptSourceMapReference } from "../../domain/javascript/javascriptSourceMapPaths.js";
import { analyzeParsedJavaScriptStaticSource } from "../../domain/javascript/javascriptStaticAnalysis.js";
import {
analyzeParsedJavaScriptSemantics,
analyzeParsedJavaScriptSemanticsSteps,
classifyParsedJavaScriptOpenReceivers,
} from "../../domain/javascript/javascriptSemanticAnalysis.js";
import type { JavaScriptSemanticIr } from "../../domain/javascript/javascriptSemanticIr.js";
@@ -189,6 +189,7 @@ function* analyzeArtifactFileSteps<
return;
}
const openReceiverFacts = classifyParsedJavaScriptOpenReceivers(parsed);
yield;
const analysis = analyzeParsedJavaScriptStaticSource(
file.text.value,
parsed,
@@ -198,7 +199,7 @@ function* analyzeArtifactFileSteps<
yield;
const semantics =
analysis.parse_status === "complete" || analysis.parse_status === "partial"
? analyzeParsedJavaScriptSemantics(parsed)
? yield* analyzeParsedJavaScriptSemanticsSteps(parsed)
: null;
const projected =
semantics === null