fix(server): favicon resolution no longer pins the event loop - #5538
fix(server): favicon resolution no longer pins the event loop#5538murenovich wants to merge 1 commit into
Conversation
`LINK_ICON_OBJ_RE` was unanchored, so it restarted at every offset in an icon source file and rescanned forward from each one. A project with no icon file and a large `index.html` that has no `<link rel="icon">` made favicon resolution spin for minutes on the server's only thread, so every connection stopped being answered and the desktop client dropped into a permanent reconnect loop. Measured on a 1.6 MB generated `index.html`: 200 KB already cost ~4s, and the full file never completed. That pattern accepted any position from which both `rel` and `href` were visible before the next `}`, which is exactly "both live in the same brace-free run". Walking those runs directly gives the same answers in linear time, and keeps working where a single anchored pattern would not: runs holding `rel` but no `href` fall through to the next candidate, and metadata sitting beside a nested object still resolves. The same 1.6 MB file now finishes in 2 ms. The object branch had no test coverage, so this adds both key orders, a nested-object case, a no-href-then-valid case, and a large brace-sparse source that hangs without the fix. Model: Claude Opus 5 · Harness: Claude Code Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Approved 6ba92f5 Straightforward performance fix replacing a quadratic regex pattern with a linear split-and-scan approach for favicon resolution. The change is isolated, well-documented, and includes comprehensive test coverage including a performance regression test. You can customize Macroscope's approvability policy. Learn more. |
What Changed
LINK_ICON_OBJ_REis gone. Object icon metadata is now found by scanning brace-free runs instead of by one combined pattern:Five tests come with it. The object branch had no coverage at all — every existing case exercises the
<link>branch — so this adds both key orders, a nested-object case, a no-href-then-valid case, and a large brace-sparse source that hangs the suite without the fix.LINK_ICON_HTML_REis untouched. It is already anchored on<link\b, so it was never part of the problem.Why
Fixes #5537.
The old pattern began with a lookahead and no literal anchor, so the engine retried at every offset and rescanned forward with
[^}]*from each one. On a brace-sparse file that is quadratic.That turns one file into a full environment outage. A project with no icon and a large
index.htmllacking<link rel="icon">— the shape of a generated single-file build — maderesolvePathspin for minutes on the server's only thread. Every endpoint stopped answering, including/.well-known/t3/environment; the desktop client timed out at 10s, respawned the server, and it re-scanned and re-wedged. The environment never recovered on its own.Why runs rather than an anchored pattern
Anchoring the existing pattern on
{is the obvious fix and it is not equivalent. It breaks two cases the current code handles:\{…\}{ attributes: {}, rel: "icon", href: "/x.svg" }/x.svgnull/x.svg[{ rel: "icon" }, { rel: "icon", href: "/x.svg" }]/x.svgnull/x.svgThe old pattern accepted any position from which both
relandhrefwere visible before the next}— which is exactly "both live in the same brace-free run". Walking those runs reproduces that rule directly: a run holdingrelbut nohreffalls through to the next candidate, and metadata beside a nested object still resolves because the run boundary sits at}, not at the enclosing object.I checked this against the old pattern across both key orders,
shortcut icon, query stripping,rel: "stylesheet", a TanStackhead()block, and the two rows above: same result on every one.UI Changes
None.
Verification
vp test run src/project/ProjectFaviconResolver.test.ts— 17 passed (12 existing + 5 new), 445 ms.vp linton both changed files: clean.tsgo --noEmitforapps/server: exit 0, no diagnostics in the changed files.Branched off
main@e4abc31f.Checklist
Model: Claude Opus 5 · Harness: Claude Code
Note
Medium Risk
Touches server-side favicon discovery on every workspace scan; behavior is intended to be equivalent for object metadata but the parsing path changed, so edge-case regressions are possible despite new tests.
Overview
Fixes event-loop wedging when
ProjectFaviconResolverscans large project sources that have no icon metadata (e.g. generated single-fileindex.html).Object-literal icon detection no longer uses the unanchored
LINK_ICON_OBJ_REregex (which retried at every offset and could run for minutes).extractIconHrefnow splits the source on}and, within each brace-free run, looks forrel: "icon"/shortcut iconand a matchinghref—same semantics as before for TanStack-stylehead()blocks, arbitrary key order, nested objects, and “icon without href then valid entry” cases. HTML<link rel="icon">matching is unchanged.Adds five tests covering object metadata cases plus a large-file timing guard (< 5s, expects
null).Reviewed by Cursor Bugbot for commit 6ba92f5. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Fix
extractIconHrefto resolve object-literal favicons without pinning the event loopLINK_ICON_OBJ_REregex with a segment-based scan inProjectFaviconResolver.ts: the source is split on}into brace-free runs, each checked forrel: "icon"thenhref.hrefbeforerel, extra nested properties, or rel-only segments caused resolution to fail.Macroscope summarized 6ba92f5.