You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(web): release the first value-bound select - #4253
AI-assisted: prepared and reviewed with AI coding agents; the results below come from the commands shown.
Summary
The first value-bound select, its form, and its first bound value can remain reachable after disposal. writeSelectValue creates the module-global selectInsert callback inside a per-select activation. Both queued closures capture that activation: the nullish branch captures node and value, and the trailing retry captures node. V8 shares that context with the stored callback, retaining the first node and bound value, possibly a multi-select array. Removing only the trailing closure still leaks.
Move the callback to module scope, preserving lazy installation and both microtasks. SSR never reaches this code.
How did you test this change?
pnpm --dir packages/web exec vitest run --maxWorkers=1: 161 files, 1,439 tests passed. The inspector-GC regression fails on the original source and passes with the patch, without --expose-gc.
Differential tests covered initial and late options, multi-select, optgroups, and reactive, nullish and same-turn updates. The existing client, hydration and server suites pass unchanged, including select-multiple, select-async-value and server select-value specs.
Merging this PR will improve performance by 15.07%
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.
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
AI-assisted: prepared and reviewed with AI coding agents; the results below come from the commands shown.
Summary
The first value-bound select, its form, and its first bound value can remain reachable after disposal.
writeSelectValuecreates the module-globalselectInsertcallback inside a per-select activation. Both queued closures capture that activation: the nullish branch capturesnodeandvalue, and the trailing retry capturesnode. V8 shares that context with the stored callback, retaining the first node and bound value, possibly a multi-select array. Removing only the trailing closure still leaks.Move the callback to module scope, preserving lazy installation and both microtasks. SSR never reaches this code.
How did you test this change?
pnpm --dir packages/web exec vitest run --maxWorkers=1: 161 files, 1,439 tests passed. The inspector-GC regression fails on the original source and passes with the patch, without--expose-gc.JSX_COMPILER=babel pnpm --dir packages/web exec vitest run --config vite.config.hydrate.mjs --maxWorkers=1: 123 files passed, 1 skipped; 520 tests passed, 16 expected failures, 2 skipped.pnpm --dir packages/web exec vitest run --config vite.config.server.mjs --maxWorkers=1: 201 files passed; 1,790 tests passed, 3 expected failures, 2 skipped.Differential tests covered initial and late options, multi-select, optgroups, and reactive, nullish and same-turn updates. The existing client, hydration and server suites pass unchanged, including select-multiple, select-async-value and server select-value specs.