refactor: replace internal weak-registry with Atom.family - #99
Merged
Conversation
Merged
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What
Deletes
packages/form/src/internal/weak-registry.ts— a hand-rolledWeakRef+FinalizationRegistrykeyed-memoization helper — and replaces every use of it inFormAtoms.tswith effect v4's nativeAtom.family, which implements the exact same mechanism (including the identicalMapfallback for environments withoutWeakRef/FinalizationRegistry).Net: -154/+146 lines, all of the get/compare/set boilerplate gone.
Design
Composite
{ path, schema }family keys preserve the schema-identity recreation behavior.getOrCreateValidationAtomandgetOrCreateFieldAtomspreviously kept a sideMap<string, Schema.Top>and recreated atoms when the schema instance for a path changed (contract-tested in "recreates field atoms when schema changes for the same path"). SincegetOrCreateFieldAtoms/getOrCreateValidationAtomare on the publicFormAtomsinterface, a different-schema call for the same path is reachable, so the behavior is not dead and was kept.Atom.familycompares keys with structural Hash/Equal: in a plain-object key,pathcompares by value andschema(a non-plain object) by reference — so a fresh{ path, schema }literal with the same schema reference hits the memoized entry, and a different schema instance yields a new one. Verified by executing the pinnedeffect@4.0.0-beta.52before designing (fresh literals memoize; different schema ref creates; two separately-built identical schemas are notEqual, matching the old===check exactly).Reset iteration via key maps.
Atom.familydoes not expose iteration, butresetValidationAtomsmust visit every created validation atom and zero everyfieldValidationCountAtom. Two plainMap<string, key>s record the latest key per path (paths are bounded by the form's field/array-item structure, so no GC concern); reset iterates them and callsfamily(key)to obtain each entry. If an entry was garbage-collected,family(key)recreates a fresh atom and theAtom.Resetwrite / count-to-0 write is a harmless no-op — same observable behavior as the old registry, which simply skipped collected entries. These maps also subsume the oldvalidationSchemaRegistry/fieldSchemaRegistry.Plain-object bundles memoize directly.
Atom.familyis generic overT extends object, not atom-specific, so theFieldAtomsandPublicFieldAtomsbundles are returned straight from their families with no extra memo layer.isDirtyAtomfamily keyed by path only. The old code shared oneisDirtyAtomsRegistrybetweengetOrCreateFieldAtomsandgetFieldIsDirtyso the dirty atom survives a schema-driven bundle recreation; a dedicatedisDirtyAtomFamily(path)keeps that sharing, and the now-redundantgetFieldIsDirtywrapper is inlined.Breaking change (beta)
FormAtoms.validationAtomsRegistryandFormAtoms.fieldAtomsRegistryare removed from the public interface along with theWeakRegistrytype. They were only used by two tests in this repo (updated to assert instance identity throughgetOrCreateFieldAtoms/getOrCreateValidationAtom, which is a stronger check than the old "registry entry is defined"). External consumers should use those getters instead.Tests
Failure, bumps both counts, resets, and asserts both validation atoms return toInitialand both counts to 0.pnpm vitest run(303 passed),pnpm check:types, andpnpm lintare green.