react-relay 0.0.0-main-960835bc → 0.0.0-main-b925743b

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Relay v0.0.0-main-960835bc
2
+ * Relay v0.0.0-main-b925743b
3
3
  *
4
4
  * Copyright (c) Facebook, Inc. and its affiliates.
5
5
  *
package/hooks.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Relay v0.0.0-main-960835bc
2
+ * Relay v0.0.0-main-b925743b
3
3
  *
4
4
  * Copyright (c) Facebook, Inc. and its affiliates.
5
5
  *
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Relay v0.0.0-main-960835bc
2
+ * Relay v0.0.0-main-b925743b
3
3
  *
4
4
  * Copyright (c) Facebook, Inc. and its affiliates.
5
5
  *
package/legacy.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Relay v0.0.0-main-960835bc
2
+ * Relay v0.0.0-main-b925743b
3
3
  *
4
4
  * Copyright (c) Facebook, Inc. and its affiliates.
5
5
  *
@@ -15,19 +15,32 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
15
15
 
16
16
  var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
17
17
 
18
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
19
+
18
20
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
19
21
 
20
22
  var LRUCache = require('./LRUCache');
21
23
 
24
+ var _require = require('./QueryResource'),
25
+ getQueryResourceForEnvironment = _require.getQueryResourceForEnvironment;
26
+
27
+ var SuspenseResource = require('./SuspenseResource');
28
+
22
29
  var invariant = require('invariant');
23
30
 
24
- var _require = require('relay-runtime'),
25
- getFragmentIdentifier = _require.getFragmentIdentifier,
26
- getPendingOperationsForFragment = _require.getPendingOperationsForFragment,
27
- getSelector = _require.getSelector,
28
- isPromise = _require.isPromise,
29
- recycleNodesInto = _require.recycleNodesInto,
30
- reportMissingRequiredFields = _require.reportMissingRequiredFields;
31
+ var _require2 = require('relay-runtime'),
32
+ RelayFeatureFlags = _require2.RelayFeatureFlags,
33
+ _require2$__internal = _require2.__internal,
34
+ fetchQuery = _require2$__internal.fetchQuery,
35
+ getPromiseForActiveRequest = _require2$__internal.getPromiseForActiveRequest,
36
+ createOperationDescriptor = _require2.createOperationDescriptor,
37
+ getFragmentIdentifier = _require2.getFragmentIdentifier,
38
+ getPendingOperationsForFragment = _require2.getPendingOperationsForFragment,
39
+ getSelector = _require2.getSelector,
40
+ getVariablesFromFragment = _require2.getVariablesFromFragment,
41
+ isPromise = _require2.isPromise,
42
+ recycleNodesInto = _require2.recycleNodesInto,
43
+ reportMissingRequiredFields = _require2.reportMissingRequiredFields;
31
44
 
32
45
  var WEAKMAP_SUPPORTED = typeof WeakMap === 'function';
33
46
  // TODO: Fix to not rely on LRU. If the number of active fragments exceeds this
@@ -47,6 +60,28 @@ function isMissingData(snapshot) {
47
60
  return snapshot.isMissingData;
48
61
  }
49
62
 
63
+ function hasMissingClientEdges(snapshot) {
64
+ var _snapshot$missingClie, _snapshot$missingClie2;
65
+
66
+ if (Array.isArray(snapshot)) {
67
+ return snapshot.some(function (s) {
68
+ var _s$missingClientEdges, _s$missingClientEdges2;
69
+
70
+ return ((_s$missingClientEdges = (_s$missingClientEdges2 = s.missingClientEdges) === null || _s$missingClientEdges2 === void 0 ? void 0 : _s$missingClientEdges2.length) !== null && _s$missingClientEdges !== void 0 ? _s$missingClientEdges : 0) > 0;
71
+ });
72
+ }
73
+
74
+ return ((_snapshot$missingClie = (_snapshot$missingClie2 = snapshot.missingClientEdges) === null || _snapshot$missingClie2 === void 0 ? void 0 : _snapshot$missingClie2.length) !== null && _snapshot$missingClie !== void 0 ? _snapshot$missingClie : 0) > 0;
75
+ }
76
+
77
+ function singularOrPluralForEach(snapshot, f) {
78
+ if (Array.isArray(snapshot)) {
79
+ snapshot.forEach(f);
80
+ } else {
81
+ f(snapshot);
82
+ }
83
+ }
84
+
50
85
  function getFragmentResult(cacheKey, snapshot, storeEpoch) {
51
86
  if (Array.isArray(snapshot)) {
52
87
  return {
@@ -68,11 +103,90 @@ function getFragmentResult(cacheKey, snapshot, storeEpoch) {
68
103
  storeEpoch: storeEpoch
69
104
  };
70
105
  }
106
+ /**
107
+ * The purpose of this cache is to allow information to be passed from an
108
+ * initial read which suspends through to the commit that follows a subsequent
109
+ * successful read. Specifically, the QueryResource result for the data fetch
110
+ * is passed through so that that query can be retained on commit.
111
+ */
112
+
113
+
114
+ var ClientEdgeQueryResultsCache = /*#__PURE__*/function () {
115
+ function ClientEdgeQueryResultsCache(environment) {
116
+ (0, _defineProperty2["default"])(this, "_cache", new Map());
117
+ (0, _defineProperty2["default"])(this, "_retainCounts", new Map());
118
+ this._environment = environment;
119
+ }
120
+
121
+ var _proto = ClientEdgeQueryResultsCache.prototype;
122
+
123
+ _proto.get = function get(fragmentIdentifier) {
124
+ var _this$_cache$get$, _this$_cache$get;
125
+
126
+ 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;
127
+ };
128
+
129
+ _proto.recordQueryResults = function recordQueryResults(fragmentIdentifier, value) {
130
+ var _this = this;
131
+
132
+ var existing = this._cache.get(fragmentIdentifier);
133
+
134
+ if (!existing) {
135
+ var suspenseResource = new SuspenseResource(function () {
136
+ return _this._retain(fragmentIdentifier);
137
+ });
138
+
139
+ this._cache.set(fragmentIdentifier, [value, suspenseResource]);
140
+
141
+ suspenseResource.temporaryRetain(this._environment);
142
+ } else {
143
+ var existingResults = existing[0],
144
+ _suspenseResource = existing[1];
145
+ value.forEach(function (queryResult) {
146
+ existingResults.push(queryResult);
147
+ });
148
+
149
+ _suspenseResource.temporaryRetain(this._environment);
150
+ }
151
+ };
152
+
153
+ _proto._retain = function _retain(id) {
154
+ var _this2 = this;
155
+
156
+ var _this$_retainCounts$g;
157
+
158
+ var retainCount = ((_this$_retainCounts$g = this._retainCounts.get(id)) !== null && _this$_retainCounts$g !== void 0 ? _this$_retainCounts$g : 0) + 1;
159
+
160
+ this._retainCounts.set(id, retainCount);
161
+
162
+ return {
163
+ dispose: function dispose() {
164
+ var _this$_retainCounts$g2;
165
+
166
+ var newRetainCount = ((_this$_retainCounts$g2 = _this2._retainCounts.get(id)) !== null && _this$_retainCounts$g2 !== void 0 ? _this$_retainCounts$g2 : 0) - 1;
167
+
168
+ if (newRetainCount > 0) {
169
+ _this2._retainCounts.set(id, newRetainCount);
170
+ } else {
171
+ _this2._retainCounts["delete"](id);
172
+
173
+ _this2._cache["delete"](id);
174
+ }
175
+ }
176
+ };
177
+ };
178
+
179
+ return ClientEdgeQueryResultsCache;
180
+ }();
71
181
 
72
182
  var FragmentResourceImpl = /*#__PURE__*/function () {
73
183
  function FragmentResourceImpl(environment) {
74
184
  this._environment = environment;
75
185
  this._cache = LRUCache.create(CACHE_CAPACITY);
186
+
187
+ if (RelayFeatureFlags.ENABLE_CLIENT_EDGES) {
188
+ this._clientEdgeQueryResultsCache = new ClientEdgeQueryResultsCache(environment);
189
+ }
76
190
  }
77
191
  /**
78
192
  * This function should be called during a Component's render function,
@@ -81,9 +195,9 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
81
195
  */
82
196
 
83
197
 
84
- var _proto = FragmentResourceImpl.prototype;
198
+ var _proto2 = FragmentResourceImpl.prototype;
85
199
 
86
- _proto.read = function read(fragmentNode, fragmentRef, componentDisplayName, fragmentKey) {
200
+ _proto2.read = function read(fragmentNode, fragmentRef, componentDisplayName, fragmentKey) {
87
201
  return this.readWithIdentifier(fragmentNode, fragmentRef, getFragmentIdentifier(fragmentNode, fragmentRef), componentDisplayName, fragmentKey);
88
202
  }
89
203
  /**
@@ -93,8 +207,10 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
93
207
  */
94
208
  ;
95
209
 
96
- _proto.readWithIdentifier = function readWithIdentifier(fragmentNode, fragmentRef, fragmentIdentifier, componentDisplayName, fragmentKey) {
97
- var _fragmentNode$metadat;
210
+ _proto2.readWithIdentifier = function readWithIdentifier(fragmentNode, fragmentRef, fragmentIdentifier, componentDisplayName, fragmentKey) {
211
+ var _this3 = this;
212
+
213
+ var _fragmentNode$metadat, _clientEdgePromises;
98
214
 
99
215
  var environment = this._environment; // If fragmentRef is null or undefined, pass it directly through.
100
216
  // This is a convenience when consuming fragments via a HOC API, when the
@@ -171,18 +287,67 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
171
287
  });
172
288
 
173
289
  return fragmentResult;
174
- } // 3. If we don't have data in the store, check if a request is in
175
- // flight for the fragment's parent query, or for another operation
176
- // that may affect the parent's query data, such as a mutation
177
- // or subscription. If a promise exists, cache the promise and use it
178
- // to suspend.
290
+ } // 3. If we don't have data in the store, there's two cases where we should
291
+ // suspend to await the data: First if any client edges were traversed where
292
+ // the destination record was missing data; in that case we initiate a query
293
+ // here to fetch the missing data. Second, there may already be a request
294
+ // in flight for the fragment's parent query, or for another operation that
295
+ // may affect the parent's query data, such as a mutation or subscription.
296
+ // For any of these cases we can get a promise, which we will cache and
297
+ // suspend on.
298
+ // First, initiate a query for any client edges that were missing data:
299
+
300
+
301
+ var clientEdgeRequests = null;
302
+
303
+ if (RelayFeatureFlags.ENABLE_CLIENT_EDGES && hasMissingClientEdges(snapshot)) {
304
+ clientEdgeRequests = [];
305
+ var queryResource = getQueryResourceForEnvironment(this._environment);
306
+ var queryResults = [];
307
+ singularOrPluralForEach(snapshot, function (snap) {
308
+ var _snap$missingClientEd;
309
+
310
+ (_snap$missingClientEd = snap.missingClientEdges) === null || _snap$missingClientEd === void 0 ? void 0 : _snap$missingClientEd.forEach(function (_ref) {
311
+ var _clientEdgeRequests;
312
+
313
+ var request = _ref.request,
314
+ clientEdgeDestinationID = _ref.clientEdgeDestinationID;
315
+
316
+ var _this3$_performClient = _this3._performClientEdgeQuery(queryResource, fragmentNode, fragmentRef, request, clientEdgeDestinationID),
317
+ queryResult = _this3$_performClient.queryResult,
318
+ requestDescriptor = _this3$_performClient.requestDescriptor;
319
+
320
+ queryResults.push(queryResult);
321
+ (_clientEdgeRequests = clientEdgeRequests) === null || _clientEdgeRequests === void 0 ? void 0 : _clientEdgeRequests.push(requestDescriptor);
322
+ });
323
+ }); // Store the query so that it can be retained when our own fragment is
324
+ // subscribed to. This merges with any existing query results:
325
+
326
+ !(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;
327
+
328
+ this._clientEdgeQueryResultsCache.recordQueryResults(fragmentIdentifier, queryResults);
329
+ }
330
+
331
+ var clientEdgePromises = null;
332
+
333
+ if (RelayFeatureFlags.ENABLE_CLIENT_EDGES && clientEdgeRequests) {
334
+ clientEdgePromises = clientEdgeRequests.map(function (request) {
335
+ return getPromiseForActiveRequest(_this3._environment, request);
336
+ }).filter(function (p) {
337
+ return p != null;
338
+ });
339
+ } // Finally look for operations in flight for our parent query:
179
340
 
180
341
 
181
342
  var fragmentOwner = fragmentSelector.kind === 'PluralReaderSelector' ? fragmentSelector.selectors[0].owner : fragmentSelector.owner;
182
343
 
183
- var networkPromiseResult = this._getAndSavePromiseForFragmentRequestInFlight(fragmentIdentifier, fragmentNode, fragmentOwner, fragmentResult);
344
+ var parentQueryPromiseResult = this._getAndSavePromiseForFragmentRequestInFlight(fragmentIdentifier, fragmentNode, fragmentOwner, fragmentResult);
345
+
346
+ var parentQueryPromiseResultPromise = parentQueryPromiseResult === null || parentQueryPromiseResult === void 0 ? void 0 : parentQueryPromiseResult.promise; // for refinement
347
+
348
+ if (((_clientEdgePromises = clientEdgePromises) === null || _clientEdgePromises === void 0 ? void 0 : _clientEdgePromises.length) || isPromise(parentQueryPromiseResultPromise)) {
349
+ var _parentQueryPromiseRe, _clientEdgeRequests2, _clientEdgePromises2;
184
350
 
185
- if (networkPromiseResult != null && isPromise(networkPromiseResult.promise)) {
186
351
  environment.__log({
187
352
  name: 'suspense.fragment',
188
353
  data: fragmentResult.data,
@@ -190,10 +355,10 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
190
355
  isRelayHooks: true,
191
356
  isPromiseCached: false,
192
357
  isMissingData: fragmentResult.isMissingData,
193
- pendingOperations: networkPromiseResult.pendingOperations
358
+ 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 : []))
194
359
  });
195
360
 
196
- throw networkPromiseResult.promise;
361
+ throw ((_clientEdgePromises2 = clientEdgePromises) === null || _clientEdgePromises2 === void 0 ? void 0 : _clientEdgePromises2.length) ? Promise.all([parentQueryPromiseResultPromise].concat((0, _toConsumableArray2["default"])(clientEdgePromises))) : parentQueryPromiseResultPromise;
197
362
  }
198
363
 
199
364
  this._reportMissingRequiredFieldsInSnapshot(snapshot);
@@ -201,13 +366,30 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
201
366
  return getFragmentResult(fragmentIdentifier, snapshot, storeEpoch);
202
367
  };
203
368
 
204
- _proto._reportMissingRequiredFieldsInSnapshot = function _reportMissingRequiredFieldsInSnapshot(snapshot) {
205
- var _this = this;
369
+ _proto2._performClientEdgeQuery = function _performClientEdgeQuery(queryResource, fragmentNode, fragmentRef, request, clientEdgeDestinationID) {
370
+ var originalVariables = getVariablesFromFragment(fragmentNode, fragmentRef);
371
+ var variables = (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, originalVariables), {}, {
372
+ id: clientEdgeDestinationID // TODO should be a reserved name
373
+
374
+ });
375
+ var operation = createOperationDescriptor(request, variables, {} // TODO cacheConfig should probably inherent from parent operation
376
+ );
377
+ var fetchObservable = fetchQuery(this._environment, operation);
378
+ var queryResult = queryResource.prepare(operation, fetchObservable // TODO should inherent render policy etc. from parent operation
379
+ );
380
+ return {
381
+ requestDescriptor: operation.request,
382
+ queryResult: queryResult
383
+ };
384
+ };
385
+
386
+ _proto2._reportMissingRequiredFieldsInSnapshot = function _reportMissingRequiredFieldsInSnapshot(snapshot) {
387
+ var _this4 = this;
206
388
 
207
389
  if (Array.isArray(snapshot)) {
208
390
  snapshot.forEach(function (s) {
209
391
  if (s.missingRequiredFields != null) {
210
- reportMissingRequiredFields(_this._environment, s.missingRequiredFields);
392
+ reportMissingRequiredFields(_this4._environment, s.missingRequiredFields);
211
393
  }
212
394
  });
213
395
  } else {
@@ -217,7 +399,7 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
217
399
  }
218
400
  };
219
401
 
220
- _proto.readSpec = function readSpec(fragmentNodes, fragmentRefs, componentDisplayName) {
402
+ _proto2.readSpec = function readSpec(fragmentNodes, fragmentRefs, componentDisplayName) {
221
403
  var result = {};
222
404
 
223
405
  for (var _key in fragmentNodes) {
@@ -227,8 +409,8 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
227
409
  return result;
228
410
  };
229
411
 
230
- _proto.subscribe = function subscribe(fragmentResult, callback) {
231
- var _this2 = this;
412
+ _proto2.subscribe = function subscribe(fragmentResult, callback) {
413
+ var _this5 = this;
232
414
 
233
415
  var environment = this._environment;
234
416
  var cacheKey = fragmentResult.cacheKey;
@@ -253,25 +435,25 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
253
435
  } // 3. Establish subscriptions on the snapshot(s)
254
436
 
255
437
 
256
- var dataSubscriptions = [];
438
+ var disposables = [];
257
439
 
258
440
  if (Array.isArray(renderedSnapshot)) {
259
441
  !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;
260
442
  currentSnapshot.forEach(function (snapshot, idx) {
261
- dataSubscriptions.push(environment.subscribe(snapshot, function (latestSnapshot) {
443
+ disposables.push(environment.subscribe(snapshot, function (latestSnapshot) {
262
444
  var storeEpoch = environment.getStore().getEpoch();
263
445
 
264
- _this2._updatePluralSnapshot(cacheKey, currentSnapshot, latestSnapshot, idx, storeEpoch);
446
+ _this5._updatePluralSnapshot(cacheKey, currentSnapshot, latestSnapshot, idx, storeEpoch);
265
447
 
266
448
  callback();
267
449
  }));
268
450
  });
269
451
  } else {
270
452
  !(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;
271
- dataSubscriptions.push(environment.subscribe(currentSnapshot, function (latestSnapshot) {
453
+ disposables.push(environment.subscribe(currentSnapshot, function (latestSnapshot) {
272
454
  var storeEpoch = environment.getStore().getEpoch();
273
455
 
274
- _this2._cache.set(cacheKey, {
456
+ _this5._cache.set(cacheKey, {
275
457
  kind: 'done',
276
458
  result: getFragmentResult(cacheKey, latestSnapshot, storeEpoch)
277
459
  });
@@ -280,22 +462,35 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
280
462
  }));
281
463
  }
282
464
 
465
+ if (RelayFeatureFlags.ENABLE_CLIENT_EDGES) {
466
+ var _this$_clientEdgeQuer, _this$_clientEdgeQuer2;
467
+
468
+ var clientEdgeQueryResults = (_this$_clientEdgeQuer = (_this$_clientEdgeQuer2 = this._clientEdgeQueryResultsCache) === null || _this$_clientEdgeQuer2 === void 0 ? void 0 : _this$_clientEdgeQuer2.get(cacheKey)) !== null && _this$_clientEdgeQuer !== void 0 ? _this$_clientEdgeQuer : undefined;
469
+
470
+ if (clientEdgeQueryResults === null || clientEdgeQueryResults === void 0 ? void 0 : clientEdgeQueryResults.length) {
471
+ var queryResource = getQueryResourceForEnvironment(this._environment);
472
+ clientEdgeQueryResults.forEach(function (queryResult) {
473
+ disposables.push(queryResource.retain(queryResult));
474
+ });
475
+ }
476
+ }
477
+
283
478
  return {
284
479
  dispose: function dispose() {
285
- dataSubscriptions.map(function (s) {
480
+ disposables.forEach(function (s) {
286
481
  return s.dispose();
287
482
  });
288
483
 
289
- _this2._cache["delete"](cacheKey);
484
+ _this5._cache["delete"](cacheKey);
290
485
  }
291
486
  };
292
487
  };
293
488
 
294
- _proto.subscribeSpec = function subscribeSpec(fragmentResults, callback) {
295
- var _this3 = this;
489
+ _proto2.subscribeSpec = function subscribeSpec(fragmentResults, callback) {
490
+ var _this6 = this;
296
491
 
297
492
  var disposables = Object.keys(fragmentResults).map(function (key) {
298
- return _this3.subscribe(fragmentResults[key], callback);
493
+ return _this6.subscribe(fragmentResults[key], callback);
299
494
  });
300
495
  return {
301
496
  dispose: function dispose() {
@@ -306,7 +501,7 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
306
501
  };
307
502
  };
308
503
 
309
- _proto.checkMissedUpdates = function checkMissedUpdates(fragmentResult) {
504
+ _proto2.checkMissedUpdates = function checkMissedUpdates(fragmentResult) {
310
505
  var environment = this._environment;
311
506
  var renderedSnapshot = fragmentResult.snapshot;
312
507
 
@@ -361,6 +556,7 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
361
556
  var updatedCurrentSnapshot = {
362
557
  data: updatedData,
363
558
  isMissingData: currentSnapshot.isMissingData,
559
+ missingClientEdges: currentSnapshot.missingClientEdges,
364
560
  seenRecords: currentSnapshot.seenRecords,
365
561
  selector: currentSnapshot.selector,
366
562
  missingRequiredFields: currentSnapshot.missingRequiredFields
@@ -376,16 +572,16 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
376
572
  return [updatedData !== renderData, updatedCurrentSnapshot];
377
573
  };
378
574
 
379
- _proto.checkMissedUpdatesSpec = function checkMissedUpdatesSpec(fragmentResults) {
380
- var _this4 = this;
575
+ _proto2.checkMissedUpdatesSpec = function checkMissedUpdatesSpec(fragmentResults) {
576
+ var _this7 = this;
381
577
 
382
578
  return Object.keys(fragmentResults).some(function (key) {
383
- return _this4.checkMissedUpdates(fragmentResults[key])[0];
579
+ return _this7.checkMissedUpdates(fragmentResults[key])[0];
384
580
  });
385
581
  };
386
582
 
387
- _proto._getAndSavePromiseForFragmentRequestInFlight = function _getAndSavePromiseForFragmentRequestInFlight(cacheKey, fragmentNode, fragmentOwner, fragmentResult) {
388
- var _this5 = this;
583
+ _proto2._getAndSavePromiseForFragmentRequestInFlight = function _getAndSavePromiseForFragmentRequestInFlight(cacheKey, fragmentNode, fragmentOwner, fragmentResult) {
584
+ var _this8 = this;
389
585
 
390
586
  var pendingOperationsResult = getPendingOperationsForFragment(this._environment, fragmentNode, fragmentOwner);
391
587
 
@@ -399,9 +595,9 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
399
595
  var networkPromise = pendingOperationsResult.promise;
400
596
  var pendingOperations = pendingOperationsResult.pendingOperations;
401
597
  var promise = networkPromise.then(function () {
402
- _this5._cache["delete"](cacheKey);
598
+ _this8._cache["delete"](cacheKey);
403
599
  })["catch"](function (error) {
404
- _this5._cache["delete"](cacheKey);
600
+ _this8._cache["delete"](cacheKey);
405
601
  }); // $FlowExpectedError[prop-missing] Expando to annotate Promises.
406
602
 
407
603
  promise.displayName = networkPromise.displayName;
@@ -419,7 +615,7 @@ var FragmentResourceImpl = /*#__PURE__*/function () {
419
615
  };
420
616
  };
421
617
 
422
- _proto._updatePluralSnapshot = function _updatePluralSnapshot(cacheKey, baseSnapshots, latestSnapshot, idx, storeEpoch) {
618
+ _proto2._updatePluralSnapshot = function _updatePluralSnapshot(cacheKey, baseSnapshots, latestSnapshot, idx, storeEpoch) {
423
619
  var _currentFragmentResul;
424
620
 
425
621
  var currentFragmentResult = this._cache.get(cacheKey);
@@ -19,16 +19,18 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
19
19
 
20
20
  var LRUCache = require('./LRUCache');
21
21
 
22
+ var SuspenseResource = require('./SuspenseResource');
23
+
22
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
 
27
30
  var warning = require("fbjs/lib/warning");
28
31
 
29
32
  var CACHE_CAPACITY = 1000;
30
33
  var DEFAULT_FETCH_POLICY = 'store-or-network';
31
- var DATA_RETENTION_TIMEOUT = 5 * 60 * 1000;
32
34
  var WEAKMAP_SUPPORTED = typeof WeakMap === 'function';
33
35
 
34
36
  function operationIsLiveQuery(operation) {
@@ -64,6 +66,77 @@ function getQueryResult(operation, cacheIdentifier) {
64
66
  var nextID = 200000;
65
67
 
66
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) {
67
140
  var isLiveQuery = operationIsLiveQuery(operation);
68
141
  var currentValue = value;
69
142
  var retainCount = 0;
@@ -202,8 +275,14 @@ var QueryResourceImpl = /*#__PURE__*/function () {
202
275
  var _this = this;
203
276
 
204
277
  (0, _defineProperty2["default"])(this, "_clearCacheEntry", function (cacheEntry) {
205
- 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) {
206
281
  _this._cache["delete"](cacheEntry.cacheIdentifier);
282
+ } else {
283
+ if (cacheEntry.getRetainCount() <= 0) {
284
+ _this._cache["delete"](cacheEntry.cacheIdentifier);
285
+ }
207
286
  }
208
287
  });
209
288
  this._environment = environment;