@wordpress/core-data 4.0.1 → 4.0.5

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 (116) hide show
  1. package/README.md +13 -7
  2. package/build/actions.js +178 -122
  3. package/build/actions.js.map +1 -1
  4. package/build/batch/default-processor.js +58 -27
  5. package/build/batch/default-processor.js.map +1 -1
  6. package/build/entities.js +70 -23
  7. package/build/entities.js.map +1 -1
  8. package/build/fetch/__experimental-fetch-url-data.js +1 -1
  9. package/build/fetch/__experimental-fetch-url-data.js.map +1 -1
  10. package/build/index.js +9 -17
  11. package/build/index.js.map +1 -1
  12. package/build/locks/actions.js +17 -77
  13. package/build/locks/actions.js.map +1 -1
  14. package/build/locks/engine.js +77 -0
  15. package/build/locks/engine.js.map +1 -0
  16. package/build/locks/reducer.js +1 -5
  17. package/build/locks/reducer.js.map +1 -1
  18. package/build/locks/selectors.js +6 -6
  19. package/build/locks/selectors.js.map +1 -1
  20. package/build/queried-data/get-query-parts.js +9 -4
  21. package/build/queried-data/get-query-parts.js.map +1 -1
  22. package/build/queried-data/selectors.js +3 -9
  23. package/build/queried-data/selectors.js.map +1 -1
  24. package/build/reducer.js +17 -22
  25. package/build/reducer.js.map +1 -1
  26. package/build/resolvers.js +151 -97
  27. package/build/resolvers.js.map +1 -1
  28. package/build/selectors.js +79 -14
  29. package/build/selectors.js.map +1 -1
  30. package/build/utils/forward-resolver.js +23 -0
  31. package/build/utils/forward-resolver.js.map +1 -0
  32. package/build/utils/index.js +11 -3
  33. package/build/utils/index.js.map +1 -1
  34. package/build/utils/is-raw-attribute.js +19 -0
  35. package/build/utils/is-raw-attribute.js.map +1 -0
  36. package/build-module/actions.js +155 -112
  37. package/build-module/actions.js.map +1 -1
  38. package/build-module/batch/default-processor.js +57 -27
  39. package/build-module/batch/default-processor.js.map +1 -1
  40. package/build-module/entities.js +65 -19
  41. package/build-module/entities.js.map +1 -1
  42. package/build-module/fetch/__experimental-fetch-url-data.js +1 -1
  43. package/build-module/fetch/__experimental-fetch-url-data.js.map +1 -1
  44. package/build-module/index.js +10 -14
  45. package/build-module/index.js.map +1 -1
  46. package/build-module/locks/actions.js +14 -68
  47. package/build-module/locks/actions.js.map +1 -1
  48. package/build-module/locks/engine.js +66 -0
  49. package/build-module/locks/engine.js.map +1 -0
  50. package/build-module/locks/reducer.js +1 -2
  51. package/build-module/locks/reducer.js.map +1 -1
  52. package/build-module/locks/selectors.js +4 -4
  53. package/build-module/locks/selectors.js.map +1 -1
  54. package/build-module/queried-data/get-query-parts.js +9 -4
  55. package/build-module/queried-data/get-query-parts.js.map +1 -1
  56. package/build-module/queried-data/selectors.js +3 -9
  57. package/build-module/queried-data/selectors.js.map +1 -1
  58. package/build-module/reducer.js +15 -19
  59. package/build-module/reducer.js.map +1 -1
  60. package/build-module/resolvers.js +123 -81
  61. package/build-module/resolvers.js.map +1 -1
  62. package/build-module/selectors.js +74 -13
  63. package/build-module/selectors.js.map +1 -1
  64. package/build-module/utils/forward-resolver.js +15 -0
  65. package/build-module/utils/forward-resolver.js.map +1 -0
  66. package/build-module/utils/index.js +2 -1
  67. package/build-module/utils/index.js.map +1 -1
  68. package/build-module/utils/is-raw-attribute.js +12 -0
  69. package/build-module/utils/is-raw-attribute.js.map +1 -0
  70. package/package.json +10 -11
  71. package/src/actions.js +163 -194
  72. package/src/batch/default-processor.js +57 -26
  73. package/src/batch/test/default-processor.js +53 -26
  74. package/src/entities.js +47 -19
  75. package/src/fetch/__experimental-fetch-url-data.js +1 -1
  76. package/src/index.js +7 -10
  77. package/src/locks/actions.js +10 -61
  78. package/src/locks/engine.js +43 -0
  79. package/src/locks/reducer.js +1 -3
  80. package/src/locks/selectors.js +4 -4
  81. package/src/locks/test/engine.js +135 -0
  82. package/src/locks/test/reducer.js +1 -1
  83. package/src/locks/test/selectors.js +105 -124
  84. package/src/queried-data/get-query-parts.js +11 -6
  85. package/src/queried-data/selectors.js +2 -9
  86. package/src/queried-data/test/get-query-parts.js +1 -1
  87. package/src/queried-data/test/selectors.js +1 -0
  88. package/src/reducer.js +14 -19
  89. package/src/resolvers.js +132 -120
  90. package/src/selectors.js +156 -44
  91. package/src/test/actions.js +330 -170
  92. package/src/test/entities.js +40 -26
  93. package/src/test/resolvers.js +270 -223
  94. package/src/test/selectors.js +127 -1
  95. package/src/utils/forward-resolver.js +14 -0
  96. package/src/utils/index.js +2 -1
  97. package/src/utils/is-raw-attribute.js +11 -0
  98. package/src/utils/test/is-raw-attribute.js +22 -0
  99. package/build/controls.js +0 -44
  100. package/build/controls.js.map +0 -1
  101. package/build/locks/index.js +0 -47
  102. package/build/locks/index.js.map +0 -1
  103. package/build/utils/if-not-resolved.js +0 -46
  104. package/build/utils/if-not-resolved.js.map +0 -1
  105. package/build-module/controls.js +0 -31
  106. package/build-module/controls.js.map +0 -1
  107. package/build-module/locks/index.js +0 -4
  108. package/build-module/locks/index.js.map +0 -1
  109. package/build-module/utils/if-not-resolved.js +0 -36
  110. package/build-module/utils/if-not-resolved.js.map +0 -1
  111. package/src/controls.js +0 -31
  112. package/src/locks/index.js +0 -3
  113. package/src/locks/test/actions.js +0 -307
  114. package/src/test/integration.js +0 -264
  115. package/src/utils/if-not-resolved.js +0 -40
  116. package/src/utils/test/if-not-resolved.js +0 -75
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import createLocks from '../engine';
5
+
6
+ jest.useRealTimers();
7
+
8
+ // we correctly await all promises with expect calls, but the rule doesn't detect that
9
+ /* eslint-disable jest/valid-expect-in-promise */
10
+
11
+ describe( 'Locks engine', () => {
12
+ it( 'does not grant two exclusive locks at once', async () => {
13
+ const locks = createLocks();
14
+
15
+ let l1Granted = false;
16
+ let l2Granted = false;
17
+
18
+ // request two locks
19
+ const l1 = locks.acquire( 'store', [ 'root' ], true );
20
+ const l2 = locks.acquire( 'store', [ 'root' ], true );
21
+
22
+ // on each grant, verify that the other lock is not granted at the same time
23
+ const check1 = l1.then( () => {
24
+ l1Granted = true;
25
+ expect( l2Granted ).toBe( false );
26
+ } );
27
+
28
+ const check2 = l2.then( () => {
29
+ l2Granted = true;
30
+ expect( l1Granted ).toBe( false );
31
+ } );
32
+
33
+ // unlock both
34
+ const lock1 = await l1;
35
+ locks.release( lock1 );
36
+ l1Granted = false;
37
+
38
+ const lock2 = await l2;
39
+ locks.release( lock2 );
40
+ l2Granted = false;
41
+
42
+ // ensure that both locks were granted and checked
43
+ return await Promise.all( [ check1, check2 ] );
44
+ } );
45
+
46
+ it( 'does not grant an exclusive lock if a non-exclusive one already exists', async () => {
47
+ const locks = createLocks();
48
+
49
+ let l1Granted = false;
50
+ let l2Granted = false;
51
+
52
+ // request two locks
53
+ const l1 = locks.acquire( 'store', [ 'root' ], false );
54
+ const l2 = locks.acquire( 'store', [ 'root' ], true );
55
+
56
+ // on each grant, verify that the other lock is not granted at the same time
57
+ const check1 = l1.then( () => {
58
+ l1Granted = true;
59
+ expect( l2Granted ).toBe( false );
60
+ } );
61
+
62
+ const check2 = l2.then( () => {
63
+ l2Granted = true;
64
+ expect( l1Granted ).toBe( false );
65
+ } );
66
+
67
+ // unlock both
68
+ const lock1 = await l1;
69
+ locks.release( lock1 );
70
+ l1Granted = false;
71
+
72
+ const lock2 = await l2;
73
+ locks.release( lock2 );
74
+ l2Granted = false;
75
+
76
+ // ensure that both locks were granted and checked
77
+ return await Promise.all( [ check1, check2 ] );
78
+ } );
79
+
80
+ it( 'does not grant two exclusive locks to parent and child', async () => {
81
+ const locks = createLocks();
82
+
83
+ let l1Granted = false;
84
+ let l2Granted = false;
85
+
86
+ // request two locks
87
+ const l1 = locks.acquire( 'store', [ 'root' ], true );
88
+ const l2 = locks.acquire( 'store', [ 'root', 'child' ], true );
89
+
90
+ // on each grant, verify that the other lock is not granted at the same time
91
+ const check1 = l1.then( () => {
92
+ l1Granted = true;
93
+ expect( l2Granted ).toBe( false );
94
+ } );
95
+
96
+ const check2 = l2.then( () => {
97
+ l2Granted = true;
98
+ expect( l1Granted ).toBe( false );
99
+ } );
100
+
101
+ // unlock both
102
+ const lock1 = await l1;
103
+ locks.release( lock1 );
104
+ l1Granted = false;
105
+
106
+ const lock2 = await l2;
107
+ locks.release( lock2 );
108
+ l2Granted = false;
109
+
110
+ // ensure that both locks were granted and checked
111
+ return await Promise.all( [ check1, check2 ] );
112
+ } );
113
+
114
+ it( 'grants two non-exclusive locks at once', async () => {
115
+ const locks = createLocks();
116
+
117
+ const l1 = await locks.acquire( 'store', [ 'root' ], false );
118
+ const l2 = await locks.acquire( 'store', [ 'root' ], false );
119
+
120
+ expect( l1 ).not.toBeUndefined();
121
+ expect( l2 ).not.toBeUndefined();
122
+ } );
123
+
124
+ it( 'grants two exclusive locks to different branches', async () => {
125
+ const locks = createLocks();
126
+
127
+ const l1 = await locks.acquire( 'store', [ 'a' ], true );
128
+ const l2 = await locks.acquire( 'store', [ 'b' ], true );
129
+
130
+ expect( l1 ).not.toBeUndefined();
131
+ expect( l2 ).not.toBeUndefined();
132
+ } );
133
+ } );
134
+
135
+ /* eslint-enable jest/valid-expect-in-promise */
@@ -6,7 +6,7 @@ import deepFreeze from 'deep-freeze';
6
6
  /**
7
7
  * Internal dependencies
8
8
  */
9
- import { locks } from '../reducer';
9
+ import locks from '../reducer';
10
10
 
11
11
  const buildNode = ( children = {} ) => ( {
12
12
  locks: [],
@@ -6,58 +6,45 @@ import deepFreeze from 'deep-freeze';
6
6
  /**
7
7
  * Internal dependencies
8
8
  */
9
- import {
10
- __unstableGetPendingLockRequests,
11
- __unstableIsLockAvailable,
12
- } from '../selectors';
9
+ import { getPendingLockRequests, isLockAvailable } from '../selectors';
13
10
  import { deepCopyLocksTreePath, getNode } from '../utils';
14
11
 
15
- describe( '__unstableGetPendingLockRequests', () => {
12
+ describe( 'getPendingLockRequests', () => {
16
13
  it( 'returns pending lock requests', () => {
17
14
  const state = deepFreeze( {
18
- locks: {
19
- requests: [ 1, 2, 3 ],
20
- },
15
+ requests: [ 1, 2, 3 ],
21
16
  } );
22
17
 
23
- expect( __unstableGetPendingLockRequests( state ) ).toEqual( [
24
- 1,
25
- 2,
26
- 3,
27
- ] );
18
+ expect( getPendingLockRequests( state ) ).toEqual( [ 1, 2, 3 ] );
28
19
  } );
29
20
  } );
30
21
 
31
- describe( '__unstableIsLockAvailable', () => {
22
+ describe( 'isLockAvailable', () => {
32
23
  describe( 'smoke tests', () => {
33
24
  it( 'returns true if lock is available', () => {
34
25
  const state = deepFreeze( {
35
- locks: {
36
- tree: {
37
- children: {},
38
- locks: [],
39
- },
26
+ tree: {
27
+ children: {},
28
+ locks: [],
40
29
  },
41
30
  } );
42
31
 
43
32
  expect(
44
- __unstableIsLockAvailable( state, 'core', [], {
33
+ isLockAvailable( state, 'core', [], {
45
34
  exclusive: true,
46
35
  } )
47
36
  ).toBe( true );
48
37
  } );
49
38
  it( 'returns false if lock is not available', () => {
50
39
  const state = deepFreeze( {
51
- locks: {
52
- tree: {
53
- children: {},
54
- locks: [ { exclusive: false } ],
55
- },
40
+ tree: {
41
+ children: {},
42
+ locks: [ { exclusive: false } ],
56
43
  },
57
44
  } );
58
45
 
59
46
  expect(
60
- __unstableIsLockAvailable( state, 'core', [], {
47
+ isLockAvailable( state, 'core', [], {
61
48
  exclusive: true,
62
49
  } )
63
50
  ).toBe( false );
@@ -75,7 +62,7 @@ describe( '__unstableIsLockAvailable', () => {
75
62
  } );
76
63
  it( `returns true if no parent or descendant has any locks`, () => {
77
64
  expect(
78
- __unstableIsLockAvailable(
65
+ isLockAvailable(
79
66
  deepFreeze( state ),
80
67
  'core',
81
68
  [ 'entities', 'root' ],
@@ -89,7 +76,7 @@ describe( '__unstableIsLockAvailable', () => {
89
76
  exclusive: true,
90
77
  } );
91
78
  expect(
92
- __unstableIsLockAvailable(
79
+ isLockAvailable(
93
80
  deepFreeze( state ),
94
81
  'core',
95
82
  [ 'entities', 'root' ],
@@ -103,7 +90,7 @@ describe( '__unstableIsLockAvailable', () => {
103
90
  exclusive: true,
104
91
  } );
105
92
  expect(
106
- __unstableIsLockAvailable(
93
+ isLockAvailable(
107
94
  deepFreeze( state ),
108
95
  'core',
109
96
  [ 'entities', 'root' ],
@@ -114,41 +101,39 @@ describe( '__unstableIsLockAvailable', () => {
114
101
 
115
102
  it( `returns true if another branch holds a locks (3)`, () => {
116
103
  const subState = {
117
- locks: {
118
- tree: {
119
- locks: [],
120
- children: {
121
- postType: {
122
- locks: [],
123
- children: {
124
- post: {
125
- locks: [],
126
- children: {
127
- 16: {
128
- locks: [
129
- {
130
- store: 'core',
131
- path: [
132
- 'entities',
133
- 'data',
134
- 'postType',
135
- 'post',
136
- 16,
137
- ],
138
- exclusive: true,
139
- },
140
- ],
141
- children: {},
142
- },
104
+ tree: {
105
+ locks: [],
106
+ children: {
107
+ postType: {
108
+ locks: [],
109
+ children: {
110
+ post: {
111
+ locks: [],
112
+ children: {
113
+ 16: {
114
+ locks: [
115
+ {
116
+ store: 'core',
117
+ path: [
118
+ 'entities',
119
+ 'data',
120
+ 'postType',
121
+ 'post',
122
+ 16,
123
+ ],
124
+ exclusive: true,
125
+ },
126
+ ],
127
+ children: {},
143
128
  },
144
129
  },
145
- wp_template_part: {
146
- locks: [],
147
- children: {
148
- 17: {
149
- locks: [],
150
- children: {},
151
- },
130
+ },
131
+ wp_template_part: {
132
+ locks: [],
133
+ children: {
134
+ 17: {
135
+ locks: [],
136
+ children: {},
152
137
  },
153
138
  },
154
139
  },
@@ -158,7 +143,7 @@ describe( '__unstableIsLockAvailable', () => {
158
143
  },
159
144
  };
160
145
  expect(
161
- __unstableIsLockAvailable(
146
+ isLockAvailable(
162
147
  deepFreeze( subState ),
163
148
  'core',
164
149
  [ 'postType', 'wp_template_part', 17 ],
@@ -169,41 +154,39 @@ describe( '__unstableIsLockAvailable', () => {
169
154
 
170
155
  it( `returns true if another branch holds a locks (4)`, () => {
171
156
  const subState = {
172
- locks: {
173
- tree: {
174
- locks: [],
175
- children: {
176
- core: {
177
- locks: [],
178
- children: {
179
- entities: {
180
- locks: [],
181
- children: {
182
- data: {
183
- locks: [],
184
- children: {
185
- postType: {
186
- locks: [],
187
- children: {
188
- book: {
189
- locks: [],
190
- children: {
191
- 67: {
192
- locks: [
193
- {
194
- path: [
195
- 'core',
196
- 'entities',
197
- 'data',
198
- 'postType',
199
- 'book',
200
- 67,
201
- ],
202
- exclusive: true,
203
- },
204
- ],
205
- children: {},
206
- },
157
+ tree: {
158
+ locks: [],
159
+ children: {
160
+ core: {
161
+ locks: [],
162
+ children: {
163
+ entities: {
164
+ locks: [],
165
+ children: {
166
+ data: {
167
+ locks: [],
168
+ children: {
169
+ postType: {
170
+ locks: [],
171
+ children: {
172
+ book: {
173
+ locks: [],
174
+ children: {
175
+ 67: {
176
+ locks: [
177
+ {
178
+ path: [
179
+ 'core',
180
+ 'entities',
181
+ 'data',
182
+ 'postType',
183
+ 'book',
184
+ 67,
185
+ ],
186
+ exclusive: true,
187
+ },
188
+ ],
189
+ children: {},
207
190
  },
208
191
  },
209
192
  },
@@ -219,7 +202,7 @@ describe( '__unstableIsLockAvailable', () => {
219
202
  },
220
203
  };
221
204
  expect(
222
- __unstableIsLockAvailable(
205
+ isLockAvailable(
223
206
  deepFreeze( subState ),
224
207
  'core',
225
208
  [ 'entities', 'data', 'postType', 'book', 67 ],
@@ -231,7 +214,7 @@ describe( '__unstableIsLockAvailable', () => {
231
214
  [ true, false ].forEach( ( exclusive ) => {
232
215
  it( `returns true if the path is not accessible and no parent holds a lock`, () => {
233
216
  expect(
234
- __unstableIsLockAvailable(
217
+ isLockAvailable(
235
218
  deepFreeze( state ),
236
219
  'core',
237
220
  [ 'fake', 'path' ],
@@ -245,7 +228,7 @@ describe( '__unstableIsLockAvailable', () => {
245
228
  exclusive,
246
229
  } );
247
230
  expect(
248
- __unstableIsLockAvailable(
231
+ isLockAvailable(
249
232
  deepFreeze( state ),
250
233
  'core',
251
234
  [ 'fake', 'path' ],
@@ -259,7 +242,7 @@ describe( '__unstableIsLockAvailable', () => {
259
242
  exclusive,
260
243
  } );
261
244
  expect(
262
- __unstableIsLockAvailable(
245
+ isLockAvailable(
263
246
  deepFreeze( state ),
264
247
  'core',
265
248
  [ 'entities', 'root' ],
@@ -273,7 +256,7 @@ describe( '__unstableIsLockAvailable', () => {
273
256
  exclusive,
274
257
  } );
275
258
  expect(
276
- __unstableIsLockAvailable(
259
+ isLockAvailable(
277
260
  deepFreeze( state ),
278
261
  'core',
279
262
  [ 'entities', 'root' ],
@@ -287,7 +270,7 @@ describe( '__unstableIsLockAvailable', () => {
287
270
  exclusive,
288
271
  } );
289
272
  expect(
290
- __unstableIsLockAvailable(
273
+ isLockAvailable(
291
274
  deepFreeze( state ),
292
275
  'core',
293
276
  [ 'entities', 'root' ],
@@ -306,7 +289,7 @@ describe( '__unstableIsLockAvailable', () => {
306
289
  }
307
290
  );
308
291
  expect(
309
- __unstableIsLockAvailable(
292
+ isLockAvailable(
310
293
  deepFreeze( state ),
311
294
  'core',
312
295
  [ 'entities', 'root' ],
@@ -325,7 +308,7 @@ describe( '__unstableIsLockAvailable', () => {
325
308
  }
326
309
  );
327
310
  expect(
328
- __unstableIsLockAvailable(
311
+ isLockAvailable(
329
312
  deepFreeze( state ),
330
313
  'core',
331
314
  [ 'entities', 'root' ],
@@ -345,7 +328,7 @@ describe( '__unstableIsLockAvailable', () => {
345
328
  } );
346
329
  it( `returns true if no parent or descendant has any locks`, () => {
347
330
  expect(
348
- __unstableIsLockAvailable(
331
+ isLockAvailable(
349
332
  deepFreeze( state ),
350
333
  'core',
351
334
  [ 'entities', 'root' ],
@@ -361,7 +344,7 @@ describe( '__unstableIsLockAvailable', () => {
361
344
  exclusive: isOtherLockExclusive,
362
345
  } );
363
346
  expect(
364
- __unstableIsLockAvailable(
347
+ isLockAvailable(
365
348
  deepFreeze( state ),
366
349
  'core',
367
350
  [ 'fake', 'path' ],
@@ -375,7 +358,7 @@ describe( '__unstableIsLockAvailable', () => {
375
358
  exclusive: isOtherLockExclusive,
376
359
  } );
377
360
  expect(
378
- __unstableIsLockAvailable(
361
+ isLockAvailable(
379
362
  deepFreeze( state ),
380
363
  'core',
381
364
  [ 'entities', 'root' ],
@@ -389,7 +372,7 @@ describe( '__unstableIsLockAvailable', () => {
389
372
  exclusive: isOtherLockExclusive,
390
373
  } );
391
374
  expect(
392
- __unstableIsLockAvailable(
375
+ isLockAvailable(
393
376
  deepFreeze( state ),
394
377
  'core',
395
378
  [ 'entities', 'root' ],
@@ -403,7 +386,7 @@ describe( '__unstableIsLockAvailable', () => {
403
386
  exclusive: isOtherLockExclusive,
404
387
  } );
405
388
  expect(
406
- __unstableIsLockAvailable(
389
+ isLockAvailable(
407
390
  deepFreeze( state ),
408
391
  'core',
409
392
  [ 'entities', 'root' ],
@@ -422,7 +405,7 @@ describe( '__unstableIsLockAvailable', () => {
422
405
  }
423
406
  );
424
407
  expect(
425
- __unstableIsLockAvailable(
408
+ isLockAvailable(
426
409
  deepFreeze( state ),
427
410
  'core',
428
411
  [ 'entities', 'root' ],
@@ -441,7 +424,7 @@ describe( '__unstableIsLockAvailable', () => {
441
424
  }
442
425
  );
443
426
  expect(
444
- __unstableIsLockAvailable(
427
+ isLockAvailable(
445
428
  deepFreeze( state ),
446
429
  'core',
447
430
  [ 'entities', 'root' ],
@@ -454,20 +437,18 @@ describe( '__unstableIsLockAvailable', () => {
454
437
  } );
455
438
 
456
439
  function appendLock( state, store, path, lock ) {
457
- getNode( state.locks.tree, [ store, ...path ] ).locks.push( lock );
440
+ getNode( state.tree, [ store, ...path ] ).locks.push( lock );
458
441
  }
459
442
 
460
443
  function buildState( paths ) {
461
444
  return {
462
- locks: {
463
- requests: [],
464
- tree: paths.reduce(
465
- ( tree, path ) => deepCopyLocksTreePath( tree, path ),
466
- {
467
- locks: [],
468
- children: {},
469
- }
470
- ),
471
- },
445
+ requests: [],
446
+ tree: paths.reduce(
447
+ ( tree, path ) => deepCopyLocksTreePath( tree, path ),
448
+ {
449
+ locks: [],
450
+ children: {},
451
+ }
452
+ ),
472
453
  };
473
454
  }
@@ -20,6 +20,8 @@ import { withWeakMapCache, getNormalizedCommaSeparable } from '../utils';
20
20
  * @property {?(string[])} fields Target subset of fields to derive from
21
21
  * item objects.
22
22
  * @property {?(number[])} include Specific item IDs to include.
23
+ * @property {string} context Scope under which the request is made;
24
+ * determines returned fields in response.
23
25
  */
24
26
 
25
27
  /**
@@ -60,12 +62,6 @@ export function getQueryParts( query ) {
60
62
  parts.perPage = Number( value );
61
63
  break;
62
64
 
63
- case 'include':
64
- parts.include = getNormalizedCommaSeparable( value ).map(
65
- Number
66
- );
67
- break;
68
-
69
65
  case 'context':
70
66
  parts.context = value;
71
67
  break;
@@ -82,6 +78,15 @@ export function getQueryParts( query ) {
82
78
  value = parts.fields.join();
83
79
  }
84
80
 
81
+ // Two requests with different include values cannot have same results.
82
+ if ( key === 'include' ) {
83
+ parts.include = getNormalizedCommaSeparable( value ).map(
84
+ Number
85
+ );
86
+ // Normalize value for `stableKey`.
87
+ value = parts.include.join();
88
+ }
89
+
85
90
  // While it could be any deterministic string, for simplicity's
86
91
  // sake mimic querystring encoding for stable key.
87
92
  //
@@ -38,15 +38,7 @@ function getQueriedItemsUncached( state, query ) {
38
38
  } = getQueryParts( query );
39
39
  let itemIds;
40
40
 
41
- if ( Array.isArray( include ) && ! stableKey ) {
42
- // If the parsed query yields a set of IDs, but otherwise no filtering,
43
- // it's safe to consider targeted item IDs as the include set. This
44
- // doesn't guarantee that those objects have been queried, which is
45
- // accounted for below in the loop `null` return.
46
- itemIds = include;
47
- // TODO: Avoid storing the empty stable string in reducer, since it
48
- // can be computed dynamically here always.
49
- } else if ( state.queries?.[ context ]?.[ stableKey ] ) {
41
+ if ( state.queries?.[ context ]?.[ stableKey ] ) {
50
42
  itemIds = state.queries[ context ][ stableKey ];
51
43
  }
52
44
 
@@ -67,6 +59,7 @@ function getQueriedItemsUncached( state, query ) {
67
59
  continue;
68
60
  }
69
61
 
62
+ // Having a target item ID doesn't guarantee that this object has been queried.
70
63
  if ( ! state.items[ context ]?.hasOwnProperty( itemId ) ) {
71
64
  return null;
72
65
  }
@@ -24,7 +24,7 @@ describe( 'getQueryParts', () => {
24
24
  context: 'default',
25
25
  page: 1,
26
26
  perPage: 10,
27
- stableKey: '',
27
+ stableKey: 'include=1',
28
28
  fields: null,
29
29
  include: [ 1 ],
30
30
  } );
@@ -82,6 +82,7 @@ describe( 'getQueriedItems', () => {
82
82
  queries: {
83
83
  default: {
84
84
  '': [ 1, 2 ],
85
+ 'include=1': [ 1 ],
85
86
  },
86
87
  },
87
88
  };