Skip to content

Fix effect-flushing for radix and animations#5163

Open
JoviDeCroock wants to merge 3 commits into
mainfrom
JoviDeCroock/investigate-3666
Open

Fix effect-flushing for radix and animations#5163
JoviDeCroock wants to merge 3 commits into
mainfrom
JoviDeCroock/investigate-3666

Conversation

@JoviDeCroock

Copy link
Copy Markdown
Member

Fixes #3666.

Flushes pending passive effects before scheduled renders.

Fixes the Radix Slider reproduction and the Base UI + Motion exit-animation reproduction from #5055.

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown

📊 Tachometer Benchmark Results

Summary

duration

  • create10k: unsure 🔍 -0% - +1% (-2.21ms - +10.10ms)
    preact-local vs preact-main
  • filter-list: unsure 🔍 -0% - +1% (-0.07ms - +0.13ms)
    preact-local vs preact-main
  • hydrate1k: faster ✔ 0% - 3% (0.10ms - 1.85ms)
    preact-local vs preact-main
  • many-updates: unsure 🔍 -1% - +0% (-0.12ms - +0.02ms)
    preact-local vs preact-main
  • replace1k: unsure 🔍 -0% - +4% (-0.04ms - +1.94ms)
    preact-local vs preact-main
  • text-update: unsure 🔍 -3% - +6% (-0.06ms - +0.12ms)
    preact-local vs preact-main
  • todo: unsure 🔍 -2% - +3% (-0.54ms - +1.05ms)
    preact-local vs preact-main
  • update10th1k: unsure 🔍 -3% - +4% (-1.00ms - +1.53ms)
    preact-local vs preact-main

usedJSHeapSize

  • create10k: unsure 🔍 -0% - +0% (-0.00ms - +0.00ms)
    preact-local vs preact-main
  • filter-list: unsure 🔍 -0% - +0% (-0.00ms - +0.00ms)
    preact-local vs preact-main
  • hydrate1k: unsure 🔍 -4% - +0% (-0.23ms - +0.02ms)
    preact-local vs preact-main
  • many-updates: unsure 🔍 -0% - +0% (-0.00ms - +0.00ms)
    preact-local vs preact-main
  • replace1k: unsure 🔍 -0% - +0% (-0.00ms - +0.00ms)
    preact-local vs preact-main
  • text-update: unsure 🔍 -0% - +5% (-0.00ms - +0.05ms)
    preact-local vs preact-main
  • todo: unsure 🔍 -0% - +0% (-0.00ms - +0.00ms)
    preact-local vs preact-main
  • update10th1k: unsure 🔍 -0% - +0% (-0.01ms - +0.01ms)
    preact-local vs preact-main

Results

create10k

duration

VersionAvg timevs preact-localvs preact-main
preact-local689.93ms - 700.27ms-unsure 🔍
-0% - +1%
-2.21ms - +10.10ms
preact-main687.81ms - 694.50msunsure 🔍
-1% - +0%
-10.10ms - +2.21ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local19.08ms - 19.08ms-unsure 🔍
-0% - +0%
-0.00ms - +0.00ms
preact-main19.07ms - 19.08msunsure 🔍
-0% - +0%
-0.00ms - +0.00ms
-
filter-list

duration

VersionAvg timevs preact-localvs preact-main
preact-local16.48ms - 16.67ms-unsure 🔍
-0% - +1%
-0.07ms - +0.13ms
preact-main16.51ms - 16.59msunsure 🔍
-1% - +0%
-0.13ms - +0.07ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local1.55ms - 1.55ms-unsure 🔍
-0% - +0%
-0.00ms - +0.00ms
preact-main1.55ms - 1.55msunsure 🔍
-0% - +0%
-0.00ms - +0.00ms
-
hydrate1k

duration

VersionAvg timevs preact-localvs preact-main
preact-local56.72ms - 57.80ms-faster ✔
0% - 3%
0.10ms - 1.85ms
preact-main57.55ms - 58.92msslower ❌
0% - 3%
0.10ms - 1.85ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local5.00ms - 5.01ms-unsure 🔍
-4% - +0%
-0.23ms - +0.02ms
preact-main4.98ms - 5.23msunsure 🔍
-0% - +5%
-0.02ms - +0.23ms
-
many-updates

duration

VersionAvg timevs preact-localvs preact-main
preact-local16.45ms - 16.57ms-unsure 🔍
-1% - +0%
-0.12ms - +0.02ms
preact-main16.53ms - 16.60msunsure 🔍
-0% - +1%
-0.02ms - +0.12ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local3.74ms - 3.74ms-unsure 🔍
-0% - +0%
-0.00ms - +0.00ms
preact-main3.74ms - 3.74msunsure 🔍
-0% - +0%
-0.00ms - +0.00ms
-
replace1k
  • Browser: chrome-headless
  • Sample size: 100
  • Built by: CI #5682
  • Commit: 4520b2d

duration

VersionAvg timevs preact-localvs preact-main
preact-local55.50ms - 57.21ms-unsure 🔍
-0% - +4%
-0.04ms - +1.94ms
preact-main54.89ms - 55.92msunsure 🔍
-3% - +0%
-1.94ms - +0.04ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local3.01ms - 3.01ms-unsure 🔍
-0% - +0%
-0.00ms - +0.00ms
preact-main3.01ms - 3.01msunsure 🔍
-0% - +0%
-0.00ms - +0.00ms
-

run-warmup-0

VersionAvg timevs preact-localvs preact-main
preact-local28.80ms - 29.58ms-unsure 🔍
-2% - +2%
-0.49ms - +0.61ms
preact-main28.74ms - 29.52msunsure 🔍
-2% - +2%
-0.61ms - +0.49ms
-

run-warmup-1

VersionAvg timevs preact-localvs preact-main
preact-local33.91ms - 35.28ms-unsure 🔍
-3% - +2%
-1.19ms - +0.82ms
preact-main34.05ms - 35.52msunsure 🔍
-2% - +3%
-0.82ms - +1.19ms
-

run-warmup-2

VersionAvg timevs preact-localvs preact-main
preact-local30.00ms - 31.31ms-unsure 🔍
-3% - +3%
-0.93ms - +0.85ms
preact-main30.10ms - 31.30msunsure 🔍
-3% - +3%
-0.85ms - +0.93ms
-

run-warmup-3

VersionAvg timevs preact-localvs preact-main
preact-local25.82ms - 26.20ms-unsure 🔍
-1% - +1%
-0.33ms - +0.15ms
preact-main25.95ms - 26.25msunsure 🔍
-1% - +1%
-0.15ms - +0.33ms
-

run-warmup-4

VersionAvg timevs preact-localvs preact-main
preact-local23.56ms - 25.25ms-unsure 🔍
-4% - +5%
-1.08ms - +1.15ms
preact-main23.64ms - 25.10msunsure 🔍
-5% - +4%
-1.15ms - +1.08ms
-

run-final

VersionAvg timevs preact-localvs preact-main
preact-local20.74ms - 21.25ms-unsure 🔍
-1% - +2%
-0.26ms - +0.41ms
preact-main20.71ms - 21.13msunsure 🔍
-2% - +1%
-0.41ms - +0.26ms
-
text-update
  • Browser: chrome-headless
  • Sample size: 230
  • Built by: CI #5682
  • Commit: 4520b2d

duration

VersionAvg timevs preact-localvs preact-main
preact-local1.94ms - 2.07ms-unsure 🔍
-3% - +6%
-0.06ms - +0.12ms
preact-main1.91ms - 2.04msunsure 🔍
-6% - +3%
-0.12ms - +0.06ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local1.02ms - 1.07ms-unsure 🔍
-0% - +5%
-0.00ms - +0.05ms
preact-main1.01ms - 1.04msunsure 🔍
-5% - +0%
-0.05ms - +0.00ms
-
todo

duration

VersionAvg timevs preact-localvs preact-main
preact-local31.53ms - 33.06ms-unsure 🔍
-2% - +3%
-0.54ms - +1.05ms
preact-main31.81ms - 32.27msunsure 🔍
-3% - +2%
-1.05ms - +0.54ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local1.26ms - 1.26ms-unsure 🔍
-0% - +0%
-0.00ms - +0.00ms
preact-main1.26ms - 1.26msunsure 🔍
-0% - +0%
-0.00ms - +0.00ms
-
update10th1k

duration

VersionAvg timevs preact-localvs preact-main
preact-local34.50ms - 36.25ms-unsure 🔍
-3% - +4%
-1.00ms - +1.53ms
preact-main34.19ms - 36.02msunsure 🔍
-4% - +3%
-1.53ms - +1.00ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local2.96ms - 2.98ms-unsure 🔍
-0% - +0%
-0.01ms - +0.01ms
preact-main2.96ms - 2.97msunsure 🔍
-0% - +0%
-0.01ms - +0.01ms
-

tachometer-reporter-action v2 for CI

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown

Size Change: +31 B (+0.2%)

Total Size: 15.8 kB

📦 View Changed
Filename Size Change
hooks/dist/hooks.mjs 1.58 kB +33 B (+2.13%)
test-utils/dist/testUtils.mjs 471 B -2 B (-0.42%)
ℹ️ View Unchanged
Filename Size
compat/dist/compat.mjs 3.87 kB
debug/dist/debug.mjs 3.89 kB
devtools/dist/devtools.mjs 274 B
dist/preact.mjs 4.83 kB
jsx-runtime/dist/jsxRuntime.mjs 861 B

compressed-size-action

@coveralls

coveralls commented Jul 16, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 98.536% (+0.004%) from 98.532% — JoviDeCroock/investigate-3666 into main

Now that pending passive effects are flushed before every scheduled
render, the flush in options._render only served renders that bypass
the scheduler. Move that responsibility to options._root so explicit
render() calls flush pending effects before entering the diff instead
of during it, skipping unmounting renders (vnode == null) to keep
pending effects of unmounting components cancelable.

This also fixes test-utils resetting options.debounceRendering to
undefined on teardown, which silently uninstalled the effect-flushing
scheduler. Teardown now distinguishes a saved undefined (act must
restore it) from "setupRerender was never called" and falls back to
the scheduler that was present at load time.

The suspense effect-cleanup and useSyncExternalStore tests asserted
flush-before-render ordering through rerender(), which replaces the
flushing scheduler; they now exercise the default scheduler instead.
Comment thread hooks/src/index.js
}
hookItem._pendingArgs = hookItem._nextValue = undefined;
});
} else {

@JoviDeCroock JoviDeCroock Jul 16, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Now because we flush when we start a new render cycle this isn't needed anymore. It was basically a hack for what we're adding. For predictability though I would love to also add this into signals, that would however require a major and it's already behaving like this currently so... it's not pressing for v11 itself

@JoviDeCroock
JoviDeCroock marked this pull request as ready for review July 16, 2026 18:09
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.

[preact/compat] radix-ui Slider component drag points (Thumbs) not working

2 participants