@wordpress/data 6.2.1 → 6.3.1-next.a55ed9455a.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/build/components/use-select/index.js +1 -1
  3. package/build/components/use-select/index.js.map +1 -1
  4. package/build/factory.js +1 -1
  5. package/build/factory.js.map +1 -1
  6. package/build/plugins/persistence/index.js +114 -12
  7. package/build/plugins/persistence/index.js.map +1 -1
  8. package/build/redux-store/index.js +25 -14
  9. package/build/redux-store/index.js.map +1 -1
  10. package/build/redux-store/metadata/actions.js +51 -8
  11. package/build/redux-store/metadata/actions.js.map +1 -1
  12. package/build/redux-store/metadata/reducer.js +58 -5
  13. package/build/redux-store/metadata/reducer.js.map +1 -1
  14. package/build/redux-store/metadata/selectors.js +93 -26
  15. package/build/redux-store/metadata/selectors.js.map +1 -1
  16. package/build/redux-store/metadata/utils.js +31 -13
  17. package/build/redux-store/metadata/utils.js.map +1 -1
  18. package/build/registry.js +0 -2
  19. package/build/registry.js.map +1 -1
  20. package/build/resolvers-cache-middleware.js +3 -3
  21. package/build/resolvers-cache-middleware.js.map +1 -1
  22. package/build-module/components/use-select/index.js +1 -1
  23. package/build-module/components/use-select/index.js.map +1 -1
  24. package/build-module/factory.js +1 -1
  25. package/build-module/factory.js.map +1 -1
  26. package/build-module/plugins/persistence/index.js +111 -12
  27. package/build-module/plugins/persistence/index.js.map +1 -1
  28. package/build-module/redux-store/index.js +25 -14
  29. package/build-module/redux-store/index.js.map +1 -1
  30. package/build-module/redux-store/metadata/actions.js +47 -8
  31. package/build-module/redux-store/metadata/actions.js.map +1 -1
  32. package/build-module/redux-store/metadata/reducer.js +59 -6
  33. package/build-module/redux-store/metadata/reducer.js.map +1 -1
  34. package/build-module/redux-store/metadata/selectors.js +86 -26
  35. package/build-module/redux-store/metadata/selectors.js.map +1 -1
  36. package/build-module/redux-store/metadata/utils.js +29 -13
  37. package/build-module/redux-store/metadata/utils.js.map +1 -1
  38. package/build-module/registry.js +0 -2
  39. package/build-module/registry.js.map +1 -1
  40. package/build-module/resolvers-cache-middleware.js +3 -3
  41. package/build-module/resolvers-cache-middleware.js.map +1 -1
  42. package/build-types/redux-store/metadata/actions.d.ts +44 -11
  43. package/build-types/redux-store/metadata/actions.d.ts.map +1 -1
  44. package/build-types/redux-store/metadata/reducer.d.ts +10 -2
  45. package/build-types/redux-store/metadata/reducer.d.ts.map +1 -1
  46. package/build-types/redux-store/metadata/selectors.d.ts +56 -16
  47. package/build-types/redux-store/metadata/selectors.d.ts.map +1 -1
  48. package/build-types/redux-store/metadata/utils.d.ts +20 -1
  49. package/build-types/redux-store/metadata/utils.d.ts.map +1 -1
  50. package/build-types/types.d.ts.map +1 -1
  51. package/package.json +8 -8
  52. package/src/components/use-select/index.js +1 -1
  53. package/src/components/use-select/test/index.js +7 -7
  54. package/src/components/with-select/test/index.js +3 -3
  55. package/src/factory.js +1 -1
  56. package/src/plugins/persistence/index.js +142 -8
  57. package/src/plugins/persistence/test/index.js +405 -0
  58. package/src/redux-store/index.js +44 -19
  59. package/src/redux-store/metadata/actions.js +47 -8
  60. package/src/redux-store/metadata/reducer.ts +63 -9
  61. package/src/redux-store/metadata/selectors.js +81 -23
  62. package/src/redux-store/metadata/test/reducer.js +98 -18
  63. package/src/redux-store/metadata/test/selectors.js +266 -45
  64. package/src/redux-store/metadata/test/utils.js +28 -1
  65. package/src/redux-store/metadata/utils.ts +59 -0
  66. package/src/redux-store/test/index.js +42 -0
  67. package/src/registry.js +0 -2
  68. package/src/resolvers-cache-middleware.js +4 -3
  69. package/src/test/controls.js +7 -7
  70. package/src/test/registry.js +6 -6
  71. package/src/types.ts +1 -3
  72. package/tsconfig.tsbuildinfo +1 -1
  73. package/src/redux-store/metadata/utils.js +0 -37
package/src/factory.js CHANGED
@@ -36,7 +36,7 @@
36
36
  * @return {Function} Registry selector that can be registered with a store.
37
37
  */
38
38
  export function createRegistrySelector( registrySelector ) {
39
- // create a selector function that is bound to the registry referenced by `selector.registry`
39
+ // Create a selector function that is bound to the registry referenced by `selector.registry`
40
40
  // and that has the same API as a regular selector. Binding it in such a way makes it
41
41
  // possible to call the selector directly from another selector.
42
42
  const selector = ( ...args ) =>
@@ -222,6 +222,128 @@ function persistencePlugin( registry, pluginOptions ) {
222
222
  };
223
223
  }
224
224
 
225
+ /**
226
+ * Move the 'features' object in local storage from the sourceStoreName to the
227
+ * preferences store.
228
+ *
229
+ * @param {Object} persistence The persistence interface.
230
+ * @param {string} sourceStoreName The name of the store that has persisted
231
+ * preferences to migrate to the preferences
232
+ * package.
233
+ */
234
+ export function migrateFeaturePreferencesToPreferencesStore(
235
+ persistence,
236
+ sourceStoreName
237
+ ) {
238
+ const preferencesStoreName = 'core/preferences';
239
+ const interfaceStoreName = 'core/interface';
240
+
241
+ const state = persistence.get();
242
+
243
+ // Features most recently (and briefly) lived in the interface package.
244
+ // If data exists there, prioritize using that for the migration. If not
245
+ // also check the original package as the user may have updated from an
246
+ // older block editor version.
247
+ const interfaceFeatures =
248
+ state[ interfaceStoreName ]?.preferences?.features?.[ sourceStoreName ];
249
+ const sourceFeatures = state[ sourceStoreName ]?.preferences?.features;
250
+ const featuresToMigrate = interfaceFeatures
251
+ ? interfaceFeatures
252
+ : sourceFeatures;
253
+
254
+ if ( featuresToMigrate ) {
255
+ const targetFeatures = state[ preferencesStoreName ]?.preferences;
256
+
257
+ // Avoid migrating features again if they've previously been migrated.
258
+ if ( ! targetFeatures?.[ sourceStoreName ] ) {
259
+ // Set the feature values in the interface store, the features
260
+ // object is keyed by 'scope', which matches the store name for
261
+ // the source.
262
+ persistence.set( preferencesStoreName, {
263
+ preferences: {
264
+ ...targetFeatures,
265
+ [ sourceStoreName ]: featuresToMigrate,
266
+ },
267
+ } );
268
+
269
+ // Remove migrated feature preferences from `interface`.
270
+ if ( interfaceFeatures ) {
271
+ const otherInterfaceFeatures =
272
+ state[ interfaceStoreName ]?.preferences?.features;
273
+
274
+ persistence.set( interfaceStoreName, {
275
+ preferences: {
276
+ features: {
277
+ ...otherInterfaceFeatures,
278
+ [ sourceStoreName ]: undefined,
279
+ },
280
+ },
281
+ } );
282
+ }
283
+
284
+ // Remove migrated feature preferences from the source.
285
+ if ( sourceFeatures ) {
286
+ const sourcePreferences = state[ sourceStoreName ]?.preferences;
287
+
288
+ persistence.set( sourceStoreName, {
289
+ preferences: {
290
+ ...sourcePreferences,
291
+ features: undefined,
292
+ },
293
+ } );
294
+ }
295
+ }
296
+ }
297
+ }
298
+
299
+ export function migrateIndividualPreferenceToPreferencesStore(
300
+ persistence,
301
+ sourceStoreName,
302
+ key
303
+ ) {
304
+ const preferencesStoreName = 'core/preferences';
305
+ const state = persistence.get();
306
+ const sourcePreference = state[ sourceStoreName ]?.preferences?.[ key ];
307
+
308
+ // There's nothing to migrate, exit early.
309
+ if ( ! sourcePreference ) {
310
+ return;
311
+ }
312
+
313
+ const targetPreference =
314
+ state[ preferencesStoreName ]?.preferences?.[ sourceStoreName ]?.[
315
+ key
316
+ ];
317
+
318
+ // There's existing data at the target, so don't overwrite it, exit early.
319
+ if ( targetPreference ) {
320
+ return;
321
+ }
322
+
323
+ const allPreferences = state[ preferencesStoreName ]?.preferences;
324
+ const targetPreferences =
325
+ state[ preferencesStoreName ]?.preferences?.[ sourceStoreName ];
326
+
327
+ persistence.set( preferencesStoreName, {
328
+ preferences: {
329
+ ...allPreferences,
330
+ [ sourceStoreName ]: {
331
+ ...targetPreferences,
332
+ [ key ]: sourcePreference,
333
+ },
334
+ },
335
+ } );
336
+
337
+ // Remove migrated feature preferences from the source.
338
+ const allSourcePreferences = state[ sourceStoreName ]?.preferences;
339
+ persistence.set( sourceStoreName, {
340
+ preferences: {
341
+ ...allSourcePreferences,
342
+ [ key ]: undefined,
343
+ },
344
+ } );
345
+ }
346
+
225
347
  /**
226
348
  * Move the 'features' object in local storage from the sourceStoreName to the
227
349
  * interface store.
@@ -269,23 +391,35 @@ export function migrateFeaturePreferencesToInterfaceStore(
269
391
  }
270
392
  }
271
393
 
272
- /**
273
- * Deprecated: Remove this function and the code in WordPress Core that calls
274
- * it once WordPress 6.0 is released.
275
- */
276
-
277
394
  persistencePlugin.__unstableMigrate = ( pluginOptions ) => {
278
395
  const persistence = createPersistenceInterface( pluginOptions );
279
396
 
280
- migrateFeaturePreferencesToInterfaceStore(
397
+ migrateFeaturePreferencesToPreferencesStore(
281
398
  persistence,
282
399
  'core/edit-widgets'
283
400
  );
284
- migrateFeaturePreferencesToInterfaceStore(
401
+ migrateFeaturePreferencesToPreferencesStore(
285
402
  persistence,
286
403
  'core/customize-widgets'
287
404
  );
288
- migrateFeaturePreferencesToInterfaceStore( persistence, 'core/edit-post' );
405
+ migrateFeaturePreferencesToPreferencesStore(
406
+ persistence,
407
+ 'core/edit-post'
408
+ );
409
+ migrateIndividualPreferenceToPreferencesStore(
410
+ persistence,
411
+ 'core/edit-post',
412
+ 'hiddenBlockTypes'
413
+ );
414
+ migrateFeaturePreferencesToPreferencesStore(
415
+ persistence,
416
+ 'core/edit-site'
417
+ );
418
+ migrateIndividualPreferenceToPreferencesStore(
419
+ persistence,
420
+ 'core/edit-site',
421
+ 'editorMode'
422
+ );
289
423
  };
290
424
 
291
425
  export default persistencePlugin;
@@ -10,6 +10,8 @@ import plugin, {
10
10
  createPersistenceInterface,
11
11
  withLazySameState,
12
12
  migrateFeaturePreferencesToInterfaceStore,
13
+ migrateFeaturePreferencesToPreferencesStore,
14
+ migrateIndividualPreferenceToPreferencesStore,
13
15
  } from '../';
14
16
  import objectStorage from '../storage/object';
15
17
  import { createRegistry } from '../../../';
@@ -492,4 +494,407 @@ describe( 'migrateFeaturePreferencesToInterfaceStore', () => {
492
494
  },
493
495
  } );
494
496
  } );
497
+
498
+ describe( 'migrateFeaturePreferencesToPreferencesStore', () => {
499
+ it( 'migrates multiple preferences from persisted source stores to preferences', () => {
500
+ const persistenceInterface = createPersistenceInterface( {
501
+ storageKey: 'test-username',
502
+ } );
503
+
504
+ const sourceStateA = {
505
+ preferences: {
506
+ features: {
507
+ featureA: true,
508
+ featureB: false,
509
+ featureC: true,
510
+ },
511
+ },
512
+ };
513
+
514
+ const sourceStateB = {
515
+ preferences: {
516
+ features: {
517
+ featureD: true,
518
+ featureE: false,
519
+ featureF: true,
520
+ },
521
+ },
522
+ };
523
+
524
+ persistenceInterface.set( 'core/test-a', sourceStateA );
525
+ persistenceInterface.set( 'core/test-b', sourceStateB );
526
+
527
+ migrateFeaturePreferencesToPreferencesStore(
528
+ persistenceInterface,
529
+ 'core/test-a'
530
+ );
531
+
532
+ migrateFeaturePreferencesToPreferencesStore(
533
+ persistenceInterface,
534
+ 'core/test-b'
535
+ );
536
+
537
+ expect( persistenceInterface.get() ).toEqual( {
538
+ 'core/preferences': {
539
+ preferences: {
540
+ 'core/test-a': {
541
+ featureA: true,
542
+ featureB: false,
543
+ featureC: true,
544
+ },
545
+ 'core/test-b': {
546
+ featureD: true,
547
+ featureE: false,
548
+ featureF: true,
549
+ },
550
+ },
551
+ },
552
+ 'core/test-a': {
553
+ preferences: {
554
+ features: undefined,
555
+ },
556
+ },
557
+ 'core/test-b': {
558
+ preferences: {
559
+ features: undefined,
560
+ },
561
+ },
562
+ } );
563
+ } );
564
+
565
+ it( 'migrates multiple preferences from the persisted interface store to preferences, with interface state taking precedence over source stores', () => {
566
+ const persistenceInterface = createPersistenceInterface( {
567
+ storageKey: 'test-username',
568
+ } );
569
+
570
+ const sourceStateA = {
571
+ preferences: {
572
+ features: {
573
+ featureA: true,
574
+ featureB: false,
575
+ featureC: true,
576
+ },
577
+ },
578
+ };
579
+
580
+ const sourceStateB = {
581
+ preferences: {
582
+ features: {
583
+ featureD: true,
584
+ featureE: false,
585
+ featureF: true,
586
+ },
587
+ },
588
+ };
589
+
590
+ const interfaceState = {
591
+ preferences: {
592
+ features: {
593
+ 'core/test-a': {
594
+ featureG: true,
595
+ featureH: false,
596
+ featureI: true,
597
+ },
598
+ 'core/test-b': {
599
+ featureJ: true,
600
+ featureK: false,
601
+ featureL: true,
602
+ },
603
+ },
604
+ },
605
+ };
606
+
607
+ persistenceInterface.set( 'core/test-a', sourceStateA );
608
+ persistenceInterface.set( 'core/test-b', sourceStateB );
609
+ persistenceInterface.set( 'core/interface', interfaceState );
610
+
611
+ migrateFeaturePreferencesToPreferencesStore(
612
+ persistenceInterface,
613
+ 'core/test-a'
614
+ );
615
+
616
+ migrateFeaturePreferencesToPreferencesStore(
617
+ persistenceInterface,
618
+ 'core/test-b'
619
+ );
620
+
621
+ expect( persistenceInterface.get() ).toEqual( {
622
+ 'core/preferences': {
623
+ preferences: {
624
+ 'core/test-a': {
625
+ featureG: true,
626
+ featureH: false,
627
+ featureI: true,
628
+ },
629
+ 'core/test-b': {
630
+ featureJ: true,
631
+ featureK: false,
632
+ featureL: true,
633
+ },
634
+ },
635
+ },
636
+ 'core/interface': {
637
+ preferences: {
638
+ features: {
639
+ 'core/test-a': undefined,
640
+ 'core/test-b': undefined,
641
+ },
642
+ },
643
+ },
644
+ 'core/test-a': {
645
+ preferences: {
646
+ features: undefined,
647
+ },
648
+ },
649
+ 'core/test-b': {
650
+ preferences: {
651
+ features: undefined,
652
+ },
653
+ },
654
+ } );
655
+ } );
656
+
657
+ it( 'only migrates persisted data for the source name from source stores', () => {
658
+ const persistenceInterface = createPersistenceInterface( {
659
+ storageKey: 'test-username',
660
+ } );
661
+
662
+ const sourceStateA = {
663
+ preferences: {
664
+ features: {
665
+ featureA: true,
666
+ featureB: false,
667
+ featureC: true,
668
+ },
669
+ },
670
+ };
671
+
672
+ const sourceStateB = {
673
+ preferences: {
674
+ features: {
675
+ featureD: true,
676
+ featureE: false,
677
+ featureF: true,
678
+ },
679
+ },
680
+ };
681
+
682
+ persistenceInterface.set( 'core/test-a', sourceStateA );
683
+ persistenceInterface.set( 'core/test-b', sourceStateB );
684
+
685
+ migrateFeaturePreferencesToPreferencesStore(
686
+ persistenceInterface,
687
+ 'core/test-a'
688
+ );
689
+
690
+ expect( persistenceInterface.get() ).toEqual( {
691
+ 'core/preferences': {
692
+ preferences: {
693
+ 'core/test-a': {
694
+ featureA: true,
695
+ featureB: false,
696
+ featureC: true,
697
+ },
698
+ },
699
+ },
700
+ 'core/test-a': {
701
+ preferences: {
702
+ features: undefined,
703
+ },
704
+ },
705
+ 'core/test-b': {
706
+ preferences: {
707
+ features: {
708
+ featureD: true,
709
+ featureE: false,
710
+ featureF: true,
711
+ },
712
+ },
713
+ },
714
+ } );
715
+ } );
716
+
717
+ it( 'only migrates persisted data for the source name from interface', () => {
718
+ const persistenceInterface = createPersistenceInterface( {
719
+ storageKey: 'test-username',
720
+ } );
721
+
722
+ const interfaceState = {
723
+ preferences: {
724
+ features: {
725
+ 'core/test-a': {
726
+ featureG: true,
727
+ featureH: false,
728
+ featureI: true,
729
+ },
730
+ 'core/test-b': {
731
+ featureJ: true,
732
+ featureK: false,
733
+ featureL: true,
734
+ },
735
+ },
736
+ },
737
+ };
738
+
739
+ persistenceInterface.set( 'core/interface', interfaceState );
740
+
741
+ migrateFeaturePreferencesToPreferencesStore(
742
+ persistenceInterface,
743
+ 'core/test-a'
744
+ );
745
+
746
+ expect( persistenceInterface.get() ).toEqual( {
747
+ 'core/preferences': {
748
+ preferences: {
749
+ 'core/test-a': {
750
+ featureG: true,
751
+ featureH: false,
752
+ featureI: true,
753
+ },
754
+ },
755
+ },
756
+ 'core/interface': {
757
+ preferences: {
758
+ features: {
759
+ 'core/test-a': undefined,
760
+ 'core/test-b': {
761
+ featureJ: true,
762
+ featureK: false,
763
+ featureL: true,
764
+ },
765
+ },
766
+ },
767
+ },
768
+ } );
769
+ } );
770
+ } );
771
+
772
+ describe( 'migrateIndividualPreferenceToPreferencesStore', () => {
773
+ it( 'migrates an individual preference from the source to the preferences store', () => {
774
+ const persistenceInterface = createPersistenceInterface( {
775
+ storageKey: 'test-username',
776
+ } );
777
+
778
+ const initialState = {
779
+ preferences: {
780
+ myPreference: '123',
781
+ },
782
+ };
783
+
784
+ persistenceInterface.set( 'core/test', initialState );
785
+
786
+ migrateIndividualPreferenceToPreferencesStore(
787
+ persistenceInterface,
788
+ 'core/test',
789
+ 'myPreference'
790
+ );
791
+
792
+ expect( persistenceInterface.get() ).toEqual( {
793
+ 'core/preferences': {
794
+ preferences: {
795
+ 'core/test': {
796
+ myPreference: '123',
797
+ },
798
+ },
799
+ },
800
+ 'core/test': {
801
+ preferences: {
802
+ myPreference: undefined,
803
+ },
804
+ },
805
+ } );
806
+ } );
807
+
808
+ it( 'does not overwrite other preferences in the preferences store', () => {
809
+ const persistenceInterface = createPersistenceInterface( {
810
+ storageKey: 'test-username',
811
+ } );
812
+
813
+ const initialState = {
814
+ preferences: {
815
+ myPreference: '123',
816
+ },
817
+ };
818
+
819
+ persistenceInterface.set( 'core/test', initialState );
820
+ persistenceInterface.set( 'core/preferences', {
821
+ preferences: {
822
+ 'core/other-store': {
823
+ preferenceA: 1,
824
+ preferenceB: 2,
825
+ },
826
+ 'core/test': {
827
+ unrelatedPreference: 'unrelated-value',
828
+ },
829
+ },
830
+ } );
831
+
832
+ migrateIndividualPreferenceToPreferencesStore(
833
+ persistenceInterface,
834
+ 'core/test',
835
+ 'myPreference'
836
+ );
837
+
838
+ expect( persistenceInterface.get() ).toEqual( {
839
+ 'core/preferences': {
840
+ preferences: {
841
+ 'core/other-store': {
842
+ preferenceA: 1,
843
+ preferenceB: 2,
844
+ },
845
+ 'core/test': {
846
+ unrelatedPreference: 'unrelated-value',
847
+ myPreference: '123',
848
+ },
849
+ },
850
+ },
851
+ 'core/test': {
852
+ preferences: {
853
+ myPreference: undefined,
854
+ },
855
+ },
856
+ } );
857
+ } );
858
+
859
+ it( 'does not migrate data if there is already a matching preference key at the target', () => {
860
+ const persistenceInterface = createPersistenceInterface( {
861
+ storageKey: 'test-username',
862
+ } );
863
+
864
+ persistenceInterface.set( 'core/test', {
865
+ preferences: {
866
+ myPreference: '123',
867
+ },
868
+ } );
869
+
870
+ persistenceInterface.set( 'core/preferences', {
871
+ preferences: {
872
+ 'core/test': {
873
+ myPreference: 'already-set',
874
+ },
875
+ },
876
+ } );
877
+
878
+ migrateIndividualPreferenceToPreferencesStore(
879
+ persistenceInterface,
880
+ 'core/test',
881
+ 'myPreference'
882
+ );
883
+
884
+ expect( persistenceInterface.get() ).toEqual( {
885
+ 'core/preferences': {
886
+ preferences: {
887
+ 'core/test': {
888
+ myPreference: 'already-set',
889
+ },
890
+ },
891
+ },
892
+ 'core/test': {
893
+ preferences: {
894
+ myPreference: '123',
895
+ },
896
+ },
897
+ } );
898
+ } );
899
+ } );
495
900
  } );
@@ -232,12 +232,9 @@ function instantiateReduxStore( key, options, registry, thunkArgs ) {
232
232
  createResolversCacheMiddleware( registry, key ),
233
233
  promise,
234
234
  createReduxRoutineMiddleware( normalizedControls ),
235
+ createThunkMiddleware( thunkArgs ),
235
236
  ];
236
237
 
237
- if ( options.__experimentalUseThunks ) {
238
- middlewares.push( createThunkMiddleware( thunkArgs ) );
239
- }
240
-
241
238
  const enhancers = [ applyMiddleware( ...middlewares ) ];
242
239
  if (
243
240
  typeof window !== 'undefined' &&
@@ -333,20 +330,35 @@ function mapResolveSelectors( selectors, store ) {
333
330
  'getCachedResolvers',
334
331
  ] ),
335
332
  ( selector, selectorName ) => ( ...args ) =>
336
- new Promise( ( resolve ) => {
333
+ new Promise( ( resolve, reject ) => {
337
334
  const hasFinished = () =>
338
335
  selectors.hasFinishedResolution( selectorName, args );
336
+ const finalize = ( result ) => {
337
+ const hasFailed = selectors.hasResolutionFailed(
338
+ selectorName,
339
+ args
340
+ );
341
+ if ( hasFailed ) {
342
+ const error = selectors.getResolutionError(
343
+ selectorName,
344
+ args
345
+ );
346
+ reject( error );
347
+ } else {
348
+ resolve( result );
349
+ }
350
+ };
339
351
  const getResult = () => selector.apply( null, args );
340
- // trigger the selector (to trigger the resolver)
352
+ // Trigger the selector (to trigger the resolver)
341
353
  const result = getResult();
342
354
  if ( hasFinished() ) {
343
- return resolve( result );
355
+ return finalize( result );
344
356
  }
345
357
 
346
358
  const unsubscribe = store.subscribe( () => {
347
359
  if ( hasFinished() ) {
348
360
  unsubscribe();
349
- resolve( getResult() );
361
+ finalize( getResult() );
350
362
  }
351
363
  } );
352
364
  } )
@@ -373,8 +385,8 @@ function mapResolvers( resolvers, selectors, store, resolversCache ) {
373
385
  }
374
386
 
375
387
  return {
376
- ...resolver, // copy the enumerable properties of the resolver function
377
- fulfill: resolver, // add the fulfill method
388
+ ...resolver, // Copy the enumerable properties of the resolver function.
389
+ fulfill: resolver, // Add the fulfill method.
378
390
  };
379
391
  } );
380
392
 
@@ -416,15 +428,28 @@ function mapResolvers( resolvers, selectors, store, resolversCache ) {
416
428
  store.dispatch(
417
429
  metadataActions.startResolution( selectorName, args )
418
430
  );
419
- await fulfillResolver(
420
- store,
421
- mappedResolvers,
422
- selectorName,
423
- ...args
424
- );
425
- store.dispatch(
426
- metadataActions.finishResolution( selectorName, args )
427
- );
431
+ try {
432
+ await fulfillResolver(
433
+ store,
434
+ mappedResolvers,
435
+ selectorName,
436
+ ...args
437
+ );
438
+ store.dispatch(
439
+ metadataActions.finishResolution(
440
+ selectorName,
441
+ args
442
+ )
443
+ );
444
+ } catch ( error ) {
445
+ store.dispatch(
446
+ metadataActions.failResolution(
447
+ selectorName,
448
+ args,
449
+ error
450
+ )
451
+ );
452
+ }
428
453
  } );
429
454
  }
430
455