Skip to content

fix(inspector): registry query cycle deadlock, error surfacing, and back-navigation - #200

Merged
antfu merged 3 commits into
antfu:mainfrom
antfubot:fix/registry-query-cycle-and-nav
Aug 24, 2026
Merged

fix(inspector): registry query cycle deadlock, error surfacing, and back-navigation#200
antfu merged 3 commits into
antfu:mainfrom
antfubot:fix/registry-query-cycle-and-nav

Conversation

@antfubot

Copy link
Copy Markdown
Contributor

What & why

Fixes three issues with the web build's Registry Query (Instant) mode.

1. Registry query can silently deadlock on dependency cycles

Some specs (e.g. @nuxt/devtools@4.0.0-alpha.15) never resolved — the resolver froze partway through with the event loop idle and all network requests already completed.

Root cause: in resolveRegistryDependencies, a node's spec was only returned after await-ing its entire subtree expansion. A dependency cycle that revisits the same in-flight name@range therefore produced resolution promises awaiting each other forever.

Fix: decouple node identity from subtree expansion — a node resolves to its spec as soon as its version is picked, and expansion is deferred to a queue drained to a fixpoint by the driver. Cyclic edges back to an in-flight node now resolve immediately. @nuxt/devtools@4.0.0-alpha.15 resolves in a few seconds again.

2. A failed top-level query dropped users into an empty graph

When none of the requested top-level packages could be resolved, the resolver only recorded warnings and still returned a payload, so the app navigated into an empty grid with just a small toast. It now throws in that case, so the landing page shows its "Failed to Resolve Dependencies" error box instead.

3. Landing → inspector didn't create a history entry

Navigating from the landing into the graph used an implicit router.replace, so the browser Back button couldn't return to the landing. The landing now lives at / and pushes into /grid/depth, so Back works. (The landing renders outside <NuxtPage>, where useRoute() returns a stale snapshot — the reactive router.currentRoute is used instead.)

Tests

  • New resolver unit tests for 2-/3-node same-range cycles and a self-referential dependency.
  • New e2e tests: error-on-landing for an unresolvable query, and Back returns to the landing after a query.
  • pnpm test, pnpm typecheck, pnpm lint, and the instant + webcontainer Playwright suites all pass.

This PR was created with the help of an agent.

A node's spec was only returned after awaiting its full subtree expansion, so a cyclic edge back to an in-flight name@range made the resolution promises await each other forever (e.g. @nuxt/devtools@4.0.0-alpha.15 froze partway through). Defer subtree expansion to a queue drained to a fixpoint by the driver, so a node resolves to its spec as soon as its version is picked.
…ation

When a top-level registry query resolves nothing, throw so the landing shows an error box instead of dropping into an empty graph. Navigate landing -> inspector with router.push (not the implicit replace) so the browser Back button returns to the landing; gate the landing on the reactive router.currentRoute since Landing renders outside <NuxtPage>.
@pkg-pr-new

pkg-pr-new Bot commented Aug 24, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/node-modules-inspector@200
npm i https://pkg.pr.new/node-modules-tools@200

commit: cc0e68c

// Navigate into the inspector with a real history push (not a replace) so
// the browser Back button returns here to the landing. The landing lives
// at `/`; once we're on an inspector route the payload renders MainEntry.
if (isLanding.value)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isLanding and no errors maybe?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call — guarded the push on isLanding.value && !error.value in cc0e68c so a failed query keeps the user on the landing. (It's inside the try after a successful resolve today, but the explicit !error.value makes the intent clear and is defensive against any non-throwing error path.)

Guard the landing -> inspector push on `!error.value` as well, per review, so a failed query keeps the user on the landing.
@antfu
antfu merged commit 8ff1bab into antfu:main Aug 24, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants