react-relay 11.0.1 → 13.0.0-rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. package/ReactRelayContext.js +1 -1
  2. package/ReactRelayContext.js.flow +2 -3
  3. package/ReactRelayFragmentContainer.js.flow +24 -24
  4. package/ReactRelayFragmentMockRenderer.js.flow +1 -1
  5. package/ReactRelayLocalQueryRenderer.js.flow +6 -7
  6. package/ReactRelayPaginationContainer.js.flow +111 -58
  7. package/ReactRelayQueryFetcher.js.flow +9 -10
  8. package/ReactRelayQueryRenderer.js.flow +115 -81
  9. package/ReactRelayRefetchContainer.js.flow +41 -38
  10. package/ReactRelayTestMocker.js.flow +16 -14
  11. package/ReactRelayTypes.js.flow +10 -10
  12. package/RelayContext.js.flow +3 -3
  13. package/__flowtests__/ReactRelayFragmentContainer-flowtest.js.flow +1 -2
  14. package/__flowtests__/ReactRelayPaginationContainer-flowtest.js.flow +11 -7
  15. package/__flowtests__/ReactRelayRefetchContainer-flowtest.js.flow +10 -6
  16. package/__flowtests__/RelayModern-flowtest.js.flow +78 -46
  17. package/__flowtests__/RelayModernFlowtest_badref.graphql.js.flow +5 -4
  18. package/__flowtests__/RelayModernFlowtest_notref.graphql.js.flow +5 -4
  19. package/__flowtests__/RelayModernFlowtest_user.graphql.js.flow +4 -3
  20. package/__flowtests__/RelayModernFlowtest_users.graphql.js.flow +4 -3
  21. package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer.graphql.js.flow +72 -0
  22. package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer2.graphql.js.flow +72 -0
  23. package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtestQuery.graphql.js.flow +227 -0
  24. package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtest_viewer.graphql.js.flow +164 -0
  25. package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtestQuery.graphql.js.flow +227 -0
  26. package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtest_viewer.graphql.js.flow +164 -0
  27. package/__flowtests__/__generated__/RelayModernFlowtest_badref.graphql.js.flow +66 -0
  28. package/__flowtests__/__generated__/RelayModernFlowtest_notref.graphql.js.flow +66 -0
  29. package/__flowtests__/__generated__/RelayModernFlowtest_user.graphql.js.flow +59 -0
  30. package/__flowtests__/__generated__/RelayModernFlowtest_users.graphql.js.flow +61 -0
  31. package/assertFragmentMap.js.flow +2 -2
  32. package/buildReactRelayContainer.js.flow +15 -12
  33. package/getRootVariablesForFragments.js.flow +2 -4
  34. package/hooks.js +1 -1
  35. package/hooks.js.flow +5 -6
  36. package/index.js +1 -1
  37. package/index.js.flow +6 -7
  38. package/jest-react/enqueueTask.js.flow +56 -0
  39. package/jest-react/index.js.flow +12 -0
  40. package/jest-react/internalAct.js.flow +139 -0
  41. package/legacy.js +1 -1
  42. package/lib/ReactRelayFragmentContainer.js +21 -15
  43. package/lib/ReactRelayFragmentMockRenderer.js +2 -2
  44. package/lib/ReactRelayLocalQueryRenderer.js +7 -8
  45. package/lib/ReactRelayPaginationContainer.js +96 -38
  46. package/lib/ReactRelayQueryFetcher.js +3 -3
  47. package/lib/ReactRelayQueryRenderer.js +86 -53
  48. package/lib/ReactRelayRefetchContainer.js +38 -25
  49. package/lib/ReactRelayTestMocker.js +8 -9
  50. package/lib/RelayContext.js +3 -2
  51. package/lib/assertFragmentMap.js +3 -2
  52. package/lib/buildReactRelayContainer.js +14 -11
  53. package/lib/getRootVariablesForFragments.js +1 -2
  54. package/lib/hooks.js +5 -5
  55. package/lib/index.js +7 -7
  56. package/lib/jest-react/enqueueTask.js +53 -0
  57. package/lib/jest-react/index.js +13 -0
  58. package/lib/jest-react/internalAct.js +116 -0
  59. package/lib/multi-actor/ActorChange.js +30 -0
  60. package/lib/multi-actor/index.js +11 -0
  61. package/lib/multi-actor/useRelayActorEnvironment.js +29 -0
  62. package/lib/relay-hooks/EntryPointContainer.react.js +3 -3
  63. package/lib/relay-hooks/FragmentResource.js +347 -92
  64. package/lib/relay-hooks/LRUCache.js +1 -1
  65. package/lib/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js +4 -4
  66. package/lib/relay-hooks/MatchContainer.js +1 -1
  67. package/lib/relay-hooks/QueryResource.js +172 -29
  68. package/lib/relay-hooks/RelayEnvironmentProvider.js +5 -3
  69. package/lib/relay-hooks/SuspenseResource.js +130 -0
  70. package/lib/relay-hooks/loadQuery.js +42 -20
  71. package/lib/relay-hooks/preloadQuery_DEPRECATED.js +24 -15
  72. package/lib/relay-hooks/useBlockingPaginationFragment.js +4 -5
  73. package/lib/relay-hooks/useEntryPointLoader.js +2 -2
  74. package/lib/relay-hooks/useFetchTrackingRef.js +2 -1
  75. package/lib/relay-hooks/useFragment.js +8 -7
  76. package/lib/relay-hooks/useFragmentNode.js +4 -4
  77. package/lib/relay-hooks/useIsOperationNodeActive.js +3 -3
  78. package/lib/relay-hooks/useLazyLoadQuery.js +3 -3
  79. package/lib/relay-hooks/useLazyLoadQueryNode.js +10 -4
  80. package/lib/relay-hooks/useLoadMoreFunction.js +8 -12
  81. package/lib/relay-hooks/useMemoOperationDescriptor.js +2 -2
  82. package/lib/relay-hooks/useMemoVariables.js +2 -2
  83. package/lib/relay-hooks/useMutation.js +17 -6
  84. package/lib/relay-hooks/usePaginationFragment.js +2 -3
  85. package/lib/relay-hooks/usePreloadedQuery.js +8 -7
  86. package/lib/relay-hooks/useQueryLoader.js +30 -10
  87. package/lib/relay-hooks/useRefetchableFragmentNode.js +13 -17
  88. package/lib/relay-hooks/useRelayEnvironment.js +3 -3
  89. package/lib/relay-hooks/useStaticFragmentNodeWarning.js +2 -2
  90. package/lib/relay-hooks/useSubscribeToInvalidationState.js +2 -1
  91. package/lib/relay-hooks/useSubscription.js +10 -7
  92. package/multi-actor/ActorChange.js.flow +58 -0
  93. package/multi-actor/index.js.flow +14 -0
  94. package/multi-actor/useRelayActorEnvironment.js.flow +49 -0
  95. package/package.json +3 -2
  96. package/react-relay-hooks.js +2 -2
  97. package/react-relay-hooks.min.js +2 -2
  98. package/react-relay-legacy.js +2 -2
  99. package/react-relay-legacy.min.js +2 -2
  100. package/react-relay.js +2 -2
  101. package/react-relay.min.js +2 -2
  102. package/relay-hooks/EntryPointContainer.react.js.flow +8 -15
  103. package/relay-hooks/EntryPointTypes.flow.js.flow +24 -25
  104. package/relay-hooks/FragmentResource.js.flow +368 -94
  105. package/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js.flow +32 -46
  106. package/relay-hooks/MatchContainer.js.flow +3 -2
  107. package/relay-hooks/QueryResource.js.flow +216 -25
  108. package/relay-hooks/RelayEnvironmentProvider.js.flow +14 -4
  109. package/relay-hooks/SuspenseResource.js.flow +115 -0
  110. package/relay-hooks/__flowtests__/EntryPointTypes/EntryPointElementConfig-flowtest.js.flow +4 -3
  111. package/relay-hooks/__flowtests__/EntryPointTypes/NestedEntrypoints-flowtest.js.flow +1 -1
  112. package/relay-hooks/__flowtests__/useBlockingPaginationFragment-flowtest.js.flow +10 -9
  113. package/relay-hooks/__flowtests__/useFragment-flowtest.js.flow +8 -7
  114. package/relay-hooks/__flowtests__/usePaginationFragment-flowtest.js.flow +10 -9
  115. package/relay-hooks/__flowtests__/useRefetchableFragment-flowtest.js.flow +10 -9
  116. package/relay-hooks/__flowtests__/utils.js.flow +8 -12
  117. package/relay-hooks/loadEntryPoint.js.flow +6 -12
  118. package/relay-hooks/loadQuery.js.flow +49 -31
  119. package/relay-hooks/preloadQuery_DEPRECATED.js.flow +30 -21
  120. package/relay-hooks/prepareEntryPoint_DEPRECATED.js.flow +6 -12
  121. package/relay-hooks/useBlockingPaginationFragment.js.flow +13 -11
  122. package/relay-hooks/useEntryPointLoader.js.flow +7 -10
  123. package/relay-hooks/useFetchTrackingRef.js.flow +2 -2
  124. package/relay-hooks/useFragment.js.flow +26 -46
  125. package/relay-hooks/useFragmentNode.js.flow +5 -7
  126. package/relay-hooks/useIsOperationNodeActive.js.flow +3 -5
  127. package/relay-hooks/useIsParentQueryActive.js.flow +3 -4
  128. package/relay-hooks/useLazyLoadQuery.js.flow +9 -10
  129. package/relay-hooks/useLazyLoadQueryNode.js.flow +19 -13
  130. package/relay-hooks/useLoadMoreFunction.js.flow +20 -29
  131. package/relay-hooks/useMemoOperationDescriptor.js.flow +5 -7
  132. package/relay-hooks/useMemoVariables.js.flow +6 -6
  133. package/relay-hooks/useMutation.js.flow +26 -26
  134. package/relay-hooks/usePaginationFragment.js.flow +38 -44
  135. package/relay-hooks/usePreloadedQuery.js.flow +18 -14
  136. package/relay-hooks/useQueryLoader.js.flow +41 -22
  137. package/relay-hooks/useRefetchableFragment.js.flow +7 -8
  138. package/relay-hooks/useRefetchableFragmentNode.js.flow +24 -32
  139. package/relay-hooks/useRelayEnvironment.js.flow +2 -4
  140. package/relay-hooks/useStaticFragmentNodeWarning.js.flow +2 -3
  141. package/relay-hooks/useSubscribeToInvalidationState.js.flow +3 -6
  142. package/relay-hooks/useSubscription.js.flow +20 -10
  143. package/lib/relay-hooks/getPaginationMetadata.js +0 -41
  144. package/lib/relay-hooks/getPaginationVariables.js +0 -67
  145. package/lib/relay-hooks/getRefetchMetadata.js +0 -36
  146. package/lib/relay-hooks/getValueAtPath.js +0 -51
  147. package/relay-hooks/getPaginationMetadata.js.flow +0 -74
  148. package/relay-hooks/getPaginationVariables.js.flow +0 -110
  149. package/relay-hooks/getRefetchMetadata.js.flow +0 -80
  150. package/relay-hooks/getValueAtPath.js.flow +0 -46
@@ -11,14 +11,14 @@
11
11
  // flowlint ambiguous-object-type:error
12
12
  'use strict';
13
13
 
14
- var ProfilerContext = require('./ProfilerContext');
15
-
16
- var React = require('react');
17
-
18
14
  var preloadQuery_DEPRECATED = require('./preloadQuery_DEPRECATED');
19
15
 
16
+ var ProfilerContext = require('./ProfilerContext');
17
+
20
18
  var useRelayEnvironment = require('./useRelayEnvironment');
21
19
 
20
+ var React = require('react');
21
+
22
22
  var _require = require('react'),
23
23
  useContext = _require.useContext,
24
24
  useEffect = _require.useEffect,
@@ -98,7 +98,7 @@ function MatchContainer(_ref2) {
98
98
 
99
99
  if (match != null && typeof match !== 'object') {
100
100
  throw new Error('MatchContainer: Expected `match` value to be an object or null/undefined.');
101
- } // NOTE: the MatchPointer type has a $fragmentRefs field to ensure that only
101
+ } // NOTE: the MatchPointer type has a $fragmentSpreads field to ensure that only
102
102
  // an object that contains a FragmentSpread can be passed. If the fragment
103
103
  // spread matches, then the metadata fields below (__id, __fragments, etc.)
104
104
  // will be present. But they can be missing if all the fragment spreads use
@@ -19,16 +19,24 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
19
19
 
20
20
  var LRUCache = require('./LRUCache');
21
21
 
22
- var invariant = require("fbjs/lib/invariant");
22
+ var SuspenseResource = require('./SuspenseResource');
23
+
24
+ var invariant = require('invariant');
23
25
 
24
26
  var _require = require('relay-runtime'),
27
+ RelayFeatureFlags = _require.RelayFeatureFlags,
25
28
  isPromise = _require.isPromise;
26
29
 
30
+ var warning = require("fbjs/lib/warning");
31
+
27
32
  var CACHE_CAPACITY = 1000;
28
33
  var DEFAULT_FETCH_POLICY = 'store-or-network';
29
- var DATA_RETENTION_TIMEOUT = 5 * 60 * 1000;
30
34
  var WEAKMAP_SUPPORTED = typeof WeakMap === 'function';
31
35
 
36
+ function operationIsLiveQuery(operation) {
37
+ return operation.request.node.params.metadata.live !== undefined;
38
+ }
39
+
32
40
  function getQueryCacheIdentifier(environment, operation, maybeFetchPolicy, maybeRenderPolicy, cacheBreaker) {
33
41
  var fetchPolicy = maybeFetchPolicy !== null && maybeFetchPolicy !== void 0 ? maybeFetchPolicy : DEFAULT_FETCH_POLICY;
34
42
  var renderPolicy = maybeRenderPolicy !== null && maybeRenderPolicy !== void 0 ? maybeRenderPolicy : environment.UNSTABLE_getDefaultRenderPolicy();
@@ -57,11 +65,83 @@ function getQueryResult(operation, cacheIdentifier) {
57
65
 
58
66
  var nextID = 200000;
59
67
 
60
- function createCacheEntry(cacheIdentifier, operation, value, networkSubscription, onDispose) {
68
+ function createCacheEntry(cacheIdentifier, operation, operationAvailability, value, networkSubscription, onDispose) {
69
+ // There should be no behavior difference between createCacheEntry_new and
70
+ // createCacheEntry_old, and it doesn't directly relate to Client Edges.
71
+ // It was just a refactoring that was needed for Client Edges but that
72
+ // is behind the feature flag just in case there is any accidental breakage.
73
+ if (RelayFeatureFlags.REFACTOR_SUSPENSE_RESOURCE) {
74
+ return createCacheEntry_new(cacheIdentifier, operation, operationAvailability, value, networkSubscription, onDispose);
75
+ } else {
76
+ return createCacheEntry_old(cacheIdentifier, operation, operationAvailability, value, networkSubscription, onDispose);
77
+ }
78
+ }
79
+
80
+ function createCacheEntry_new(cacheIdentifier, operation, operationAvailability, value, networkSubscription, onDispose) {
81
+ var isLiveQuery = operationIsLiveQuery(operation);
82
+ var currentValue = value;
83
+ var currentNetworkSubscription = networkSubscription;
84
+ var suspenseResource = new SuspenseResource(function (environment) {
85
+ var retention = environment.retain(operation);
86
+ return {
87
+ dispose: function dispose() {
88
+ // Normally if this entry never commits, the request would've ended by the
89
+ // time this timeout expires and the temporary retain is released. However,
90
+ // we need to do this for live queries which remain open indefinitely.
91
+ if (isLiveQuery && currentNetworkSubscription != null) {
92
+ currentNetworkSubscription.unsubscribe();
93
+ }
94
+
95
+ retention.dispose();
96
+ onDispose(cacheEntry);
97
+ }
98
+ };
99
+ });
100
+ var cacheEntry = {
101
+ cacheIdentifier: cacheIdentifier,
102
+ id: nextID++,
103
+ processedPayloadsCount: 0,
104
+ operationAvailability: operationAvailability,
105
+ getValue: function getValue() {
106
+ return currentValue;
107
+ },
108
+ setValue: function setValue(val) {
109
+ currentValue = val;
110
+ },
111
+ getRetainCount: function getRetainCount() {
112
+ return suspenseResource.getRetainCount();
113
+ },
114
+ getNetworkSubscription: function getNetworkSubscription() {
115
+ return currentNetworkSubscription;
116
+ },
117
+ setNetworkSubscription: function setNetworkSubscription(subscription) {
118
+ if (isLiveQuery && currentNetworkSubscription != null) {
119
+ currentNetworkSubscription.unsubscribe();
120
+ }
121
+
122
+ currentNetworkSubscription = subscription;
123
+ },
124
+ temporaryRetain: function temporaryRetain(environment) {
125
+ return suspenseResource.temporaryRetain(environment);
126
+ },
127
+ permanentRetain: function permanentRetain(environment) {
128
+ return suspenseResource.permanentRetain(environment);
129
+ },
130
+ releaseTemporaryRetain: function releaseTemporaryRetain() {
131
+ suspenseResource.releaseTemporaryRetain();
132
+ }
133
+ };
134
+ return cacheEntry;
135
+ }
136
+
137
+ var DATA_RETENTION_TIMEOUT = 5 * 60 * 1000;
138
+
139
+ function createCacheEntry_old(cacheIdentifier, operation, operationAvailability, value, networkSubscription, onDispose) {
140
+ var isLiveQuery = operationIsLiveQuery(operation);
61
141
  var currentValue = value;
62
142
  var retainCount = 0;
63
143
  var retainDisposable = null;
64
- var releaseTemporaryRetain = null;
144
+ var _releaseTemporaryRetain = null;
65
145
  var currentNetworkSubscription = networkSubscription;
66
146
 
67
147
  var retain = function retain(environment) {
@@ -89,6 +169,8 @@ function createCacheEntry(cacheIdentifier, operation, value, networkSubscription
89
169
  var cacheEntry = {
90
170
  cacheIdentifier: cacheIdentifier,
91
171
  id: nextID++,
172
+ processedPayloadsCount: 0,
173
+ operationAvailability: operationAvailability,
92
174
  getValue: function getValue() {
93
175
  return currentValue;
94
176
  },
@@ -102,7 +184,7 @@ function createCacheEntry(cacheIdentifier, operation, value, networkSubscription
102
184
  return currentNetworkSubscription;
103
185
  },
104
186
  setNetworkSubscription: function setNetworkSubscription(subscription) {
105
- if (currentNetworkSubscription != null) {
187
+ if (isLiveQuery && currentNetworkSubscription != null) {
106
188
  currentNetworkSubscription.unsubscribe();
107
189
  }
108
190
 
@@ -129,12 +211,12 @@ function createCacheEntry(cacheIdentifier, operation, value, networkSubscription
129
211
  var localReleaseTemporaryRetain = function localReleaseTemporaryRetain() {
130
212
  clearTimeout(releaseQueryTimeout);
131
213
  releaseQueryTimeout = null;
132
- releaseTemporaryRetain = null;
214
+ _releaseTemporaryRetain = null;
133
215
  disposable.dispose(); // Normally if this entry never commits, the request would've ended by the
134
216
  // time this timeout expires and the temporary retain is released. However,
135
217
  // we need to do this for live queries which remain open indefinitely.
136
218
 
137
- if (retainCount <= 0 && currentNetworkSubscription != null) {
219
+ if (isLiveQuery && retainCount <= 0 && currentNetworkSubscription != null) {
138
220
  currentNetworkSubscription.unsubscribe();
139
221
  }
140
222
  };
@@ -147,34 +229,42 @@ function createCacheEntry(cacheIdentifier, operation, value, networkSubscription
147
229
  // phase, as well as multiple times by other query components that are
148
230
  // rendering the same query/variables.
149
231
 
150
- if (releaseTemporaryRetain != null) {
151
- releaseTemporaryRetain();
232
+ if (_releaseTemporaryRetain != null) {
233
+ _releaseTemporaryRetain();
152
234
  }
153
235
 
154
- releaseTemporaryRetain = localReleaseTemporaryRetain;
236
+ _releaseTemporaryRetain = localReleaseTemporaryRetain;
155
237
  return {
156
238
  dispose: function dispose() {
157
- releaseTemporaryRetain && releaseTemporaryRetain();
239
+ _releaseTemporaryRetain && _releaseTemporaryRetain();
158
240
  }
159
241
  };
160
242
  },
161
243
  permanentRetain: function permanentRetain(environment) {
162
244
  var disposable = retain(environment);
163
245
 
164
- if (releaseTemporaryRetain != null) {
165
- releaseTemporaryRetain();
166
- releaseTemporaryRetain = null;
246
+ if (_releaseTemporaryRetain != null) {
247
+ _releaseTemporaryRetain();
248
+
249
+ _releaseTemporaryRetain = null;
167
250
  }
168
251
 
169
252
  return {
170
253
  dispose: function dispose() {
171
254
  disposable.dispose();
172
255
 
173
- if (retainCount <= 0 && currentNetworkSubscription != null) {
256
+ if (isLiveQuery && retainCount <= 0 && currentNetworkSubscription != null) {
174
257
  currentNetworkSubscription.unsubscribe();
175
258
  }
176
259
  }
177
260
  };
261
+ },
262
+ releaseTemporaryRetain: function releaseTemporaryRetain() {
263
+ if (_releaseTemporaryRetain != null) {
264
+ _releaseTemporaryRetain();
265
+
266
+ _releaseTemporaryRetain = null;
267
+ }
178
268
  }
179
269
  };
180
270
  return cacheEntry;
@@ -185,8 +275,14 @@ var QueryResourceImpl = /*#__PURE__*/function () {
185
275
  var _this = this;
186
276
 
187
277
  (0, _defineProperty2["default"])(this, "_clearCacheEntry", function (cacheEntry) {
188
- if (cacheEntry.getRetainCount() <= 0) {
278
+ // The new code does this retainCount <= 0 check within SuspenseResource
279
+ // before calling _clearCacheEntry, whereas with the old code we do it here.
280
+ if (RelayFeatureFlags.REFACTOR_SUSPENSE_RESOURCE) {
189
281
  _this._cache["delete"](cacheEntry.cacheIdentifier);
282
+ } else {
283
+ if (cacheEntry.getRetainCount() <= 0) {
284
+ _this._cache["delete"](cacheEntry.cacheIdentifier);
285
+ }
190
286
  }
191
287
  });
192
288
  this._environment = environment;
@@ -215,6 +311,7 @@ var QueryResourceImpl = /*#__PURE__*/function () {
215
311
  var cacheEntry = this._cache.get(cacheIdentifier);
216
312
 
217
313
  var temporaryRetainDisposable = null;
314
+ var entryWasCached = cacheEntry != null;
218
315
 
219
316
  if (cacheEntry == null) {
220
317
  // 2. If a cached value isn't available, try fetching the operation.
@@ -245,7 +342,20 @@ var QueryResourceImpl = /*#__PURE__*/function () {
245
342
  temporaryRetainDisposable = cacheEntry.temporaryRetain(environment);
246
343
  var cachedValue = cacheEntry.getValue();
247
344
 
248
- if (isPromise(cachedValue) || cachedValue instanceof Error) {
345
+ if (isPromise(cachedValue)) {
346
+ environment.__log({
347
+ name: 'suspense.query',
348
+ fetchPolicy: fetchPolicy,
349
+ isPromiseCached: entryWasCached,
350
+ operation: operation,
351
+ queryAvailability: cacheEntry.operationAvailability,
352
+ renderPolicy: renderPolicy
353
+ });
354
+
355
+ throw cachedValue;
356
+ }
357
+
358
+ if (cachedValue instanceof Error) {
249
359
  throw cachedValue;
250
360
  }
251
361
 
@@ -263,7 +373,7 @@ var QueryResourceImpl = /*#__PURE__*/function () {
263
373
  var cacheIdentifier = queryResult.cacheIdentifier,
264
374
  operation = queryResult.operation;
265
375
 
266
- var cacheEntry = this._getOrCreateCacheEntry(cacheIdentifier, operation, queryResult, null);
376
+ var cacheEntry = this._getOrCreateCacheEntry(cacheIdentifier, operation, null, queryResult, null);
267
377
 
268
378
  var disposable = cacheEntry.permanentRetain(environment);
269
379
 
@@ -280,17 +390,25 @@ var QueryResourceImpl = /*#__PURE__*/function () {
280
390
  };
281
391
  };
282
392
 
393
+ _proto.releaseTemporaryRetain = function releaseTemporaryRetain(queryResult) {
394
+ var cacheEntry = this._cache.get(queryResult.cacheIdentifier);
395
+
396
+ if (cacheEntry != null) {
397
+ cacheEntry.releaseTemporaryRetain();
398
+ }
399
+ };
400
+
283
401
  _proto.TESTS_ONLY__getCacheEntry = function TESTS_ONLY__getCacheEntry(operation, maybeFetchPolicy, maybeRenderPolicy, cacheBreaker) {
284
402
  var environment = this._environment;
285
403
  var cacheIdentifier = getQueryCacheIdentifier(environment, operation, maybeFetchPolicy, maybeRenderPolicy, cacheBreaker);
286
404
  return this._cache.get(cacheIdentifier);
287
405
  };
288
406
 
289
- _proto._getOrCreateCacheEntry = function _getOrCreateCacheEntry(cacheIdentifier, operation, value, networkSubscription) {
407
+ _proto._getOrCreateCacheEntry = function _getOrCreateCacheEntry(cacheIdentifier, operation, operationAvailability, value, networkSubscription) {
290
408
  var cacheEntry = this._cache.get(cacheIdentifier);
291
409
 
292
410
  if (cacheEntry == null) {
293
- cacheEntry = createCacheEntry(cacheIdentifier, operation, value, networkSubscription, this._clearCacheEntry);
411
+ cacheEntry = createCacheEntry(cacheIdentifier, operation, operationAvailability, value, networkSubscription, this._clearCacheEntry);
294
412
 
295
413
  this._cache.set(cacheIdentifier, cacheEntry);
296
414
  }
@@ -353,7 +471,7 @@ var QueryResourceImpl = /*#__PURE__*/function () {
353
471
  if (shouldAllowRender) {
354
472
  var queryResult = getQueryResult(operation, cacheIdentifier);
355
473
 
356
- var _cacheEntry = createCacheEntry(cacheIdentifier, operation, queryResult, null, this._clearCacheEntry);
474
+ var _cacheEntry = createCacheEntry(cacheIdentifier, operation, queryAvailability, queryResult, null, this._clearCacheEntry);
357
475
 
358
476
  this._cache.set(cacheIdentifier, _cacheEntry);
359
477
  }
@@ -373,22 +491,47 @@ var QueryResourceImpl = /*#__PURE__*/function () {
373
491
  }
374
492
 
375
493
  var observerStart = observer === null || observer === void 0 ? void 0 : observer.start;
376
- observerStart && observerStart(subscription);
494
+
495
+ if (observerStart) {
496
+ var subscriptionWithConditionalCancelation = (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, subscription), {}, {
497
+ unsubscribe: function unsubscribe() {
498
+ // Only live queries should have their network requests canceled.
499
+ if (operationIsLiveQuery(operation)) {
500
+ subscription.unsubscribe();
501
+ }
502
+ }
503
+ });
504
+ observerStart(subscriptionWithConditionalCancelation);
505
+ }
377
506
  },
378
507
  next: function next() {
379
- var snapshot = environment.lookup(operation.fragment);
380
-
381
- var cacheEntry = _this2._getOrCreateCacheEntry(cacheIdentifier, operation, _queryResult, networkSubscription);
508
+ var cacheEntry = _this2._getOrCreateCacheEntry(cacheIdentifier, operation, queryAvailability, _queryResult, networkSubscription);
382
509
 
510
+ cacheEntry.processedPayloadsCount += 1;
383
511
  cacheEntry.setValue(_queryResult);
384
512
  resolveNetworkPromise();
385
513
  var observerNext = observer === null || observer === void 0 ? void 0 : observer.next;
386
- observerNext && observerNext(snapshot);
514
+
515
+ if (observerNext != null) {
516
+ var snapshot = environment.lookup(operation.fragment);
517
+ observerNext(snapshot);
518
+ }
387
519
  },
388
520
  error: function error(_error) {
389
- var cacheEntry = _this2._getOrCreateCacheEntry(cacheIdentifier, operation, _error, networkSubscription);
521
+ var cacheEntry = _this2._getOrCreateCacheEntry(cacheIdentifier, operation, queryAvailability, _error, networkSubscription); // If, this is the first thing we receive for the query,
522
+ // before any other payload handled is error, we will cache and
523
+ // re-throw that error later.
524
+ // We will ignore errors for any incremental payloads we receive.
525
+
526
+
527
+ if (cacheEntry.processedPayloadsCount === 0) {
528
+ cacheEntry.setValue(_error);
529
+ } else {
530
+ // TODO:T92030819 Remove this warning and actually throw the network error
531
+ // To complete this task we need to have a way of precisely tracking suspendable points
532
+ process.env.NODE_ENV !== "production" ? warning(false, 'QueryResource: An incremental payload for query `%` returned an error: `%`:`%`.', operation.fragment.node.name, _error.message, _error.stack) : void 0;
533
+ }
390
534
 
391
- cacheEntry.setValue(_error);
392
535
  resolveNetworkPromise();
393
536
  networkSubscription = null;
394
537
  cacheEntry.setNetworkSubscription(null);
@@ -419,7 +562,7 @@ var QueryResourceImpl = /*#__PURE__*/function () {
419
562
  }); // $FlowExpectedError[prop-missing] Expando to annotate Promises.
420
563
 
421
564
  networkPromise.displayName = 'Relay(' + operation.fragment.node.name + ')';
422
- _cacheEntry2 = createCacheEntry(cacheIdentifier, operation, networkPromise, networkSubscription, this._clearCacheEntry);
565
+ _cacheEntry2 = createCacheEntry(cacheIdentifier, operation, queryAvailability, networkPromise, networkSubscription, this._clearCacheEntry);
423
566
 
424
567
  this._cache.set(cacheIdentifier, _cacheEntry2);
425
568
  }
@@ -19,12 +19,14 @@ var useMemo = React.useMemo;
19
19
 
20
20
  function RelayEnvironmentProvider(props) {
21
21
  var children = props.children,
22
- environment = props.environment;
22
+ environment = props.environment,
23
+ getEnvironmentForActor = props.getEnvironmentForActor;
23
24
  var context = useMemo(function () {
24
25
  return {
25
- environment: environment
26
+ environment: environment,
27
+ getEnvironmentForActor: getEnvironmentForActor
26
28
  };
27
- }, [environment]);
29
+ }, [environment, getEnvironmentForActor]);
28
30
  return /*#__PURE__*/React.createElement(ReactRelayContext.Provider, {
29
31
  value: context
30
32
  }, children);
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ *
8
+ * @emails oncall+relay
9
+ * @format
10
+ */
11
+ // flowlint ambiguous-object-type:error
12
+ 'use strict';
13
+
14
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
15
+
16
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
17
+
18
+ var invariant = require('invariant');
19
+
20
+ var TEMPORARY_RETAIN_DURATION_MS = 5 * 60 * 1000;
21
+ /**
22
+ * Allows you to retain a resource as part of a component lifecycle accounting
23
+ * for Suspense. You temporarily retain the resource during render, then
24
+ * permanently retain it during commit and release it during unmount.
25
+ */
26
+
27
+ var SuspenseResource = /*#__PURE__*/function () {
28
+ function SuspenseResource(retain) {
29
+ var _this = this;
30
+
31
+ (0, _defineProperty2["default"])(this, "_retainCount", 0);
32
+ (0, _defineProperty2["default"])(this, "_retainDisposable", null);
33
+ (0, _defineProperty2["default"])(this, "_releaseTemporaryRetain", null);
34
+
35
+ this._retain = function (environment) {
36
+ _this._retainCount++;
37
+
38
+ if (_this._retainCount === 1) {
39
+ _this._retainDisposable = retain(environment);
40
+ }
41
+
42
+ return {
43
+ dispose: function dispose() {
44
+ _this._retainCount = Math.max(0, _this._retainCount - 1);
45
+
46
+ if (_this._retainCount === 0) {
47
+ !(_this._retainDisposable != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected disposable to release query to be defined.' + "If you're seeing this, this is likely a bug in Relay.") : invariant(false) : void 0;
48
+
49
+ _this._retainDisposable.dispose();
50
+
51
+ _this._retainDisposable = null;
52
+ }
53
+ }
54
+ };
55
+ };
56
+ }
57
+
58
+ var _proto = SuspenseResource.prototype;
59
+
60
+ _proto.temporaryRetain = function temporaryRetain(environment) {
61
+ var _this2 = this;
62
+
63
+ var _this$_releaseTempora;
64
+
65
+ // If we're executing in a server environment, there's no need
66
+ // to create temporary retains, since the component will never commit.
67
+ if (environment.isServer()) {
68
+ return {
69
+ dispose: function dispose() {}
70
+ };
71
+ } // temporaryRetain is called during the render phase. However,
72
+ // given that we can't tell if this render will eventually commit or not,
73
+ // we create a timer to autodispose of this retain in case the associated
74
+ // component never commits.
75
+ // If the component /does/ commit, permanentRetain will clear this timeout
76
+ // and permanently retain the data.
77
+
78
+
79
+ var retention = this._retain(environment);
80
+
81
+ var releaseQueryTimeout = null;
82
+
83
+ var releaseTemporaryRetain = function releaseTemporaryRetain() {
84
+ clearTimeout(releaseQueryTimeout);
85
+ releaseQueryTimeout = null;
86
+ _this2._releaseTemporaryRetain = null;
87
+ retention.dispose();
88
+ };
89
+
90
+ releaseQueryTimeout = setTimeout(releaseTemporaryRetain, TEMPORARY_RETAIN_DURATION_MS); // NOTE: Since temporaryRetain can be called multiple times, we release
91
+ // the previous temporary retain after we re-establish a new one, since
92
+ // we only ever need a single temporary retain until the permanent retain is
93
+ // established.
94
+ // temporaryRetain may be called multiple times by React during the render
95
+ // phase, as well as multiple times by other query components that are
96
+ // rendering the same query/variables.
97
+
98
+ (_this$_releaseTempora = this._releaseTemporaryRetain) === null || _this$_releaseTempora === void 0 ? void 0 : _this$_releaseTempora.call(this);
99
+ this._releaseTemporaryRetain = releaseTemporaryRetain;
100
+ return {
101
+ dispose: function dispose() {
102
+ var _this$_releaseTempora2;
103
+
104
+ (_this$_releaseTempora2 = _this2._releaseTemporaryRetain) === null || _this$_releaseTempora2 === void 0 ? void 0 : _this$_releaseTempora2.call(_this2);
105
+ }
106
+ };
107
+ };
108
+
109
+ _proto.permanentRetain = function permanentRetain(environment) {
110
+ var disposable = this._retain(environment);
111
+
112
+ this.releaseTemporaryRetain();
113
+ return disposable;
114
+ };
115
+
116
+ _proto.releaseTemporaryRetain = function releaseTemporaryRetain() {
117
+ var _this$_releaseTempora3;
118
+
119
+ (_this$_releaseTempora3 = this._releaseTemporaryRetain) === null || _this$_releaseTempora3 === void 0 ? void 0 : _this$_releaseTempora3.call(this);
120
+ this._releaseTemporaryRetain = null;
121
+ };
122
+
123
+ _proto.getRetainCount = function getRetainCount() {
124
+ return this._retainCount;
125
+ };
126
+
127
+ return SuspenseResource;
128
+ }();
129
+
130
+ module.exports = SuspenseResource;
@@ -14,21 +14,21 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
14
14
 
15
15
  var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
16
16
 
17
- var React = require('react');
18
-
19
- var invariant = require("fbjs/lib/invariant");
17
+ var invariant = require('invariant');
20
18
 
21
- var warning = require("fbjs/lib/warning");
19
+ var React = require('react');
22
20
 
23
21
  var _require = require('relay-runtime'),
22
+ Observable = _require.Observable,
24
23
  PreloadableQueryRegistry = _require.PreloadableQueryRegistry,
24
+ RelayFeatureFlags = _require.RelayFeatureFlags,
25
25
  ReplaySubject = _require.ReplaySubject,
26
+ fetchQueryDeduped = _require.__internal.fetchQueryDeduped,
26
27
  createOperationDescriptor = _require.createOperationDescriptor,
27
28
  getRequest = _require.getRequest,
28
- getRequestIdentifier = _require.getRequestIdentifier,
29
- Observable = _require.Observable,
30
- RelayFeatureFlags = _require.RelayFeatureFlags,
31
- fetchQueryDeduped = _require.__internal.fetchQueryDeduped;
29
+ getRequestIdentifier = _require.getRequestIdentifier;
30
+
31
+ var warning = require("fbjs/lib/warning");
32
32
 
33
33
  var RenderDispatcher = null;
34
34
  var fetchKey = 100001;
@@ -252,10 +252,9 @@ function loadQuery(environment, preloadableRequest, variables, options, environm
252
252
  // ast, and we know that if we don't have the query ast
253
253
  // available, then this query could've never been written to the
254
254
  // store in the first place, so it couldn't have been cached.
255
- var networkObservable = fetchPolicy === 'store-only' ? null : makeNetworkRequest(params);
255
+ var networkObservable = fetchPolicy === 'store-only' ? null : makeNetworkRequest(params); // $FlowFixMe[method-unbinding] added when improving typing for this parameters
256
256
 
257
- var _PreloadableQueryRegi = PreloadableQueryRegistry.onLoad( // $FlowFixMe[incompatible-call]
258
- queryId, function (preloadedModule) {
257
+ var _PreloadableQueryRegi = PreloadableQueryRegistry.onLoad(queryId, function (preloadedModule) {
259
258
  cancelOnLoadCallback();
260
259
  var operation = createOperationDescriptor(preloadedModule, variables, networkCacheConfig);
261
260
  retainReference = environment.retain(operation);
@@ -278,6 +277,33 @@ function loadQuery(environment, preloadableRequest, variables, options, environm
278
277
  }
279
278
 
280
279
  var isDisposed = false;
280
+ var isReleased = false;
281
+ var isNetworkRequestCancelled = false;
282
+
283
+ var releaseQuery = function releaseQuery() {
284
+ if (isReleased) {
285
+ return;
286
+ }
287
+
288
+ retainReference && retainReference.dispose();
289
+ isReleased = true;
290
+ };
291
+
292
+ var cancelNetworkRequest = function cancelNetworkRequest() {
293
+ if (isNetworkRequestCancelled) {
294
+ return;
295
+ }
296
+
297
+ if (didExecuteNetworkSource) {
298
+ unsubscribeFromExecution && unsubscribeFromExecution();
299
+ } else {
300
+ unsubscribeFromNetworkRequest && unsubscribeFromNetworkRequest();
301
+ }
302
+
303
+ cancelOnLoadCallback && cancelOnLoadCallback();
304
+ isNetworkRequestCancelled = true;
305
+ };
306
+
281
307
  return {
282
308
  kind: 'PreloadedQuery',
283
309
  environment: environment,
@@ -287,22 +313,18 @@ function loadQuery(environment, preloadableRequest, variables, options, environm
287
313
  return;
288
314
  }
289
315
 
290
- if (didExecuteNetworkSource) {
291
- unsubscribeFromExecution && unsubscribeFromExecution();
292
- } else {
293
- unsubscribeFromNetworkRequest && unsubscribeFromNetworkRequest();
294
- }
295
-
296
- retainReference && retainReference.dispose();
297
- cancelOnLoadCallback && cancelOnLoadCallback();
316
+ releaseQuery();
317
+ cancelNetworkRequest();
298
318
  isDisposed = true;
299
319
  },
320
+ releaseQuery: releaseQuery,
321
+ cancelNetworkRequest: cancelNetworkRequest,
300
322
  fetchKey: fetchKey,
301
323
  id: queryId,
302
324
 
303
325
  // $FlowFixMe[unsafe-getters-setters] - this has no side effects
304
326
  get isDisposed() {
305
- return isDisposed;
327
+ return isDisposed || isReleased;
306
328
  },
307
329
 
308
330
  // $FlowFixMe[unsafe-getters-setters] - this has no side effects