Commit 76b09e5
committed
fix(EffectComposer): fix StrictMode composer leak, guard against r3f reorder bug
EffectComposerImpl was created inside useMemo, which doesn't guarantee
its cleanup runs before React discards a memoized value - this leaked
the composer (and its WebGL resources) under StrictMode. It's now
created and disposed inside a useState/useEffect lifecycle instead.
Pass collection walks the real r3f instance tree (group.current.__r3f
.children) and rebuilds the pass list from scratch whenever it or the
composer changes, so the order always matches current JSX - including
through wrapper components - after a reorder or a remount.
While testing the reorder case, found a genuine bug in r3f's host
config: when React moves (not remounts) an existing child - e.g. a
key-preserving reorder of a keyed effect list - insertBefore/
appendChild splice the moved instance into its new slot without
detaching it from the old one first, leaving a stale duplicate in
Instance.children. Worth reporting upstream. Added a cheap dedupe
(keep each object's last occurrence, sorted by that position) that
recovers the correct order either way and is a no-op when the bug
isn't present.
Also widens `children` from JSX.Element | JSX.Element[] to ReactNode,
which was rejecting the common `condition && <Effect/>` idiom (that
expression is `false | Element`, and `false` isn't assignable to
either half of the union). The tree-walk already tolerates arbitrary
children gracefully - it just filters for `instanceof Effect ||
instanceof Pass` - so the stricter type wasn't buying any actual
safety.
Replaces the old root-level EffectComposer.test.tsx (superseded,
predates this suite and used a different mock-root setup) with a
suite covering pass registration/composition order, StrictMode
disposal, and the reorder/dedupe behavior above. (ColorAverage-specific
dispose coverage lands with the primitive-effect dispose fix, a few
commits later - ColorAverage doesn't dispose itself until then.)1 parent e018959 commit 76b09e5
3 files changed
Lines changed: 842 additions & 275 deletions
This file was deleted.
0 commit comments