You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
tsc -b can hang when two referenced projects extend into one circular extends chain #64833
This is the behavior in every version I tried: a build of main at 257e874 on linux-x64.
⏯ Playground Link
tsc -b is not in the playground. The reproduction is a small file tree.
💻 Code
cycle/tsconfig.json extends cycle/a.json, which extends cycle/b.json, which extends cycle/tsconfig.json again. p1/tsconfig.json extends ../cycle/a.json and p2/tsconfig.json extends ../cycle/b.json, each with one .ts file. The root tsconfig.json is { "files": [], "references": [{ "path": "./p1" }, { "path": "./p2" }] }.
$ tsc -b tsconfig.json --dry
🙁 Actual behavior
The build sometimes never returns. Here it hung in 3 of 6 runs; a unit test that parses p1 and p2 concurrently on one ExtendedConfigCache hangs in every process at -test.count=200.
🙂 Expected behavior
The build returns, and both projects report TS18000, as tsc -p p1 and tsc -p p2 do.
Additional information about the issue
ExtendedConfigCache.GetExtendedConfig parses an entry while holding that entry's lock, and the parse re-enters the cache for each config it extends. Two projects that enter a cycle at different points each hold one entry and wait for the other's. The cycle bypass in getExtendedConfig only covers a config already on the same goroutine's stack. tsc -b, watch mode and the API's build orchestrator use this cache.
The same lock pattern was removed from the project service's cache in #64825. Here the cache has no owners and no expiry, so the fix can be smaller: a collections.SyncMap of entries, where a miss parses without any lock and stores with LoadOrStore. Concurrent first loads of one config may then each parse it.
Activity