relay-runtime 9.0.0 → 9.1.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 (111) hide show
  1. package/handlers/RelayDefaultHandlerProvider.js.flow +34 -0
  2. package/handlers/connection/ConnectionHandler.js.flow +549 -0
  3. package/handlers/connection/ConnectionInterface.js.flow +92 -0
  4. package/index.js +1 -1
  5. package/index.js.flow +314 -0
  6. package/lib/handlers/connection/ConnectionHandler.js +1 -3
  7. package/lib/index.js +1 -2
  8. package/lib/mutations/RelayDeclarativeMutationConfig.js +22 -45
  9. package/lib/mutations/RelayRecordProxy.js +1 -3
  10. package/lib/mutations/RelayRecordSourceMutator.js +1 -3
  11. package/lib/mutations/RelayRecordSourceProxy.js +1 -3
  12. package/lib/mutations/RelayRecordSourceSelectorProxy.js +1 -3
  13. package/lib/mutations/commitMutation.js +2 -0
  14. package/lib/mutations/validateMutation.js +13 -4
  15. package/lib/network/RelayObservable.js +9 -9
  16. package/lib/network/RelayQueryResponseCache.js +8 -6
  17. package/lib/query/fetchQueryInternal.js +1 -8
  18. package/lib/store/DataChecker.js +23 -51
  19. package/lib/store/RelayConcreteVariables.js +6 -2
  20. package/lib/store/RelayModernEnvironment.js +30 -12
  21. package/lib/store/RelayModernFragmentSpecResolver.js +9 -13
  22. package/lib/store/RelayModernQueryExecutor.js +73 -37
  23. package/lib/store/RelayModernRecord.js +14 -9
  24. package/lib/store/RelayModernStore.js +107 -70
  25. package/lib/store/RelayOperationTracker.js +35 -78
  26. package/lib/store/RelayOptimisticRecordSource.js +7 -5
  27. package/lib/store/RelayPublishQueue.js +1 -3
  28. package/lib/store/RelayReader.js +1 -3
  29. package/lib/store/RelayRecordSource.js +1 -3
  30. package/lib/store/RelayRecordSourceMapImpl.js +13 -18
  31. package/lib/store/RelayReferenceMarker.js +2 -6
  32. package/lib/store/RelayResponseNormalizer.js +9 -10
  33. package/lib/store/StoreInspector.js +7 -5
  34. package/lib/store/normalizeRelayPayload.js +6 -2
  35. package/lib/subscription/requestSubscription.js +4 -2
  36. package/lib/util/RelayFeatureFlags.js +1 -1
  37. package/lib/util/RelayReplaySubject.js +1 -3
  38. package/lib/util/createPayloadFor3DField.js +7 -2
  39. package/mutations/RelayDeclarativeMutationConfig.js.flow +380 -0
  40. package/mutations/RelayRecordProxy.js.flow +165 -0
  41. package/mutations/RelayRecordSourceMutator.js.flow +238 -0
  42. package/mutations/RelayRecordSourceProxy.js.flow +164 -0
  43. package/mutations/RelayRecordSourceSelectorProxy.js.flow +119 -0
  44. package/mutations/applyOptimisticMutation.js.flow +76 -0
  45. package/mutations/commitLocalUpdate.js.flow +24 -0
  46. package/mutations/commitMutation.js.flow +184 -0
  47. package/mutations/validateMutation.js.flow +211 -0
  48. package/network/ConvertToExecuteFunction.js.flow +49 -0
  49. package/network/RelayNetwork.js.flow +84 -0
  50. package/network/RelayNetworkTypes.js.flow +123 -0
  51. package/network/RelayObservable.js.flow +634 -0
  52. package/network/RelayQueryResponseCache.js.flow +111 -0
  53. package/package.json +1 -1
  54. package/query/GraphQLTag.js.flow +166 -0
  55. package/query/fetchQuery.js.flow +47 -0
  56. package/query/fetchQueryInternal.js.flow +349 -0
  57. package/relay-runtime.js +2 -2
  58. package/relay-runtime.min.js +2 -2
  59. package/store/ClientID.js.flow +43 -0
  60. package/store/DataChecker.js.flow +426 -0
  61. package/store/RelayConcreteVariables.js.flow +96 -0
  62. package/store/RelayModernEnvironment.js.flow +526 -0
  63. package/store/RelayModernFragmentSpecResolver.js.flow +426 -0
  64. package/store/RelayModernOperationDescriptor.js.flow +88 -0
  65. package/store/RelayModernQueryExecutor.js.flow +1327 -0
  66. package/store/RelayModernRecord.js.flow +403 -0
  67. package/store/RelayModernSelector.js.flow +444 -0
  68. package/store/RelayModernStore.js.flow +757 -0
  69. package/store/RelayOperationTracker.js.flow +164 -0
  70. package/store/RelayOptimisticRecordSource.js.flow +119 -0
  71. package/store/RelayPublishQueue.js.flow +401 -0
  72. package/store/RelayReader.js.flow +376 -0
  73. package/store/RelayRecordSource.js.flow +29 -0
  74. package/store/RelayRecordSourceMapImpl.js.flow +87 -0
  75. package/store/RelayRecordState.js.flow +37 -0
  76. package/store/RelayReferenceMarker.js.flow +236 -0
  77. package/store/RelayResponseNormalizer.js.flow +556 -0
  78. package/store/RelayStoreTypes.js.flow +873 -0
  79. package/store/RelayStoreUtils.js.flow +218 -0
  80. package/store/StoreInspector.js.flow +173 -0
  81. package/store/ViewerPattern.js.flow +26 -0
  82. package/store/cloneRelayHandleSourceField.js.flow +66 -0
  83. package/store/createFragmentSpecResolver.js.flow +55 -0
  84. package/store/createRelayContext.js.flow +44 -0
  85. package/store/defaultGetDataID.js.flow +27 -0
  86. package/store/hasOverlappingIDs.js.flow +34 -0
  87. package/store/isRelayModernEnvironment.js.flow +27 -0
  88. package/store/normalizeRelayPayload.js.flow +51 -0
  89. package/store/readInlineData.js.flow +75 -0
  90. package/subscription/requestSubscription.js.flow +100 -0
  91. package/util/JSResourceTypes.flow.js.flow +20 -0
  92. package/util/NormalizationNode.js.flow +191 -0
  93. package/util/ReaderNode.js.flow +208 -0
  94. package/util/RelayConcreteNode.js.flow +80 -0
  95. package/util/RelayDefaultHandleKey.js.flow +17 -0
  96. package/util/RelayError.js.flow +33 -0
  97. package/util/RelayFeatureFlags.js.flow +30 -0
  98. package/util/RelayProfiler.js.flow +284 -0
  99. package/util/RelayReplaySubject.js.flow +134 -0
  100. package/util/RelayRuntimeTypes.js.flow +70 -0
  101. package/util/createPayloadFor3DField.js.flow +43 -0
  102. package/util/deepFreeze.js.flow +36 -0
  103. package/util/generateID.js.flow +21 -0
  104. package/util/getFragmentIdentifier.js.flow +52 -0
  105. package/util/getRelayHandleKey.js.flow +41 -0
  106. package/util/getRequestIdentifier.js.flow +41 -0
  107. package/util/isPromise.js.flow +21 -0
  108. package/util/isScalarAndEqual.js.flow +26 -0
  109. package/util/recycleNodesInto.js.flow +80 -0
  110. package/util/resolveImmediate.js.flow +30 -0
  111. package/util/stableCopy.js.flow +35 -0
@@ -12,7 +12,11 @@
12
12
 
13
13
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
14
14
 
15
- var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread"));
15
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
16
+
17
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
18
+
19
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
16
20
 
17
21
  var areEqual = require("fbjs/lib/areEqual");
18
22
 
@@ -30,7 +34,8 @@ var _require2 = require('./RelayStoreUtils'),
30
34
  REF_KEY = _require2.REF_KEY,
31
35
  REFS_KEY = _require2.REFS_KEY,
32
36
  TYPENAME_KEY = _require2.TYPENAME_KEY,
33
- INVALIDATED_AT_KEY = _require2.INVALIDATED_AT_KEY;
37
+ INVALIDATED_AT_KEY = _require2.INVALIDATED_AT_KEY,
38
+ ROOT_ID = _require2.ROOT_ID;
34
39
 
35
40
  /**
36
41
  * @public
@@ -82,7 +87,7 @@ var _require2 = require('./RelayStoreUtils'),
82
87
  * Clone a record.
83
88
  */
84
89
  function clone(record) {
85
- return (0, _objectSpread2["default"])({}, record);
90
+ return _objectSpread({}, record);
86
91
  }
87
92
  /**
88
93
  * @public
@@ -233,7 +238,7 @@ function update(prevRecord, nextRecord) {
233
238
 
234
239
  var prevType = (_getType = getType(prevRecord)) !== null && _getType !== void 0 ? _getType : null;
235
240
  var nextType = (_getType2 = getType(nextRecord)) !== null && _getType2 !== void 0 ? _getType2 : null;
236
- process.env.NODE_ENV !== "production" ? warning(isClientID(nextID) || prevType === nextType, 'RelayModernRecord: Invalid record update, expected both versions of ' + 'record `%s` to have the same `%s` but got conflicting types `%s` ' + 'and `%s`. The GraphQL server likely violated the globally unique ' + 'id requirement by returning the same id for different objects.', prevID, TYPENAME_KEY, prevType, nextType) : void 0;
241
+ process.env.NODE_ENV !== "production" ? warning(isClientID(nextID) && nextID !== ROOT_ID || prevType === nextType, 'RelayModernRecord: Invalid record update, expected both versions of ' + 'record `%s` to have the same `%s` but got conflicting types `%s` ' + 'and `%s`. The GraphQL server likely violated the globally unique ' + 'id requirement by returning the same id for different objects.', prevID, TYPENAME_KEY, prevType, nextType) : void 0;
237
242
  }
238
243
 
239
244
  var updated = null;
@@ -243,7 +248,7 @@ function update(prevRecord, nextRecord) {
243
248
  var key = keys[ii];
244
249
 
245
250
  if (updated || !areEqual(prevRecord[key], nextRecord[key])) {
246
- updated = updated !== null ? updated : (0, _objectSpread2["default"])({}, prevRecord);
251
+ updated = updated !== null ? updated : _objectSpread({}, prevRecord);
247
252
  updated[key] = nextRecord[key];
248
253
  }
249
254
  }
@@ -268,7 +273,7 @@ function merge(record1, record2) {
268
273
 
269
274
  var prevType = (_getType3 = getType(record1)) !== null && _getType3 !== void 0 ? _getType3 : null;
270
275
  var nextType = (_getType4 = getType(record2)) !== null && _getType4 !== void 0 ? _getType4 : null;
271
- process.env.NODE_ENV !== "production" ? warning(isClientID(nextID) || prevType === nextType, 'RelayModernRecord: Invalid record merge, expected both versions of ' + 'record `%s` to have the same `%s` but got conflicting types `%s` ' + 'and `%s`. The GraphQL server likely violated the globally unique ' + 'id requirement by returning the same id for different objects.', prevID, TYPENAME_KEY, prevType, nextType) : void 0;
276
+ process.env.NODE_ENV !== "production" ? warning(isClientID(nextID) && nextID !== ROOT_ID || prevType === nextType, 'RelayModernRecord: Invalid record merge, expected both versions of ' + 'record `%s` to have the same `%s` but got conflicting types `%s` ' + 'and `%s`. The GraphQL server likely violated the globally unique ' + 'id requirement by returning the same id for different objects.', prevID, TYPENAME_KEY, prevType, nextType) : void 0;
272
277
  }
273
278
 
274
279
  return Object.assign({}, record1, record2);
@@ -298,12 +303,12 @@ function setValue(record, storageKey, value) {
298
303
  if (storageKey === ID_KEY) {
299
304
  process.env.NODE_ENV !== "production" ? warning(prevID === value, 'RelayModernRecord: Invalid field update, expected both versions of ' + 'the record to have the same id, got `%s` and `%s`.', prevID, value) : void 0;
300
305
  } else if (storageKey === TYPENAME_KEY) {
301
- var _getType5, _value;
306
+ var _getType5;
302
307
 
303
308
  // note: coalesce null/undefined to null
304
309
  var prevType = (_getType5 = getType(record)) !== null && _getType5 !== void 0 ? _getType5 : null;
305
- var nextType = (_value = value) !== null && _value !== void 0 ? _value : null;
306
- process.env.NODE_ENV !== "production" ? warning(isClientID(getDataID(record)) || prevType === nextType, 'RelayModernRecord: Invalid field update, expected both versions of ' + 'record `%s` to have the same `%s` but got conflicting types `%s` ' + 'and `%s`. The GraphQL server likely violated the globally unique ' + 'id requirement by returning the same id for different objects.', prevID, TYPENAME_KEY, prevType, nextType) : void 0;
310
+ var nextType = value !== null && value !== void 0 ? value : null;
311
+ process.env.NODE_ENV !== "production" ? warning(isClientID(getDataID(record)) && getDataID(record) !== ROOT_ID || prevType === nextType, 'RelayModernRecord: Invalid field update, expected both versions of ' + 'record `%s` to have the same `%s` but got conflicting types `%s` ' + 'and `%s`. The GraphQL server likely violated the globally unique ' + 'id requirement by returning the same id for different objects.', prevID, TYPENAME_KEY, prevType, nextType) : void 0;
307
312
  }
308
313
  }
309
314
 
@@ -10,6 +10,12 @@
10
10
  // flowlint ambiguous-object-type:error
11
11
  'use strict';
12
12
 
13
+ function _createForOfIteratorHelper(o) { if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) { var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var it, normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
14
+
15
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
16
+
17
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
18
+
13
19
  var DataChecker = require('./DataChecker');
14
20
 
15
21
  var RelayModernRecord = require('./RelayModernRecord');
@@ -54,11 +60,9 @@ var DEFAULT_RELEASE_BUFFER_SIZE = 0;
54
60
  * is also enforced in development mode by freezing all records passed to a store.
55
61
  */
56
62
 
57
- var RelayModernStore =
58
- /*#__PURE__*/
59
- function () {
63
+ var RelayModernStore = /*#__PURE__*/function () {
60
64
  function RelayModernStore(source, options) {
61
- var _ref, _ref2, _ref3, _ref4;
65
+ var _options$gcReleaseBuf, _options$gcScheduler, _options$UNSTABLE_DO_, _options$operationLoa;
62
66
 
63
67
  // Prevent mutation of a record from outside the store.
64
68
  if (process.env.NODE_ENV !== "production") {
@@ -75,15 +79,16 @@ function () {
75
79
 
76
80
  this._currentWriteEpoch = 0;
77
81
  this._gcHoldCounter = 0;
78
- this._gcReleaseBufferSize = (_ref = options === null || options === void 0 ? void 0 : options.gcReleaseBufferSize) !== null && _ref !== void 0 ? _ref : DEFAULT_RELEASE_BUFFER_SIZE;
79
- this._gcScheduler = (_ref2 = options === null || options === void 0 ? void 0 : options.gcScheduler) !== null && _ref2 !== void 0 ? _ref2 : resolveImmediate;
80
- this._getDataID = (_ref3 = options === null || options === void 0 ? void 0 : options.UNSTABLE_DO_NOT_USE_getDataID) !== null && _ref3 !== void 0 ? _ref3 : defaultGetDataID;
82
+ this._gcReleaseBufferSize = (_options$gcReleaseBuf = options === null || options === void 0 ? void 0 : options.gcReleaseBufferSize) !== null && _options$gcReleaseBuf !== void 0 ? _options$gcReleaseBuf : DEFAULT_RELEASE_BUFFER_SIZE;
83
+ this._gcScheduler = (_options$gcScheduler = options === null || options === void 0 ? void 0 : options.gcScheduler) !== null && _options$gcScheduler !== void 0 ? _options$gcScheduler : resolveImmediate;
84
+ this._getDataID = (_options$UNSTABLE_DO_ = options === null || options === void 0 ? void 0 : options.UNSTABLE_DO_NOT_USE_getDataID) !== null && _options$UNSTABLE_DO_ !== void 0 ? _options$UNSTABLE_DO_ : defaultGetDataID;
81
85
  this._globalInvalidationEpoch = null;
82
86
  this._hasScheduledGC = false;
83
87
  this._index = 0;
84
88
  this._invalidationSubscriptions = new Set();
85
89
  this._invalidatedRecordIDs = new Set();
86
- this._operationLoader = (_ref4 = options === null || options === void 0 ? void 0 : options.operationLoader) !== null && _ref4 !== void 0 ? _ref4 : null;
90
+ this._queryCacheExpirationTime = options === null || options === void 0 ? void 0 : options.queryCacheExpirationTime;
91
+ this._operationLoader = (_options$operationLoa = options === null || options === void 0 ? void 0 : options.operationLoader) !== null && _options$operationLoa !== void 0 ? _options$operationLoa : null;
87
92
  this._optimisticSource = null;
88
93
  this._recordSource = source;
89
94
  this._releaseBuffer = [];
@@ -103,7 +108,7 @@ function () {
103
108
  };
104
109
 
105
110
  _proto.check = function check(operation, options) {
106
- var _this$_optimisticSour2, _ref5, _ref6;
111
+ var _this$_optimisticSour2, _options$target, _options$handlers;
107
112
 
108
113
  var selector = operation.root;
109
114
  var source = (_this$_optimisticSour2 = this._optimisticSource) !== null && _this$_optimisticSour2 !== void 0 ? _this$_optimisticSour2 : this._recordSource;
@@ -117,58 +122,68 @@ function () {
117
122
  // If so, check if the operation we're checking was last written
118
123
  // before or after invalidation occured.
119
124
  if (operationLastWrittenAt == null || operationLastWrittenAt <= globalInvalidationEpoch) {
120
- // If the operation was written /before/ global invalidation ocurred,
125
+ // If the operation was written /before/ global invalidation occurred,
121
126
  // or if this operation has never been written to the store before,
122
127
  // we will consider the data for this operation to be stale
123
- // (i.e. not resolvable from the store).
128
+ // (i.e. not resolvable from the store).
124
129
  return {
125
130
  status: 'stale'
126
131
  };
127
132
  }
128
133
  }
129
134
 
130
- var target = (_ref5 = options === null || options === void 0 ? void 0 : options.target) !== null && _ref5 !== void 0 ? _ref5 : source;
131
- var handlers = (_ref6 = options === null || options === void 0 ? void 0 : options.handlers) !== null && _ref6 !== void 0 ? _ref6 : [];
135
+ var target = (_options$target = options === null || options === void 0 ? void 0 : options.target) !== null && _options$target !== void 0 ? _options$target : source;
136
+ var handlers = (_options$handlers = options === null || options === void 0 ? void 0 : options.handlers) !== null && _options$handlers !== void 0 ? _options$handlers : [];
132
137
  var operationAvailability = DataChecker.check(source, target, selector, handlers, this._operationLoader, this._getDataID);
133
- return getAvailablityStatus(operationAvailability, operationLastWrittenAt, rootEntry === null || rootEntry === void 0 ? void 0 : rootEntry.fetchTime);
138
+ return getAvailabilityStatus(operationAvailability, operationLastWrittenAt, rootEntry === null || rootEntry === void 0 ? void 0 : rootEntry.fetchTime, this._queryCacheExpirationTime);
134
139
  };
135
140
 
136
141
  _proto.retain = function retain(operation) {
137
142
  var _this = this;
138
143
 
139
144
  var id = operation.request.identifier;
145
+ var disposed = false;
140
146
 
141
147
  var dispose = function dispose() {
142
- // When disposing, instead of immediately decrementing the refCount and
143
- // potentially deleting/collecting the root, move the operation onto
144
- // the release buffer. When the operation is extracted from the release
145
- // buffer, we will determine if it needs to be collected.
146
- _this._releaseBuffer.push(id); // Only when the release buffer is full do we actually:
147
- // - extract the least recent operation in the release buffer
148
- // - attempt to release it and run GC if it's no longer referenced
149
- // (refCount reached 0).
148
+ // Ensure each retain can only dispose once
149
+ if (disposed) {
150
+ return;
151
+ }
150
152
 
153
+ disposed = true; // For Flow: guard against the entry somehow not existing
151
154
 
152
- if (_this._releaseBuffer.length > _this._gcReleaseBufferSize) {
153
- var _id = _this._releaseBuffer.shift();
155
+ var rootEntry = _this._roots.get(id);
154
156
 
155
- var _rootEntry = _this._roots.get(_id);
157
+ if (rootEntry == null) {
158
+ return;
159
+ } // Decrement the ref count: if it becomes zero it is eligible
160
+ // for release.
156
161
 
157
- if (_rootEntry == null) {
158
- // If operation has already been fully released, we don't need
159
- // to do anything.
160
- return;
161
- }
162
162
 
163
- if (_rootEntry.refCount > 0) {
164
- // If the operation is still retained by other callers
165
- // decrement the refCount
166
- _rootEntry.refCount -= 1;
167
- } else {
168
- // Otherwise fully release the query and run GC.
169
- _this._roots["delete"](_id);
163
+ rootEntry.refCount--;
164
+
165
+ if (rootEntry.refCount === 0) {
166
+ var _queryCacheExpirationTime = _this._queryCacheExpirationTime;
167
+
168
+ var rootEntryIsStale = rootEntry.fetchTime != null && _queryCacheExpirationTime != null && rootEntry.fetchTime <= Date.now() - _queryCacheExpirationTime;
169
+
170
+ if (rootEntryIsStale) {
171
+ _this._roots["delete"](id);
170
172
 
171
173
  _this._scheduleGC();
174
+ } else {
175
+ _this._releaseBuffer.push(id); // If the release buffer is now over-full, remove the least-recently
176
+ // added entry and schedule a GC. Note that all items in the release
177
+ // buffer have a refCount of 0.
178
+
179
+
180
+ if (_this._releaseBuffer.length > _this._gcReleaseBufferSize) {
181
+ var _id = _this._releaseBuffer.shift();
182
+
183
+ _this._roots["delete"](_id);
184
+
185
+ _this._scheduleGC();
186
+ }
172
187
  }
173
188
  }
174
189
  };
@@ -176,13 +191,22 @@ function () {
176
191
  var rootEntry = this._roots.get(id);
177
192
 
178
193
  if (rootEntry != null) {
179
- // If we've previously retained this operation, inrement the refCount
194
+ if (rootEntry.refCount === 0) {
195
+ // This entry should be in the release buffer, but it no longer belongs
196
+ // there since it's retained. Remove it to maintain the invariant that
197
+ // all release buffer entries have a refCount of 0.
198
+ this._releaseBuffer = this._releaseBuffer.filter(function (_id) {
199
+ return _id !== id;
200
+ });
201
+ } // If we've previously retained this operation, increment the refCount
202
+
203
+
180
204
  rootEntry.refCount += 1;
181
205
  } else {
182
206
  // Otherwise create a new entry for the operation
183
207
  this._roots.set(id, {
184
208
  operation: operation,
185
- refCount: 0,
209
+ refCount: 1,
186
210
  epoch: null,
187
211
  fetchTime: null
188
212
  });
@@ -202,7 +226,7 @@ function () {
202
226
  }
203
227
 
204
228
  return snapshot;
205
- } // This method will return a list of updated owners form the subscriptions
229
+ } // This method will return a list of updated owners from the subscriptions
206
230
  ;
207
231
 
208
232
  _proto.notify = function notify(sourceOperation, invalidateStore) {
@@ -249,10 +273,21 @@ function () {
249
273
  var rootEntry = this._roots.get(id);
250
274
 
251
275
  if (rootEntry != null) {
252
- var _rootEntry$fetchTime;
253
-
254
276
  rootEntry.epoch = this._currentWriteEpoch;
255
- rootEntry.fetchTime = (_rootEntry$fetchTime = rootEntry.fetchTime) !== null && _rootEntry$fetchTime !== void 0 ? _rootEntry$fetchTime : Date.now();
277
+ rootEntry.fetchTime = Date.now();
278
+ } else if (sourceOperation.request.node.params.operationKind === 'query' && this._gcReleaseBufferSize > 0 && this._releaseBuffer.length < this._gcReleaseBufferSize) {
279
+ // The operation isn't retained but there is space in the release buffer:
280
+ // temporarily track this operation in case the data can be reused soon.
281
+ var temporaryRootEntry = {
282
+ operation: sourceOperation,
283
+ refCount: 0,
284
+ epoch: this._currentWriteEpoch,
285
+ fetchTime: Date.now()
286
+ };
287
+
288
+ this._releaseBuffer.push(id);
289
+
290
+ this._roots.set(id, temporaryRootEntry);
256
291
  }
257
292
  }
258
293
 
@@ -384,12 +419,11 @@ function () {
384
419
  } // Check if the invalidation state for any of the ids has changed.
385
420
 
386
421
 
387
- var _iteratorNormalCompletion = true;
388
- var _didIteratorError = false;
389
- var _iteratorError = undefined;
422
+ var _iterator = _createForOfIteratorHelper(prevInvalidationState.dataIDs),
423
+ _step;
390
424
 
391
425
  try {
392
- for (var _iterator = prevInvalidationState.dataIDs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
426
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
393
427
  var dataID = _step.value;
394
428
 
395
429
  if (currentInvalidations.get(dataID) !== prevInvalidations.get(dataID)) {
@@ -397,18 +431,9 @@ function () {
397
431
  }
398
432
  }
399
433
  } catch (err) {
400
- _didIteratorError = true;
401
- _iteratorError = err;
434
+ _iterator.e(err);
402
435
  } finally {
403
- try {
404
- if (!_iteratorNormalCompletion && _iterator["return"] != null) {
405
- _iterator["return"]();
406
- }
407
- } finally {
408
- if (_didIteratorError) {
409
- throw _iteratorError;
410
- }
411
- }
436
+ _iterator.f();
412
437
  }
413
438
 
414
439
  return false;
@@ -540,8 +565,8 @@ function () {
540
565
 
541
566
  var references = new Set(); // Mark all records that are traversable from a root
542
567
 
543
- this._roots.forEach(function (_ref7) {
544
- var operation = _ref7.operation;
568
+ this._roots.forEach(function (_ref) {
569
+ var operation = _ref.operation;
545
570
  var selector = operation.root;
546
571
  RelayReferenceMarker.mark(_this10._recordSource, selector, references, _this10._operationLoader);
547
572
  });
@@ -664,7 +689,7 @@ function updateTargetFromSource(target, source, currentWriteEpoch, idsMarkedForI
664
689
  /**
665
690
  * Returns an OperationAvailability given the Availability returned
666
691
  * by checking an operation, and when that operation was last written to the store.
667
- * Specifically, the provided Availablity of a an operation will contain the
692
+ * Specifically, the provided Availability of an operation will contain the
668
693
  * value of when a record referenced by the operation was most recently
669
694
  * invalidated; given that value, and given when this operation was last
670
695
  * written to the store, this function will return the overall
@@ -672,11 +697,9 @@ function updateTargetFromSource(target, source, currentWriteEpoch, idsMarkedForI
672
697
  */
673
698
 
674
699
 
675
- function getAvailablityStatus(opearionAvailability, operationLastWrittenAt, operationFetchTime) {
676
- var _operationFetchTime;
677
-
678
- var mostRecentlyInvalidatedAt = opearionAvailability.mostRecentlyInvalidatedAt,
679
- status = opearionAvailability.status;
700
+ function getAvailabilityStatus(operationAvailability, operationLastWrittenAt, operationFetchTime, queryCacheExpirationTime) {
701
+ var mostRecentlyInvalidatedAt = operationAvailability.mostRecentlyInvalidatedAt,
702
+ status = operationAvailability.status;
680
703
 
681
704
  if (typeof mostRecentlyInvalidatedAt === 'number') {
682
705
  // If some record referenced by this operation is stale, then the operation itself is stale
@@ -687,15 +710,29 @@ function getAvailablityStatus(opearionAvailability, operationLastWrittenAt, oper
687
710
  status: 'stale'
688
711
  };
689
712
  }
713
+ }
714
+
715
+ if (status === 'missing') {
716
+ return {
717
+ status: 'missing'
718
+ };
719
+ }
720
+
721
+ if (operationFetchTime != null && queryCacheExpirationTime != null) {
722
+ var isStale = operationFetchTime <= Date.now() - queryCacheExpirationTime;
723
+
724
+ if (isStale) {
725
+ return {
726
+ status: 'stale'
727
+ };
728
+ }
690
729
  } // There were no invalidations of any reachable records *or* the operation is known to have
691
730
  // been fetched after the most recent record invalidation.
692
731
 
693
732
 
694
- return status === 'missing' ? {
695
- status: 'missing'
696
- } : {
733
+ return {
697
734
  status: 'available',
698
- fetchTime: (_operationFetchTime = operationFetchTime) !== null && _operationFetchTime !== void 0 ? _operationFetchTime : null
735
+ fetchTime: operationFetchTime !== null && operationFetchTime !== void 0 ? operationFetchTime : null
699
736
  };
700
737
  }
701
738
 
@@ -10,11 +10,15 @@
10
10
  // flowlint ambiguous-object-type:error
11
11
  'use strict';
12
12
 
13
+ function _createForOfIteratorHelper(o) { if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) { var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var it, normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
14
+
15
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
16
+
17
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
18
+
13
19
  var invariant = require("fbjs/lib/invariant");
14
20
 
15
- var RelayOperationTracker =
16
- /*#__PURE__*/
17
- function () {
21
+ var RelayOperationTracker = /*#__PURE__*/function () {
18
22
  function RelayOperationTracker() {
19
23
  this._ownersToPendingOperations = new Map();
20
24
  this._pendingOperationsToOwners = new Map();
@@ -34,12 +38,12 @@ function () {
34
38
  }
35
39
 
36
40
  var newlyAffectedOwners = new Set();
37
- var _iteratorNormalCompletion = true;
38
- var _didIteratorError = false;
39
- var _iteratorError = undefined;
41
+
42
+ var _iterator = _createForOfIteratorHelper(affectedOwners),
43
+ _step;
40
44
 
41
45
  try {
42
- for (var _iterator = affectedOwners[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
46
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
43
47
  var owner = _step.value;
44
48
 
45
49
  var pendingOperationsAffectingOwner = this._ownersToPendingOperations.get(owner);
@@ -61,18 +65,9 @@ function () {
61
65
  } // No new owners were affected by this operation, we may stop here
62
66
 
63
67
  } catch (err) {
64
- _didIteratorError = true;
65
- _iteratorError = err;
68
+ _iterator.e(err);
66
69
  } finally {
67
- try {
68
- if (!_iteratorNormalCompletion && _iterator["return"] != null) {
69
- _iterator["return"]();
70
- }
71
- } finally {
72
- if (_didIteratorError) {
73
- throw _iteratorError;
74
- }
75
- }
70
+ _iterator.f();
76
71
  }
77
72
 
78
73
  if (newlyAffectedOwners.size === 0) {
@@ -82,12 +77,12 @@ function () {
82
77
 
83
78
 
84
79
  var ownersAffectedByOperation = this._pendingOperationsToOwners.get(pendingOperation) || new Set();
85
- var _iteratorNormalCompletion2 = true;
86
- var _didIteratorError2 = false;
87
- var _iteratorError2 = undefined;
80
+
81
+ var _iterator2 = _createForOfIteratorHelper(newlyAffectedOwners),
82
+ _step2;
88
83
 
89
84
  try {
90
- for (var _iterator2 = newlyAffectedOwners[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
85
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
91
86
  var _owner = _step2.value;
92
87
 
93
88
  this._resolveOwnerResolvers(_owner);
@@ -95,18 +90,9 @@ function () {
95
90
  ownersAffectedByOperation.add(_owner);
96
91
  }
97
92
  } catch (err) {
98
- _didIteratorError2 = true;
99
- _iteratorError2 = err;
93
+ _iterator2.e(err);
100
94
  } finally {
101
- try {
102
- if (!_iteratorNormalCompletion2 && _iterator2["return"] != null) {
103
- _iterator2["return"]();
104
- }
105
- } finally {
106
- if (_didIteratorError2) {
107
- throw _iteratorError2;
108
- }
109
- }
95
+ _iterator2.f();
110
96
  }
111
97
 
112
98
  this._pendingOperationsToOwners.set(pendingOperation, ownersAffectedByOperation);
@@ -129,12 +115,12 @@ function () {
129
115
  // and some other operations
130
116
 
131
117
  var updatedOwners = new Set();
132
- var _iteratorNormalCompletion3 = true;
133
- var _didIteratorError3 = false;
134
- var _iteratorError3 = undefined;
118
+
119
+ var _iterator3 = _createForOfIteratorHelper(affectedOwners),
120
+ _step3;
135
121
 
136
122
  try {
137
- for (var _iterator3 = affectedOwners[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
123
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
138
124
  var owner = _step3.value;
139
125
 
140
126
  var pendingOperationsAffectingOwner = this._ownersToPendingOperations.get(owner);
@@ -153,26 +139,16 @@ function () {
153
139
  } // Complete subscriptions for all owners, affected by `pendingOperation`
154
140
 
155
141
  } catch (err) {
156
- _didIteratorError3 = true;
157
- _iteratorError3 = err;
142
+ _iterator3.e(err);
158
143
  } finally {
159
- try {
160
- if (!_iteratorNormalCompletion3 && _iterator3["return"] != null) {
161
- _iterator3["return"]();
162
- }
163
- } finally {
164
- if (_didIteratorError3) {
165
- throw _iteratorError3;
166
- }
167
- }
144
+ _iterator3.f();
168
145
  }
169
146
 
170
- var _iteratorNormalCompletion4 = true;
171
- var _didIteratorError4 = false;
172
- var _iteratorError4 = undefined;
147
+ var _iterator4 = _createForOfIteratorHelper(completedOwners),
148
+ _step4;
173
149
 
174
150
  try {
175
- for (var _iterator4 = completedOwners[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
151
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
176
152
  var _owner2 = _step4.value;
177
153
 
178
154
  this._resolveOwnerResolvers(_owner2);
@@ -182,44 +158,25 @@ function () {
182
158
  // are affected by other operations
183
159
 
184
160
  } catch (err) {
185
- _didIteratorError4 = true;
186
- _iteratorError4 = err;
161
+ _iterator4.e(err);
187
162
  } finally {
188
- try {
189
- if (!_iteratorNormalCompletion4 && _iterator4["return"] != null) {
190
- _iterator4["return"]();
191
- }
192
- } finally {
193
- if (_didIteratorError4) {
194
- throw _iteratorError4;
195
- }
196
- }
163
+ _iterator4.f();
197
164
  }
198
165
 
199
- var _iteratorNormalCompletion5 = true;
200
- var _didIteratorError5 = false;
201
- var _iteratorError5 = undefined;
166
+ var _iterator5 = _createForOfIteratorHelper(updatedOwners),
167
+ _step5;
202
168
 
203
169
  try {
204
- for (var _iterator5 = updatedOwners[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
170
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
205
171
  var _owner3 = _step5.value;
206
172
 
207
173
  this._resolveOwnerResolvers(_owner3);
208
174
  } // Finally, remove pending operation
209
175
 
210
176
  } catch (err) {
211
- _didIteratorError5 = true;
212
- _iteratorError5 = err;
177
+ _iterator5.e(err);
213
178
  } finally {
214
- try {
215
- if (!_iteratorNormalCompletion5 && _iterator5["return"] != null) {
216
- _iterator5["return"]();
217
- }
218
- } finally {
219
- if (_didIteratorError5) {
220
- throw _iteratorError5;
221
- }
222
- }
179
+ _iterator5.f();
223
180
  }
224
181
 
225
182
  this._pendingOperationsToOwners["delete"](pendingOperation);
@@ -12,7 +12,11 @@
12
12
 
13
13
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
14
14
 
15
- var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread"));
15
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
16
+
17
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
18
+
19
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
16
20
 
17
21
  var RelayRecordSource = require('./RelayRecordSource');
18
22
 
@@ -25,9 +29,7 @@ var UNPUBLISH_RECORD_SENTINEL = Object.freeze({
25
29
  * shadow the base version of the record rather than updating/replacing them.
26
30
  */
27
31
 
28
- var RelayOptimisticRecordSource =
29
- /*#__PURE__*/
30
- function () {
32
+ var RelayOptimisticRecordSource = /*#__PURE__*/function () {
31
33
  function RelayOptimisticRecordSource(base) {
32
34
  this._base = base;
33
35
  this._sink = RelayRecordSource.create();
@@ -100,7 +102,7 @@ function () {
100
102
  _proto.toJSON = function toJSON() {
101
103
  var _this = this;
102
104
 
103
- var merged = (0, _objectSpread2["default"])({}, this._base.toJSON());
105
+ var merged = _objectSpread({}, this._base.toJSON());
104
106
 
105
107
  this._sink.getRecordIDs().forEach(function (dataID) {
106
108
  var record = _this.get(dataID);
@@ -37,9 +37,7 @@ var warning = require("fbjs/lib/warning");
37
37
  * - Executes handlers for "handle" fields.
38
38
  * - Reverts and reapplies pending optimistic updates.
39
39
  */
40
- var RelayPublishQueue =
41
- /*#__PURE__*/
42
- function () {
40
+ var RelayPublishQueue = /*#__PURE__*/function () {
43
41
  // True if the next `run()` should apply the backup and rerun all optimistic
44
42
  // updates performing a rebase.
45
43
  // Payloads to apply or Sources to publish to the store with the next `run()`.
@@ -45,9 +45,7 @@ function read(recordSource, selector) {
45
45
  */
46
46
 
47
47
 
48
- var RelayReader =
49
- /*#__PURE__*/
50
- function () {
48
+ var RelayReader = /*#__PURE__*/function () {
51
49
  function RelayReader(recordSource, selector) {
52
50
  this._isMissingData = false;
53
51
  this._owner = selector.owner;
@@ -12,9 +12,7 @@
12
12
 
13
13
  var RelayRecordSourceMapImpl = require('./RelayRecordSourceMapImpl');
14
14
 
15
- var RelayRecordSource =
16
- /*#__PURE__*/
17
- function () {
15
+ var RelayRecordSource = /*#__PURE__*/function () {
18
16
  function RelayRecordSource(records) {
19
17
  return RelayRecordSource.create(records);
20
18
  }