diff --git a/packages/data/src/resolvers-cache-middleware.js b/packages/data/src/resolvers-cache-middleware.js index 68945db2535752..13a0214a8bc930 100644 --- a/packages/data/src/resolvers-cache-middleware.js +++ b/packages/data/src/resolvers-cache-middleware.js @@ -1,53 +1,47 @@ -/** - * Internal dependencies - */ -import coreDataStore from './store'; - /** @typedef {import('./registry').WPDataRegistry} WPDataRegistry */ /** * Creates a middleware handling resolvers cache invalidation. * - * @param {WPDataRegistry} registry The registry reference for which to create - * the middleware. - * @param {string} reducerKey The namespace for which to create the - * middleware. + * @param {WPDataRegistry} registry Registry for which to create the middleware. + * @param {string} storeName Name of the store for which to create the middleware. * * @return {Function} Middleware function. */ const createResolversCacheMiddleware = - ( registry, reducerKey ) => () => ( next ) => ( action ) => { - const resolvers = registry - .select( coreDataStore ) - .getCachedResolvers( reducerKey ); - Object.entries( resolvers ).forEach( - ( [ selectorName, resolversByArgs ] ) => { - const resolver = - registry.stores?.[ reducerKey ]?.resolvers?.[ - selectorName - ]; - if ( ! resolver || ! resolver.shouldInvalidate ) { + ( registry, storeName ) => () => ( next ) => ( action ) => { + const resolvers = registry.select( storeName ).getCachedResolvers(); + const resolverEntries = Object.entries( resolvers ); + resolverEntries.forEach( ( [ selectorName, resolversByArgs ] ) => { + const resolver = + registry.stores[ storeName ]?.resolvers?.[ selectorName ]; + if ( ! resolver || ! resolver.shouldInvalidate ) { + return; + } + resolversByArgs.forEach( ( value, args ) => { + // Works around a bug in `EquivalentKeyMap` where `map.delete` merely sets an entry value + // to `undefined` and `map.forEach` then iterates also over these orphaned entries. + if ( value === undefined ) { return; } - resolversByArgs.forEach( ( value, args ) => { - // resolversByArgs is the map Map([ args ] => boolean) storing the cache resolution status for a given selector. - // If the value is "finished" or "error" it means this resolver has finished its resolution which means we need - // to invalidate it, if it's true it means it's inflight and the invalidation is not necessary. - if ( - ( value?.status !== 'finished' && - value?.status !== 'error' ) || - ! resolver.shouldInvalidate( action, ...args ) - ) { - return; - } - // Trigger cache invalidation - registry - .dispatch( coreDataStore ) - .invalidateResolution( reducerKey, selectorName, args ); - } ); - } - ); + // resolversByArgs is the map Map([ args ] => boolean) storing the cache resolution status for a given selector. + // If the value is "finished" or "error" it means this resolver has finished its resolution which means we need + // to invalidate it, if it's true it means it's inflight and the invalidation is not necessary. + if ( value.status !== 'finished' && value.status !== 'error' ) { + return; + } + + if ( ! resolver.shouldInvalidate( action, ...args ) ) { + return; + } + + // Trigger cache invalidation + registry + .dispatch( storeName ) + .invalidateResolution( selectorName, args ); + } ); + } ); return next( action ); };