Skip to content

components: fix and improve defer blocks and control flow from the October 2026 audit #317

Closed as duplicate

Description

@erkamyaman

Context

This comes from a code audit of the defer block, control flow and hydration code, done during a comparison with other devtools in October 2026. Roadmap items live in #310, #311, #312 and #313. Items marked (to confirm) were not reproduced.

Problems

Medium

  • Stuck placeholder noise: deferNotes flags every block that sits on its placeholder for 10s as "Needs attention", even with a viewport, interaction or hover trigger, where waiting is normal. Only flag idle, immediate, timer, when or no triggers, and give the others a plain "waiting for trigger" note outside the attention list (packages/devtools/src/rpc/component-tools.ts:121-136, 164).
  • No runtime @let: @let values never show in component detail; the only handling is a source regex. If the debug API exposes @let slots in the component's LView, list them read-only through serialize and redaction; otherwise document the gap in components.md (packages/devtools/src/rpc/get-pipes.ts:333) (to confirm).

Low

  • Missing hydratedAt: it is set only when the tracker saw the block dehydrated on an earlier read, so blocks that hydrate before the first collect, or between two reads, never get a time. Mark blocks first seen hydrated as "hydrated before inspection", or catch the transition another way (packages/devtools/src/defer-blocks.ts:96-100).
  • Silent 500-block cap: collect returns early at MAX_BLOCKS and the server slices to 500 again, with no flag. Return a truncated flag and say so in deferBlocksText and the panel pill (packages/devtools/src/defer-blocks.ts:79, packages/devtools/src/rpc/component-tools.ts:42).
  • Unfocusable rows: rows without an owner use [disabled], so keyboard users can't focus them to highlight the block while mouse users can hover them. Use aria-disabled with a guard in showOwner (app/src/pages/component-tree.ts:521-530).
  • Panel hides data it has: the panel's DeferBlock type drops since, hydratedAt, loading/placeholder timings, hasErrorBlock and the notes the agent tool computes, and the section is hidden both when there are no blocks and when the util is missing. Add an expandable row detail, reuse deferNotes for badges, and show a one-line notice when deferBlocks is undefined (app/src/pages/component-tree.ts:87-95, 513-548).
  • Clock skew: deferBlocksText compares the server's Date.now() with since from the page clock, so ages are wrong on remote or Angular Native devices whose clock differs. Send the page's now() with each report, or an age per block (packages/devtools/src/rpc/component-tools.ts:123-125, packages/devtools/src/devframe.ts:1917) (to confirm).
  • Mismatch "component" is a node name: hydration mismatches set component to node.nodeName, for example div or #text. Resolve the owning component and send the node name, component class and element id (packages/devtools/src/http-hydration.ts:59).
  • Partial block highlight: highlightBlock uses only rootIds[0], so blocks with several roots are under-highlighted. Let request-page-highlight take several ids and draw the union (app/src/pages/component-tree.ts:1921-1923, packages/devtools/src/defer-blocks.ts:111-114).

Improvements

  • Badges on component tree nodes for the control flow blocks they own ("2 defer, 1 for") (app/src/pages/component-tree.ts, packages/devtools/src/defer-blocks.ts).
  • An action tool to trigger or force-load a defer block, like DeferBlockFixture.render(state), listed in ACTION_TOOLS (packages/devtools/src/devframe.ts, packages/devtools/src/config.ts).
  • Record defer state transitions with timestamps and add them as a layer of the timeline in phase 3 of 4: a devframe shell as good as Vue and Nuxt DevTools #312, so chunk loads tie to defer triggers (packages/devtools/src/defer-blocks.ts).
  • Link hydration mismatches on the Network page to the component tree: click to select and highlight the owner (packages/devtools/src/http-hydration.ts, app/src/pages).
  • Include the defer blocks a component owns in the pangular:component-tree detail of that instance, so agents need one call (packages/devtools/src/rpc/component-tools.ts).

Already tracked elsewhere

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or shows wrong datafeatureA feature request or a pull request that adds one

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions