Repository navigation
components: fix and improve change detection recording from the October 2026 audit #316
Copy link
Copy link
Closed as duplicate
Closed as duplicate
Copy link
Labels
bugSomething is broken or shows wrong dataSomething is broken or shows wrong datafeatureA feature request or a pull request that adds oneA feature request or a pull request that adds one
Description
Context
This comes from a code audit of change detection recording (cd-overlay.ts, cd-recorder.ts, change-detection.ts, rpc/cd-tools.ts, app/src/pages/cd-recording.ts). The audit was done in October 2026 while comparing Pangular with other devtools. Roadmap items live in #310, #311, #312 and #313. Items marked (to confirm) were not reproduced.
Problems
Medium
- A second start wipes a running recording:
setRecording(true)callsrecorder.start()every time, andstart()callsreset(). An agentrecord: "start"with nopageis broadcast to every tab, so it erases the user's panel recording. A double click does the same. Makeon: truea no-op when already recording, and clear only onclear: true. Consider requiringpagefor agent start and clear when more than one tab is connected (packages/devtools/src/cd-overlay.ts:56-61,packages/devtools/src/cd-recorder.ts:228-232,packages/devtools/src/devframe.ts:1949-1954). - Stale output trigger:
lastOutputstays set until the nextChangeDetectionStart. An output that started no tick (zoneless with no signal change, or an output nobody listens to) is then credited to a later tick caused by a timer, HTTP or a signal. StamplastOutputwithnow()and drop it when change detection starts more than about one frame later, or clear it in a microtask after the output ends (packages/devtools/src/cd-recorder.ts:119-132).
Low
- Wrong "needs Angular 20" message:
supportedbecomesfalsewheneveraddProfilerListenerreturnsnull. That also happens whenngis not available yet, when the page has no[ng-version](createApplication, Angular Elements, whereangularMajorreturns 0), or whenɵsetProfilerthrows. The panel and the agent tool then show a fixed "needs Angular 20" text, and nothing retries until the user toggles again. Report a reason (no-ng-yet,angular<20,no-profiler-api), retry the attach on the next refresh while recording is wanted, and read the version another way whenng-versionis missing (packages/devtools/src/cd-overlay.ts:58-60,packages/devtools/src/change-detection.ts:55-59,app/src/pages/cd-recording.ts:66-68,packages/devtools/src/rpc/cd-tools.ts:161-163). - Start is confirmed without an answer from the page:
change-detection-recordis broadcast withoptional: true, and the panel and agent tool say "Recording started" as soon as the hub accepts the request. "Could not reach the page" only shows when the hub itself fails. Wait up to about 1 s for a push withrecording: true(orsupported: false) from thatpageId, and say when the page did not answer (packages/devtools/src/devframe.ts:1256-1263,packages/devtools/src/devframe.ts:1955-1961,app/src/pages/cd-recording.ts:313-332). - Limits are hit silently: totals stop taking new classes at 1000, host
WeakRefs stop at 2000 instances, and a failedgetHostElementis cached asnullforever. Tree badges and totals then go missing with no note, unlike cycles, which carrydropped. AdddroppedClassesanddroppedHoststoCdRecording, show them inLimitNoteand the agent text, and do not cache anullhost id (packages/devtools/src/cd-recorder.ts:165,packages/devtools/src/cd-recorder.ts:180-187,packages/devtools/src/cd-overlay.ts:42-54). - Nested tick replaces the cycle in progress: a
ChangeDetectionStartwhilecurrentis set overwrites it and resets the frame stack, so the outer cycle is lost. Keep a cycle stack, or count a nested tick as a pass (packages/devtools/src/cd-recorder.ts:122-133) (to confirm). - Panel shows less than the agent tool: the agent answer has a "Most often checked" list, the panel does not. Cycle rows can't be expanded to their top 10
components, component names don't link to their tree row or highlight, and the zone mode is not shown next to Record. The slowest table usestrack $indexinstead ofc.name(app/src/pages/cd-recording.ts:75-126,app/src/pages/cd-recording.ts:89,packages/devtools/src/rpc/cd-tools.ts:171-186). - Duplicated types: the panel declares
CdCheck,CdCycle,CdComponentStatandCdPageagain instead of importing them, so the copies can drift without a compile error. Export them from@pangular-inspector/devtools/config(or a shared types entry), aslimit-note.tsandnetwork-inspector.tsalready do (app/src/pages/cd-recording.ts:8-38,packages/devtools/src/cd-recorder.ts:17-53,packages/devtools/src/cd-overlay.ts:18-22).
Improvements
- Keep recording across a reload: store a "recording wanted" flag in
sessionStorageperpageId, likestoredInstrumented()does for the router, so a reload profile with bootstrap and the first cycles can be captured (packages/devtools/src/cd-overlay.ts,packages/devtools/src/router-actions.ts:91). - Slow cycle budget: add
limits.cdSlowMs(default 16 ms). Highlight cycles over budget in the panel and count them in the agent answer, so an agent can check "no frame-dropping ticks" after a change (packages/devtools/src/config.ts,packages/devtools/src/rpc/cd-tools.ts,app/src/pages/cd-recording.ts).
Already tracked elsewhere
- Push deltas instead of the full recording on every refresh: phase 3 of 4: a devframe shell as good as Vue and Nuxt DevTools #312 (performance and scale).
- Lifecycle hook and
afterRendertiming (profiler events 4/5 and 16/17): phase 2 of 4: match the official Angular DevTools #311. - Flame graph, cycle bar chart with a brush, export and import, Chrome Performance track, live flash overlay: phase 2 of 4: match the official Angular DevTools #311.
- Naming the trigger source (
Zone.currentTask.source, zoneless notify sources), OnPush and wasted-check hints, before/after session comparison: phase 4 of 4: lead where no Angular devtools goes today #313.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething is broken or shows wrong dataSomething is broken or shows wrong datafeatureA feature request or a pull request that adds oneA feature request or a pull request that adds one
Activity