| 39 | |
| 40 | // Targets: handles in `nodes[]`, listeners in `bindings[]`, running `animations[]` rooted in `el` (inclusive). Slots nulled, not spliced. |
| 41 | const cleanSubtree = (el) => { |
| 42 | const all = new Set([el, ...el.querySelectorAll('*')]); |
| 43 | for (const e of all) { |
| 44 | const set = handleByEl.get(e); |
| 45 | if (set) { |
| 46 | for (const h of set) nodes[h] = null; |
| 47 | handleByEl.delete(e); |
| 48 | } |
| 49 | } |
| 50 | for (let i = 0; i < bindings.length; i++) { |
| 51 | const b = bindings[i]; |
| 52 | if (b && all.has(b.target)) { |
| 53 | b.target.removeEventListener(b.type, b.listener, { capture: b.capture }); |
| 54 | bindings[i] = null; |
| 55 | } |
| 56 | } |
| 57 | for (let i = 0; i < animations.length; i++) { |
| 58 | const a = animations[i]; |
| 59 | if (a && a.effect && all.has(a.effect.target)) { |
| 60 | a.cancel(); |
| 61 | animations[i] = null; |
| 62 | } |
| 63 | } |
| 64 | }; |
| 65 | |
| 66 | return { |
| 67 | nodes, bindings, intersectionObservers, resizeObservers, mutationObservers, |