react-relay 15.0.0 → 16.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/ReactRelayContext.js +1 -1
  2. package/ReactRelayQueryFetcher.js.flow +1 -5
  3. package/ReactRelayQueryRenderer.js.flow +9 -36
  4. package/ReactRelayTypes.js.flow +1 -0
  5. package/buildReactRelayContainer.js.flow +3 -1
  6. package/hooks.js +1 -1
  7. package/index.js +1 -1
  8. package/legacy.js +1 -1
  9. package/lib/ReactRelayContainerUtils.js +0 -11
  10. package/lib/ReactRelayContext.js +0 -11
  11. package/lib/ReactRelayFragmentContainer.js +6 -78
  12. package/lib/ReactRelayFragmentMockRenderer.js +0 -11
  13. package/lib/ReactRelayLocalQueryRenderer.js +0 -17
  14. package/lib/ReactRelayPaginationContainer.js +5 -208
  15. package/lib/ReactRelayQueryFetcher.js +2 -51
  16. package/lib/ReactRelayQueryRenderer.js +6 -94
  17. package/lib/ReactRelayQueryRendererContext.js +0 -11
  18. package/lib/ReactRelayRefetchContainer.js +5 -91
  19. package/lib/ReactRelayTestMocker.js +9 -85
  20. package/lib/ReactRelayTypes.js +0 -11
  21. package/lib/RelayContext.js +0 -21
  22. package/lib/assertFragmentMap.js +0 -15
  23. package/lib/buildReactRelayContainer.js +0 -19
  24. package/lib/getRootVariablesForFragments.js +0 -14
  25. package/lib/hooks.js +0 -15
  26. package/lib/index.js +0 -17
  27. package/lib/isRelayEnvironment.js +1 -18
  28. package/lib/jest-react/enqueueTask.js +0 -20
  29. package/lib/jest-react/internalAct.js +0 -38
  30. package/lib/legacy.js +0 -15
  31. package/lib/multi-actor/ActorChange.js +0 -11
  32. package/lib/multi-actor/index.js +0 -11
  33. package/lib/multi-actor/useRelayActorEnvironment.js +0 -11
  34. package/lib/relay-hooks/EntryPointContainer.react.js +0 -11
  35. package/lib/relay-hooks/EntryPointTypes.flow.js +1 -14
  36. package/lib/relay-hooks/FragmentResource.js +76 -132
  37. package/lib/relay-hooks/HooksImplementation.js +0 -11
  38. package/lib/relay-hooks/InternalLogger.js +0 -11
  39. package/lib/relay-hooks/LRUCache.js +0 -22
  40. package/lib/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js +0 -18
  41. package/lib/relay-hooks/MatchContainer.js +0 -94
  42. package/lib/relay-hooks/NestedRelayEntryPointBuilderUtils.js +9 -0
  43. package/lib/relay-hooks/ProfilerContext.js +0 -15
  44. package/lib/relay-hooks/QueryResource.js +2 -68
  45. package/lib/relay-hooks/RelayEnvironmentProvider.js +0 -11
  46. package/lib/relay-hooks/SuspenseResource.js +0 -34
  47. package/lib/relay-hooks/loadEntryPoint.js +1 -24
  48. package/lib/relay-hooks/loadQuery.js +2 -106
  49. package/lib/relay-hooks/preloadQuery_DEPRECATED.js +2 -27
  50. package/lib/relay-hooks/prepareEntryPoint_DEPRECATED.js +0 -13
  51. package/lib/relay-hooks/react-cache/RelayReactCache.js +0 -12
  52. package/lib/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js +1 -36
  53. package/lib/relay-hooks/react-cache/readFragmentInternal_REACT_CACHE.js +3 -27
  54. package/lib/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js +34 -99
  55. package/lib/relay-hooks/react-cache/useFragment_REACT_CACHE.js +0 -15
  56. package/lib/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js +0 -16
  57. package/lib/relay-hooks/react-cache/usePaginationFragment_REACT_CACHE.js +1 -23
  58. package/lib/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js +0 -29
  59. package/lib/relay-hooks/react-cache/useRefetchableFragmentInternal_REACT_CACHE.js +12 -96
  60. package/lib/relay-hooks/react-cache/useRefetchableFragment_REACT_CACHE.js +0 -14
  61. package/lib/relay-hooks/useBlockingPaginationFragment.js +0 -42
  62. package/lib/relay-hooks/useClientQuery.js +0 -18
  63. package/lib/relay-hooks/useEntryPointLoader.js +0 -69
  64. package/lib/relay-hooks/useFetchTrackingRef.js +0 -26
  65. package/lib/relay-hooks/useFragment.js +0 -17
  66. package/lib/relay-hooks/useFragmentNode.js +2 -32
  67. package/lib/relay-hooks/useIsMountedRef.js +0 -11
  68. package/lib/relay-hooks/useIsOperationNodeActive.js +0 -11
  69. package/lib/relay-hooks/useIsParentQueryActive.js +0 -11
  70. package/lib/relay-hooks/useLazyLoadQuery.js +0 -18
  71. package/lib/relay-hooks/useLazyLoadQueryNode.js +0 -35
  72. package/lib/relay-hooks/useLoadMoreFunction.js +9 -34
  73. package/lib/relay-hooks/useMemoOperationDescriptor.js +0 -11
  74. package/lib/relay-hooks/useMemoVariables.js +0 -17
  75. package/lib/relay-hooks/useMutation.js +0 -11
  76. package/lib/relay-hooks/usePaginationFragment.js +1 -26
  77. package/lib/relay-hooks/usePreloadedQuery.js +0 -27
  78. package/lib/relay-hooks/useQueryLoader.js +0 -74
  79. package/lib/relay-hooks/useRefetchableFragment.js +0 -16
  80. package/lib/relay-hooks/useRefetchableFragmentNode.js +14 -97
  81. package/lib/relay-hooks/useRelayEnvironment.js +0 -11
  82. package/lib/relay-hooks/useStaticFragmentNodeWarning.js +0 -15
  83. package/lib/relay-hooks/useSubscribeToInvalidationState.js +0 -25
  84. package/lib/relay-hooks/useSubscription.js +0 -15
  85. package/lib/relay-hooks/useUnsafeRef_DEPRECATED.js +0 -17
  86. package/package.json +2 -2
  87. package/react-relay-hooks.js +2 -2
  88. package/react-relay-hooks.min.js +2 -2
  89. package/react-relay-legacy.js +2 -2
  90. package/react-relay-legacy.min.js +2 -2
  91. package/react-relay.js +2 -2
  92. package/react-relay.min.js +2 -2
  93. package/relay-hooks/EntryPointContainer.react.js.flow +5 -0
  94. package/relay-hooks/EntryPointTypes.flow.js.flow +20 -19
  95. package/relay-hooks/FragmentResource.js.flow +114 -26
  96. package/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js.flow +4 -2
  97. package/relay-hooks/NestedRelayEntryPointBuilderUtils.js.flow +51 -0
  98. package/relay-hooks/__flowtests__/EntryPointTypes/NestedEntrypoints-flowtest.js.flow +7 -5
  99. package/relay-hooks/__flowtests__/useBlockingPaginationFragment-flowtest.js.flow +5 -0
  100. package/relay-hooks/__flowtests__/usePaginationFragment-flowtest.js.flow +5 -0
  101. package/relay-hooks/__flowtests__/useRefetchableFragment-flowtest.js.flow +2 -0
  102. package/relay-hooks/loadEntryPoint.js.flow +4 -2
  103. package/relay-hooks/loadQuery.js.flow +21 -1
  104. package/relay-hooks/prepareEntryPoint_DEPRECATED.js.flow +4 -2
  105. package/relay-hooks/react-cache/readFragmentInternal_REACT_CACHE.js.flow +2 -1
  106. package/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js.flow +28 -10
  107. package/relay-hooks/react-cache/useFragment_REACT_CACHE.js.flow +3 -9
  108. package/relay-hooks/react-cache/usePaginationFragment_REACT_CACHE.js.flow +28 -57
  109. package/relay-hooks/react-cache/useRefetchableFragmentInternal_REACT_CACHE.js.flow +19 -12
  110. package/relay-hooks/react-cache/useRefetchableFragment_REACT_CACHE.js.flow +15 -31
  111. package/relay-hooks/useBlockingPaginationFragment.js.flow +2 -4
  112. package/relay-hooks/useClientQuery.js.flow +2 -2
  113. package/relay-hooks/useFragmentNode.js.flow +2 -2
  114. package/relay-hooks/useLoadMoreFunction.js.flow +15 -9
  115. package/relay-hooks/useMutation.js.flow +26 -9
  116. package/relay-hooks/usePaginationFragment.js.flow +2 -8
  117. package/relay-hooks/useQueryLoader.js.flow +2 -8
  118. package/relay-hooks/useRefetchableFragment.js.flow +3 -2
  119. package/relay-hooks/useRefetchableFragmentNode.js.flow +28 -13
@@ -1,33 +1,7 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and 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
- * @format
8
- * @oncall relay
9
- */
10
-
11
- /* global jest */
12
-
13
- // This file is sync'd from https://github.com/facebook/react/tree/main/packages/jest-react
14
-
15
- // This version of `act` is only used by our tests. Unlike the public version
16
- // of `act`, it's designed to work identically in both production and
17
- // development. It may have slightly different behavior from the public
18
- // version, too, since our constraints in our test suite are not the same as
19
- // those of developers using React — we're testing React itself, as opposed to
20
- // building an app with React.
21
-
22
1
  'use strict';
23
2
 
24
3
  var enqueueTask = require('./enqueueTask');
25
4
  var Scheduler = require('scheduler/unstable_mock');
26
-
27
- // The subset of a Promise that React APIs rely on. This resolves a value.
28
- // This doesn't require a return value neither from the handler nor the
29
- // then function.
30
-
31
5
  var actingUpdatesScopeDepth = 0;
32
6
  function act(scope) {
33
7
  if (Scheduler.unstable_flushAllWithoutAsserting === undefined) {
@@ -40,8 +14,6 @@ function act(scope) {
40
14
  var previousActingUpdatesScopeDepth = actingUpdatesScopeDepth;
41
15
  actingUpdatesScopeDepth++;
42
16
  if (process.env.NODE_ENV !== "production" && actingUpdatesScopeDepth === 1) {
43
- // Because this is not the "real" `act`, we set this to `false` so React
44
- // knows not to fire `act` warnings.
45
17
  global.IS_REACT_ACT_ENVIRONMENT = false;
46
18
  }
47
19
  var unwind = function unwind() {
@@ -51,16 +23,10 @@ function act(scope) {
51
23
  actingUpdatesScopeDepth--;
52
24
  if (process.env.NODE_ENV !== "production") {
53
25
  if (actingUpdatesScopeDepth > previousActingUpdatesScopeDepth) {
54
- // if it's _less than_ previousActingUpdatesScopeDepth, then we can
55
- // assume the 'other' one has warned
56
26
  console.error('You seem to have overlapping act() calls, this is not supported. ' + 'Be sure to await previous act() calls before making a new one. ');
57
27
  }
58
28
  }
59
29
  };
60
-
61
- // TODO: This would be way simpler if 1) we required a promise to be
62
- // returned and 2) we could use async/await. Since it's only our used in
63
- // our test suite, we should be able to.
64
30
  try {
65
31
  var result = scope();
66
32
  if (typeof result === 'object' && result !== null && typeof result.then === 'function') {
@@ -84,8 +50,6 @@ function act(scope) {
84
50
  } else {
85
51
  var returnValue = result;
86
52
  try {
87
- // TODO: Let's not support non-async scopes at all in our tests. Need to
88
- // migrate existing tests.
89
53
  var didFlushWork;
90
54
  do {
91
55
  didFlushWork = Scheduler.unstable_flushAllWithoutAsserting();
@@ -105,8 +69,6 @@ function act(scope) {
105
69
  }
106
70
  }
107
71
  function flushActWork(resolve, reject) {
108
- // Flush suspended fallbacks
109
- // $FlowFixMe: Flow doesn't know about global Jest object
110
72
  jest.runOnlyPendingTimers();
111
73
  enqueueTask(function () {
112
74
  try {
package/lib/legacy.js CHANGED
@@ -1,14 +1,3 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and 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
- * @format
9
- * @oncall relay
10
- */
11
-
12
1
  'use strict';
13
2
 
14
3
  var ReactRelayContext = require('./ReactRelayContext');
@@ -18,10 +7,6 @@ var ReactRelayPaginationContainer = require('./ReactRelayPaginationContainer');
18
7
  var ReactRelayQueryRenderer = require('./ReactRelayQueryRenderer');
19
8
  var ReactRelayRefetchContainer = require('./ReactRelayRefetchContainer');
20
9
  var RelayRuntime = require('relay-runtime');
21
- /**
22
- * Legacy react-relay exports.
23
- * Should prefer using interface defined in ./hooks.js
24
- */
25
10
  module.exports = {
26
11
  ConnectionHandler: RelayRuntime.ConnectionHandler,
27
12
  QueryRenderer: ReactRelayQueryRenderer,
@@ -1,14 +1,3 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and 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
- * @format
9
- * @oncall relay
10
- */
11
-
12
1
  'use strict';
13
2
 
14
3
  var RelayEnvironmentProvider = require('../relay-hooks/RelayEnvironmentProvider');
@@ -1,12 +1 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and 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
- * @format
9
- * @oncall relay
10
- */
11
-
12
1
  'use strict';
@@ -1,14 +1,3 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and 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
- * @format
9
- * @oncall relay
10
- */
11
-
12
1
  'use strict';
13
2
 
14
3
  var ReactRelayContext = require('./../ReactRelayContext');
@@ -1,14 +1,3 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and 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
- * @format
9
- * @oncall relay
10
- */
11
-
12
1
  'use strict';
13
2
 
14
3
  var ProfilerContext = require('./ProfilerContext');
@@ -1,14 +1 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and 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
- * @format
9
- * @oncall relay
10
- */
11
-
12
- 'use strict';
13
-
14
- /* eslint-disable no-unused-vars */
1
+ 'use strict';
@@ -1,14 +1,3 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and 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
- * @format
9
- * @oncall relay
10
- */
11
-
12
1
  'use strict';
13
2
 
14
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
@@ -34,12 +23,7 @@ var _require2 = require('relay-runtime'),
34
23
  isPromise = _require2.isPromise,
35
24
  recycleNodesInto = _require2.recycleNodesInto;
36
25
  var WEAKMAP_SUPPORTED = typeof WeakMap === 'function';
37
- // TODO: Fix to not rely on LRU. If the number of active fragments exceeds this
38
- // capacity, readSpec() will fail to find cached entries and break object
39
- // identity even if data hasn't changed.
40
26
  var CACHE_CAPACITY = 1000000;
41
-
42
- // this is frozen so that users don't accidentally push data into the array
43
27
  var CONSTANT_READONLY_EMPTY_ARRAY = Object.freeze([]);
44
28
  function isMissingData(snapshot) {
45
29
  if (Array.isArray(snapshot)) {
@@ -94,13 +78,6 @@ function getFragmentResult(cacheKey, snapshot, storeEpoch) {
94
78
  storeEpoch: storeEpoch
95
79
  };
96
80
  }
97
-
98
- /**
99
- * The purpose of this cache is to allow information to be passed from an
100
- * initial read which suspends through to the commit that follows a subsequent
101
- * successful read. Specifically, the QueryResource result for the data fetch
102
- * is passed through so that that query can be retained on commit.
103
- */
104
81
  var ClientEdgeQueryResultsCache = /*#__PURE__*/function () {
105
82
  function ClientEdgeQueryResultsCache(environment) {
106
83
  (0, _defineProperty2["default"])(this, "_cache", new Map());
@@ -112,8 +89,7 @@ var ClientEdgeQueryResultsCache = /*#__PURE__*/function () {
112
89
  var _this$_cache$get$, _this$_cache$get;
113
90
  return (_this$_cache$get$ = (_this$_cache$get = this._cache.get(fragmentIdentifier)) === null || _this$_cache$get === void 0 ? void 0 : _this$_cache$get[0]) !== null && _this$_cache$get$ !== void 0 ? _this$_cache$get$ : undefined;
114
91
  };
115
- _proto.recordQueryResults = function recordQueryResults(fragmentIdentifier, value // may be mutated after being passed here
116
- ) {
92
+ _proto.recordQueryResults = function recordQueryResults(fragmentIdentifier, value) {
117
93
  var _this = this;
118
94
  var existing = this._cache.get(fragmentIdentifier);
119
95
  if (!existing) {
@@ -159,30 +135,14 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
159
135
  this._clientEdgeQueryResultsCache = new ClientEdgeQueryResultsCache(environment);
160
136
  }
161
137
  }
162
-
163
- /**
164
- * This function should be called during a Component's render function,
165
- * to read the data for a fragment, or suspend if the fragment is being
166
- * fetched.
167
- */
168
138
  var _proto2 = FragmentResourceImpl.prototype;
169
139
  _proto2.read = function read(fragmentNode, fragmentRef, componentDisplayName, fragmentKey) {
170
140
  return this.readWithIdentifier(fragmentNode, fragmentRef, getFragmentIdentifier(fragmentNode, fragmentRef), componentDisplayName, fragmentKey);
171
- }
172
-
173
- /**
174
- * Like `read`, but with a pre-computed fragmentIdentifier that should be
175
- * equal to `getFragmentIdentifier(fragmentNode, fragmentRef)` from the
176
- * arguments.
177
- */;
141
+ };
178
142
  _proto2.readWithIdentifier = function readWithIdentifier(fragmentNode, fragmentRef, fragmentIdentifier, componentDisplayName, fragmentKey) {
179
143
  var _this3 = this;
180
144
  var _fragmentNode$metadat, _fragmentNode$metadat2, _missingLiveResolverF2, _missingLiveResolverF3;
181
145
  var environment = this._environment;
182
-
183
- // If fragmentRef is null or undefined, pass it directly through.
184
- // This is a convenience when consuming fragments via a HOC API, when the
185
- // prop corresponding to the fragment ref might be passed as null.
186
146
  if (fragmentRef == null) {
187
147
  return {
188
148
  cacheKey: fragmentIdentifier,
@@ -193,9 +153,6 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
193
153
  };
194
154
  }
195
155
  var storeEpoch = environment.getStore().getEpoch();
196
-
197
- // If fragmentRef is plural, ensure that it is an array.
198
- // If it's empty, return the empty array directly before doing any more work.
199
156
  if ((fragmentNode === null || fragmentNode === void 0 ? void 0 : (_fragmentNode$metadat = fragmentNode.metadata) === null || _fragmentNode$metadat === void 0 ? void 0 : _fragmentNode$metadat.plural) === true) {
200
157
  !Array.isArray(fragmentRef) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected fragment pointer%s for fragment `%s` to be ' + 'an array, instead got `%s`. Remove `@relay(plural: true)` ' + 'from fragment `%s` to allow the prop to be an object.', fragmentKey != null ? " for key `".concat(fragmentKey, "`") : '', fragmentNode.name, typeof fragmentRef, fragmentNode.name) : invariant(false) : void 0;
201
158
  if (fragmentRef.length === 0) {
@@ -208,10 +165,6 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
208
165
  };
209
166
  }
210
167
  }
211
-
212
- // Now we actually attempt to read the fragment:
213
-
214
- // 1. Check if there's a cached value for this fragment
215
168
  var cachedValue = this._cache.get(fragmentIdentifier);
216
169
  if (cachedValue != null) {
217
170
  var _missingLiveResolverF;
@@ -228,13 +181,7 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
228
181
  throw cachedValue.promise;
229
182
  }
230
183
  if (cachedValue.kind === 'done' && cachedValue.result.snapshot && !((_missingLiveResolverF = missingLiveResolverFields(cachedValue.result.snapshot)) !== null && _missingLiveResolverF !== void 0 && _missingLiveResolverF.length)) {
231
- this._throwOrLogErrorsInSnapshot(
232
- // $FlowFixMe[incompatible-call]
233
- cachedValue.result.snapshot);
234
-
235
- // This cache gets populated directly whenever the store notifies us of
236
- // an update. That mechanism does not check for missing data, or
237
- // in-flight requests.
184
+ this._throwOrLogErrorsInSnapshot(cachedValue.result.snapshot);
238
185
  if (cachedValue.result.isMissingData) {
239
186
  environment.__log({
240
187
  name: 'fragmentresource.missing_data',
@@ -247,15 +194,19 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
247
194
  return cachedValue.result;
248
195
  }
249
196
  }
250
-
251
- // 2. If not, try reading the fragment from the Relay store.
252
- // If the snapshot has data, return it and save it in cache
253
197
  var fragmentSelector = getSelector(fragmentNode, fragmentRef);
254
198
  !(fragmentSelector != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected to receive an object where `...%s` was spread, ' + 'but the fragment reference was not found`. This is most ' + 'likely the result of:\n' + "- Forgetting to spread `%s` in `%s`'s parent's fragment.\n" + '- Conditionally fetching `%s` but unconditionally passing %s prop ' + 'to `%s`. If the parent fragment only fetches the fragment conditionally ' + '- with e.g. `@include`, `@skip`, or inside a `... on SomeType { }` ' + 'spread - then the fragment reference will not exist. ' + 'In this case, pass `null` if the conditions for evaluating the ' + 'fragment are not met (e.g. if the `@include(if)` value is false.)', fragmentNode.name, fragmentNode.name, componentDisplayName, fragmentNode.name, fragmentKey == null ? 'a fragment reference' : "the `".concat(fragmentKey, "`"), componentDisplayName) : invariant(false) : void 0;
255
- var snapshot = fragmentSelector.kind === 'PluralReaderSelector' ? fragmentSelector.selectors.map(function (s) {
256
- return environment.lookup(s);
257
- }) : environment.lookup(fragmentSelector);
258
- var fragmentResult = getFragmentResult(fragmentIdentifier, snapshot, storeEpoch);
199
+ var fragmentResult = null;
200
+ var snapshot = null;
201
+ if (RelayFeatureFlags.ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE && cachedValue != null && cachedValue.kind === 'missing') {
202
+ fragmentResult = cachedValue.result;
203
+ snapshot = cachedValue.snapshot;
204
+ } else {
205
+ snapshot = fragmentSelector.kind === 'PluralReaderSelector' ? fragmentSelector.selectors.map(function (s) {
206
+ return environment.lookup(s);
207
+ }) : environment.lookup(fragmentSelector);
208
+ fragmentResult = getFragmentResult(fragmentIdentifier, snapshot, storeEpoch);
209
+ }
259
210
  if (!fragmentResult.isMissingData) {
260
211
  this._throwOrLogErrorsInSnapshot(snapshot);
261
212
  this._cache.set(fragmentIdentifier, {
@@ -264,17 +215,6 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
264
215
  });
265
216
  return fragmentResult;
266
217
  }
267
-
268
- // 3. If we don't have data in the store, there's two cases where we should
269
- // suspend to await the data: First if any client edges were traversed where
270
- // the destination record was missing data; in that case we initiate a query
271
- // here to fetch the missing data. Second, there may already be a request
272
- // in flight for the fragment's parent query, or for another operation that
273
- // may affect the parent's query data, such as a mutation or subscription.
274
- // For any of these cases we can get a promise, which we will cache and
275
- // suspend on.
276
-
277
- // First, initiate a query for any client edges that were missing data:
278
218
  var clientEdgeRequests = null;
279
219
  if (RelayFeatureFlags.ENABLE_CLIENT_EDGES && ((_fragmentNode$metadat2 = fragmentNode.metadata) === null || _fragmentNode$metadat2 === void 0 ? void 0 : _fragmentNode$metadat2.hasClientEdges) === true && hasMissingClientEdges(snapshot)) {
280
220
  clientEdgeRequests = [];
@@ -293,8 +233,6 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
293
233
  (_clientEdgeRequests = clientEdgeRequests) === null || _clientEdgeRequests === void 0 ? void 0 : _clientEdgeRequests.push(requestDescriptor);
294
234
  });
295
235
  });
296
- // Store the query so that it can be retained when our own fragment is
297
- // subscribed to. This merges with any existing query results:
298
236
  !(this._clientEdgeQueryResultsCache != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Client edge query result cache should exist when ENABLE_CLIENT_EDGES is on.') : invariant(false) : void 0;
299
237
  this._clientEdgeQueryResultsCache.recordQueryResults(fragmentIdentifier, queryResults);
300
238
  }
@@ -304,16 +242,12 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
304
242
  return getPromiseForActiveRequest(_this3._environment, request);
305
243
  }).filter(Boolean);
306
244
  }
307
-
308
- // Finally look for operations in flight for our parent query:
309
245
  var fragmentOwner = fragmentSelector.kind === 'PluralReaderSelector' ? fragmentSelector.selectors[0].owner : fragmentSelector.owner;
310
246
  var parentQueryPromiseResult = this._getAndSavePromiseForFragmentRequestInFlight(fragmentIdentifier, fragmentNode, fragmentOwner, fragmentResult);
311
- var parentQueryPromiseResultPromise = parentQueryPromiseResult === null || parentQueryPromiseResult === void 0 ? void 0 : parentQueryPromiseResult.promise; // for refinement
247
+ var parentQueryPromiseResultPromise = parentQueryPromiseResult === null || parentQueryPromiseResult === void 0 ? void 0 : parentQueryPromiseResult.promise;
312
248
  var missingResolverFieldPromises = (_missingLiveResolverF2 = (_missingLiveResolverF3 = missingLiveResolverFields(snapshot)) === null || _missingLiveResolverF3 === void 0 ? void 0 : _missingLiveResolverF3.map(function (_ref2) {
313
249
  var liveStateID = _ref2.liveStateID;
314
250
  var store = environment.getStore();
315
-
316
- // $FlowFixMe[prop-missing] This is expected to be a LiveResolverStore
317
251
  return store.getLiveResolverPromise(liveStateID);
318
252
  })) !== null && _missingLiveResolverF2 !== void 0 ? _missingLiveResolverF2 : [];
319
253
  if (clientEdgePromises.length || missingResolverFieldPromises.length || isPromise(parentQueryPromiseResultPromise)) {
@@ -325,7 +259,6 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
325
259
  isRelayHooks: true,
326
260
  isPromiseCached: false,
327
261
  isMissingData: fragmentResult.isMissingData,
328
- // TODO! Attach information here about missing live resolver fields
329
262
  pendingOperations: [].concat((0, _toConsumableArray2["default"])((_parentQueryPromiseRe = parentQueryPromiseResult === null || parentQueryPromiseResult === void 0 ? void 0 : parentQueryPromiseResult.pendingOperations) !== null && _parentQueryPromiseRe !== void 0 ? _parentQueryPromiseRe : []), (0, _toConsumableArray2["default"])((_clientEdgeRequests2 = clientEdgeRequests) !== null && _clientEdgeRequests2 !== void 0 ? _clientEdgeRequests2 : []))
330
263
  });
331
264
  var promises = [];
@@ -341,20 +274,17 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
341
274
  }
342
275
  throw Promise.all(promises);
343
276
  }
344
-
345
- // Note: we are re-throwing the `parentQueryPromiseResultPromise` here,
346
- // because some of our suspense-related code is relying on the instance equality
347
- // of thrown promises. See FragmentResource-test.js
348
277
  if (parentQueryPromiseResultPromise) {
349
278
  throw parentQueryPromiseResultPromise;
350
279
  }
351
280
  }
281
+ if (RelayFeatureFlags.ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE && fragmentResult.isMissingData) {
282
+ this._cache.set(fragmentIdentifier, {
283
+ kind: 'done',
284
+ result: fragmentResult
285
+ });
286
+ }
352
287
  this._throwOrLogErrorsInSnapshot(snapshot);
353
-
354
- // At this point, there's nothing we can do. We don't have all the expected
355
- // data, but there's no indication the missing data will be fulfilled. So we
356
- // choose to return potentially non-typesafe data. The data returned here
357
- // might not match the generated types for this fragment/operation.
358
288
  environment.__log({
359
289
  name: 'fragmentresource.missing_data',
360
290
  data: fragmentResult.data,
@@ -367,17 +297,11 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
367
297
  _proto2._performClientEdgeQuery = function _performClientEdgeQuery(queryResource, fragmentNode, fragmentRef, request, clientEdgeDestinationID) {
368
298
  var originalVariables = getVariablesFromFragment(fragmentNode, fragmentRef);
369
299
  var variables = (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, originalVariables), {}, {
370
- id: clientEdgeDestinationID // TODO should be a reserved name
300
+ id: clientEdgeDestinationID
371
301
  });
372
-
373
- var operation = createOperationDescriptor(request, variables, {} // TODO cacheConfig should probably inherent from parent operation
374
- );
375
-
302
+ var operation = createOperationDescriptor(request, variables, {});
376
303
  var fetchObservable = fetchQuery(this._environment, operation);
377
- var queryResult = queryResource.prepare(operation, fetchObservable
378
- // TODO should inherent render policy etc. from parent operation
379
- );
380
-
304
+ var queryResult = queryResource.prepare(operation, fetchObservable);
381
305
  return {
382
306
  requestDescriptor: operation.request,
383
307
  queryResult: queryResult
@@ -410,20 +334,12 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
410
334
  dispose: function dispose() {}
411
335
  };
412
336
  }
413
-
414
- // 1. Check for any updates missed during render phase
415
- // TODO(T44066760): More efficiently detect if we missed an update
416
337
  var _this$checkMissedUpda = this.checkMissedUpdates(fragmentResult),
417
338
  didMissUpdates = _this$checkMissedUpda[0],
418
339
  currentSnapshot = _this$checkMissedUpda[1];
419
-
420
- // 2. If an update was missed, notify the component so it updates with
421
- // the latest data.
422
340
  if (didMissUpdates) {
423
341
  callback();
424
342
  }
425
-
426
- // 3. Establish subscriptions on the snapshot(s)
427
343
  var disposables = [];
428
344
  if (Array.isArray(renderedSnapshot)) {
429
345
  !Array.isArray(currentSnapshot) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected snapshots to be plural. ' + "If you're seeing this, this is likely a bug in Relay.") : invariant(false) : void 0;
@@ -438,10 +354,19 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
438
354
  !(currentSnapshot != null && !Array.isArray(currentSnapshot)) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected snapshot to be singular. ' + "If you're seeing this, this is likely a bug in Relay.") : invariant(false) : void 0;
439
355
  disposables.push(environment.subscribe(currentSnapshot, function (latestSnapshot) {
440
356
  var storeEpoch = environment.getStore().getEpoch();
441
- _this5._cache.set(cacheKey, {
442
- kind: 'done',
443
- result: getFragmentResult(cacheKey, latestSnapshot, storeEpoch)
444
- });
357
+ var result = getFragmentResult(cacheKey, latestSnapshot, storeEpoch);
358
+ if (RelayFeatureFlags.ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE && result.isMissingData) {
359
+ _this5._cache.set(cacheKey, {
360
+ kind: 'missing',
361
+ result: result,
362
+ snapshot: latestSnapshot
363
+ });
364
+ } else {
365
+ _this5._cache.set(cacheKey, {
366
+ kind: 'done',
367
+ result: getFragmentResult(cacheKey, latestSnapshot, storeEpoch)
368
+ });
369
+ }
445
370
  callback();
446
371
  }));
447
372
  }
@@ -484,7 +409,6 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
484
409
  return [false, null];
485
410
  }
486
411
  var storeEpoch = null;
487
- // Bail out if the store hasn't been written since last read
488
412
  storeEpoch = environment.getStore().getEpoch();
489
413
  if (fragmentResult.storeEpoch === storeEpoch) {
490
414
  return [false, fragmentResult.snapshot];
@@ -506,13 +430,20 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
506
430
  }
507
431
  currentSnapshots[idx] = currentSnapshot;
508
432
  });
509
- // Only update the cache when the data is changed to avoid
510
- // returning different `data` instances
511
433
  if (didMissUpdates) {
512
- this._cache.set(cacheKey, {
513
- kind: 'done',
514
- result: getFragmentResult(cacheKey, currentSnapshots, storeEpoch)
515
- });
434
+ var result = getFragmentResult(cacheKey, currentSnapshots, storeEpoch);
435
+ if (RelayFeatureFlags.ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE && result.isMissingData) {
436
+ this._cache.set(cacheKey, {
437
+ kind: 'missing',
438
+ result: result,
439
+ snapshot: currentSnapshots
440
+ });
441
+ } else {
442
+ this._cache.set(cacheKey, {
443
+ kind: 'done',
444
+ result: result
445
+ });
446
+ }
516
447
  }
517
448
  return [didMissUpdates, currentSnapshots];
518
449
  }
@@ -531,10 +462,19 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
531
462
  relayResolverErrors: currentSnapshot.relayResolverErrors
532
463
  };
533
464
  if (updatedData !== renderData) {
534
- this._cache.set(cacheKey, {
535
- kind: 'done',
536
- result: getFragmentResult(cacheKey, updatedCurrentSnapshot, storeEpoch)
537
- });
465
+ var _result = getFragmentResult(cacheKey, updatedCurrentSnapshot, storeEpoch);
466
+ if (RelayFeatureFlags.ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE && _result.isMissingData) {
467
+ this._cache.set(cacheKey, {
468
+ kind: 'missing',
469
+ result: _result,
470
+ snapshot: updatedCurrentSnapshot
471
+ });
472
+ } else {
473
+ this._cache.set(cacheKey, {
474
+ kind: 'done',
475
+ result: _result
476
+ });
477
+ }
538
478
  }
539
479
  return [updatedData !== renderData, updatedCurrentSnapshot];
540
480
  };
@@ -550,10 +490,6 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
550
490
  if (pendingOperationsResult == null) {
551
491
  return null;
552
492
  }
553
-
554
- // When the Promise for the request resolves, we need to make sure to
555
- // update the cache with the latest data available in the store before
556
- // resolving the Promise
557
493
  var networkPromise = pendingOperationsResult.promise;
558
494
  var pendingOperations = pendingOperationsResult.pendingOperations;
559
495
  var promise = networkPromise.then(function () {
@@ -561,7 +497,6 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
561
497
  })["catch"](function (error) {
562
498
  _this8._cache["delete"](cacheKey);
563
499
  });
564
- // $FlowExpectedError[prop-missing] Expando to annotate Promises.
565
500
  promise.displayName = networkPromise.displayName;
566
501
  this._cache.set(cacheKey, {
567
502
  kind: 'pending',
@@ -588,10 +523,19 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
588
523
  }
589
524
  var nextSnapshots = currentSnapshot ? (0, _toConsumableArray2["default"])(currentSnapshot) : (0, _toConsumableArray2["default"])(baseSnapshots);
590
525
  nextSnapshots[idx] = latestSnapshot;
591
- this._cache.set(cacheKey, {
592
- kind: 'done',
593
- result: getFragmentResult(cacheKey, nextSnapshots, storeEpoch)
594
- });
526
+ var result = getFragmentResult(cacheKey, nextSnapshots, storeEpoch);
527
+ if (RelayFeatureFlags.ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE && result.isMissingData) {
528
+ this._cache.set(cacheKey, {
529
+ kind: 'missing',
530
+ result: result,
531
+ snapshot: nextSnapshots
532
+ });
533
+ } else {
534
+ this._cache.set(cacheKey, {
535
+ kind: 'done',
536
+ result: result
537
+ });
538
+ }
595
539
  };
596
540
  return FragmentResourceImpl;
597
541
  }();
@@ -1,14 +1,3 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and 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
- * @format
9
- * @oncall relay
10
- */
11
-
12
1
  'use strict';
13
2
 
14
3
  var warning = require("fbjs/lib/warning");
@@ -1,14 +1,3 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and 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
- * @format
9
- * @oncall relay
10
- */
11
-
12
1
  'use strict';
13
2
 
14
3
  var loggerImpl = function loggerImpl(eventData) {};
@@ -1,28 +1,6 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and 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
- * @format
9
- * @oncall relay
10
- */
11
-
12
1
  'use strict';
13
2
 
14
3
  var invariant = require('invariant');
15
- /**
16
- * JS maps (both plain objects and Map) maintain key insertion
17
- * order, which means there is an easy way to simulate LRU behavior
18
- * that should also perform quite well:
19
- *
20
- * To insert a new value, first delete the key from the inner _map,
21
- * then _map.set(k, v). By deleting and reinserting, you ensure that the
22
- * map sees the key as the last inserted key.
23
- *
24
- * Get does the same: if the key is present, delete and reinsert it.
25
- */
26
4
  var LRUCache = /*#__PURE__*/function () {
27
5
  function LRUCache(capacity) {
28
6
  this._capacity = capacity;