relay-runtime 9.0.0 → 10.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.
- package/handlers/RelayDefaultHandlerProvider.js.flow +47 -0
- package/handlers/connection/ConnectionHandler.js.flow +549 -0
- package/handlers/connection/ConnectionInterface.js.flow +92 -0
- package/handlers/connection/MutationHandlers.js.flow +199 -0
- package/index.js +1 -1
- package/index.js.flow +335 -0
- package/lib/handlers/RelayDefaultHandlerProvider.js +20 -0
- package/lib/handlers/connection/ConnectionHandler.js +1 -3
- package/lib/handlers/connection/MutationHandlers.js +212 -0
- package/lib/index.js +14 -2
- package/lib/mutations/RelayDeclarativeMutationConfig.js +22 -45
- package/lib/mutations/RelayRecordProxy.js +1 -3
- package/lib/mutations/RelayRecordSourceMutator.js +1 -3
- package/lib/mutations/RelayRecordSourceProxy.js +1 -3
- package/lib/mutations/RelayRecordSourceSelectorProxy.js +1 -3
- package/lib/mutations/commitMutation.js +2 -3
- package/lib/mutations/validateMutation.js +40 -9
- package/lib/network/RelayObservable.js +9 -9
- package/lib/network/RelayQueryResponseCache.js +8 -6
- package/lib/query/GraphQLTag.js +2 -1
- package/lib/query/PreloadableQueryRegistry.js +70 -0
- package/lib/query/fetchQuery.js +2 -3
- package/lib/query/fetchQueryInternal.js +5 -14
- package/lib/store/DataChecker.js +200 -71
- package/lib/store/RelayConcreteVariables.js +6 -2
- package/lib/store/RelayModernEnvironment.js +124 -65
- package/lib/store/RelayModernFragmentSpecResolver.js +19 -14
- package/lib/store/RelayModernOperationDescriptor.js +6 -5
- package/lib/store/RelayModernQueryExecutor.js +122 -73
- package/lib/store/RelayModernRecord.js +14 -9
- package/lib/store/RelayModernSelector.js +6 -2
- package/lib/store/RelayModernStore.js +281 -131
- package/lib/store/RelayOperationTracker.js +35 -78
- package/lib/store/RelayOptimisticRecordSource.js +7 -5
- package/lib/store/RelayPublishQueue.js +2 -4
- package/lib/store/RelayReader.js +304 -52
- package/lib/store/RelayRecordSource.js +1 -3
- package/lib/store/RelayRecordSourceMapImpl.js +13 -18
- package/lib/store/RelayReferenceMarker.js +125 -14
- package/lib/store/RelayResponseNormalizer.js +261 -66
- package/lib/store/RelayStoreReactFlightUtils.js +47 -0
- package/lib/store/RelayStoreUtils.js +1 -0
- package/lib/store/StoreInspector.js +8 -8
- package/lib/store/TypeID.js +28 -0
- package/lib/store/cloneRelayScalarHandleSourceField.js +44 -0
- package/lib/store/defaultRequiredFieldLogger.js +18 -0
- package/lib/store/normalizeRelayPayload.js +6 -2
- package/lib/store/readInlineData.js +1 -1
- package/lib/subscription/requestSubscription.js +4 -3
- package/lib/util/NormalizationNode.js +1 -5
- package/lib/util/RelayConcreteNode.js +11 -6
- package/lib/util/RelayError.js +39 -9
- package/lib/util/RelayFeatureFlags.js +6 -3
- package/lib/util/RelayReplaySubject.js +3 -3
- package/lib/util/createPayloadFor3DField.js +7 -2
- package/lib/util/getFragmentIdentifier.js +12 -3
- package/lib/util/getOperation.js +33 -0
- package/lib/util/getRequestIdentifier.js +2 -2
- package/lib/util/isEmptyObject.js +25 -0
- package/lib/util/recycleNodesInto.js +6 -7
- package/lib/util/reportMissingRequiredFields.js +48 -0
- package/mutations/RelayDeclarativeMutationConfig.js.flow +380 -0
- package/mutations/RelayRecordProxy.js.flow +165 -0
- package/mutations/RelayRecordSourceMutator.js.flow +238 -0
- package/mutations/RelayRecordSourceProxy.js.flow +164 -0
- package/mutations/RelayRecordSourceSelectorProxy.js.flow +119 -0
- package/mutations/applyOptimisticMutation.js.flow +76 -0
- package/mutations/commitLocalUpdate.js.flow +24 -0
- package/mutations/commitMutation.js.flow +181 -0
- package/mutations/validateMutation.js.flow +242 -0
- package/network/ConvertToExecuteFunction.js.flow +49 -0
- package/network/RelayNetwork.js.flow +84 -0
- package/network/RelayNetworkTypes.js.flow +145 -0
- package/network/RelayObservable.js.flow +634 -0
- package/network/RelayQueryResponseCache.js.flow +111 -0
- package/package.json +2 -2
- package/query/GraphQLTag.js.flow +168 -0
- package/query/PreloadableQueryRegistry.js.flow +65 -0
- package/query/fetchQuery.js.flow +47 -0
- package/query/fetchQueryInternal.js.flow +343 -0
- package/relay-runtime.js +2 -2
- package/relay-runtime.min.js +2 -2
- package/store/ClientID.js.flow +43 -0
- package/store/DataChecker.js.flow +568 -0
- package/store/RelayConcreteVariables.js.flow +96 -0
- package/store/RelayModernEnvironment.js.flow +571 -0
- package/store/RelayModernFragmentSpecResolver.js.flow +438 -0
- package/store/RelayModernOperationDescriptor.js.flow +92 -0
- package/store/RelayModernQueryExecutor.js.flow +1345 -0
- package/store/RelayModernRecord.js.flow +403 -0
- package/store/RelayModernSelector.js.flow +455 -0
- package/store/RelayModernStore.js.flow +858 -0
- package/store/RelayOperationTracker.js.flow +164 -0
- package/store/RelayOptimisticRecordSource.js.flow +119 -0
- package/store/RelayPublishQueue.js.flow +401 -0
- package/store/RelayReader.js.flow +638 -0
- package/store/RelayRecordSource.js.flow +29 -0
- package/store/RelayRecordSourceMapImpl.js.flow +87 -0
- package/store/RelayRecordState.js.flow +37 -0
- package/store/RelayReferenceMarker.js.flow +324 -0
- package/store/RelayResponseNormalizer.js.flow +791 -0
- package/store/RelayStoreReactFlightUtils.js.flow +64 -0
- package/store/RelayStoreTypes.js.flow +958 -0
- package/store/RelayStoreUtils.js.flow +219 -0
- package/store/StoreInspector.js.flow +171 -0
- package/store/TypeID.js.flow +28 -0
- package/store/ViewerPattern.js.flow +26 -0
- package/store/cloneRelayHandleSourceField.js.flow +66 -0
- package/store/cloneRelayScalarHandleSourceField.js.flow +62 -0
- package/store/createFragmentSpecResolver.js.flow +55 -0
- package/store/createRelayContext.js.flow +44 -0
- package/store/defaultGetDataID.js.flow +27 -0
- package/store/defaultRequiredFieldLogger.js.flow +23 -0
- package/store/hasOverlappingIDs.js.flow +34 -0
- package/store/isRelayModernEnvironment.js.flow +27 -0
- package/store/normalizeRelayPayload.js.flow +51 -0
- package/store/readInlineData.js.flow +75 -0
- package/subscription/requestSubscription.js.flow +103 -0
- package/util/JSResourceTypes.flow.js.flow +20 -0
- package/util/NormalizationNode.js.flow +213 -0
- package/util/ReaderNode.js.flow +227 -0
- package/util/RelayConcreteNode.js.flow +99 -0
- package/util/RelayDefaultHandleKey.js.flow +17 -0
- package/util/RelayError.js.flow +62 -0
- package/util/RelayFeatureFlags.js.flow +37 -0
- package/util/RelayProfiler.js.flow +284 -0
- package/util/RelayReplaySubject.js.flow +135 -0
- package/util/RelayRuntimeTypes.js.flow +72 -0
- package/util/createPayloadFor3DField.js.flow +43 -0
- package/util/deepFreeze.js.flow +36 -0
- package/util/generateID.js.flow +21 -0
- package/util/getFragmentIdentifier.js.flow +76 -0
- package/util/getOperation.js.flow +40 -0
- package/util/getRelayHandleKey.js.flow +41 -0
- package/util/getRequestIdentifier.js.flow +42 -0
- package/util/isEmptyObject.js.flow +25 -0
- package/util/isPromise.js.flow +21 -0
- package/util/isScalarAndEqual.js.flow +26 -0
- package/util/recycleNodesInto.js.flow +87 -0
- package/util/reportMissingRequiredFields.js.flow +51 -0
- package/util/resolveImmediate.js.flow +30 -0
- package/util/stableCopy.js.flow +35 -0
|
@@ -10,6 +10,16 @@
|
|
|
10
10
|
// flowlint ambiguous-object-type:error
|
|
11
11
|
'use strict';
|
|
12
12
|
|
|
13
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
14
|
+
|
|
15
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
16
|
+
|
|
17
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; 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 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; } } }; }
|
|
18
|
+
|
|
19
|
+
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(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
20
|
+
|
|
21
|
+
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; }
|
|
22
|
+
|
|
13
23
|
var DataChecker = require('./DataChecker');
|
|
14
24
|
|
|
15
25
|
var RelayModernRecord = require('./RelayModernRecord');
|
|
@@ -22,6 +32,8 @@ var RelayReader = require('./RelayReader');
|
|
|
22
32
|
|
|
23
33
|
var RelayReferenceMarker = require('./RelayReferenceMarker');
|
|
24
34
|
|
|
35
|
+
var RelayStoreReactFlightUtils = require('./RelayStoreReactFlightUtils');
|
|
36
|
+
|
|
25
37
|
var RelayStoreUtils = require('./RelayStoreUtils');
|
|
26
38
|
|
|
27
39
|
var deepFreeze = require('../util/deepFreeze');
|
|
@@ -32,6 +44,8 @@ var hasOverlappingIDs = require('./hasOverlappingIDs');
|
|
|
32
44
|
|
|
33
45
|
var invariant = require("fbjs/lib/invariant");
|
|
34
46
|
|
|
47
|
+
var isEmptyObject = require('../util/isEmptyObject');
|
|
48
|
+
|
|
35
49
|
var recycleNodesInto = require('../util/recycleNodesInto');
|
|
36
50
|
|
|
37
51
|
var resolveImmediate = require('../util/resolveImmediate');
|
|
@@ -54,11 +68,21 @@ var DEFAULT_RELEASE_BUFFER_SIZE = 0;
|
|
|
54
68
|
* is also enforced in development mode by freezing all records passed to a store.
|
|
55
69
|
*/
|
|
56
70
|
|
|
57
|
-
var RelayModernStore =
|
|
58
|
-
/*#__PURE__*/
|
|
59
|
-
function () {
|
|
71
|
+
var RelayModernStore = /*#__PURE__*/function () {
|
|
60
72
|
function RelayModernStore(source, options) {
|
|
61
|
-
var
|
|
73
|
+
var _this = this;
|
|
74
|
+
|
|
75
|
+
var _options$gcReleaseBuf, _options$gcScheduler, _options$UNSTABLE_DO_, _options$log, _options$operationLoa;
|
|
76
|
+
|
|
77
|
+
(0, _defineProperty2["default"])(this, "_gcStep", function () {
|
|
78
|
+
if (_this._gcRun) {
|
|
79
|
+
if (_this._gcRun.next().done) {
|
|
80
|
+
_this._gcRun = null;
|
|
81
|
+
} else {
|
|
82
|
+
_this._gcScheduler(_this._gcStep);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
62
86
|
|
|
63
87
|
// Prevent mutation of a record from outside the store.
|
|
64
88
|
if (process.env.NODE_ENV !== "production") {
|
|
@@ -75,15 +99,16 @@ function () {
|
|
|
75
99
|
|
|
76
100
|
this._currentWriteEpoch = 0;
|
|
77
101
|
this._gcHoldCounter = 0;
|
|
78
|
-
this._gcReleaseBufferSize = (
|
|
79
|
-
this.
|
|
80
|
-
this.
|
|
102
|
+
this._gcReleaseBufferSize = (_options$gcReleaseBuf = options === null || options === void 0 ? void 0 : options.gcReleaseBufferSize) !== null && _options$gcReleaseBuf !== void 0 ? _options$gcReleaseBuf : DEFAULT_RELEASE_BUFFER_SIZE;
|
|
103
|
+
this._gcRun = null;
|
|
104
|
+
this._gcScheduler = (_options$gcScheduler = options === null || options === void 0 ? void 0 : options.gcScheduler) !== null && _options$gcScheduler !== void 0 ? _options$gcScheduler : resolveImmediate;
|
|
105
|
+
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
106
|
this._globalInvalidationEpoch = null;
|
|
82
|
-
this._hasScheduledGC = false;
|
|
83
|
-
this._index = 0;
|
|
84
107
|
this._invalidationSubscriptions = new Set();
|
|
85
108
|
this._invalidatedRecordIDs = new Set();
|
|
86
|
-
this.
|
|
109
|
+
this.__log = (_options$log = options === null || options === void 0 ? void 0 : options.log) !== null && _options$log !== void 0 ? _options$log : null;
|
|
110
|
+
this._queryCacheExpirationTime = options === null || options === void 0 ? void 0 : options.queryCacheExpirationTime;
|
|
111
|
+
this._operationLoader = (_options$operationLoa = options === null || options === void 0 ? void 0 : options.operationLoader) !== null && _options$operationLoa !== void 0 ? _options$operationLoa : null;
|
|
87
112
|
this._optimisticSource = null;
|
|
88
113
|
this._recordSource = source;
|
|
89
114
|
this._releaseBuffer = [];
|
|
@@ -103,7 +128,7 @@ function () {
|
|
|
103
128
|
};
|
|
104
129
|
|
|
105
130
|
_proto.check = function check(operation, options) {
|
|
106
|
-
var _this$_optimisticSour2,
|
|
131
|
+
var _this$_optimisticSour2, _options$target, _options$handlers;
|
|
107
132
|
|
|
108
133
|
var selector = operation.root;
|
|
109
134
|
var source = (_this$_optimisticSour2 = this._optimisticSource) !== null && _this$_optimisticSour2 !== void 0 ? _this$_optimisticSour2 : this._recordSource;
|
|
@@ -117,58 +142,68 @@ function () {
|
|
|
117
142
|
// If so, check if the operation we're checking was last written
|
|
118
143
|
// before or after invalidation occured.
|
|
119
144
|
if (operationLastWrittenAt == null || operationLastWrittenAt <= globalInvalidationEpoch) {
|
|
120
|
-
// If the operation was written /before/ global invalidation
|
|
145
|
+
// If the operation was written /before/ global invalidation occurred,
|
|
121
146
|
// or if this operation has never been written to the store before,
|
|
122
147
|
// we will consider the data for this operation to be stale
|
|
123
|
-
//
|
|
148
|
+
// (i.e. not resolvable from the store).
|
|
124
149
|
return {
|
|
125
150
|
status: 'stale'
|
|
126
151
|
};
|
|
127
152
|
}
|
|
128
153
|
}
|
|
129
154
|
|
|
130
|
-
var target = (
|
|
131
|
-
var handlers = (
|
|
155
|
+
var target = (_options$target = options === null || options === void 0 ? void 0 : options.target) !== null && _options$target !== void 0 ? _options$target : source;
|
|
156
|
+
var handlers = (_options$handlers = options === null || options === void 0 ? void 0 : options.handlers) !== null && _options$handlers !== void 0 ? _options$handlers : [];
|
|
132
157
|
var operationAvailability = DataChecker.check(source, target, selector, handlers, this._operationLoader, this._getDataID);
|
|
133
|
-
return
|
|
158
|
+
return getAvailabilityStatus(operationAvailability, operationLastWrittenAt, rootEntry === null || rootEntry === void 0 ? void 0 : rootEntry.fetchTime, this._queryCacheExpirationTime);
|
|
134
159
|
};
|
|
135
160
|
|
|
136
161
|
_proto.retain = function retain(operation) {
|
|
137
|
-
var
|
|
162
|
+
var _this2 = this;
|
|
138
163
|
|
|
139
164
|
var id = operation.request.identifier;
|
|
165
|
+
var disposed = false;
|
|
140
166
|
|
|
141
167
|
var dispose = function dispose() {
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
// - attempt to release it and run GC if it's no longer referenced
|
|
149
|
-
// (refCount reached 0).
|
|
168
|
+
// Ensure each retain can only dispose once
|
|
169
|
+
if (disposed) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
disposed = true; // For Flow: guard against the entry somehow not existing
|
|
150
174
|
|
|
175
|
+
var rootEntry = _this2._roots.get(id);
|
|
151
176
|
|
|
152
|
-
if (
|
|
153
|
-
|
|
177
|
+
if (rootEntry == null) {
|
|
178
|
+
return;
|
|
179
|
+
} // Decrement the ref count: if it becomes zero it is eligible
|
|
180
|
+
// for release.
|
|
154
181
|
|
|
155
|
-
var _rootEntry = _this._roots.get(_id);
|
|
156
182
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
183
|
+
rootEntry.refCount--;
|
|
184
|
+
|
|
185
|
+
if (rootEntry.refCount === 0) {
|
|
186
|
+
var _queryCacheExpirationTime = _this2._queryCacheExpirationTime;
|
|
187
|
+
|
|
188
|
+
var rootEntryIsStale = rootEntry.fetchTime != null && _queryCacheExpirationTime != null && rootEntry.fetchTime <= Date.now() - _queryCacheExpirationTime;
|
|
162
189
|
|
|
163
|
-
if (
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
190
|
+
if (rootEntryIsStale) {
|
|
191
|
+
_this2._roots["delete"](id);
|
|
192
|
+
|
|
193
|
+
_this2.scheduleGC();
|
|
167
194
|
} else {
|
|
168
|
-
//
|
|
169
|
-
|
|
195
|
+
_this2._releaseBuffer.push(id); // If the release buffer is now over-full, remove the least-recently
|
|
196
|
+
// added entry and schedule a GC. Note that all items in the release
|
|
197
|
+
// buffer have a refCount of 0.
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
if (_this2._releaseBuffer.length > _this2._gcReleaseBufferSize) {
|
|
201
|
+
var _id = _this2._releaseBuffer.shift();
|
|
202
|
+
|
|
203
|
+
_this2._roots["delete"](_id);
|
|
170
204
|
|
|
171
|
-
|
|
205
|
+
_this2.scheduleGC();
|
|
206
|
+
}
|
|
172
207
|
}
|
|
173
208
|
}
|
|
174
209
|
};
|
|
@@ -176,13 +211,22 @@ function () {
|
|
|
176
211
|
var rootEntry = this._roots.get(id);
|
|
177
212
|
|
|
178
213
|
if (rootEntry != null) {
|
|
179
|
-
|
|
214
|
+
if (rootEntry.refCount === 0) {
|
|
215
|
+
// This entry should be in the release buffer, but it no longer belongs
|
|
216
|
+
// there since it's retained. Remove it to maintain the invariant that
|
|
217
|
+
// all release buffer entries have a refCount of 0.
|
|
218
|
+
this._releaseBuffer = this._releaseBuffer.filter(function (_id) {
|
|
219
|
+
return _id !== id;
|
|
220
|
+
});
|
|
221
|
+
} // If we've previously retained this operation, increment the refCount
|
|
222
|
+
|
|
223
|
+
|
|
180
224
|
rootEntry.refCount += 1;
|
|
181
225
|
} else {
|
|
182
226
|
// Otherwise create a new entry for the operation
|
|
183
227
|
this._roots.set(id, {
|
|
184
228
|
operation: operation,
|
|
185
|
-
refCount:
|
|
229
|
+
refCount: 1,
|
|
186
230
|
epoch: null,
|
|
187
231
|
fetchTime: null
|
|
188
232
|
});
|
|
@@ -202,14 +246,22 @@ function () {
|
|
|
202
246
|
}
|
|
203
247
|
|
|
204
248
|
return snapshot;
|
|
205
|
-
} // This method will return a list of updated owners
|
|
249
|
+
} // This method will return a list of updated owners from the subscriptions
|
|
206
250
|
;
|
|
207
251
|
|
|
208
252
|
_proto.notify = function notify(sourceOperation, invalidateStore) {
|
|
209
|
-
var
|
|
253
|
+
var _this3 = this;
|
|
254
|
+
|
|
255
|
+
var log = this.__log;
|
|
210
256
|
|
|
211
|
-
|
|
257
|
+
if (log != null) {
|
|
258
|
+
log({
|
|
259
|
+
name: 'store.notify.start'
|
|
260
|
+
});
|
|
261
|
+
} // Increment the current write when notifying after executing
|
|
212
262
|
// a set of changes to the store.
|
|
263
|
+
|
|
264
|
+
|
|
213
265
|
this._currentWriteEpoch++;
|
|
214
266
|
|
|
215
267
|
if (invalidateStore === true) {
|
|
@@ -218,9 +270,10 @@ function () {
|
|
|
218
270
|
|
|
219
271
|
var source = this.getSource();
|
|
220
272
|
var updatedOwners = [];
|
|
273
|
+
var hasUpdatedRecords = !isEmptyObject(this._updatedRecordIDs);
|
|
221
274
|
|
|
222
275
|
this._subscriptions.forEach(function (subscription) {
|
|
223
|
-
var owner =
|
|
276
|
+
var owner = _this3._updateSubscription(source, subscription, hasUpdatedRecords);
|
|
224
277
|
|
|
225
278
|
if (owner != null) {
|
|
226
279
|
updatedOwners.push(owner);
|
|
@@ -228,9 +281,17 @@ function () {
|
|
|
228
281
|
});
|
|
229
282
|
|
|
230
283
|
this._invalidationSubscriptions.forEach(function (subscription) {
|
|
231
|
-
|
|
284
|
+
_this3._updateInvalidationSubscription(subscription, invalidateStore === true);
|
|
232
285
|
});
|
|
233
286
|
|
|
287
|
+
if (log != null) {
|
|
288
|
+
log({
|
|
289
|
+
name: 'store.notify.complete',
|
|
290
|
+
updatedRecordIDs: this._updatedRecordIDs,
|
|
291
|
+
invalidatedRecordIDs: this._invalidatedRecordIDs
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
234
295
|
this._updatedRecordIDs = {};
|
|
235
296
|
|
|
236
297
|
this._invalidatedRecordIDs.clear(); // If a source operation was provided (indicating the operation
|
|
@@ -249,10 +310,21 @@ function () {
|
|
|
249
310
|
var rootEntry = this._roots.get(id);
|
|
250
311
|
|
|
251
312
|
if (rootEntry != null) {
|
|
252
|
-
var _rootEntry$fetchTime;
|
|
253
|
-
|
|
254
313
|
rootEntry.epoch = this._currentWriteEpoch;
|
|
255
|
-
rootEntry.fetchTime =
|
|
314
|
+
rootEntry.fetchTime = Date.now();
|
|
315
|
+
} else if (sourceOperation.request.node.params.operationKind === 'query' && this._gcReleaseBufferSize > 0 && this._releaseBuffer.length < this._gcReleaseBufferSize) {
|
|
316
|
+
// The operation isn't retained but there is space in the release buffer:
|
|
317
|
+
// temporarily track this operation in case the data can be reused soon.
|
|
318
|
+
var temporaryRootEntry = {
|
|
319
|
+
operation: sourceOperation,
|
|
320
|
+
refCount: 0,
|
|
321
|
+
epoch: this._currentWriteEpoch,
|
|
322
|
+
fetchTime: Date.now()
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
this._releaseBuffer.push(id);
|
|
326
|
+
|
|
327
|
+
this._roots.set(id, temporaryRootEntry);
|
|
256
328
|
}
|
|
257
329
|
}
|
|
258
330
|
|
|
@@ -266,11 +338,22 @@ function () {
|
|
|
266
338
|
updateTargetFromSource(target, source, // We increment the current epoch at the end of the set of updates,
|
|
267
339
|
// in notify(). Here, we pass what will be the incremented value of
|
|
268
340
|
// the epoch to use to write to invalidated records.
|
|
269
|
-
this._currentWriteEpoch + 1, idsMarkedForInvalidation, this._updatedRecordIDs, this._invalidatedRecordIDs);
|
|
341
|
+
this._currentWriteEpoch + 1, idsMarkedForInvalidation, this._updatedRecordIDs, this._invalidatedRecordIDs); // NOTE: log *after* processing the source so that even if a bad log function
|
|
342
|
+
// mutates the source, it doesn't affect Relay processing of it.
|
|
343
|
+
|
|
344
|
+
var log = this.__log;
|
|
345
|
+
|
|
346
|
+
if (log != null) {
|
|
347
|
+
log({
|
|
348
|
+
name: 'store.publish',
|
|
349
|
+
source: source,
|
|
350
|
+
optimistic: target === this._optimisticSource
|
|
351
|
+
});
|
|
352
|
+
}
|
|
270
353
|
};
|
|
271
354
|
|
|
272
355
|
_proto.subscribe = function subscribe(snapshot, callback) {
|
|
273
|
-
var
|
|
356
|
+
var _this4 = this;
|
|
274
357
|
|
|
275
358
|
var subscription = {
|
|
276
359
|
backup: null,
|
|
@@ -280,7 +363,7 @@ function () {
|
|
|
280
363
|
};
|
|
281
364
|
|
|
282
365
|
var dispose = function dispose() {
|
|
283
|
-
|
|
366
|
+
_this4._subscriptions["delete"](subscription);
|
|
284
367
|
};
|
|
285
368
|
|
|
286
369
|
this._subscriptions.add(subscription);
|
|
@@ -291,18 +374,23 @@ function () {
|
|
|
291
374
|
};
|
|
292
375
|
|
|
293
376
|
_proto.holdGC = function holdGC() {
|
|
294
|
-
var
|
|
377
|
+
var _this5 = this;
|
|
378
|
+
|
|
379
|
+
if (this._gcRun) {
|
|
380
|
+
this._gcRun = null;
|
|
381
|
+
this._shouldScheduleGC = true;
|
|
382
|
+
}
|
|
295
383
|
|
|
296
384
|
this._gcHoldCounter++;
|
|
297
385
|
|
|
298
386
|
var dispose = function dispose() {
|
|
299
|
-
if (
|
|
300
|
-
|
|
387
|
+
if (_this5._gcHoldCounter > 0) {
|
|
388
|
+
_this5._gcHoldCounter--;
|
|
301
389
|
|
|
302
|
-
if (
|
|
303
|
-
|
|
390
|
+
if (_this5._gcHoldCounter === 0 && _this5._shouldScheduleGC) {
|
|
391
|
+
_this5.scheduleGC();
|
|
304
392
|
|
|
305
|
-
|
|
393
|
+
_this5._shouldScheduleGC = false;
|
|
306
394
|
}
|
|
307
395
|
}
|
|
308
396
|
};
|
|
@@ -323,12 +411,12 @@ function () {
|
|
|
323
411
|
// latest update, or null if it was not affected.
|
|
324
412
|
;
|
|
325
413
|
|
|
326
|
-
_proto._updateSubscription = function _updateSubscription(source, subscription) {
|
|
414
|
+
_proto._updateSubscription = function _updateSubscription(source, subscription, hasUpdatedRecords) {
|
|
327
415
|
var backup = subscription.backup,
|
|
328
416
|
callback = subscription.callback,
|
|
329
417
|
snapshot = subscription.snapshot,
|
|
330
418
|
stale = subscription.stale;
|
|
331
|
-
var hasOverlappingUpdates = hasOverlappingIDs(snapshot.seenRecords, this._updatedRecordIDs);
|
|
419
|
+
var hasOverlappingUpdates = hasUpdatedRecords && hasOverlappingIDs(snapshot.seenRecords, this._updatedRecordIDs);
|
|
332
420
|
|
|
333
421
|
if (!stale && !hasOverlappingUpdates) {
|
|
334
422
|
return;
|
|
@@ -340,7 +428,8 @@ function () {
|
|
|
340
428
|
data: nextData,
|
|
341
429
|
isMissingData: nextSnapshot.isMissingData,
|
|
342
430
|
seenRecords: nextSnapshot.seenRecords,
|
|
343
|
-
selector: nextSnapshot.selector
|
|
431
|
+
selector: nextSnapshot.selector,
|
|
432
|
+
missingRequiredFields: nextSnapshot.missingRequiredFields
|
|
344
433
|
};
|
|
345
434
|
|
|
346
435
|
if (process.env.NODE_ENV !== "production") {
|
|
@@ -357,13 +446,13 @@ function () {
|
|
|
357
446
|
};
|
|
358
447
|
|
|
359
448
|
_proto.lookupInvalidationState = function lookupInvalidationState(dataIDs) {
|
|
360
|
-
var
|
|
449
|
+
var _this6 = this;
|
|
361
450
|
|
|
362
451
|
var invalidations = new Map();
|
|
363
452
|
dataIDs.forEach(function (dataID) {
|
|
364
453
|
var _RelayModernRecord$ge;
|
|
365
454
|
|
|
366
|
-
var record =
|
|
455
|
+
var record = _this6.getSource().get(dataID);
|
|
367
456
|
|
|
368
457
|
invalidations.set(dataID, (_RelayModernRecord$ge = RelayModernRecord.getInvalidationEpoch(record)) !== null && _RelayModernRecord$ge !== void 0 ? _RelayModernRecord$ge : null);
|
|
369
458
|
});
|
|
@@ -384,12 +473,11 @@ function () {
|
|
|
384
473
|
} // Check if the invalidation state for any of the ids has changed.
|
|
385
474
|
|
|
386
475
|
|
|
387
|
-
var
|
|
388
|
-
|
|
389
|
-
var _iteratorError = undefined;
|
|
476
|
+
var _iterator = _createForOfIteratorHelper(prevInvalidationState.dataIDs),
|
|
477
|
+
_step;
|
|
390
478
|
|
|
391
479
|
try {
|
|
392
|
-
for (
|
|
480
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
393
481
|
var dataID = _step.value;
|
|
394
482
|
|
|
395
483
|
if (currentInvalidations.get(dataID) !== prevInvalidations.get(dataID)) {
|
|
@@ -397,25 +485,16 @@ function () {
|
|
|
397
485
|
}
|
|
398
486
|
}
|
|
399
487
|
} catch (err) {
|
|
400
|
-
|
|
401
|
-
_iteratorError = err;
|
|
488
|
+
_iterator.e(err);
|
|
402
489
|
} finally {
|
|
403
|
-
|
|
404
|
-
if (!_iteratorNormalCompletion && _iterator["return"] != null) {
|
|
405
|
-
_iterator["return"]();
|
|
406
|
-
}
|
|
407
|
-
} finally {
|
|
408
|
-
if (_didIteratorError) {
|
|
409
|
-
throw _iteratorError;
|
|
410
|
-
}
|
|
411
|
-
}
|
|
490
|
+
_iterator.f();
|
|
412
491
|
}
|
|
413
492
|
|
|
414
493
|
return false;
|
|
415
494
|
};
|
|
416
495
|
|
|
417
496
|
_proto.subscribeToInvalidationState = function subscribeToInvalidationState(invalidationState, callback) {
|
|
418
|
-
var
|
|
497
|
+
var _this7 = this;
|
|
419
498
|
|
|
420
499
|
var subscription = {
|
|
421
500
|
callback: callback,
|
|
@@ -423,7 +502,7 @@ function () {
|
|
|
423
502
|
};
|
|
424
503
|
|
|
425
504
|
var dispose = function dispose() {
|
|
426
|
-
|
|
505
|
+
_this7._invalidationSubscriptions["delete"](subscription);
|
|
427
506
|
};
|
|
428
507
|
|
|
429
508
|
this._invalidationSubscriptions.add(subscription);
|
|
@@ -434,13 +513,13 @@ function () {
|
|
|
434
513
|
};
|
|
435
514
|
|
|
436
515
|
_proto._updateInvalidationSubscription = function _updateInvalidationSubscription(subscription, invalidatedStore) {
|
|
437
|
-
var
|
|
516
|
+
var _this8 = this;
|
|
438
517
|
|
|
439
518
|
var callback = subscription.callback,
|
|
440
519
|
invalidationState = subscription.invalidationState;
|
|
441
520
|
var dataIDs = invalidationState.dataIDs;
|
|
442
521
|
var isSubscribedToInvalidatedIDs = invalidatedStore || dataIDs.some(function (dataID) {
|
|
443
|
-
return
|
|
522
|
+
return _this8._invalidatedRecordIDs.has(dataID);
|
|
444
523
|
});
|
|
445
524
|
|
|
446
525
|
if (!isSubscribedToInvalidatedIDs) {
|
|
@@ -451,9 +530,16 @@ function () {
|
|
|
451
530
|
};
|
|
452
531
|
|
|
453
532
|
_proto.snapshot = function snapshot() {
|
|
454
|
-
var
|
|
533
|
+
var _this9 = this;
|
|
455
534
|
|
|
456
535
|
!(this._optimisticSource == null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernStore: Unexpected call to snapshot() while a previous ' + 'snapshot exists.') : invariant(false) : void 0;
|
|
536
|
+
var log = this.__log;
|
|
537
|
+
|
|
538
|
+
if (log != null) {
|
|
539
|
+
log({
|
|
540
|
+
name: 'store.snapshot'
|
|
541
|
+
});
|
|
542
|
+
}
|
|
457
543
|
|
|
458
544
|
this._subscriptions.forEach(function (subscription) {
|
|
459
545
|
// Backup occurs after writing a new "final" payload(s) and before (re)applying
|
|
@@ -474,20 +560,37 @@ function () {
|
|
|
474
560
|
}
|
|
475
561
|
|
|
476
562
|
var snapshot = subscription.snapshot;
|
|
477
|
-
var backup = RelayReader.read(
|
|
563
|
+
var backup = RelayReader.read(_this9.getSource(), snapshot.selector);
|
|
478
564
|
var nextData = recycleNodesInto(snapshot.data, backup.data);
|
|
479
565
|
backup.data = nextData; // backup owns the snapshot and can safely mutate
|
|
480
566
|
|
|
481
567
|
subscription.backup = backup;
|
|
482
568
|
});
|
|
483
569
|
|
|
570
|
+
if (this._gcRun) {
|
|
571
|
+
this._gcRun = null;
|
|
572
|
+
this._shouldScheduleGC = true;
|
|
573
|
+
}
|
|
574
|
+
|
|
484
575
|
this._optimisticSource = RelayOptimisticRecordSource.create(this.getSource());
|
|
485
576
|
};
|
|
486
577
|
|
|
487
578
|
_proto.restore = function restore() {
|
|
488
579
|
!(this._optimisticSource != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernStore: Unexpected call to restore(), expected a snapshot ' + 'to exist (make sure to call snapshot()).') : invariant(false) : void 0;
|
|
580
|
+
var log = this.__log;
|
|
581
|
+
|
|
582
|
+
if (log != null) {
|
|
583
|
+
log({
|
|
584
|
+
name: 'store.restore'
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
|
|
489
588
|
this._optimisticSource = null;
|
|
490
589
|
|
|
590
|
+
if (this._shouldScheduleGC) {
|
|
591
|
+
this.scheduleGC();
|
|
592
|
+
}
|
|
593
|
+
|
|
491
594
|
this._subscriptions.forEach(function (subscription) {
|
|
492
595
|
var backup = subscription.backup;
|
|
493
596
|
subscription.backup = null;
|
|
@@ -501,7 +604,8 @@ function () {
|
|
|
501
604
|
data: subscription.snapshot.data,
|
|
502
605
|
isMissingData: backup.isMissingData,
|
|
503
606
|
seenRecords: backup.seenRecords,
|
|
504
|
-
selector: backup.selector
|
|
607
|
+
selector: backup.selector,
|
|
608
|
+
missingRequiredFields: backup.missingRequiredFields
|
|
505
609
|
};
|
|
506
610
|
} else {
|
|
507
611
|
subscription.stale = true;
|
|
@@ -509,57 +613,90 @@ function () {
|
|
|
509
613
|
});
|
|
510
614
|
};
|
|
511
615
|
|
|
512
|
-
_proto.
|
|
513
|
-
var _this9 = this;
|
|
514
|
-
|
|
616
|
+
_proto.scheduleGC = function scheduleGC() {
|
|
515
617
|
if (this._gcHoldCounter > 0) {
|
|
516
618
|
this._shouldScheduleGC = true;
|
|
517
619
|
return;
|
|
518
620
|
}
|
|
519
621
|
|
|
520
|
-
if (this.
|
|
622
|
+
if (this._gcRun) {
|
|
521
623
|
return;
|
|
522
624
|
}
|
|
523
625
|
|
|
524
|
-
this.
|
|
525
|
-
|
|
526
|
-
this._gcScheduler(function () {
|
|
527
|
-
_this9.__gc();
|
|
626
|
+
this._gcRun = this._collect();
|
|
528
627
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
628
|
+
this._gcScheduler(this._gcStep);
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Run a full GC synchronously.
|
|
632
|
+
*/
|
|
633
|
+
;
|
|
532
634
|
|
|
533
635
|
_proto.__gc = function __gc() {
|
|
534
|
-
var _this10 = this;
|
|
535
|
-
|
|
536
636
|
// Don't run GC while there are optimistic updates applied
|
|
537
637
|
if (this._optimisticSource != null) {
|
|
538
638
|
return;
|
|
539
639
|
}
|
|
540
640
|
|
|
541
|
-
var
|
|
641
|
+
var gcRun = this._collect();
|
|
542
642
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
var selector = operation.root;
|
|
546
|
-
RelayReferenceMarker.mark(_this10._recordSource, selector, references, _this10._operationLoader);
|
|
547
|
-
});
|
|
643
|
+
while (!gcRun.next().done) {}
|
|
644
|
+
};
|
|
548
645
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
//
|
|
554
|
-
var storeIDs = this._recordSource.getRecordIDs();
|
|
646
|
+
_proto._collect = function* _collect() {
|
|
647
|
+
/* eslint-disable no-labels */
|
|
648
|
+
top: while (true) {
|
|
649
|
+
var startEpoch = this._currentWriteEpoch;
|
|
650
|
+
var references = new Set(); // Mark all records that are traversable from a root
|
|
555
651
|
|
|
556
|
-
|
|
557
|
-
|
|
652
|
+
var _iterator2 = _createForOfIteratorHelper(this._roots.values()),
|
|
653
|
+
_step2;
|
|
654
|
+
|
|
655
|
+
try {
|
|
656
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
657
|
+
var operation = _step2.value.operation;
|
|
658
|
+
var selector = operation.root;
|
|
659
|
+
RelayReferenceMarker.mark(this._recordSource, selector, references, this._operationLoader); // Yield for other work after each operation
|
|
660
|
+
|
|
661
|
+
yield; // If the store was updated, restart
|
|
662
|
+
|
|
663
|
+
if (startEpoch !== this._currentWriteEpoch) {
|
|
664
|
+
continue top;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
} catch (err) {
|
|
668
|
+
_iterator2.e(err);
|
|
669
|
+
} finally {
|
|
670
|
+
_iterator2.f();
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
var log = this.__log;
|
|
674
|
+
|
|
675
|
+
if (log != null) {
|
|
676
|
+
log({
|
|
677
|
+
name: 'store.gc',
|
|
678
|
+
references: references
|
|
679
|
+
});
|
|
680
|
+
} // Sweep records without references
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
if (references.size === 0) {
|
|
684
|
+
// Short-circuit if *nothing* is referenced
|
|
685
|
+
this._recordSource.clear();
|
|
686
|
+
} else {
|
|
687
|
+
// Evict any unreferenced nodes
|
|
688
|
+
var storeIDs = this._recordSource.getRecordIDs();
|
|
689
|
+
|
|
690
|
+
for (var ii = 0; ii < storeIDs.length; ii++) {
|
|
691
|
+
var dataID = storeIDs[ii];
|
|
558
692
|
|
|
559
|
-
|
|
560
|
-
|
|
693
|
+
if (!references.has(dataID)) {
|
|
694
|
+
this._recordSource.remove(dataID);
|
|
695
|
+
}
|
|
561
696
|
}
|
|
562
697
|
}
|
|
698
|
+
|
|
699
|
+
return;
|
|
563
700
|
}
|
|
564
701
|
};
|
|
565
702
|
|
|
@@ -575,7 +712,7 @@ function initializeRecordSource(target) {
|
|
|
575
712
|
/**
|
|
576
713
|
* Updates the target with information from source, also updating a mapping of
|
|
577
714
|
* which records in the target were changed as a result.
|
|
578
|
-
* Additionally, will
|
|
715
|
+
* Additionally, will mark records as invalidated at the current write epoch
|
|
579
716
|
* given the set of record ids marked as stale in this update.
|
|
580
717
|
*/
|
|
581
718
|
|
|
@@ -637,7 +774,11 @@ function updateTargetFromSource(target, source, currentWriteEpoch, idsMarkedForI
|
|
|
637
774
|
}
|
|
638
775
|
|
|
639
776
|
if (sourceRecord && targetRecord) {
|
|
640
|
-
|
|
777
|
+
// ReactFlightClientResponses are lazy and only materialize when readRoot
|
|
778
|
+
// is called when we read the field, so if the record is a Flight field
|
|
779
|
+
// we always use the new record's data regardless of whether
|
|
780
|
+
// it actually changed. Let React take care of reconciliation instead.
|
|
781
|
+
var nextRecord = RelayModernRecord.getType(targetRecord) === RelayStoreReactFlightUtils.REACT_FLIGHT_TYPE_NAME ? sourceRecord : RelayModernRecord.update(targetRecord, sourceRecord);
|
|
641
782
|
|
|
642
783
|
if (nextRecord !== targetRecord) {
|
|
643
784
|
// Prevent mutation of a record from outside the store.
|
|
@@ -664,7 +805,7 @@ function updateTargetFromSource(target, source, currentWriteEpoch, idsMarkedForI
|
|
|
664
805
|
/**
|
|
665
806
|
* Returns an OperationAvailability given the Availability returned
|
|
666
807
|
* by checking an operation, and when that operation was last written to the store.
|
|
667
|
-
* Specifically, the provided
|
|
808
|
+
* Specifically, the provided Availability of an operation will contain the
|
|
668
809
|
* value of when a record referenced by the operation was most recently
|
|
669
810
|
* invalidated; given that value, and given when this operation was last
|
|
670
811
|
* written to the store, this function will return the overall
|
|
@@ -672,11 +813,9 @@ function updateTargetFromSource(target, source, currentWriteEpoch, idsMarkedForI
|
|
|
672
813
|
*/
|
|
673
814
|
|
|
674
815
|
|
|
675
|
-
function
|
|
676
|
-
var
|
|
677
|
-
|
|
678
|
-
var mostRecentlyInvalidatedAt = opearionAvailability.mostRecentlyInvalidatedAt,
|
|
679
|
-
status = opearionAvailability.status;
|
|
816
|
+
function getAvailabilityStatus(operationAvailability, operationLastWrittenAt, operationFetchTime, queryCacheExpirationTime) {
|
|
817
|
+
var mostRecentlyInvalidatedAt = operationAvailability.mostRecentlyInvalidatedAt,
|
|
818
|
+
status = operationAvailability.status;
|
|
680
819
|
|
|
681
820
|
if (typeof mostRecentlyInvalidatedAt === 'number') {
|
|
682
821
|
// If some record referenced by this operation is stale, then the operation itself is stale
|
|
@@ -687,22 +826,33 @@ function getAvailablityStatus(opearionAvailability, operationLastWrittenAt, oper
|
|
|
687
826
|
status: 'stale'
|
|
688
827
|
};
|
|
689
828
|
}
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
if (status === 'missing') {
|
|
832
|
+
return {
|
|
833
|
+
status: 'missing'
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
if (operationFetchTime != null && queryCacheExpirationTime != null) {
|
|
838
|
+
var isStale = operationFetchTime <= Date.now() - queryCacheExpirationTime;
|
|
839
|
+
|
|
840
|
+
if (isStale) {
|
|
841
|
+
return {
|
|
842
|
+
status: 'stale'
|
|
843
|
+
};
|
|
844
|
+
}
|
|
690
845
|
} // There were no invalidations of any reachable records *or* the operation is known to have
|
|
691
846
|
// been fetched after the most recent record invalidation.
|
|
692
847
|
|
|
693
848
|
|
|
694
|
-
return
|
|
695
|
-
status: 'missing'
|
|
696
|
-
} : {
|
|
849
|
+
return {
|
|
697
850
|
status: 'available',
|
|
698
|
-
fetchTime:
|
|
851
|
+
fetchTime: operationFetchTime !== null && operationFetchTime !== void 0 ? operationFetchTime : null
|
|
699
852
|
};
|
|
700
853
|
}
|
|
701
854
|
|
|
702
855
|
RelayProfiler.instrumentMethods(RelayModernStore.prototype, {
|
|
703
|
-
lookup: 'RelayModernStore.prototype.lookup'
|
|
704
|
-
notify: 'RelayModernStore.prototype.notify',
|
|
705
|
-
publish: 'RelayModernStore.prototype.publish',
|
|
706
|
-
__gc: 'RelayModernStore.prototype.__gc'
|
|
856
|
+
lookup: 'RelayModernStore.prototype.lookup'
|
|
707
857
|
});
|
|
708
858
|
module.exports = RelayModernStore;
|