[utils] Port x-internals store improvements - #5489
Conversation
Imports the @mui/x-internals selector implementation so the two store codebases converge: 7-8 input selector support, the createSelectorMemoizedWithOptions factory, the single-combiner identity fix, and Store.create. Adds Store.test.ts covering selector arity, memoization cache-key behavior, and extra-args passing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
commit: |
Bundle size
PerformanceTotal duration: 971.26 ms -108.93 ms(-10.1%) | Renders: 92 (+0) | Paint: 1,594.51 ms -193.31 ms(-10.8%)
…and 3 more (+7 within noise) — details Metric alarms
Check out the code infra dashboard for more information about this PR. |
✅ Deploy Preview for base-ui ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Deletes the Store, useStore, and createSelector implementations and re-exports @base-ui/utils/store, which now contains the same selector features (mui/base-ui#5489). useStoreEffect stays local, rebuilt on the public store surface. Adjustments for the stricter @base-ui/utils store typings: - update() takes an exact key subset instead of Partial<State>: cast the accumulated-changes call sites in ChatStore, SchedulerStore, MinimalTreeViewStore, and EventCalendarStore. - The generic set() is no longer callable on a union of store classes: seed errors through a typed helper in dataSource.test.ts. The catalog temporarily points at the pkg.pr.new build of the base-ui PR and must be repointed to a released version before merging. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PR reviewTwo merge-blocking public API issues remain: the new Reselect options parameter is effectively untyped, and Bugs (4)1. 🔴 The options factory exposes the wrong Reselect typeLocation: export const createSelectorMemoizedWithOptions =
(options?: OverrideMemoizeOptions<UnknownMemoizer>): CreateSelectorFunction =>
Failure scenario: An Fix: Type this with an appropriately generic Reselect 2. 🔴
|
- Type createSelectorMemoizedWithOptions with the Reselect CreateSelectorOptions shape, generic over override memoizers, instead of the effectively-untyped OverrideMemoizeOptions<UnknownMemoizer>. - Make Store.create construct the class it is called on, so inherited factories return proper subclass instances. - Bound CreateSelectorFunction to the runtime limits: up to seven input selectors, and up to three extra combiner arguments when the parameter count is statically known. Open-ended parameter tuples (rest params or contextually typed combiners) cannot be distinguished at the type level and remain covered by the runtime guards. - Require the state argument in the single-function form's result type, so a zero-parameter combiner can no longer be invoked without the state object its cache key is stored on. - Add runtime regression tests and a type-level spec for the above. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
All four findings addressed in 9f1f7e4:
Verification: utils typecheck, lint, and 84 store tests pass here; the full mui-x monorepo also typechecks cleanly against the pkg.pr.new build of this commit (mui/mui-x#23335 is now pinned to it), which exercises ~80 selector call sites including the 🤖 Generated with Claude Code |
Only createSelector dispatches through fixed arities capped at seven input selectors; the memoized variant delegates to reselect and has no such limit. CreateSelectorFunction<BoundedSelectors> expresses the difference; MUI X has memoized selectors with eight inputs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PR reviewReviewed at Bugs (5)1. 🟠
|
- Restore the runtime guard for combiners whose Function.length under-reports (rest parameters, wrappers): only a zero-length combiner may ignore its inputs; any other length below the selector count throws instead of silently dropping arguments. Static rejection of rest parameters is not possible: open-ended parameter tuples also occur for contextually-typed combiners, and DropFirst erases open tails behind fixed elements, so the runtime guard covers them. - Merge object-form memoizeOptions over the module defaults so passing options no longer silently discards the Object.is equality check. - Split CreateSelectorFunction into two plain types instead of the BoundedSelectors parameter: createSelector keeps its seven-input bound (matching its unrolled dispatch) and regains master parity for the single-function form (returned verbatim, no state requirement), while CreateSelectorMemoizedFunction is unbounded on inputs and carries the state-required and three-extra-args constraints. - Document that Store.create on a generic base class degrades the inferred type to Store, and pin the degradation in the specs. - Split tests per module, cover the extra-args dispatch paths (argsLength 1-3), the six-selector branch, the options merge, and real Store behavior; document the memoized single-function form's state-identity caching. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
115b60a to
94bb4d4
Compare
|
Review findings addressed in 94bb4d4. Summary per finding, including two deliberate divergences: Bug 1 (runtime guard) — Restored: only a zero-length combiner may ignore its inputs (a deliberate pattern in MUI X's virtualizer); any other length below the selector count throws Bug 2 (options clobbering) — Object-form Bug 3 ( Bug 4 (type tightenings) — Fixed via the type split: Bug 5 + Docs 1/2 — JSDoc added on both memoized exports (state-identity caching of the single-function form, options-merge semantics, Function.length constraints); both incorrect comments rewritten. Tests 1–5 — Split per module ( Simplification 2 (drop the arity cap) — Not taken: Simplification 1 (fallthrough switch) — Not taken for the switch itself (kept intentionally); the leaked suppression is fixed with a matching Simplifications 3/4 — Verification: utils typecheck/lint clean, 101 store tests passing, and all twelve store-consuming MUI X packages typecheck clean against the pkg.pr.new build of this commit (mui/mui-x#23335 is pinned to it). 🤖 Generated with Claude Code |
PR reviewThe author’s response at Bugs (3)1. 🔴 A custom memoizer still receives
|
Part of the effort to deduplicate the store implementations between
@mui/x-internalsand@base-ui/utils, so MUI X packages can consume the Base UI store instead of shipping a parallel copy.Ports the
@mui/x-internalsselector implementation into@base-ui/utils/store(supersedes the store changes from therefactor-store-mergebranch, rebased onto current master):createSelector: support 7–8 input selectors (previously capped at 6).createSelectorMemoized: rewrap ascreateSelectorMemoizedWithOptions(options)factory exposing reselect memoize overrides (used by x-charts), and fix the single-combiner case to wrap an identity input selector instead of passing the bare combiner to reselect.Store.create(): restore the static factory used by MUI X call sites.Store.test.tscovering selector arity limits, memoization cache-key behavior, and extra-args passing.Kept over the old branch: master's stricter
set/updatetypings from #5423. Error messages are unchanged, so no new error codes.With this released,
@mui/x-internals/storecan become a re-export of@base-ui/utils/store(plus its localuseStoreEffect, which only uses the public store surface).🤖 Generated with Claude Code