Skip to content

chore(solid-router-v2-pre): merge main#7746

Open
brenelz wants to merge 26 commits into
TanStack:solid-router-v2-prefrom
brenelz:merge-main-into-solid-v2-pre
Open

chore(solid-router-v2-pre): merge main#7746
brenelz wants to merge 26 commits into
TanStack:solid-router-v2-prefrom
brenelz:merge-main-into-solid-v2-pre

Conversation

@brenelz

@brenelz brenelz commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Merges main into solid-router-v2-pre (22 commits, including the pnpm catalog migration and minimumReleaseAge supply-chain settings).

Conflict resolutions

  • Solid packages/examples: kept the v2 beta versions from this branch; carried over main's real changes hidden among the version bumps (@rsbuild/core ^2.0.8^2.0.11 in solid-start and the rspack example).
  • pnpm-workspace.yaml: adopted main's catalog + minimumReleaseAge: 1440, kept this branch's minimumReleaseAgeExclude (solid-js, @solidjs/*, babel-preset-solid, babel-plugin-jsx-dom-expressions) and scoped babel-preset-solid overrides. Dropped main's solid-js: 1.9.12 override (would downgrade the Solid v2 toolchain) and set the catalog's @tanstack/solid-query to ^6.0.0-beta.5.
  • Root package.json: adopted catalog: references for the query deps.
  • benchmarks/client-nav/package.json: kept both @platformatic/flame (this branch) and @tanstack/router-plugin (main).
  • pnpm-lock.yaml: regenerated with pnpm install --lockfile-only. The solid-js@1.9.12 entries that remain are the pre-existing intentional ones for the vite-plugin-solid@2.x consumers (devtools-core etc.).

Verification

  • pnpm install resolves cleanly
  • @tanstack/solid-router builds
  • solid-router unit tests: 813 passed, 2 skipped (46 files), no type errors

🤖 Generated with Claude Code

Sheraff and others added 23 commits June 14, 2026 12:51
…tack#7372)

* fix(start-plugin-core): support rsbuild preview SSR

* fix(start-plugin-core): always install rsbuild SSR middleware in preview

Preview is the only SSR handler in `rsbuild preview`, so gate the opt-out
to dev only and keep the option named `installDevServerMiddleware`.
* docs(start): clarify server functions and routes usage

* clean up repetition
…#7662)

extractFlattened() always allocated a new Uint8Array and copied `count`
bytes, even when the requested bytes were fully contained in the first
buffered chunk (the common case, since most frames arrive within a single
network read).

Add a fast path that returns a subarray view of the first chunk when the
bytes are contiguous, avoiding the allocation and the byte copy. The
multi-chunk path is unchanged. The returned view shares the chunk's
backing ArrayBuffer, which is safe because buffered chunks are never
mutated in place after being read.

This is on the hot path for decoding every streamed server-function
response and RawStream binary payload on the client. A micro-benchmark
shows ~3x faster extraction for 1KB frames and ~27x for 64KB frames (the
win scales with payload size).
…Segment (TanStack#7695)

* fix(router-core): preserve percent-encoded URL-unsafe chars in decodeSegment

Replace sanitizePathSegment (which stripped control characters) with a
re-encode step that keeps WHATWG path percent-encode set characters and
control characters in their encoded form after decodeURI.

This preserves the existing decodeURI-based approach which correctly
handles multi-byte UTF-8 sequences, while fixing the mismatch between
the original request URL and the router's internal representation that
caused infinite 307 redirect loops on paths containing these characters.

Fixes TanStack#7587.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: apply automated fixes

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Flo <me@florianpellet.com>
ci: changeset release

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* bench(memory): stabilize CodSpeed memory benchmarks

Memory flags on PRs were ~85% noise, from two causes:

1. Stale baselines (dominant): the Benchmarks workflow only ran on main
   pushes touching packages/** or benchmarks/**. Main commits outside
   those paths had no CodSpeed run, so PRs were compared against an old
   base run ([^unexpected-base] on every recent codspeed-hq comment; six
   late-June PRs all compared to the same June-23 run). One outlier base
   measurement then replays into every PR until the next eligible push.
   Fix: drop the paths filter for the push trigger + weekly cron backstop.

2. Wall-clock timers racing the single measured run: aborted-requests
   (solid/vue) resolved deferred loader data on 500/750ms timeouts raced
   against abort, and drained cancellation with at most one setTimeout(0);
   streaming-peak staggered deferred sections by milliseconds. Under
   variable runner load and instrumentation slowdown the interleaving —
   and therefore the allocation sequence — differed run to run. Fix:
   count 0ms timers-phase hops (event-loop turns) instead of milliseconds
   everywhere async ordering must be staged, and drain aborts with a
   fixed 8-turn settlement barrier.

Local before/after evidence (8 fresh-process runs per config, CodSpeed V8
determinism flags, idle + CPU-stressed; kernel peak RSS spread):

  aborted-requests/solid idle    11.2MB -> 1.8MB (GC counts bit-identical)
  aborted-requests/solid stress   7.7MB -> 2.5MB
  streaming-peak/solid   idle     6.2MB -> 2.5MB
  request-churn/solid (untouched control): unchanged, confirming harness

streaming-peak/vue keeps ~2% proxy-level variance at any tick count; its
PR flags were the identical -3.2% in all three occurrences, i.e. the
stale-base artifact rather than per-run jitter.

Bench names and workload shapes are unchanged; absolute values will step
once on the CodSpeed dashboard from the removed cross-iteration overlap
(e.g. aborted-requests/solid retained 15.6MB -> 2.5MB per invocation).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* bench(memory): exclude docs/examples/e2e from main benchmark runs, drop cron

paths-ignore instead of no filter: docs/examples/e2e-only pushes cannot
affect benchmark results, and falling back across such a commit is safe
because the previous run's benchmark-relevant code is identical. The
weekly cron backstop is unnecessary for the same reason.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* bench(memory): pin GC between iterations in peak-shape scenarios

A/A runs of the real memory instrument showed the two big-payload peak
scenarios were still unstable with no timers involved: whether V8
collects iteration i's garbage before iteration i+1 allocates its
payload is not reproducible run to run, so the measured peak flipped by
a whole payload (serialization-payload solid: 6.8-9.2 MB across
identical runs; peak-large-page: 3.5-3.7 MB).

Peak scenarios measure the footprint of a single request, not
accumulation, so pin the collection points: settle two event-loop turns
(so trailing renderer/stream teardown is included) and force a GC after
each iteration. Peak then deterministically measures
max(single-request footprint). Churn scenarios are unchanged — their
signal is accumulation, which a forced GC would mask; the README rule
now spells out both sides.

A/A validation (3 identical instrumented runs, solid suite):

  serialization-payload  6.8-9.2 MB  -> 3.5-3.6 MB
  peak-large-page        3.5-3.7 MB  -> 754-757 KB (0.45% spread)
  streaming-peak         38.5-39.5   -> 30.3/30.3/30.3 MB
  churn scenarios        unchanged (aborted-requests 1.4 MB x3)

Absolute values step because cross-iteration garbage no longer inflates
the peak; the new values are the per-request footprint the scenarios
were designed to track.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…7732)

* feat(benchmarks): add client-side CPU benchmark scenario suite

Add 11 client-side CPU benchmark scenarios to benchmarks/client-nav, each
implemented identically across react/solid/vue and tracked by CodSpeed
through the existing Benchmarks workflow (no CI changes needed):

async-pipeline, control-flow, head, history, links, loaders, mount,
nested-params, preload, route-tree-scale, search-params

Each scenario is an isolated file-based-routing app (route trees generated
by @tanstack/router-plugin) built for production and driven in jsdom by a
shared harness (scenarios/harness.ts): circular step sequences of real
<Link> clicks (plus hover/preload/history-traversal/invalidate steps),
each synchronized on the router's onRendered event, with a warm-up lap
that asserts every step's observable output. Determinism rules: no
wall-clock timers (counted 0ms hops only), staleTime/gcTime pinned to 0 or
1e9, deterministic preload staleness, stationary DOM and history depth.

The existing baseline apps and bench names are untouched for CodSpeed
continuity; baseline vite configs only gain an explicit root/setupFiles so
they resolve identically under the new per-framework aggregate configs.

Notable constraints encoded in the scenarios:
- Component-level Await/Suspense is excluded from async-pipeline: React 19
  throttles every Suspense reveal by ~300ms wall-clock, which is
  inherently non-deterministic to benchmark.
- control-flow/react silences React 19's onCaughtError reporting, which
  otherwise dominates the measured loop with console I/O.
- Vue route components must be defined before their createFileRoute call
  (bundled var hoisting silently yields component: undefined otherwise).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci: apply automated fixes

* chore(benchmarks): prefix client-nav bench names with "client-"

All benches in @benchmarks/client-nav now start with "client" so they are
easy to identify on the CodSpeed dashboard (the baseline already did).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(benchmarks): address review findings on client-nav scenario stability

Fixes from an adversarial review of the scenario suite:

- mount: create the browser history explicitly and destroy() it on unmount.
  The default per-router createBrowserHistory() monkey-patches
  window.history.pushState/replaceState, chaining one wrapper per router —
  per-mount cost degraded 1.8ms -> 6ms over 3000 mounts (O(N^2) drift in
  the cold-start bench). Verified flat (~1.86ms) after the fix.
- links: replace the five <MatchRoute> components with setup-scoped
  useMatchRoute probes in all three apps. vue-router's MatchRoute calls
  useMatchRoute() inside its render function, leaking one undisposed
  watcher per render — the Vue bench accumulated ~5 dead subscribers per
  navigation. Verified flat per-tick cost over 2000 ticks after the fix.
- all scenarios: bound the scroll-restoration cache with
  getScrollRestorationKey: (location) => location.pathname. The default
  key is a fresh random per-entry location key, so the module-level cache
  grew one entry per push navigation for the whole run.
- harness hover step: dispatch a single mouseover instead of
  mouseover+mouseenter. Solid/Vue attach intent-preload handlers to BOTH
  events, so the old double dispatch ran the preload pipeline twice for
  them but once for React. Verified all three adapters preload exactly
  once per hover via cached-matches probes.
- README: correct the loaders row (the invalidate step means cached routes
  re-run once per lap), the links row, and document the session-history
  growth characteristics.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(benchmarks): cover client rewrites, lazy route chunks, encoded params

Closes the three coverage gaps identified in the scenario-suite analysis:

- new `rewrites` scenario (react/solid/vue): router basepath '/app' composed
  with a locale input/output rewrite pair — the client analog of the SSR
  rewrites scenario. Every href build runs the output rewrite and every
  committed location runs the input rewrite; assertions check both the
  internal router pathname and the external window pathname. The harness
  gained an `initialUrl` option since a basepath app cannot start at '/'.
- route-tree-scale now builds with `autoCodeSplitting: true`, so its
  navigations also exercise lazy route-chunk resolution — the default shape
  of real file-based apps, previously uncovered.
- nested-params and route-tree-scale param sets now include characters that
  need percent-encoding (spaces, `&`, `%`, `+`, unicode) so the segment
  encode/decode paths run on every navigation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(benchmarks): reduce syscall time in measured loops, lengthen mount bench

CodSpeed excludes syscall time from simulation measures, and past a
threshold it warns ("cannot be consistently instrumented") and skips the
benchmark; the exclusion is also inconsistent run-to-run, which was the
root cause of the two same-code CI swings (route-tree-scale react 13%,
async-pipeline react 3.6%) and of skipped runs on hop-heavy benches like
async-pipeline solid (579 calls / 12.1ms).

- Replace all counted setTimeout(0) hops with setImmediate hops (harness
  timerHop + async-pipeline hopDelay). Both are deterministic event-loop
  turns that yield to timers and the React Node scheduler, but a timer
  costs ~3-4 syscalls (timerfd + epoll) per hop vs ~1 for an immediate.
  Same-machine instrumented before/after: preload solid 39.8ms -> 1.2ms of
  syscall time, preload vue 30.1 -> 1.1, async-pipeline solid 23.5 -> 1.1,
  async-pipeline vue 17.9 -> 0.9. head/route-tree-scale are unchanged
  (their residual syscalls are GC/scheduler, and their measures were
  already stable); history's syscalls come from jsdom's internal
  timer-queued traversal and are not reachable from bench code (its
  measured values are stable regardless).

- mount: 6 ticks per iteration instead of 2. A single mount simulates to
  only ~8ms and very short measures amplify allocator/GC quantization;
  the bench now measures ~50ms+ of simulated CPU.

All 39 benches pass; full nx typecheck green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(benchmarks): stop history benches sleeping in jsdom's traversal timers

The history benches were skip-warned by CodSpeed for excessive syscall
time (5-26ms, highly variable across runs). Root cause: jsdom delivers
history traversals through two nested window.setTimeout(0) tasks, and Node
clamps zero timers to 1ms of wall time — so while awaiting onRendered
after back/forward/go, the event loop blocked in epoll_wait until each
timer expired. That blocked wall-time is recorded as syscall time, and its
duration depends on host timer behavior, hence the variability.

The harness now reroutes zero-delay window.setTimeout calls onto
setImmediate for the duration of a benchmark (non-zero delays pass
through; clearTimeout handles both). Zero-delay timeouts carry no ordering
semantics a check-phase immediate doesn't satisfy, and the suite's
conventions already forbid real-delay timers in measured code.

Instrumented A/A verification (2 runs per framework): history syscall time
react 23-26ms -> 2.5ms, solid 14-23ms -> 1.1ms, vue 11-12ms -> 1.2ms, with
bit-identical syscall counts across runs and measured values stable to
0.06%. The benches also stopped measuring sleep: locally an iteration
dropped from ~42-49ms to ~5-11ms of actual CPU work. All 39 benches pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
…anStack#7739)

* bench(memory): settle-until-quiescent GC barrier between iterations

The fixed-turn settle before the pinned collection was hardware-fragile:
teardown needing one more event-loop turn on a given runner leaked a whole
payload of garbage past the collection point and flipped the measured peak
bimodally (serialization-payload solid/react resurfacing the pre-TanStack#7730
6.2MB attractor on some CI runners). Replace it with an adaptive barrier
that hops and collects until the post-GC heap size stops moving, with a
minimum-turn floor matching the fixed count it replaces (React's stream
teardown spans several turns and races a shorter floor).

Also pin collections in request-churn and the aborted-requests drain:
their peak floated on GC scheduling even with bit-identical work (18%
spread on CI for solid churn). Reachable accumulation stays visible to
the metric - a forced collection cannot reclaim leaked or cached objects,
it only removes floating garbage, whose collection timing was the
dominant cross-run noise source. Verified with a synthetic reachable
leak: +4.7% peak over a 0.6% A/A noise floor, where the old 18% noise
would have swallowed it.

Local A/A spreads (3x codspeed run per suite): solid <=1%, react <=2.2%
except request-churn (rare +130KB mode, framework teardown variance),
vue <=2.3% except aborted-requests (~8%, intra-iteration work variance,
down from 21% on CI).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* bench(memory): fixed-count settle barrier, drop adaptive quiescence exit

The adaptive exit (collect until post-GC heap size stops moving) made the
collection points land at data-dependent turns on CI: heap readings never
fully stabilize there, so the exit point - and every subsequent GC point -
shifted between identical runs. The first CI A/A pair showed it flipping
serialization-payload (vue) to a 6MB mode (67%), inflating peak-large-page
(vue) 3.4x, and adding 7-8% swings to the react/vue abort scenarios, while
fixing the solid suite.

Every step is now a fixed count: 16 settle turns (enough for React/Vue
multi-turn teardown that the original 2-turn barrier raced), one pinned
collection, one turn, one more collection for finalizer fallout. Fixed
counts make the GC points identical across runs by construction, which is
the property the barrier exists to provide.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* bench(memory): size iteration counts to the 2-10s measured-run window

On CI (eBPF instrument + --no-opt) one pinned iteration costs ~0.1-0.6s,
so the previous counts put request-churn at ~36s measured and the error
-paths/server-fn benches at 0.1-0.5s - outside the useful 2-10s range in
both directions. Retune: request-churn/aborted-requests/error-paths/
server-fn-churn to 40 iterations, serialization-payload to 12;
peak-large-page and streaming-peak already sit in range at 20.

The floor is raised by pinning error-paths and server-fn-churn rather
than inflating their iteration counts: thousands of unpinned iterations
would cross V8's own GC scheduling and reintroduce the timing noise the
barrier removes, while the pin's fixed per-iteration cost lifts them into
range at 40 iterations and makes their collection points deterministic.

Note: fewer churn iterations proportionally shrink the accumulation
window, so peak-based leak sensitivity drops accordingly; leaks remain
visible in total-allocated (forced compactions re-copy the growing live
set every iteration).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* bench(memory): disable V8 bytecode flushing in memory bench workers

The retuned (shorter) runs exposed a recurring V8 internal event - a
+7-13MB allocation burst with the signature of bytecode flush + lazy
recompile - that lands inside or outside the measured window at random,
flipping peaks by whole MBs between identical CI runs (request-churn vue
785KB vs 3.2MB). The pinned collections age code fast enough for V8 to
flush unused bytecode mid-run; --no-flush-bytecode keeps compiled code
alive for the process lifetime so the measured window sees no recompile
bursts. Vite's mergeConfig concatenates the scenario's test.execArgv with
the flags the CodSpeed plugin injects, so both apply to the fork workers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* bench(memory): pre-size V8 heap geometry in memory bench workers

--no-flush-bytecode alone did not stop the run-to-run flips: the
recurring event is heap-space growth, which allocates several MB at a
run-dependent moment inside the shortened measured windows (error-paths
unmatched vue 674KB vs 2MB, serialization-payload solid resurfacing its
6.4MB attractor on one run in three). Pre-sizing old space and pinning
the semi-space size removes mid-measurement growth while leaving the
per-iteration page map/unmap signal intact - local runs confirm peaks
still track payload sizes exactly (serialization 3.5MB, streaming
30.3MB, levels unchanged).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* bench(memory): size tiny benches just above the 2s measured-run floor

error-paths and server-fn-churn sat at 5-8s measured on CI; fewer
iterations bring them to ~2.3-3.4s, keeping the 2s floor while shrinking
the window a stray allocator event can land in.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* bench(memory): verify the pinned collection against the heap floor

The residual CI flips all share one signature: exactly one iteration's
payload added to the measured peak (serialization-payload vue 3.5 vs
6.9MB, peak-large-page vue 780 vs 1349KB, error-paths redirect vue 300 vs
885KB). On some runners the response teardown holds the payload past the
fixed settle window - released only by a later internal timer - so it
survives the pinned collection and bleeds into the next iteration.

After the fixed 16-turn settle and collection, compare the post-GC heap
against the smallest post-collection size seen this run (the inter-
iteration floor): while it has not returned to the floor, keep hopping
and collecting, bounded at 64 turns. The barrier stays fixed-count in the
common case and extends only in exactly the failure case. Workloads that
genuinely accumulate reachable memory raise the floor as they go, so
accumulation still measures.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* bench(memory): restrict floor verification to peak-shape scenarios

The floor-verified barrier fixed its target - the serialization family
went to <=0.45% across three CI runs, attractor gone - but destabilized
churn/abort scenarios (request-churn solid 420KB vs 3.4MB): their inter-
iteration floor legitimately drifts, so the verification capped out
chronically and the ~48 extra collections per iteration eventually hit a
compaction that double-copies the live set. Split by scenario shape:
serialization-payload, peak-large-page and streaming-peak keep the
verified barrier (flat floor, proven fix); churn and abort scenarios go
back to the plain fixed-count barrier that held them at <=1.7% in the
two previous CI rounds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	benchmarks/client-nav/package.json
#	examples/solid/authenticated-routes-firebase/package.json
#	examples/solid/authenticated-routes/package.json
#	examples/solid/basic-default-search-params/package.json
#	examples/solid/basic-devtools-panel/package.json
#	examples/solid/basic-file-based/package.json
#	examples/solid/basic-non-nested-devtools/package.json
#	examples/solid/basic-solid-query-file-based/package.json
#	examples/solid/basic-solid-query/package.json
#	examples/solid/basic-ssr-file-based/package.json
#	examples/solid/basic-ssr-streaming-file-based/package.json
#	examples/solid/basic-virtual-file-based/package.json
#	examples/solid/basic-virtual-inside-file-based/package.json
#	examples/solid/basic/package.json
#	examples/solid/deferred-data/package.json
#	examples/solid/i18n-paraglide/package.json
#	examples/solid/kitchen-sink-file-based/package.json
#	examples/solid/kitchen-sink-solid-query-file-based/package.json
#	examples/solid/kitchen-sink-solid-query/package.json
#	examples/solid/kitchen-sink/package.json
#	examples/solid/large-file-based/package.json
#	examples/solid/location-masking/package.json
#	examples/solid/navigation-blocking/package.json
#	examples/solid/quickstart-esbuild-file-based/package.json
#	examples/solid/quickstart-file-based/package.json
#	examples/solid/quickstart-rspack-file-based/package.json
#	examples/solid/quickstart-webpack-file-based/package.json
#	examples/solid/quickstart/package.json
#	examples/solid/router-monorepo-simple-lazy/package.json
#	examples/solid/router-monorepo-simple-lazy/packages/router/package.json
#	examples/solid/router-monorepo-simple/package.json
#	examples/solid/router-monorepo-simple/packages/router/package.json
#	examples/solid/router-monorepo-solid-query/package.json
#	examples/solid/router-monorepo-solid-query/packages/router/package.json
#	examples/solid/scroll-restoration/package.json
#	examples/solid/search-validator-adapters/package.json
#	examples/solid/start-basic-auth/package.json
#	examples/solid/start-basic-authjs/package.json
#	examples/solid/start-basic-cloudflare/package.json
#	examples/solid/start-basic-netlify/package.json
#	examples/solid/start-basic-nitro/package.json
#	examples/solid/start-basic-solid-query/package.json
#	examples/solid/start-basic-static/package.json
#	examples/solid/start-basic/package.json
#	examples/solid/start-bun/package.json
#	examples/solid/start-convex-better-auth/package.json
#	examples/solid/start-counter/package.json
#	examples/solid/start-i18n-paraglide/package.json
#	examples/solid/start-large/package.json
#	examples/solid/start-streaming-data-from-server-functions/package.json
#	examples/solid/start-supabase-basic/package.json
#	examples/solid/start-tailwind-v4/package.json
#	examples/solid/view-transitions/package.json
#	examples/solid/with-framer-motion/package.json
#	examples/solid/with-trpc/package.json
#	package.json
#	packages/solid-router/CHANGELOG.md
#	packages/solid-router/package.json
#	packages/solid-start-client/CHANGELOG.md
#	packages/solid-start-client/package.json
#	packages/solid-start-server/CHANGELOG.md
#	packages/solid-start-server/package.json
#	packages/solid-start/CHANGELOG.md
#	packages/solid-start/package.json
#	pnpm-lock.yaml
#	pnpm-workspace.yaml
@brenelz brenelz requested a review from a team as a code owner July 4, 2026 11:26
@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: aa31ecc2-c17e-4190-8c4a-7db8e5887d4c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@nx-cloud

nx-cloud Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit 2bb318b

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 5m 48s View ↗

☁️ Nx Cloud last updated this comment at 2026-07-04 16:35:09 UTC

@socket-security

socket-security Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednitro-nightly@​3.0.1-20260702-173353-03122331791008296100
Addedjsdom@​29.1.18110010090100
Added@​rsbuild/​core@​2.0.141001008598100
Addedbetter-auth@​1.6.19981008596100
Added@​arethetypeswrong/​cli@​0.18.410010010089100

View full report

@socket-security

socket-security Bot commented Jul 4, 2026

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm @emnapi/runtime is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: pnpm-lock.yamlnpm/nitro@3.0.260311-betanpm/wrangler@4.75.0npm/@cloudflare/vite-plugin@1.29.1npm/nitro-nightly@3.0.1-20260702-173353-03122331npm/@emnapi/runtime@1.11.1

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@emnapi/runtime@1.11.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm css-tree is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: pnpm-lock.yamlnpm/jsdom@29.1.1npm/css-tree@3.2.1

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/css-tree@3.2.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm data-urls is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: pnpm-lock.yamlnpm/jsdom@29.1.1npm/data-urls@7.0.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/data-urls@7.0.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm env-runner is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: pnpm-lock.yamlnpm/nitro-nightly@3.0.1-20260702-173353-03122331npm/env-runner@0.1.16

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/env-runner@0.1.16. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm jsdom is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: benchmarks/memory/client/package.jsonnpm/jsdom@29.1.1

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/jsdom@29.1.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm jsdom is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: benchmarks/memory/client/package.jsonnpm/jsdom@29.1.1

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/jsdom@29.1.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Medium
Low adoption: npm ocache

Location: Package overview

From: pnpm-lock.yamlnpm/nitro-nightly@3.0.1-20260702-173353-03122331npm/ocache@0.1.5

ℹ Read more on: This package | This alert | What are unpopular packages?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Unpopular packages may have less maintenance and contain other problems.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/ocache@0.1.5. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@codspeed-hq

codspeed-hq Bot commented Jul 4, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 54.53%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 5 improved benchmarks
🆕 161 new benchmarks
⏩ 1 skipped benchmark1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation ssr request loop (react) 330.5 ms 77.9 ms ×4.2
Simulation ssr request loop (vue) 420.3 ms 283.8 ms +48.11%
Simulation ssr request loop (solid) 174.6 ms 150.1 ms +16.38%
Simulation client-side navigation loop (react) 56.3 ms 50.3 ms +11.81%
Simulation client-side navigation loop (vue) 83 ms 77 ms +7.74%
🆕 Simulation ssr not-found (solid) N/A 85.4 ms N/A
🆕 Simulation ssr redirect (solid) N/A 59.2 ms N/A
🆕 Simulation ssr head (solid) N/A 105.5 ms N/A
🆕 Simulation ssr loaders (solid) N/A 86.4 ms N/A
🆕 Simulation ssr selective (solid) N/A 87.2 ms N/A
🆕 Simulation ssr server-fn GET (solid) N/A 69.7 ms N/A
🆕 Simulation ssr server-fn POST (solid) N/A 64.2 ms N/A
🆕 Simulation ssr server-route middleware (solid) N/A 56.9 ms N/A
🆕 Simulation ssr server-route (solid) N/A 55.8 ms N/A
🆕 Simulation ssr streaming deferred (solid) N/A 79.9 ms N/A
🆕 Simulation ssr assets inline-css cdn (solid) N/A 80.6 ms N/A
🆕 Simulation ssr assets linked-css control (solid) N/A 96.8 ms N/A
🆕 Simulation ssr before-load chain (solid) N/A 101.1 ms N/A
🆕 Simulation ssr control-flow error 500 (solid) N/A 100.8 ms N/A
🆕 Simulation ssr control-flow route headers (solid) N/A 113.1 ms N/A
... ... ... ... ... ...

ℹ️ Only the first 20 benchmarks are displayed. Go to the app to view all benchmarks.

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing brenelz:merge-main-into-solid-v2-pre (26d94d9) with solid-router-v2-pre (67a9040)2

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

  2. No successful run was found on solid-router-v2-pre (0e4f15d) during the generation of this report, so 67a9040 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

pnpm install --lockfile-only on darwin-arm64 dropped all other platform
optionalDependencies for @rspack/binding@2.0.8, causing the bundle-size
benchmark on Linux CI to fall back to a stale 2.0.0 binding
("Unmatched version @rspack/core@2.0.8 and @rspack/binding@2.0.0").
Restored the full platform list to match main's lockfile.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pkg-pr-new

pkg-pr-new Bot commented Jul 4, 2026

Copy link
Copy Markdown
More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/@tanstack/arktype-adapter@7746

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/@tanstack/eslint-plugin-router@7746

@tanstack/eslint-plugin-start

npm i https://pkg.pr.new/@tanstack/eslint-plugin-start@7746

@tanstack/history

npm i https://pkg.pr.new/@tanstack/history@7746

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/@tanstack/nitro-v2-vite-plugin@7746

@tanstack/react-router

npm i https://pkg.pr.new/@tanstack/react-router@7746

@tanstack/react-router-devtools

npm i https://pkg.pr.new/@tanstack/react-router-devtools@7746

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/@tanstack/react-router-ssr-query@7746

@tanstack/react-start

npm i https://pkg.pr.new/@tanstack/react-start@7746

@tanstack/react-start-client

npm i https://pkg.pr.new/@tanstack/react-start-client@7746

@tanstack/react-start-rsc

npm i https://pkg.pr.new/@tanstack/react-start-rsc@7746

@tanstack/react-start-server

npm i https://pkg.pr.new/@tanstack/react-start-server@7746

@tanstack/router-cli

npm i https://pkg.pr.new/@tanstack/router-cli@7746

@tanstack/router-core

npm i https://pkg.pr.new/@tanstack/router-core@7746

@tanstack/router-devtools

npm i https://pkg.pr.new/@tanstack/router-devtools@7746

@tanstack/router-devtools-core

npm i https://pkg.pr.new/@tanstack/router-devtools-core@7746

@tanstack/router-generator

npm i https://pkg.pr.new/@tanstack/router-generator@7746

@tanstack/router-plugin

npm i https://pkg.pr.new/@tanstack/router-plugin@7746

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/@tanstack/router-ssr-query-core@7746

@tanstack/router-utils

npm i https://pkg.pr.new/@tanstack/router-utils@7746

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/@tanstack/router-vite-plugin@7746

@tanstack/solid-router

npm i https://pkg.pr.new/@tanstack/solid-router@7746

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/@tanstack/solid-router-devtools@7746

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/@tanstack/solid-router-ssr-query@7746

@tanstack/solid-start

npm i https://pkg.pr.new/@tanstack/solid-start@7746

@tanstack/solid-start-client

npm i https://pkg.pr.new/@tanstack/solid-start-client@7746

@tanstack/solid-start-server

npm i https://pkg.pr.new/@tanstack/solid-start-server@7746

@tanstack/start-client-core

npm i https://pkg.pr.new/@tanstack/start-client-core@7746

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/@tanstack/start-fn-stubs@7746

@tanstack/start-plugin-core

npm i https://pkg.pr.new/@tanstack/start-plugin-core@7746

@tanstack/start-server-core

npm i https://pkg.pr.new/@tanstack/start-server-core@7746

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/@tanstack/start-static-server-functions@7746

@tanstack/start-storage-context

npm i https://pkg.pr.new/@tanstack/start-storage-context@7746

@tanstack/valibot-adapter

npm i https://pkg.pr.new/@tanstack/valibot-adapter@7746

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/@tanstack/virtual-file-routes@7746

@tanstack/vue-router

npm i https://pkg.pr.new/@tanstack/vue-router@7746

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/@tanstack/vue-router-devtools@7746

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/@tanstack/vue-router-ssr-query@7746

@tanstack/vue-start

npm i https://pkg.pr.new/@tanstack/vue-start@7746

@tanstack/vue-start-client

npm i https://pkg.pr.new/@tanstack/vue-start-client@7746

@tanstack/vue-start-server

npm i https://pkg.pr.new/@tanstack/vue-start-server@7746

@tanstack/zod-adapter

npm i https://pkg.pr.new/@tanstack/zod-adapter@7746

commit: 2bb318b

main's new client-nav scenarios and memory benchmarks were written for
Solid 1.x and fail against this branch's Solid 2 toolchain:

- import render/HydrationScript from @solidjs/web instead of solid-js/web
- memory benchmark manifests: solid-js 2.0.0-beta.15, @solidjs/web,
  vite-plugin-solid ^3.0.0-next.5 (matching client-nav)
- Suspense -> Loading, and createResource -> router Await in the
  memory-server solid scenarios
- skip the streaming-peak solid bench: Solid 2's renderToStream emits
  </body></html> with the shell and streams deferred Loading content
  after it, so router-core's transformStreamWithRouter tail-buffers the
  ~200 kB of deferred sections and throws 'SSR stream tail exceeded
  maximum buffer' (MAX_TAIL_CHARS = 64 kB). Needs a transformer-level
  fix on this branch before the scenario can run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@brenelz

brenelz commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Two rounds of CI fixes pushed:

`01dbb52` — bundle-size build failure (`Unmatched version @rspack/core@2.0.8 and @rspack/binding@2.0.0`): regenerating the lockfile with `pnpm install --lockfile-only` on darwin-arm64 dropped every non-local platform binary from `@rspack/binding@2.0.8`'s `optionalDependencies`, so Linux CI fell back to a stale 2.0.0 binding. Restored the full platform list to match main's lockfile. Note: pnpm 11.9.0 reproducibly re-prunes these entries on any local re-resolve, so this may bite again on future lockfile updates on this branch.

`26d94d9` — solid CodSpeed job failures: main's new client-nav scenarios and memory benchmarks are written for Solid 1.x. Adapted them to this branch's Solid 2 toolchain (@solidjs/web imports, v2 deps in the memory manifests, SuspenseLoading, createResource → router Await). All solid benchmark builds and benches now pass locally, except one:

⚠️ `streaming-peak` (solid) is skipped, and it exposes what looks like a real issue on this branch: Solid 2's `renderToStream` emits `` at the end of the initial shell and streams deferred `Loading`-boundary HTML after it. `transformStreamWithRouter` assumes deferred content arrives before `` (true for React/Vue), so it tail-buffers all post-shell Solid chunks — capped at `MAX_TAIL_CHARS = 64 kB` — and throws `SSR stream tail exceeded maximum buffer` once the scenario's ~200 kB of deferred sections arrive. Smaller payloads don't crash but are held until stream end, so Solid streaming SSR is effectively buffered rather than progressive through the transformer. Verified empirically against the built scenario server: shell + fallbacks flush, seroval payload scripts flush, then the transformer dies at the third deferred app chunk.

🤖 Generated with Claude Code

nx-cloud[bot]

This comment was marked as outdated.

- jsxImportSource solid-js -> @solidjs/web in the new scenario
  tsconfigs (Solid 2's JSX types moved; with the old value tsc fell
  back to React's JSX namespace and rejected solid components)
- createRenderEffect one-arg calls -> v2 (compute, effect) signature
  in the loaders, search-params, and nested-params solid scenarios,
  matching the existing client-nav solid app

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@nx-cloud nx-cloud Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Important

At least one additional CI pipeline execution has run since the conclusion below was written and it may no longer be applicable.

Nx Cloud has identified a possible root cause for your failed CI:

We observed that the prerender phase successfully crawled 46 pages before failing with a HeadersTimeoutError (UND_ERR_HEADERS_TIMEOUT), indicating the local SSR server became unresponsive mid-run rather than failing due to a specific code change. Our analysis found no reference to changed code in the error, no similar failures on other branches, and a pattern consistent with transient CI resource exhaustion — a re-run should resolve this.

No code changes were suggested for this issue.

You can trigger a rerun by pushing an empty commit:

git commit --allow-empty -m "chore: trigger rerun"
git push

Nx Cloud View detailed reasoning on Nx Cloud ↗


🎓 Learn more about Self-Healing CI on nx.dev

@brenelz

brenelz commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Re-ran the failed `Test` job. The only real failure was `tanstack-solid-start-e2e-basic:build:vite:prerender`, which died with `UND_ERR_HEADERS_TIMEOUT` after prerendering 46/52 pages — one page's SSR (looks like `/deferred`) never returned response headers within undici's 5-minute cap.

Analysis suggests this is a pre-existing load-sensitive race, not a merge regression:

  • The merge changes nothing in the vite prerender path — no `start-plugin-core/prerender`, no `router-core/ssr`, no solid-start source changes, and identical `srvx`/`h3`/`isbot`/`seroval` versions in the lockfile.
  • `/deferred` responds reliably in isolation (15/15 runs, ~2 s each) against the built `dist-vite-prerender` server.
  • Locally the full prerender is fine on an idle machine but intermittently hangs or drops pages (47/52) when the machine is under heavy load — consistent with a slow CI agent hitting it.

Mechanism worth noting: prerender requests carry no User-Agent, so `isbot` treats them as bots and `renderRouterToStream` awaits Solid's full-ready promise before sending headers. If Solid 2's all-ready promise loses a race under load, the response never starts and the whole build times out. Possibly related to the streaming/tail issue described above.

🤖 Generated with Claude Code

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.

5 participants