Skip to content

Commit

Permalink
Data: allow binding registry selector to multiple registries (#57943)
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix committed Jan 19, 2024
1 parent 4af8902 commit 90d7f56
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 6 deletions.
12 changes: 8 additions & 4 deletions packages/data/src/factory.js
Expand Up @@ -39,15 +39,19 @@
* @return {Function} Registry selector that can be registered with a store.
*/
export function createRegistrySelector( registrySelector ) {
let selector;
let lastRegistry;
const selectorsByRegistry = new WeakMap();
// Create a selector function that is bound to the registry referenced by `selector.registry`
// and that has the same API as a regular selector. Binding it in such a way makes it
// possible to call the selector directly from another selector.
const wrappedSelector = ( ...args ) => {
if ( ! selector || lastRegistry !== wrappedSelector.registry ) {
let selector = selectorsByRegistry.get( wrappedSelector.registry );
// We want to make sure the cache persists even when new registry
// instances are created. For example patterns create their own editors
// with their own core/block-editor stores, so we should keep track of
// the cache for each registry instance.
if ( ! selector ) {
selector = registrySelector( wrappedSelector.registry.select );
lastRegistry = wrappedSelector.registry;
selectorsByRegistry.set( wrappedSelector.registry, selector );
}
return selector( ...args );
};
Expand Down
5 changes: 5 additions & 0 deletions packages/data/src/redux-store/index.js
Expand Up @@ -237,6 +237,11 @@ export default function createReduxStore( key, options ) {
const boundSelector = ( ...args ) => {
args = normalize( selector, args );
const state = store.__unstableOriginalGetState();
// Before calling the selector, switch to the correct
// registry.
if ( selector.isRegistrySelector ) {
selector.registry = registry;
}
return selector( state.root, ...args );
};

Expand Down
23 changes: 21 additions & 2 deletions packages/data/src/test/registry-selectors.js
Expand Up @@ -78,8 +78,7 @@ describe( 'createRegistrySelector', () => {
expect( registry.select( uiStore ).getElementCount() ).toBe( 1 );
} );

// Even without createSelector, this fails in trunk.
it.skip( 'can bind one selector to multiple registries', () => {
it( 'can bind one selector to multiple registries (createRegistrySelector)', () => {
const registry1 = createRegistry();
const registry2 = createRegistry();

Expand All @@ -102,6 +101,26 @@ describe( 'createRegistrySelector', () => {
expect( registry2.select( uiStore ).getElementCount() ).toBe( 1 );
} );

it( 'can bind one selector to multiple registries (createRegistrySelector + createSelector)', () => {
const registry1 = createRegistry();
registry1.register( elementsStore );
registry1.register( uiStore );
registry1.dispatch( elementsStore ).add( 'Carbon' );

const registry2 = createRegistry();
registry2.register( elementsStore );
registry2.register( uiStore );
registry2.dispatch( elementsStore ).add( 'Helium' );

// Expects the `getFilteredElements` to be bound separately and independently to the two registries
expect( registry1.select( uiStore ).getFilteredElements() ).toEqual( [
'Carbon',
] );
expect( registry2.select( uiStore ).getFilteredElements() ).toEqual( [
'Helium',
] );
} );

it( 'can bind a memoized selector to a registry', () => {
const registry = createRegistry();
registry.register( elementsStore );
Expand Down

1 comment on commit 90d7f56

@github-actions
Copy link

Choose a reason for hiding this comment

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

Flaky tests detected in 90d7f56.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/7585027624
📝 Reported issues:

Please sign in to comment.