Commit activity
Last 12 weeks · 134 commits
Community health
6 of 6 standards met
Recent PRs & issues
Describe the bug Just a heads up, an LLM was used to discover, isolate the bug - and to create this bug report. However, I was supervising it personally and reviewed/edited what it produced. The repro test case also shows the leak. When a child component uses that reads a reactive prop from its parent, destroying the child does not properly clean up the effect's subscription. This causes detached DOM trees to accumulate in memory indefinitely. The leak requires two things in the child component: 1. that reads a prop (subscribes to parent's reactive graph) 2. (puts a DOM element reference into the same closure scope) When the child is destroyed, the 's subscription to the parent's reactive source is not removed. The effect closure shares a V8 scope context with the variable, which holds a reference to the now-detached DOM element. Since the parent is still mounted, its reactive graph keeps the stale subscription alive: This appears to be the counterpart to #11817, which fixed the same issue for (incomplete disconnection from the reactivity graph on component destruction). The fix in PR #11819 added bookkeeping to properly remove derived signals from dependency reaction arrays — likely needs the same treatment. Discovered while debugging the timeline in Immich, where scrolling through photos grew the heap from 42MB to 446MB with 200K+ detached DOM nodes. Reproduction Child.svelte App.svelte Svelte Playground (note: Performance Monitor won't show the leak in the playground iframe — clone and run locally to verify with DevTools) Steps to reproduce 1. Open Chrome DevTools → Performance Monitor (or take heap snapshots) 2. Click "Toggle" repeatedly (each click destroys and recreates 100 Child components) 3. Observe DOM node count increasing monotonically, never returning to baseline Expected behaviour DOM node count should return to baseline after each toggle cycle. Destroyed components should be fully garbage collected. Actual behaviour Each toggle cycle leaks ~327 detached DOM nodes (with 100 children). After 10 cycles: 413 → 3,682 detached nodes. Growth is linear and unbounded. Removing either the or the eliminates the leak — both are needed to trigger it. Isolation results | Plain `bind:this$effect$effectbind:this$effect$derived$effect` likely needs the same fix. #13524 — Detached nodes memory leak. Closed as a Chrome regression, but my retention chain analysis points to a Svelte-level cause (tested on Chrome only so far). Logs System Info Severity annoyance
The rough idea: When the batch that created the async derived has its run aborted/obsoleted, or it's a fork that is discarded, we know which next one to hand the "resolve this" to. The second idea: have a global variable that is set in run, then picked up in async_derived, and async_derived will tell run through this which batch is the one that was resolved with, so it continues in that batch (this ensures run switches to the correct batch when the creator was superseeded)
~~Follow-up to #19270. Draft because I don't love the new parameter to , or the addition of a flag (we are running out of space in the bitmask)~~ We say that two batches _intersect_ if they both write to the same sources (or writable deriveds). Currently, the logic is slightly faulty — #19234 clarified that async deriveds should not be treated as sources (even though they're implemented as such), but the intersection logic behaves as though they should. The same is true for each item/index sources. This PR fixes it by using the flag consistently across sources and deriveds. It also fixes a bug around async deriveds that are written to
Recent fixes
We say that two batches _intersect_ if they both write to the same sources (or writable deriveds). Currently, the logic is slightly faulty — #19234 clarified that async deriveds should not be treated as sources (even though they're implemented as such), but the intersection logic behaves as though they should. This PR fixes it with . It also tweaks the and logic accordingly. A follow-up PR will apply the same idea to block items (and their indices), which should also be treated as computed.
Repository: sveltejs/svelte. Description: web development for the rest of us Stars: 88753, Forks: 6054. Primary language: JavaScript. Languages: JavaScript (70.6%), Svelte (22.4%), TypeScript (5%), CSS (1.1%), HTML (0.8%). License: MIT. Homepage: https://svelte.dev Topics: compiler, template, ui. Latest release: svelte@5.57.3 (2w ago). Open PRs: 100, open issues: 1206. Last activity: 1h ago. Community health: 87%. Top contributors: Rich-Harris, dummdidumm, Conduitry, github-actions[bot], trueadm, tanhauhau, paoloricciuti, benmccann, PuruVJ, baseballyama and others.