@wordpress/data 8.0.0 → 8.2.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 8.2.0 (2023-01-11)
6
+
7
+ ## 8.1.0 (2023-01-02)
8
+
5
9
  ## 8.0.0 (2022-12-14)
6
10
 
7
11
  ### Breaking Changes
package/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ## Gutenberg
2
2
 
3
- Copyright 2016-2022 by the contributors
3
+ Copyright 2016-2023 by the contributors
4
4
 
5
5
  **License for Contributions (on and after April 15, 2021)**
6
6
 
@@ -8,24 +8,16 @@ Object.defineProperty(exports, "__esModule", {
8
8
  exports.default = useSelect;
9
9
  exports.useSuspenseSelect = useSuspenseSelect;
10
10
 
11
- var _useMemoOne = require("use-memo-one");
12
-
13
11
  var _priorityQueue = require("@wordpress/priority-queue");
14
12
 
15
13
  var _element = require("@wordpress/element");
16
14
 
17
15
  var _isShallowEqual = _interopRequireDefault(require("@wordpress/is-shallow-equal"));
18
16
 
19
- var _compose = require("@wordpress/compose");
20
-
21
17
  var _useRegistry = _interopRequireDefault(require("../registry-provider/use-registry"));
22
18
 
23
19
  var _useAsyncMode = _interopRequireDefault(require("../async-mode-provider/use-async-mode"));
24
20
 
25
- /**
26
- * External dependencies
27
- */
28
-
29
21
  /**
30
22
  * WordPress dependencies
31
23
  */
@@ -33,8 +25,6 @@ var _useAsyncMode = _interopRequireDefault(require("../async-mode-provider/use-a
33
25
  /**
34
26
  * Internal dependencies
35
27
  */
36
- const noop = () => {};
37
-
38
28
  const renderQueue = (0, _priorityQueue.createQueue)();
39
29
  /**
40
30
  * @typedef {import('../../types').StoreDescriptor<C>} StoreDescriptor
@@ -53,6 +43,129 @@ const renderQueue = (0, _priorityQueue.createQueue)();
53
43
 
54
44
  /** @typedef {import('../../types').MapSelect} MapSelect */
55
45
 
46
+ function Store(registry, suspense) {
47
+ const select = suspense ? registry.suspendSelect : registry.select;
48
+ const queueContext = {};
49
+ let lastMapSelect;
50
+ let lastMapResult;
51
+ let lastMapResultValid = false;
52
+ let lastIsAsync;
53
+ let subscribe;
54
+
55
+ const createSubscriber = stores => listener => {
56
+ // Invalidate the value right after subscription was created. React will
57
+ // call `getValue` after subscribing, to detect store updates that happened
58
+ // in the interval between the `getValue` call during render and creating
59
+ // the subscription, which is slightly delayed. We need to ensure that this
60
+ // second `getValue` call will compute a fresh value.
61
+ lastMapResultValid = false;
62
+
63
+ const onStoreChange = () => {
64
+ // Invalidate the value on store update, so that a fresh value is computed.
65
+ lastMapResultValid = false;
66
+ listener();
67
+ };
68
+
69
+ const onChange = () => {
70
+ if (lastIsAsync) {
71
+ renderQueue.add(queueContext, onStoreChange);
72
+ } else {
73
+ onStoreChange();
74
+ }
75
+ };
76
+
77
+ const unsubs = stores.map(storeName => {
78
+ return registry.subscribe(onChange, storeName);
79
+ });
80
+ return () => {
81
+ // The return value of the subscribe function could be undefined if the store is a custom generic store.
82
+ for (const unsub of unsubs) {
83
+ unsub === null || unsub === void 0 ? void 0 : unsub();
84
+ } // Cancel existing store updates that were already scheduled.
85
+
86
+
87
+ renderQueue.cancel(queueContext);
88
+ };
89
+ };
90
+
91
+ return (mapSelect, resubscribe, isAsync) => {
92
+ const selectValue = () => mapSelect(select, registry);
93
+
94
+ function updateValue(selectFromStore) {
95
+ // If the last value is valid, and the `mapSelect` callback hasn't changed,
96
+ // then we can safely return the cached value. The value can change only on
97
+ // store update, and in that case value will be invalidated by the listener.
98
+ if (lastMapResultValid && mapSelect === lastMapSelect) {
99
+ return lastMapResult;
100
+ }
101
+
102
+ const mapResult = selectFromStore(); // If the new value is shallow-equal to the old one, keep the old one so
103
+ // that we don't trigger unwanted updates that do a `===` check.
104
+
105
+ if (!(0, _isShallowEqual.default)(lastMapResult, mapResult)) {
106
+ lastMapResult = mapResult;
107
+ }
108
+
109
+ lastMapResultValid = true;
110
+ }
111
+
112
+ function getValue() {
113
+ // Update the value in case it's been invalidated or `mapSelect` has changed.
114
+ updateValue(selectValue);
115
+ return lastMapResult;
116
+ } // When transitioning from async to sync mode, cancel existing store updates
117
+ // that have been scheduled, and invalidate the value so that it's freshly
118
+ // computed. It might have been changed by the update we just cancelled.
119
+
120
+
121
+ if (lastIsAsync && !isAsync) {
122
+ lastMapResultValid = false;
123
+ renderQueue.cancel(queueContext);
124
+ } // Either initialize the `subscribe` function, or create a new one if `mapSelect`
125
+ // changed and has dependencies.
126
+ // Usage without dependencies, `useSelect( ( s ) => { ... } )`, will subscribe
127
+ // only once, at mount, and won't resubscibe even if `mapSelect` changes.
128
+
129
+
130
+ if (!subscribe || resubscribe && mapSelect !== lastMapSelect) {
131
+ // Find out what stores the `mapSelect` callback is selecting from and
132
+ // use that list to create subscriptions to specific stores.
133
+ const listeningStores = {
134
+ current: null
135
+ };
136
+ updateValue(() => registry.__unstableMarkListeningStores(selectValue, listeningStores));
137
+ subscribe = createSubscriber(listeningStores.current);
138
+ } else {
139
+ updateValue(selectValue);
140
+ }
141
+
142
+ lastIsAsync = isAsync;
143
+ lastMapSelect = mapSelect; // Return a pair of functions that can be passed to `useSyncExternalStore`.
144
+
145
+ return {
146
+ subscribe,
147
+ getValue
148
+ };
149
+ };
150
+ }
151
+
152
+ function useStaticSelect(storeName) {
153
+ return (0, _useRegistry.default)().select(storeName);
154
+ }
155
+
156
+ function useMappingSelect(suspense, mapSelect, deps) {
157
+ const registry = (0, _useRegistry.default)();
158
+ const isAsync = (0, _useAsyncMode.default)();
159
+ const store = (0, _element.useMemo)(() => Store(registry, suspense), [registry]);
160
+ const selector = (0, _element.useCallback)(mapSelect, deps);
161
+ const {
162
+ subscribe,
163
+ getValue
164
+ } = store(selector, !!deps, isAsync);
165
+ const result = (0, _element.useSyncExternalStore)(subscribe, getValue, getValue);
166
+ (0, _element.useDebugValue)(result);
167
+ return result;
168
+ }
56
169
  /**
57
170
  * Custom react hook for retrieving props from registered selectors.
58
171
  *
@@ -118,140 +231,25 @@ const renderQueue = (0, _priorityQueue.createQueue)();
118
231
  * @return {UseSelectReturn<T>} A custom react hook.
119
232
  */
120
233
 
121
- function useSelect(mapSelect, deps) {
122
- const hasMappingFunction = 'function' === typeof mapSelect; // If we're recalling a store by its name or by
123
- // its descriptor then we won't be caching the
124
- // calls to `mapSelect` because we won't be calling it.
125
-
126
- if (!hasMappingFunction) {
127
- deps = [];
128
- } // Because of the "rule of hooks" we have to call `useCallback`
129
- // on every invocation whether or not we have a real function
130
- // for `mapSelect`. we'll create this intermediate variable to
131
- // fulfill that need and then reference it with our "real"
132
- // `_mapSelect` if we can.
133
-
134
-
135
- const callbackMapper = (0, _element.useCallback)(hasMappingFunction ? mapSelect : noop, deps);
136
234
 
137
- const _mapSelect = hasMappingFunction ? callbackMapper : null;
138
-
139
- const registry = (0, _useRegistry.default)();
140
- const isAsync = (0, _useAsyncMode.default)();
141
- const latestRegistry = (0, _element.useRef)(registry);
142
- const latestMapSelect = (0, _element.useRef)();
143
- const latestIsAsync = (0, _element.useRef)(isAsync);
144
- const latestMapOutput = (0, _element.useRef)();
145
- const latestMapOutputError = (0, _element.useRef)(); // Keep track of the stores being selected in the _mapSelect function,
146
- // and only subscribe to those stores later.
147
-
148
- const listeningStores = (0, _element.useRef)([]);
149
- const wrapSelect = (0, _element.useCallback)(callback => registry.__unstableMarkListeningStores(() => callback(registry.select, registry), listeningStores), [registry]); // Generate a "flag" for used in the effect dependency array.
150
- // It's different than just using `mapSelect` since deps could be undefined,
151
- // in that case, we would still want to memoize it.
152
-
153
- const depsChangedFlag = (0, _element.useMemo)(() => ({}), deps || []);
154
- let mapOutput;
155
- let selectorRan = false;
156
-
157
- if (_mapSelect) {
158
- mapOutput = latestMapOutput.current;
159
- const hasReplacedRegistry = latestRegistry.current !== registry;
160
- const hasReplacedMapSelect = latestMapSelect.current !== _mapSelect;
161
- const hasLeftAsyncMode = latestIsAsync.current && !isAsync;
162
- const lastMapSelectFailed = !!latestMapOutputError.current;
163
-
164
- if (hasReplacedRegistry || hasReplacedMapSelect || hasLeftAsyncMode || lastMapSelectFailed) {
165
- try {
166
- mapOutput = wrapSelect(_mapSelect);
167
- selectorRan = true;
168
- } catch (error) {
169
- let errorMessage = `An error occurred while running 'mapSelect': ${error.message}`;
170
-
171
- if (latestMapOutputError.current) {
172
- errorMessage += `\nThe error may be correlated with this previous error:\n`;
173
- errorMessage += `${latestMapOutputError.current.stack}\n\n`;
174
- errorMessage += 'Original stack trace:';
175
- } // eslint-disable-next-line no-console
176
-
177
-
178
- console.error(errorMessage);
179
- }
180
- }
235
+ function useSelect(mapSelect, deps) {
236
+ // On initial call, on mount, determine the mode of this `useSelect` call
237
+ // and then never allow it to change on subsequent updates.
238
+ const staticSelectMode = typeof mapSelect !== 'function';
239
+ const staticSelectModeRef = (0, _element.useRef)(staticSelectMode);
240
+
241
+ if (staticSelectMode !== staticSelectModeRef.current) {
242
+ const prevMode = staticSelectModeRef.current ? 'static' : 'mapping';
243
+ const nextMode = staticSelectMode ? 'static' : 'mapping';
244
+ throw new Error(`Switching useSelect from ${prevMode} to ${nextMode} is not allowed`);
181
245
  }
246
+ /* eslint-disable react-hooks/rules-of-hooks */
247
+ // `staticSelectMode` is not allowed to change during the hook instance's,
248
+ // lifetime, so the rules of hooks are not really violated.
182
249
 
183
- (0, _compose.useIsomorphicLayoutEffect)(() => {
184
- if (!hasMappingFunction) {
185
- return;
186
- }
187
250
 
188
- latestRegistry.current = registry;
189
- latestMapSelect.current = _mapSelect;
190
- latestIsAsync.current = isAsync;
191
-
192
- if (selectorRan) {
193
- latestMapOutput.current = mapOutput;
194
- }
195
-
196
- latestMapOutputError.current = undefined;
197
- }); // React can sometimes clear the `useMemo` cache.
198
- // We use the cache-stable `useMemoOne` to avoid
199
- // losing queues.
200
-
201
- const queueContext = (0, _useMemoOne.useMemoOne)(() => ({
202
- queue: true
203
- }), [registry]);
204
- const [, forceRender] = (0, _element.useReducer)(s => s + 1, 0);
205
- const isMounted = (0, _element.useRef)(false);
206
- (0, _compose.useIsomorphicLayoutEffect)(() => {
207
- if (!hasMappingFunction) {
208
- return;
209
- }
210
-
211
- const onStoreChange = () => {
212
- try {
213
- const newMapOutput = wrapSelect(latestMapSelect.current);
214
-
215
- if ((0, _isShallowEqual.default)(latestMapOutput.current, newMapOutput)) {
216
- return;
217
- }
218
-
219
- latestMapOutput.current = newMapOutput;
220
- } catch (error) {
221
- latestMapOutputError.current = error;
222
- }
223
-
224
- forceRender();
225
- };
226
-
227
- const onChange = () => {
228
- if (!isMounted.current) {
229
- return;
230
- }
231
-
232
- if (latestIsAsync.current) {
233
- renderQueue.add(queueContext, onStoreChange);
234
- } else {
235
- onStoreChange();
236
- }
237
- }; // Catch any possible state changes during mount before the subscription
238
- // could be set.
239
-
240
-
241
- onStoreChange();
242
- const unsubscribers = listeningStores.current.map(storeName => registry.subscribe(onChange, storeName));
243
- isMounted.current = true;
244
- return () => {
245
- // The return value of the subscribe function could be undefined if the store is a custom generic store.
246
- unsubscribers.forEach(unsubscribe => unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe());
247
- renderQueue.cancel(queueContext);
248
- isMounted.current = false;
249
- }; // If you're tempted to eliminate the spread dependencies below don't do it!
250
- // We're passing these in from the calling function and want to make sure we're
251
- // examining every individual value inside the `deps` array.
252
- }, [registry, wrapSelect, hasMappingFunction, depsChangedFlag]);
253
- (0, _element.useDebugValue)(mapOutput);
254
- return hasMappingFunction ? mapOutput : registry.select(mapSelect);
251
+ return staticSelectMode ? useStaticSelect(mapSelect) : useMappingSelect(false, mapSelect, deps);
252
+ /* eslint-enable react-hooks/rules-of-hooks */
255
253
  }
256
254
  /**
257
255
  * A variant of the `useSelect` hook that has the same API, but will throw a
@@ -271,104 +269,6 @@ function useSelect(mapSelect, deps) {
271
269
 
272
270
 
273
271
  function useSuspenseSelect(mapSelect, deps) {
274
- const _mapSelect = (0, _element.useCallback)(mapSelect, deps);
275
-
276
- const registry = (0, _useRegistry.default)();
277
- const isAsync = (0, _useAsyncMode.default)();
278
- const latestRegistry = (0, _element.useRef)(registry);
279
- const latestMapSelect = (0, _element.useRef)();
280
- const latestIsAsync = (0, _element.useRef)(isAsync);
281
- const latestMapOutput = (0, _element.useRef)();
282
- const latestMapOutputError = (0, _element.useRef)(); // Keep track of the stores being selected in the `mapSelect` function,
283
- // and only subscribe to those stores later.
284
-
285
- const listeningStores = (0, _element.useRef)([]);
286
- const wrapSelect = (0, _element.useCallback)(callback => registry.__unstableMarkListeningStores(() => callback(registry.suspendSelect, registry), listeningStores), [registry]); // Generate a "flag" for used in the effect dependency array.
287
- // It's different than just using `mapSelect` since deps could be undefined,
288
- // in that case, we would still want to memoize it.
289
-
290
- const depsChangedFlag = (0, _element.useMemo)(() => ({}), deps || []);
291
- let mapOutput = latestMapOutput.current;
292
- let mapOutputError = latestMapOutputError.current;
293
- const hasReplacedRegistry = latestRegistry.current !== registry;
294
- const hasReplacedMapSelect = latestMapSelect.current !== _mapSelect;
295
- const hasLeftAsyncMode = latestIsAsync.current && !isAsync;
296
- let selectorRan = false;
297
-
298
- if (hasReplacedRegistry || hasReplacedMapSelect || hasLeftAsyncMode) {
299
- try {
300
- mapOutput = wrapSelect(_mapSelect);
301
- selectorRan = true;
302
- } catch (error) {
303
- mapOutputError = error;
304
- }
305
- }
306
-
307
- (0, _compose.useIsomorphicLayoutEffect)(() => {
308
- latestRegistry.current = registry;
309
- latestMapSelect.current = _mapSelect;
310
- latestIsAsync.current = isAsync;
311
-
312
- if (selectorRan) {
313
- latestMapOutput.current = mapOutput;
314
- }
315
-
316
- latestMapOutputError.current = mapOutputError;
317
- }); // React can sometimes clear the `useMemo` cache.
318
- // We use the cache-stable `useMemoOne` to avoid
319
- // losing queues.
320
-
321
- const queueContext = (0, _useMemoOne.useMemoOne)(() => ({
322
- queue: true
323
- }), [registry]);
324
- const [, forceRender] = (0, _element.useReducer)(s => s + 1, 0);
325
- const isMounted = (0, _element.useRef)(false);
326
- (0, _compose.useIsomorphicLayoutEffect)(() => {
327
- const onStoreChange = () => {
328
- try {
329
- const newMapOutput = wrapSelect(latestMapSelect.current);
330
-
331
- if ((0, _isShallowEqual.default)(latestMapOutput.current, newMapOutput)) {
332
- return;
333
- }
334
-
335
- latestMapOutput.current = newMapOutput;
336
- } catch (error) {
337
- latestMapOutputError.current = error;
338
- }
339
-
340
- forceRender();
341
- };
342
-
343
- const onChange = () => {
344
- if (!isMounted.current) {
345
- return;
346
- }
347
-
348
- if (latestIsAsync.current) {
349
- renderQueue.add(queueContext, onStoreChange);
350
- } else {
351
- onStoreChange();
352
- }
353
- }; // catch any possible state changes during mount before the subscription
354
- // could be set.
355
-
356
-
357
- onStoreChange();
358
- const unsubscribers = listeningStores.current.map(storeName => registry.subscribe(onChange, storeName));
359
- isMounted.current = true;
360
- return () => {
361
- // The return value of the subscribe function could be undefined if the store is a custom generic store.
362
- unsubscribers.forEach(unsubscribe => unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe());
363
- renderQueue.cancel(queueContext);
364
- isMounted.current = false;
365
- };
366
- }, [registry, wrapSelect, depsChangedFlag]);
367
-
368
- if (mapOutputError) {
369
- throw mapOutputError;
370
- }
371
-
372
- return mapOutput;
272
+ return useMappingSelect(true, mapSelect, deps);
373
273
  }
374
274
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["@wordpress/data/src/components/use-select/index.js"],"names":["noop","renderQueue","useSelect","mapSelect","deps","hasMappingFunction","callbackMapper","_mapSelect","registry","isAsync","latestRegistry","latestMapSelect","latestIsAsync","latestMapOutput","latestMapOutputError","listeningStores","wrapSelect","callback","__unstableMarkListeningStores","select","depsChangedFlag","mapOutput","selectorRan","current","hasReplacedRegistry","hasReplacedMapSelect","hasLeftAsyncMode","lastMapSelectFailed","error","errorMessage","message","stack","console","undefined","queueContext","queue","forceRender","s","isMounted","onStoreChange","newMapOutput","onChange","add","unsubscribers","map","storeName","subscribe","forEach","unsubscribe","cancel","useSuspenseSelect","suspendSelect","mapOutputError"],"mappings":";;;;;;;;;;AAGA;;AAKA;;AACA;;AAOA;;AACA;;AAKA;;AACA;;AAvBA;AACA;AACA;;AAGA;AACA;AACA;;AAYA;AACA;AACA;AAIA,MAAMA,IAAI,GAAG,MAAM,CAAE,CAArB;;AACA,MAAMC,WAAW,GAAG,iCAApB;AAEA;AACA;AACA;AACA;;AACA;AACA;AACA;AACA;;AACA;AACA;AACA;AACA;;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACe,SAASC,SAAT,CAAoBC,SAApB,EAA+BC,IAA/B,EAAsC;AACpD,QAAMC,kBAAkB,GAAG,eAAe,OAAOF,SAAjD,CADoD,CAGpD;AACA;AACA;;AACA,MAAK,CAAEE,kBAAP,EAA4B;AAC3BD,IAAAA,IAAI,GAAG,EAAP;AACA,GARmD,CAUpD;AACA;AACA;AACA;AACA;;;AACA,QAAME,cAAc,GAAG,0BACtBD,kBAAkB,GAAGF,SAAH,GAAeH,IADX,EAEtBI,IAFsB,CAAvB;;AAIA,QAAMG,UAAU,GAAGF,kBAAkB,GAAGC,cAAH,GAAoB,IAAzD;;AAEA,QAAME,QAAQ,GAAG,2BAAjB;AACA,QAAMC,OAAO,GAAG,4BAAhB;AAEA,QAAMC,cAAc,GAAG,qBAAQF,QAAR,CAAvB;AACA,QAAMG,eAAe,GAAG,sBAAxB;AACA,QAAMC,aAAa,GAAG,qBAAQH,OAAR,CAAtB;AACA,QAAMI,eAAe,GAAG,sBAAxB;AACA,QAAMC,oBAAoB,GAAG,sBAA7B,CA5BoD,CA8BpD;AACA;;AACA,QAAMC,eAAe,GAAG,qBAAQ,EAAR,CAAxB;AACA,QAAMC,UAAU,GAAG,0BAChBC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","sourcesContent":["/**\n * External dependencies\n */\nimport { useMemoOne } from 'use-memo-one';\n\n/**\n * WordPress dependencies\n */\nimport { createQueue } from '@wordpress/priority-queue';\nimport {\n\tuseRef,\n\tuseCallback,\n\tuseMemo,\n\tuseReducer,\n\tuseDebugValue,\n} from '@wordpress/element';\nimport isShallowEqual from '@wordpress/is-shallow-equal';\nimport { useIsomorphicLayoutEffect } from '@wordpress/compose';\n\n/**\n * Internal dependencies\n */\nimport useRegistry from '../registry-provider/use-registry';\nimport useAsyncMode from '../async-mode-provider/use-async-mode';\n\nconst noop = () => {};\nconst renderQueue = createQueue();\n\n/**\n * @typedef {import('../../types').StoreDescriptor<C>} StoreDescriptor\n * @template C\n */\n/**\n * @typedef {import('../../types').ReduxStoreConfig<State,Actions,Selectors>} ReduxStoreConfig\n * @template State,Actions,Selectors\n */\n/**\n * @typedef {import('../../types').UseSelectReturn<T>} UseSelectReturn\n * @template T\n */\n/** @typedef {import('../../types').MapSelect} MapSelect */\n\n/**\n * Custom react hook for retrieving props from registered selectors.\n *\n * In general, this custom React hook follows the\n * [rules of hooks](https://reactjs.org/docs/hooks-rules.html).\n *\n * @template {MapSelect | StoreDescriptor<any>} T\n * @param {T} mapSelect Function called on every state change. The returned value is\n * exposed to the component implementing this hook. The function\n * receives the `registry.select` method on the first argument\n * and the `registry` on the second argument.\n * When a store key is passed, all selectors for the store will be\n * returned. This is only meant for usage of these selectors in event\n * callbacks, not for data needed to create the element tree.\n * @param {unknown[]} deps If provided, this memoizes the mapSelect so the same `mapSelect` is\n * invoked on every state change unless the dependencies change.\n *\n * @example\n * ```js\n * import { useSelect } from '@wordpress/data';\n * import { store as myCustomStore } from 'my-custom-store';\n *\n * function HammerPriceDisplay( { currency } ) {\n * const price = useSelect( ( select ) => {\n * return select( myCustomStore ).getPrice( 'hammer', currency );\n * }, [ currency ] );\n * return new Intl.NumberFormat( 'en-US', {\n * style: 'currency',\n * currency,\n * } ).format( price );\n * }\n *\n * // Rendered in the application:\n * // <HammerPriceDisplay currency=\"USD\" />\n * ```\n *\n * In the above example, when `HammerPriceDisplay` is rendered into an\n * application, the price will be retrieved from the store state using the\n * `mapSelect` callback on `useSelect`. If the currency prop changes then\n * any price in the state for that currency is retrieved. If the currency prop\n * doesn't change and other props are passed in that do change, the price will\n * not change because the dependency is just the currency.\n *\n * When data is only used in an event callback, the data should not be retrieved\n * on render, so it may be useful to get the selectors function instead.\n *\n * **Don't use `useSelect` this way when calling the selectors in the render\n * function because your component won't re-render on a data change.**\n *\n * ```js\n * import { useSelect } from '@wordpress/data';\n * import { store as myCustomStore } from 'my-custom-store';\n *\n * function Paste( { children } ) {\n * const { getSettings } = useSelect( myCustomStore );\n * function onPaste() {\n * // Do something with the settings.\n * const settings = getSettings();\n * }\n * return <div onPaste={ onPaste }>{ children }</div>;\n * }\n * ```\n * @return {UseSelectReturn<T>} A custom react hook.\n */\nexport default function useSelect( mapSelect, deps ) {\n\tconst hasMappingFunction = 'function' === typeof mapSelect;\n\n\t// If we're recalling a store by its name or by\n\t// its descriptor then we won't be caching the\n\t// calls to `mapSelect` because we won't be calling it.\n\tif ( ! hasMappingFunction ) {\n\t\tdeps = [];\n\t}\n\n\t// Because of the \"rule of hooks\" we have to call `useCallback`\n\t// on every invocation whether or not we have a real function\n\t// for `mapSelect`. we'll create this intermediate variable to\n\t// fulfill that need and then reference it with our \"real\"\n\t// `_mapSelect` if we can.\n\tconst callbackMapper = useCallback(\n\t\thasMappingFunction ? mapSelect : noop,\n\t\tdeps\n\t);\n\tconst _mapSelect = hasMappingFunction ? callbackMapper : null;\n\n\tconst registry = useRegistry();\n\tconst isAsync = useAsyncMode();\n\n\tconst latestRegistry = useRef( registry );\n\tconst latestMapSelect = useRef();\n\tconst latestIsAsync = useRef( isAsync );\n\tconst latestMapOutput = useRef();\n\tconst latestMapOutputError = useRef();\n\n\t// Keep track of the stores being selected in the _mapSelect function,\n\t// and only subscribe to those stores later.\n\tconst listeningStores = useRef( [] );\n\tconst wrapSelect = useCallback(\n\t\t( callback ) =>\n\t\t\tregistry.__unstableMarkListeningStores(\n\t\t\t\t() => callback( registry.select, registry ),\n\t\t\t\tlisteningStores\n\t\t\t),\n\t\t[ registry ]\n\t);\n\n\t// Generate a \"flag\" for used in the effect dependency array.\n\t// It's different than just using `mapSelect` since deps could be undefined,\n\t// in that case, we would still want to memoize it.\n\tconst depsChangedFlag = useMemo( () => ( {} ), deps || [] );\n\n\tlet mapOutput;\n\n\tlet selectorRan = false;\n\tif ( _mapSelect ) {\n\t\tmapOutput = latestMapOutput.current;\n\t\tconst hasReplacedRegistry = latestRegistry.current !== registry;\n\t\tconst hasReplacedMapSelect = latestMapSelect.current !== _mapSelect;\n\t\tconst hasLeftAsyncMode = latestIsAsync.current && ! isAsync;\n\t\tconst lastMapSelectFailed = !! latestMapOutputError.current;\n\n\t\tif (\n\t\t\thasReplacedRegistry ||\n\t\t\thasReplacedMapSelect ||\n\t\t\thasLeftAsyncMode ||\n\t\t\tlastMapSelectFailed\n\t\t) {\n\t\t\ttry {\n\t\t\t\tmapOutput = wrapSelect( _mapSelect );\n\t\t\t\tselectorRan = true;\n\t\t\t} catch ( error ) {\n\t\t\t\tlet errorMessage = `An error occurred while running 'mapSelect': ${ error.message }`;\n\n\t\t\t\tif ( latestMapOutputError.current ) {\n\t\t\t\t\terrorMessage += `\\nThe error may be correlated with this previous error:\\n`;\n\t\t\t\t\terrorMessage += `${ latestMapOutputError.current.stack }\\n\\n`;\n\t\t\t\t\terrorMessage += 'Original stack trace:';\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error( errorMessage );\n\t\t\t}\n\t\t}\n\t}\n\n\tuseIsomorphicLayoutEffect( () => {\n\t\tif ( ! hasMappingFunction ) {\n\t\t\treturn;\n\t\t}\n\n\t\tlatestRegistry.current = registry;\n\t\tlatestMapSelect.current = _mapSelect;\n\t\tlatestIsAsync.current = isAsync;\n\t\tif ( selectorRan ) {\n\t\t\tlatestMapOutput.current = mapOutput;\n\t\t}\n\t\tlatestMapOutputError.current = undefined;\n\t} );\n\n\t// React can sometimes clear the `useMemo` cache.\n\t// We use the cache-stable `useMemoOne` to avoid\n\t// losing queues.\n\tconst queueContext = useMemoOne( () => ( { queue: true } ), [ registry ] );\n\tconst [ , forceRender ] = useReducer( ( s ) => s + 1, 0 );\n\tconst isMounted = useRef( false );\n\n\tuseIsomorphicLayoutEffect( () => {\n\t\tif ( ! hasMappingFunction ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst onStoreChange = () => {\n\t\t\ttry {\n\t\t\t\tconst newMapOutput = wrapSelect( latestMapSelect.current );\n\n\t\t\t\tif ( isShallowEqual( latestMapOutput.current, newMapOutput ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlatestMapOutput.current = newMapOutput;\n\t\t\t} catch ( error ) {\n\t\t\t\tlatestMapOutputError.current = error;\n\t\t\t}\n\t\t\tforceRender();\n\t\t};\n\n\t\tconst onChange = () => {\n\t\t\tif ( ! isMounted.current ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( latestIsAsync.current ) {\n\t\t\t\trenderQueue.add( queueContext, onStoreChange );\n\t\t\t} else {\n\t\t\t\tonStoreChange();\n\t\t\t}\n\t\t};\n\n\t\t// Catch any possible state changes during mount before the subscription\n\t\t// could be set.\n\t\tonStoreChange();\n\n\t\tconst unsubscribers = listeningStores.current.map( ( storeName ) =>\n\t\t\tregistry.subscribe( onChange, storeName )\n\t\t);\n\n\t\tisMounted.current = true;\n\n\t\treturn () => {\n\t\t\t// The return value of the subscribe function could be undefined if the store is a custom generic store.\n\t\t\tunsubscribers.forEach( ( unsubscribe ) => unsubscribe?.() );\n\t\t\trenderQueue.cancel( queueContext );\n\t\t\tisMounted.current = false;\n\t\t};\n\t\t// If you're tempted to eliminate the spread dependencies below don't do it!\n\t\t// We're passing these in from the calling function and want to make sure we're\n\t\t// examining every individual value inside the `deps` array.\n\t}, [ registry, wrapSelect, hasMappingFunction, depsChangedFlag ] );\n\n\tuseDebugValue( mapOutput );\n\n\treturn hasMappingFunction ? mapOutput : registry.select( mapSelect );\n}\n\n/**\n * A variant of the `useSelect` hook that has the same API, but will throw a\n * suspense Promise if any of the called selectors is in an unresolved state.\n *\n * @param {Function} mapSelect Function called on every state change. The\n * returned value is exposed to the component\n * using this hook. The function receives the\n * `registry.suspendSelect` method as the first\n * argument and the `registry` as the second one.\n * @param {Array} deps A dependency array used to memoize the `mapSelect`\n * so that the same `mapSelect` is invoked on every\n * state change unless the dependencies change.\n *\n * @return {Object} Data object returned by the `mapSelect` function.\n */\nexport function useSuspenseSelect( mapSelect, deps ) {\n\tconst _mapSelect = useCallback( mapSelect, deps );\n\n\tconst registry = useRegistry();\n\tconst isAsync = useAsyncMode();\n\n\tconst latestRegistry = useRef( registry );\n\tconst latestMapSelect = useRef();\n\tconst latestIsAsync = useRef( isAsync );\n\tconst latestMapOutput = useRef();\n\tconst latestMapOutputError = useRef();\n\n\t// Keep track of the stores being selected in the `mapSelect` function,\n\t// and only subscribe to those stores later.\n\tconst listeningStores = useRef( [] );\n\tconst wrapSelect = useCallback(\n\t\t( callback ) =>\n\t\t\tregistry.__unstableMarkListeningStores(\n\t\t\t\t() => callback( registry.suspendSelect, registry ),\n\t\t\t\tlisteningStores\n\t\t\t),\n\t\t[ registry ]\n\t);\n\n\t// Generate a \"flag\" for used in the effect dependency array.\n\t// It's different than just using `mapSelect` since deps could be undefined,\n\t// in that case, we would still want to memoize it.\n\tconst depsChangedFlag = useMemo( () => ( {} ), deps || [] );\n\n\tlet mapOutput = latestMapOutput.current;\n\tlet mapOutputError = latestMapOutputError.current;\n\n\tconst hasReplacedRegistry = latestRegistry.current !== registry;\n\tconst hasReplacedMapSelect = latestMapSelect.current !== _mapSelect;\n\tconst hasLeftAsyncMode = latestIsAsync.current && ! isAsync;\n\n\tlet selectorRan = false;\n\tif ( hasReplacedRegistry || hasReplacedMapSelect || hasLeftAsyncMode ) {\n\t\ttry {\n\t\t\tmapOutput = wrapSelect( _mapSelect );\n\t\t\tselectorRan = true;\n\t\t} catch ( error ) {\n\t\t\tmapOutputError = error;\n\t\t}\n\t}\n\n\tuseIsomorphicLayoutEffect( () => {\n\t\tlatestRegistry.current = registry;\n\t\tlatestMapSelect.current = _mapSelect;\n\t\tlatestIsAsync.current = isAsync;\n\t\tif ( selectorRan ) {\n\t\t\tlatestMapOutput.current = mapOutput;\n\t\t}\n\t\tlatestMapOutputError.current = mapOutputError;\n\t} );\n\n\t// React can sometimes clear the `useMemo` cache.\n\t// We use the cache-stable `useMemoOne` to avoid\n\t// losing queues.\n\tconst queueContext = useMemoOne( () => ( { queue: true } ), [ registry ] );\n\tconst [ , forceRender ] = useReducer( ( s ) => s + 1, 0 );\n\tconst isMounted = useRef( false );\n\n\tuseIsomorphicLayoutEffect( () => {\n\t\tconst onStoreChange = () => {\n\t\t\ttry {\n\t\t\t\tconst newMapOutput = wrapSelect( latestMapSelect.current );\n\n\t\t\t\tif ( isShallowEqual( latestMapOutput.current, newMapOutput ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlatestMapOutput.current = newMapOutput;\n\t\t\t} catch ( error ) {\n\t\t\t\tlatestMapOutputError.current = error;\n\t\t\t}\n\n\t\t\tforceRender();\n\t\t};\n\n\t\tconst onChange = () => {\n\t\t\tif ( ! isMounted.current ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( latestIsAsync.current ) {\n\t\t\t\trenderQueue.add( queueContext, onStoreChange );\n\t\t\t} else {\n\t\t\t\tonStoreChange();\n\t\t\t}\n\t\t};\n\n\t\t// catch any possible state changes during mount before the subscription\n\t\t// could be set.\n\t\tonStoreChange();\n\n\t\tconst unsubscribers = listeningStores.current.map( ( storeName ) =>\n\t\t\tregistry.subscribe( onChange, storeName )\n\t\t);\n\n\t\tisMounted.current = true;\n\n\t\treturn () => {\n\t\t\t// The return value of the subscribe function could be undefined if the store is a custom generic store.\n\t\t\tunsubscribers.forEach( ( unsubscribe ) => unsubscribe?.() );\n\t\t\trenderQueue.cancel( queueContext );\n\t\t\tisMounted.current = false;\n\t\t};\n\t}, [ registry, wrapSelect, depsChangedFlag ] );\n\n\tif ( mapOutputError ) {\n\t\tthrow mapOutputError;\n\t}\n\n\treturn mapOutput;\n}\n"]}
1
+ {"version":3,"sources":["@wordpress/data/src/components/use-select/index.js"],"names":["renderQueue","Store","registry","suspense","select","suspendSelect","queueContext","lastMapSelect","lastMapResult","lastMapResultValid","lastIsAsync","subscribe","createSubscriber","stores","listener","onStoreChange","onChange","add","unsubs","map","storeName","unsub","cancel","mapSelect","resubscribe","isAsync","selectValue","updateValue","selectFromStore","mapResult","getValue","listeningStores","current","__unstableMarkListeningStores","useStaticSelect","useMappingSelect","deps","store","selector","result","useSelect","staticSelectMode","staticSelectModeRef","prevMode","nextMode","Error","useSuspenseSelect"],"mappings":"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","sourcesContent":["/**\n * WordPress dependencies\n */\nimport { createQueue } from '@wordpress/priority-queue';\nimport {\n\tuseRef,\n\tuseCallback,\n\tuseMemo,\n\tuseSyncExternalStore,\n\tuseDebugValue,\n} from '@wordpress/element';\nimport isShallowEqual from '@wordpress/is-shallow-equal';\n\n/**\n * Internal dependencies\n */\nimport useRegistry from '../registry-provider/use-registry';\nimport useAsyncMode from '../async-mode-provider/use-async-mode';\n\nconst renderQueue = createQueue();\n\n/**\n * @typedef {import('../../types').StoreDescriptor<C>} StoreDescriptor\n * @template C\n */\n/**\n * @typedef {import('../../types').ReduxStoreConfig<State,Actions,Selectors>} ReduxStoreConfig\n * @template State,Actions,Selectors\n */\n/**\n * @typedef {import('../../types').UseSelectReturn<T>} UseSelectReturn\n * @template T\n */\n/** @typedef {import('../../types').MapSelect} MapSelect */\n\nfunction Store( registry, suspense ) {\n\tconst select = suspense ? registry.suspendSelect : registry.select;\n\tconst queueContext = {};\n\tlet lastMapSelect;\n\tlet lastMapResult;\n\tlet lastMapResultValid = false;\n\tlet lastIsAsync;\n\tlet subscribe;\n\n\tconst createSubscriber = ( stores ) => ( listener ) => {\n\t\t// Invalidate the value right after subscription was created. React will\n\t\t// call `getValue` after subscribing, to detect store updates that happened\n\t\t// in the interval between the `getValue` call during render and creating\n\t\t// the subscription, which is slightly delayed. We need to ensure that this\n\t\t// second `getValue` call will compute a fresh value.\n\t\tlastMapResultValid = false;\n\n\t\tconst onStoreChange = () => {\n\t\t\t// Invalidate the value on store update, so that a fresh value is computed.\n\t\t\tlastMapResultValid = false;\n\t\t\tlistener();\n\t\t};\n\n\t\tconst onChange = () => {\n\t\t\tif ( lastIsAsync ) {\n\t\t\t\trenderQueue.add( queueContext, onStoreChange );\n\t\t\t} else {\n\t\t\t\tonStoreChange();\n\t\t\t}\n\t\t};\n\n\t\tconst unsubs = stores.map( ( storeName ) => {\n\t\t\treturn registry.subscribe( onChange, storeName );\n\t\t} );\n\n\t\treturn () => {\n\t\t\t// The return value of the subscribe function could be undefined if the store is a custom generic store.\n\t\t\tfor ( const unsub of unsubs ) {\n\t\t\t\tunsub?.();\n\t\t\t}\n\t\t\t// Cancel existing store updates that were already scheduled.\n\t\t\trenderQueue.cancel( queueContext );\n\t\t};\n\t};\n\n\treturn ( mapSelect, resubscribe, isAsync ) => {\n\t\tconst selectValue = () => mapSelect( select, registry );\n\n\t\tfunction updateValue( selectFromStore ) {\n\t\t\t// If the last value is valid, and the `mapSelect` callback hasn't changed,\n\t\t\t// then we can safely return the cached value. The value can change only on\n\t\t\t// store update, and in that case value will be invalidated by the listener.\n\t\t\tif ( lastMapResultValid && mapSelect === lastMapSelect ) {\n\t\t\t\treturn lastMapResult;\n\t\t\t}\n\n\t\t\tconst mapResult = selectFromStore();\n\n\t\t\t// If the new value is shallow-equal to the old one, keep the old one so\n\t\t\t// that we don't trigger unwanted updates that do a `===` check.\n\t\t\tif ( ! isShallowEqual( lastMapResult, mapResult ) ) {\n\t\t\t\tlastMapResult = mapResult;\n\t\t\t}\n\t\t\tlastMapResultValid = true;\n\t\t}\n\n\t\tfunction getValue() {\n\t\t\t// Update the value in case it's been invalidated or `mapSelect` has changed.\n\t\t\tupdateValue( selectValue );\n\t\t\treturn lastMapResult;\n\t\t}\n\n\t\t// When transitioning from async to sync mode, cancel existing store updates\n\t\t// that have been scheduled, and invalidate the value so that it's freshly\n\t\t// computed. It might have been changed by the update we just cancelled.\n\t\tif ( lastIsAsync && ! isAsync ) {\n\t\t\tlastMapResultValid = false;\n\t\t\trenderQueue.cancel( queueContext );\n\t\t}\n\n\t\t// Either initialize the `subscribe` function, or create a new one if `mapSelect`\n\t\t// changed and has dependencies.\n\t\t// Usage without dependencies, `useSelect( ( s ) => { ... } )`, will subscribe\n\t\t// only once, at mount, and won't resubscibe even if `mapSelect` changes.\n\t\tif ( ! subscribe || ( resubscribe && mapSelect !== lastMapSelect ) ) {\n\t\t\t// Find out what stores the `mapSelect` callback is selecting from and\n\t\t\t// use that list to create subscriptions to specific stores.\n\t\t\tconst listeningStores = { current: null };\n\t\t\tupdateValue( () =>\n\t\t\t\tregistry.__unstableMarkListeningStores(\n\t\t\t\t\tselectValue,\n\t\t\t\t\tlisteningStores\n\t\t\t\t)\n\t\t\t);\n\t\t\tsubscribe = createSubscriber( listeningStores.current );\n\t\t} else {\n\t\t\tupdateValue( selectValue );\n\t\t}\n\n\t\tlastIsAsync = isAsync;\n\t\tlastMapSelect = mapSelect;\n\n\t\t// Return a pair of functions that can be passed to `useSyncExternalStore`.\n\t\treturn { subscribe, getValue };\n\t};\n}\n\nfunction useStaticSelect( storeName ) {\n\treturn useRegistry().select( storeName );\n}\n\nfunction useMappingSelect( suspense, mapSelect, deps ) {\n\tconst registry = useRegistry();\n\tconst isAsync = useAsyncMode();\n\tconst store = useMemo( () => Store( registry, suspense ), [ registry ] );\n\tconst selector = useCallback( mapSelect, deps );\n\tconst { subscribe, getValue } = store( selector, !! deps, isAsync );\n\tconst result = useSyncExternalStore( subscribe, getValue, getValue );\n\tuseDebugValue( result );\n\treturn result;\n}\n\n/**\n * Custom react hook for retrieving props from registered selectors.\n *\n * In general, this custom React hook follows the\n * [rules of hooks](https://reactjs.org/docs/hooks-rules.html).\n *\n * @template {MapSelect | StoreDescriptor<any>} T\n * @param {T} mapSelect Function called on every state change. The returned value is\n * exposed to the component implementing this hook. The function\n * receives the `registry.select` method on the first argument\n * and the `registry` on the second argument.\n * When a store key is passed, all selectors for the store will be\n * returned. This is only meant for usage of these selectors in event\n * callbacks, not for data needed to create the element tree.\n * @param {unknown[]} deps If provided, this memoizes the mapSelect so the same `mapSelect` is\n * invoked on every state change unless the dependencies change.\n *\n * @example\n * ```js\n * import { useSelect } from '@wordpress/data';\n * import { store as myCustomStore } from 'my-custom-store';\n *\n * function HammerPriceDisplay( { currency } ) {\n * const price = useSelect( ( select ) => {\n * return select( myCustomStore ).getPrice( 'hammer', currency );\n * }, [ currency ] );\n * return new Intl.NumberFormat( 'en-US', {\n * style: 'currency',\n * currency,\n * } ).format( price );\n * }\n *\n * // Rendered in the application:\n * // <HammerPriceDisplay currency=\"USD\" />\n * ```\n *\n * In the above example, when `HammerPriceDisplay` is rendered into an\n * application, the price will be retrieved from the store state using the\n * `mapSelect` callback on `useSelect`. If the currency prop changes then\n * any price in the state for that currency is retrieved. If the currency prop\n * doesn't change and other props are passed in that do change, the price will\n * not change because the dependency is just the currency.\n *\n * When data is only used in an event callback, the data should not be retrieved\n * on render, so it may be useful to get the selectors function instead.\n *\n * **Don't use `useSelect` this way when calling the selectors in the render\n * function because your component won't re-render on a data change.**\n *\n * ```js\n * import { useSelect } from '@wordpress/data';\n * import { store as myCustomStore } from 'my-custom-store';\n *\n * function Paste( { children } ) {\n * const { getSettings } = useSelect( myCustomStore );\n * function onPaste() {\n * // Do something with the settings.\n * const settings = getSettings();\n * }\n * return <div onPaste={ onPaste }>{ children }</div>;\n * }\n * ```\n * @return {UseSelectReturn<T>} A custom react hook.\n */\nexport default function useSelect( mapSelect, deps ) {\n\t// On initial call, on mount, determine the mode of this `useSelect` call\n\t// and then never allow it to change on subsequent updates.\n\tconst staticSelectMode = typeof mapSelect !== 'function';\n\tconst staticSelectModeRef = useRef( staticSelectMode );\n\n\tif ( staticSelectMode !== staticSelectModeRef.current ) {\n\t\tconst prevMode = staticSelectModeRef.current ? 'static' : 'mapping';\n\t\tconst nextMode = staticSelectMode ? 'static' : 'mapping';\n\t\tthrow new Error(\n\t\t\t`Switching useSelect from ${ prevMode } to ${ nextMode } is not allowed`\n\t\t);\n\t}\n\n\t/* eslint-disable react-hooks/rules-of-hooks */\n\t// `staticSelectMode` is not allowed to change during the hook instance's,\n\t// lifetime, so the rules of hooks are not really violated.\n\treturn staticSelectMode\n\t\t? useStaticSelect( mapSelect )\n\t\t: useMappingSelect( false, mapSelect, deps );\n\t/* eslint-enable react-hooks/rules-of-hooks */\n}\n\n/**\n * A variant of the `useSelect` hook that has the same API, but will throw a\n * suspense Promise if any of the called selectors is in an unresolved state.\n *\n * @param {Function} mapSelect Function called on every state change. The\n * returned value is exposed to the component\n * using this hook. The function receives the\n * `registry.suspendSelect` method as the first\n * argument and the `registry` as the second one.\n * @param {Array} deps A dependency array used to memoize the `mapSelect`\n * so that the same `mapSelect` is invoked on every\n * state change unless the dependencies change.\n *\n * @return {Object} Data object returned by the `mapSelect` function.\n */\nexport function useSuspenseSelect( mapSelect, deps ) {\n\treturn useMappingSelect( true, mapSelect, deps );\n}\n"]}
package/build/registry.js CHANGED
@@ -75,7 +75,7 @@ function createRegistry() {
75
75
  let parent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
76
76
  const stores = {};
77
77
  const emitter = (0, _emitter.createEmitter)();
78
- const listeningStores = new Set();
78
+ let listeningStores = null;
79
79
  /**
80
80
  * Global listener called for each store's update.
81
81
  */
@@ -129,8 +129,10 @@ function createRegistry() {
129
129
 
130
130
 
131
131
  function select(storeNameOrDescriptor) {
132
+ var _listeningStores;
133
+
132
134
  const storeName = getStoreName(storeNameOrDescriptor);
133
- listeningStores.add(storeName);
135
+ (_listeningStores = listeningStores) === null || _listeningStores === void 0 ? void 0 : _listeningStores.add(storeName);
134
136
  const store = stores[storeName];
135
137
 
136
138
  if (store) {
@@ -141,12 +143,13 @@ function createRegistry() {
141
143
  }
142
144
 
143
145
  function __unstableMarkListeningStores(callback, ref) {
144
- listeningStores.clear();
146
+ listeningStores = new Set();
145
147
 
146
148
  try {
147
149
  return callback.call(this);
148
150
  } finally {
149
151
  ref.current = Array.from(listeningStores);
152
+ listeningStores = null;
150
153
  }
151
154
  }
152
155
  /**
@@ -163,8 +166,10 @@ function createRegistry() {
163
166
 
164
167
 
165
168
  function resolveSelect(storeNameOrDescriptor) {
169
+ var _listeningStores2;
170
+
166
171
  const storeName = getStoreName(storeNameOrDescriptor);
167
- listeningStores.add(storeName);
172
+ (_listeningStores2 = listeningStores) === null || _listeningStores2 === void 0 ? void 0 : _listeningStores2.add(storeName);
168
173
  const store = stores[storeName];
169
174
 
170
175
  if (store) {
@@ -187,8 +192,10 @@ function createRegistry() {
187
192
 
188
193
 
189
194
  function suspendSelect(storeNameOrDescriptor) {
195
+ var _listeningStores3;
196
+
190
197
  const storeName = getStoreName(storeNameOrDescriptor);
191
- listeningStores.add(storeName);
198
+ (_listeningStores3 = listeningStores) === null || _listeningStores3 === void 0 ? void 0 : _listeningStores3.add(storeName);
192
199
  const store = stores[storeName];
193
200
 
194
201
  if (store) {