Skip to content

fix(web): delegated dispatch restores currentTarget and target (no try) - #4325

Merged
ryansolid merged 5 commits into
nextfrom
fix/delegated-event-restore-v2
Oct 27, 2026
Merged

ryansolid merged 5 commits into
nextfrom
fix/delegated-event-restore-v2

Conversation

@ryansolid

Copy link
Copy Markdown
Member

Supersedes #4311 and keeps brenelz's commit. The only change is that the restore no longer uses try/finally.

Before: Solid delegates events at the render root, so a native listener on document, window or an element above the root read the last node Solid walked as currentTarget.

After: Once its walk ends, delegated dispatch deletes its currentTarget and target overrides. Listeners that run later in the same dispatch see the native getters.

How: this is #4311 with the try/finally dropped. A throwing handler is an error path that already gets reported, and the try cost 13 B minified in every client scenario. The fix is now +23 B minified, down from +36 B. The test for a throwing handler is removed, and the other new tests stay, including the two test.fails cases that record the existing re-dispatch bug.

Size: app: hydrating + every store primitive family and page: live server components fail the gate here because next has no minified allowance left on those scenarios. Ryan approved raising those caps. A separate PR raises them for this fix and #4310 together, and this PR re-runs the gate once that lands. Hello world (app: compiled floor) stays under 10 KB.

Tests:

  • web: 1445 pass. The 4 failures are uncommitted-input-overwritten, which also fails on next in this container.
  • hydrate: 614 pass.

Generated by Claude Code

brenelz and others added 4 commits October 26, 2026 20:25
A throwing handler is an error path that is already reported, and the
try costs 13 B in every client scenario.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018LY7F9czoRqdMEvk2QwPr1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018LY7F9czoRqdMEvk2QwPr1
@changeset-bot

changeset-bot Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 48089a0

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 15 packages
Name Type
@solidjs/web Patch
@solidjs/babel-plugin Patch
@solidjs/diagnostics Patch
@solidjs/element Patch
@solidjs/h Patch
@solidjs/html Patch
test-integration Patch
board-example Patch
canvas-example Patch
server-dbmon-example Patch
todos-server-example Patch
@solidjs/compiler Patch
@solidjs/signals Patch
solid-js Patch
@solidjs/universal Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Size (brotli, eager entry chunk)

scenario head vs base minified vs base minified vs recorded cap lazy chunks (not counted)
signals: core floor (createSignal/Memo/Effect/Root/flush) 7.42 KB 0 B 0 B −119 B 7.44 KB ✅
signals: + createStore 14.87 KB 0 B 0 B −1463 B 15.04 KB ✅
signals: + isPending/latest 10.38 KB 0 B 0 B −8 B 10.38 KB ✅
signals: + until/refresh (truth readers, no optimism) 8.05 KB 0 B 0 B −123 B 8.05 KB ✅
app: render + one signal (the simple-app floor) 9.78 KB +4 B (+0.0%) +23 B −179 B 9.75 KB ⚠️ over by 26 B, 199 B minified headroom
app: hydrating (no stores) with Show/For/Loading/Errored/lazy 18.59 KB 0 B +23 B −252 B 18.49 KB ⚠️ over by 96 B, 272 B minified headroom lazy-page.js 0.04 KB
app: hydrating + every store primitive family 31.00 KB +45 B (+0.1%) +23 B −68 B 30.96 KB ⚠️ over by 40 B, 88 B minified headroom lazy-page.js 0.04 KB
app: CSR with Show/For/Loading/Errored/lazy 13.36 KB −9 B (−0.1%) +23 B −258 B 13.40 KB ✅ lazy-page.js 0.04 KB
app: CSR, observe tier (same app on the observe artifacts) 15.12 KB +7 B (+0.0%) +23 B −264 B 15.14 KB ✅ lazy-page.js 0.04 KB
app: CSR, observe tier + attribution engine enabled 29.66 KB −11 B (−0.0%) +23 B −262 B 29.70 KB ✅ lazy-page.js 0.04 KB
app: compiled floor (one template, one text hole, one delegated click) 9.97 KB +4 B (+0.0%) +23 B −178 B 9.93 KB ⚠️ over by 38 B, 198 B minified headroom
app: compiled CSR (JSX todo app: spread/merge/omit, events, class/style, keyed For, Show, Loading + lazy, store) 26.12 KB +1 B (+0.0%) +23 B −808 B 26.27 KB ✅ stats.js 0.18 KB
app: compiled hydrating (the same JSX todo app through hydrate(), compiled hydratable) 32.23 KB +3 B (+0.0%) +23 B −736 B 32.25 KB ✅ stats.js 0.20 KB
frames: eager client consumer (frames client + transport, lazy codec) 11.75 KB 0 B 0 B 0 B 11.76 KB ✅
page: base server components (hydrating + dynamic + frames + sf reference) 33.50 KB +16 B (+0.0%) +23 B −249 B 33.37 KB ⚠️ over by 131 B, 269 B minified headroom assets.js 0.78 KB, decode.js 7.09 KB, lazy-page.js 0.04 KB, regions.js 1.06 KB, trace.js 8.92 KB, wire.js 3.47 KB
page: live server components (base + live/GET + action + isPending/latest) 37.88 KB −46 B (−0.1%) +23 B −51 B 37.75 KB ⚠️ over by 134 B, 71 B minified headroom assets.js 0.78 KB, decode.js 7.09 KB, lazy-page.js 0.04 KB, regions.js 1.06 KB, trace.js 8.93 KB, wire.js 3.47 KB
page: compiled base server components (the base page as JSX: templates with class/style/attributes/events, For/Show; no spread) 35.53 KB +48 B (+0.1%) +23 B −232 B 35.43 KB ⚠️ over by 103 B, 252 B minified headroom assets.js 0.78 KB, decode.js 7.09 KB, regions.js 1.06 KB, sc-comments.js 0.20 KB, trace.js 8.94 KB, wire.js 3.47 KB
page: compiled live server components (the compiled base page + live/GET + action + isPending/latest) 41.79 KB −14 B (−0.0%) +23 B −55 B 41.56 KB ⚠️ over by 233 B, 75 B minified headroom eager (counted): web.js 22.35 KB; assets.js 0.78 KB, decode.js 7.09 KB, regions.js 1.06 KB, sc-comments.js 0.19 KB, trace.js 8.94 KB, wire.js 3.47 KB
page: base + router (base page + @solidjs/router: createRouter, two routes, preload, useNavigate) 40.95 KB −92 B (−0.2%) +23 B −243 B 40.81 KB ⚠️ over by 141 B, 263 B minified headroom assets.js 0.78 KB, decode.js 7.09 KB, lazy-page.js 0.04 KB, regions.js 1.06 KB, server.js 1.03 KB, serverForms.js 3.58 KB, trace.js 8.97 KB, wire.js 3.48 KB
page: live + router (live page + @solidjs/router: createRouter, two routes, preload, useNavigate) 47.40 KB +90 B (+0.2%) +23 B −61 B 47.16 KB ⚠️ over by 238 B, 81 B minified headroom eager (counted): client.js 27.50 KB; assets.js 0.78 KB, decode.js 7.09 KB, lazy-page.js 0.04 KB, regions.js 1.07 KB, server.js 1.03 KB, serverForms.js 3.32 KB, trace.js 8.95 KB, wire.js 3.49 KB
server: floor (getRequestEvent + isServer) 1.27 KB 0 B 0 B −69 B 1.34 KB ✅
server: renderToString (the server-render floor) 22.79 KB 0 B 0 B 0 B 22.80 KB ✅

⚠️ Over the brotli cap within the minified allowance (passes)

  • app: render + one signal (the simple-app floor): over brotli cap by 26 B; minified 26,850 B vs 27,029 B recorded with the cap (−179 B) — 199 B of the 20 B minified allowance left; +23 B minified over this PR's base
  • app: hydrating (no stores) with Show/For/Loading/Errored/lazy: over brotli cap by 96 B; minified 53,368 B vs 53,620 B recorded with the cap (−252 B) — 272 B of the 20 B minified allowance left; +23 B minified over this PR's base
  • app: hydrating + every store primitive family: over brotli cap by 40 B; minified 95,079 B vs 95,147 B recorded with the cap (−68 B) — 88 B of the 20 B minified allowance left; +23 B minified over this PR's base
  • app: compiled floor (one template, one text hole, one delegated click): over brotli cap by 38 B; minified 27,382 B vs 27,560 B recorded with the cap (−178 B) — 198 B of the 20 B minified allowance left; +23 B minified over this PR's base
  • page: base server components (hydrating + dynamic + frames + sf reference): over brotli cap by 131 B; minified 101,310 B vs 101,559 B recorded with the cap (−249 B) — 269 B of the 20 B minified allowance left; +23 B minified over this PR's base
  • page: live server components (base + live/GET + action + isPending/latest): over brotli cap by 134 B; minified 115,166 B vs 115,217 B recorded with the cap (−51 B) — 71 B of the 20 B minified allowance left; +23 B minified over this PR's base
  • page: compiled base server components (the base page as JSX: templates with class/style/attributes/events, For/Show; no spread): over brotli cap by 103 B; minified 107,686 B vs 107,918 B recorded with the cap (−232 B) — 252 B of the 20 B minified allowance left; +23 B minified over this PR's base
  • page: compiled live server components (the compiled base page + live/GET + action + isPending/latest): over brotli cap by 233 B; minified 123,161 B vs 123,216 B recorded with the cap (−55 B) — 75 B of the 20 B minified allowance left; +23 B minified over this PR's base
  • page: base + router (base page + @solidjs/router: createRouter, two routes, preload, useNavigate): over brotli cap by 141 B; minified 125,144 B vs 125,387 B recorded with the cap (−243 B) — 263 B of the 20 B minified allowance left; +23 B minified over this PR's base
  • page: live + router (live page + @solidjs/router: createRouter, two routes, preload, useNavigate): over brotli cap by 238 B; minified 140,419 B vs 140,480 B recorded with the cap (−61 B) — 81 B of the 20 B minified allowance left; +23 B minified over this PR's base

Bundled with Rolldown (what Vite ships), brotli q11, decimal KB. A scenario fails only when it is over its brotli cap and its minified size is more than 20 B over the minified recorded with the cap; over the cap within that allowance is brotli layout noise and passes with a warning. Caps and their recorded minified in scripts/size/scenarios.js; the floor and page caps in floor-caps.json are frozen (lower only, or Size-Exception: in the PR body). npm run ratchet lowers caps per RC; it never raises one (scripts/size/README.md).

Copy link
Copy Markdown
Member Author

The check failure is the size gate, as expected. It fails on app: hydrating + every store primitive family (+39 B minified vs recorded) and page: live server components (+26 B). next had no allowance left on either scenario. The cap raise Ryan approved is on branch size/caps-4310-4325. It opens as a PR once #4319 merges, because it builds on #4319's re-record. After it lands, this PR picks up next and the gate re-runs. Locally the gate passes on next + #4319 + #4310 + this PR with those caps.


Generated by Claude Code

@coveralls

coveralls commented Oct 27, 2026 •

Copy link
Copy Markdown

Coverage Report for CI Build 40544687485

Coverage remained the same at 78.727%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 1357
Covered Lines: 1127
Line Coverage: 83.05%
Relevant Branches: 1078
Covered Branches: 790
Branch Coverage: 73.28%
Branches in Coverage %: Yes
Coverage Strength: 28.36 hits per line

💛 - Coveralls

@codspeed

codspeed Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Merging this PR will improve performance by 5.93%

2 warnings

⚠️ 4 benchmarks are dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

⚠️ Base and head ran on different runner types

Some benchmarks with significant performance changes were compared across different runner types, so the changes might not come from the code. Run base and head on the same runner type, or use CodSpeed Macro Runners for more stable results.

Learn more about Macro Runners

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
✅ 195 untouched benchmarks
⏩ 5 skipped benchmarks1

Performance Changes

Benchmark BASE HEAD Efficiency
⚡ build 139.8 µs 132 µs +5.93%

Tip

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


Comparing fix/delegated-event-restore-v2 (48089a0) with next (b1b0667)

Open in CodSpeed

Footnotes

  1. 5 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

ryansolid pushed a commit that referenced this pull request Oct 27, 2026
Re-records the four scenarios the store fold stamp (#4310) and the
delegated currentTarget/target restore (#4325) push past their minified
allowance, measured over next with #4319.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018LY7F9czoRqdMEvk2QwPr1

Copy link
Copy Markdown
Member Author

The CodSpeed −5.5% is on props chain depth 1 › build in packages/signals, and this PR only changes packages/web/src/client.ts. CodSpeed itself warns that base and head ran on different runner types, and this bench swings by about ±5% from runner type alone. It isn't this PR's change, so I'm leaving it.


Generated by Claude Code

@ryansolid
ryansolid merged commit 76e9094 into next Oct 27, 2026
8 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.

4 participants