relay-runtime 18.1.0 → 19.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/experimental.js +1 -1
- package/experimental.js.flow +22 -9
- package/handlers/connection/ConnectionHandler.js.flow +6 -1
- package/index.js +1 -1
- package/index.js.flow +4 -0
- package/lib/experimental.js +5 -2
- package/lib/handlers/connection/ConnectionHandler.js +1 -1
- package/lib/index.js +3 -0
- package/lib/multi-actor-environment/ActorSpecificEnvironment.js +1 -1
- package/lib/mutations/RelayRecordProxy.js +14 -3
- package/lib/mutations/RelayRecordSourceMutator.js +17 -0
- package/lib/mutations/RelayRecordSourceProxy.js +2 -1
- package/lib/mutations/createUpdatableProxy.js +1 -1
- package/lib/mutations/validateMutation.js +2 -2
- package/lib/network/RelayObservable.js +1 -3
- package/lib/network/wrapNetworkWithLogObserver.js +2 -2
- package/lib/query/fetchQuery.js +1 -1
- package/lib/store/DataChecker.js +4 -5
- package/lib/store/OperationExecutor.js +11 -0
- package/lib/store/RelayModernEnvironment.js +13 -4
- package/lib/store/RelayModernFragmentSpecResolver.js +4 -4
- package/lib/store/RelayModernStore.js +43 -21
- package/lib/store/RelayPublishQueue.js +11 -15
- package/lib/store/RelayReader.js +244 -183
- package/lib/store/RelayReferenceMarker.js +3 -4
- package/lib/store/RelayResponseNormalizer.js +48 -26
- package/lib/store/RelayStoreSubscriptions.js +2 -2
- package/lib/store/RelayStoreUtils.js +8 -0
- package/lib/store/ResolverCache.js +1 -165
- package/lib/store/ResolverFragments.js +2 -2
- package/lib/store/createRelayLoggingContext.js +17 -0
- package/lib/store/generateTypenamePrefixedDataID.js +9 -0
- package/lib/store/live-resolvers/LiveResolverCache.js +5 -10
- package/lib/store/live-resolvers/resolverDataInjector.js +4 -4
- package/lib/store/observeFragmentExperimental.js +60 -13
- package/lib/store/observeQueryExperimental.js +21 -0
- package/lib/util/RelayFeatureFlags.js +7 -2
- package/lib/util/handlePotentialSnapshotErrors.js +12 -9
- package/multi-actor-environment/ActorSpecificEnvironment.js.flow +1 -0
- package/mutations/RelayRecordProxy.js.flow +30 -3
- package/mutations/RelayRecordSourceMutator.js.flow +27 -0
- package/mutations/RelayRecordSourceProxy.js.flow +4 -0
- package/mutations/createUpdatableProxy.js.flow +1 -1
- package/mutations/validateMutation.js.flow +3 -3
- package/network/RelayNetworkTypes.js.flow +3 -0
- package/network/RelayObservable.js.flow +1 -5
- package/network/wrapNetworkWithLogObserver.js.flow +19 -1
- package/package.json +1 -1
- package/query/fetchQuery.js.flow +1 -1
- package/store/DataChecker.js.flow +5 -2
- package/store/OperationExecutor.js.flow +12 -1
- package/store/RelayExperimentalGraphResponseTransform.js.flow +4 -4
- package/store/RelayModernEnvironment.js.flow +22 -6
- package/store/RelayModernFragmentSpecResolver.js.flow +6 -6
- package/store/RelayModernRecord.js.flow +1 -1
- package/store/RelayModernSelector.js.flow +2 -0
- package/store/RelayModernStore.js.flow +74 -27
- package/store/RelayOptimisticRecordSource.js.flow +2 -0
- package/store/RelayPublishQueue.js.flow +32 -21
- package/store/RelayReader.js.flow +400 -145
- package/store/RelayRecordState.js.flow +1 -1
- package/store/RelayReferenceMarker.js.flow +3 -4
- package/store/RelayResponseNormalizer.js.flow +94 -62
- package/store/RelayStoreSubscriptions.js.flow +2 -2
- package/store/RelayStoreTypes.js.flow +45 -15
- package/store/RelayStoreUtils.js.flow +30 -1
- package/store/ResolverCache.js.flow +2 -271
- package/store/ResolverFragments.js.flow +5 -3
- package/store/StoreInspector.js.flow +5 -0
- package/store/createRelayContext.js.flow +3 -2
- package/store/createRelayLoggingContext.js.flow +46 -0
- package/store/generateTypenamePrefixedDataID.js.flow +25 -0
- package/store/live-resolvers/LiveResolverCache.js.flow +5 -10
- package/store/live-resolvers/resolverDataInjector.js.flow +10 -6
- package/store/observeFragmentExperimental.js.flow +82 -28
- package/store/observeQueryExperimental.js.flow +61 -0
- package/store/waitForFragmentExperimental.js.flow +4 -3
- package/util/NormalizationNode.js.flow +10 -1
- package/util/ReaderNode.js.flow +9 -3
- package/util/RelayConcreteNode.js.flow +3 -1
- package/util/RelayError.js.flow +1 -0
- package/util/RelayFeatureFlags.js.flow +31 -7
- package/util/RelayRuntimeTypes.js.flow +17 -3
- package/util/getPaginationVariables.js.flow +2 -0
- package/util/handlePotentialSnapshotErrors.js.flow +24 -12
- package/util/registerEnvironmentWithDevTools.js.flow +4 -2
- package/util/withProvidedVariables.js.flow +1 -0
- package/util/withStartAndDuration.js.flow +3 -0
- package/relay-runtime-experimental.js +0 -4
- package/relay-runtime-experimental.min.js +0 -9
- package/relay-runtime.js +0 -4
- package/relay-runtime.min.js +0 -9
|
@@ -18,30 +18,13 @@ import type {
|
|
|
18
18
|
import type {DataID, Variables} from '../util/RelayRuntimeTypes';
|
|
19
19
|
import type {
|
|
20
20
|
DataIDSet,
|
|
21
|
-
|
|
22
|
-
MutableRecordSource,
|
|
23
|
-
Record,
|
|
21
|
+
FieldErrors,
|
|
24
22
|
SingularReaderSelector,
|
|
25
23
|
Snapshot,
|
|
26
24
|
} from './RelayStoreTypes';
|
|
27
25
|
|
|
28
|
-
const recycleNodesInto = require('../util/recycleNodesInto');
|
|
29
26
|
const {RELAY_LIVE_RESOLVER} = require('../util/RelayConcreteNode');
|
|
30
|
-
const RelayFeatureFlags = require('../util/RelayFeatureFlags');
|
|
31
|
-
const shallowFreeze = require('../util/shallowFreeze');
|
|
32
|
-
const {generateClientID} = require('./ClientID');
|
|
33
|
-
const RelayModernRecord = require('./RelayModernRecord');
|
|
34
|
-
const {
|
|
35
|
-
RELAY_RESOLVER_ERROR_KEY,
|
|
36
|
-
RELAY_RESOLVER_INVALIDATION_KEY,
|
|
37
|
-
RELAY_RESOLVER_SNAPSHOT_KEY,
|
|
38
|
-
RELAY_RESOLVER_VALUE_KEY,
|
|
39
|
-
getStorageKey,
|
|
40
|
-
} = require('./RelayStoreUtils');
|
|
41
27
|
const invariant = require('invariant');
|
|
42
|
-
const warning = require('warning');
|
|
43
|
-
|
|
44
|
-
type ResolverID = string;
|
|
45
28
|
|
|
46
29
|
export type EvaluationResult<T> = {
|
|
47
30
|
resolverResult: ?T,
|
|
@@ -52,7 +35,7 @@ export type EvaluationResult<T> = {
|
|
|
52
35
|
export type ResolverFragmentResult = {
|
|
53
36
|
data: mixed,
|
|
54
37
|
isMissingData: boolean,
|
|
55
|
-
|
|
38
|
+
fieldErrors: ?FieldErrors,
|
|
56
39
|
};
|
|
57
40
|
|
|
58
41
|
export type GetDataForResolverFragmentFn =
|
|
@@ -80,9 +63,6 @@ export interface ResolverCache {
|
|
|
80
63
|
notifyUpdatedSubscribers(updatedDataIDs: DataIDSet): void;
|
|
81
64
|
}
|
|
82
65
|
|
|
83
|
-
// $FlowFixMe[unclear-type] - will always be empty
|
|
84
|
-
const emptySet: $ReadOnlySet<any> = new Set();
|
|
85
|
-
|
|
86
66
|
class NoopResolverCache implements ResolverCache {
|
|
87
67
|
readFromCacheOrEvaluate<T>(
|
|
88
68
|
recordID: DataID,
|
|
@@ -116,255 +96,6 @@ class NoopResolverCache implements ResolverCache {
|
|
|
116
96
|
notifyUpdatedSubscribers(updatedDataIDs: DataIDSet): void {}
|
|
117
97
|
}
|
|
118
98
|
|
|
119
|
-
function addDependencyEdge(
|
|
120
|
-
edges: Map<ResolverID, Set<DataID>> | Map<DataID, Set<ResolverID>>,
|
|
121
|
-
from: ResolverID | DataID,
|
|
122
|
-
to: ResolverID | DataID,
|
|
123
|
-
): void {
|
|
124
|
-
let set = edges.get(from);
|
|
125
|
-
if (!set) {
|
|
126
|
-
set = new Set();
|
|
127
|
-
edges.set(from, set);
|
|
128
|
-
}
|
|
129
|
-
set.add(to);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
class RecordResolverCache implements ResolverCache {
|
|
133
|
-
_resolverIDToRecordIDs: Map<ResolverID, Set<DataID>>;
|
|
134
|
-
_recordIDToResolverIDs: Map<DataID, Set<ResolverID>>;
|
|
135
|
-
|
|
136
|
-
_getRecordSource: () => MutableRecordSource;
|
|
137
|
-
|
|
138
|
-
constructor(getRecordSource: () => MutableRecordSource) {
|
|
139
|
-
this._resolverIDToRecordIDs = new Map();
|
|
140
|
-
this._recordIDToResolverIDs = new Map();
|
|
141
|
-
this._getRecordSource = getRecordSource;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
readFromCacheOrEvaluate<T>(
|
|
145
|
-
recordID: DataID,
|
|
146
|
-
field: ReaderRelayResolver | ReaderRelayLiveResolver,
|
|
147
|
-
variables: Variables,
|
|
148
|
-
evaluate: () => EvaluationResult<T>,
|
|
149
|
-
getDataForResolverFragment: GetDataForResolverFragmentFn,
|
|
150
|
-
): [
|
|
151
|
-
?T /* Answer */,
|
|
152
|
-
?DataID /* Seen record */,
|
|
153
|
-
?Error,
|
|
154
|
-
?Snapshot,
|
|
155
|
-
?DataID /* ID of record containing a suspended Live field */,
|
|
156
|
-
?DataIDSet /** Set of dirty records after read */,
|
|
157
|
-
] {
|
|
158
|
-
const recordSource = this._getRecordSource();
|
|
159
|
-
|
|
160
|
-
// NOTE: Be very careful with `record` in this scope. After `evaluate` has
|
|
161
|
-
// been called, the `record` we have here may have been replaced in the
|
|
162
|
-
// Relay store with a new record containing new information about nested
|
|
163
|
-
// resolvers on this parent record.
|
|
164
|
-
const record = recordSource.get(recordID);
|
|
165
|
-
invariant(record != null, 'We expect record to exist in the store.');
|
|
166
|
-
|
|
167
|
-
const storageKey = getStorageKey(field, variables);
|
|
168
|
-
let linkedID = RelayModernRecord.getLinkedRecordID(record, storageKey);
|
|
169
|
-
let linkedRecord = linkedID == null ? null : recordSource.get(linkedID);
|
|
170
|
-
if (
|
|
171
|
-
linkedRecord == null ||
|
|
172
|
-
this._isInvalid(linkedRecord, getDataForResolverFragment)
|
|
173
|
-
) {
|
|
174
|
-
// Cache miss; evaluate the selector and store the result in a new record:
|
|
175
|
-
linkedID = linkedID ?? generateClientID(recordID, storageKey);
|
|
176
|
-
linkedRecord = RelayModernRecord.create(linkedID, '__RELAY_RESOLVER__');
|
|
177
|
-
|
|
178
|
-
const evaluationResult = evaluate();
|
|
179
|
-
shallowFreeze(evaluationResult.resolverResult);
|
|
180
|
-
RelayModernRecord.setValue(
|
|
181
|
-
linkedRecord,
|
|
182
|
-
RELAY_RESOLVER_VALUE_KEY,
|
|
183
|
-
evaluationResult.resolverResult,
|
|
184
|
-
);
|
|
185
|
-
RelayModernRecord.setValue(
|
|
186
|
-
linkedRecord,
|
|
187
|
-
RELAY_RESOLVER_SNAPSHOT_KEY,
|
|
188
|
-
evaluationResult.snapshot,
|
|
189
|
-
);
|
|
190
|
-
RelayModernRecord.setValue(
|
|
191
|
-
linkedRecord,
|
|
192
|
-
RELAY_RESOLVER_ERROR_KEY,
|
|
193
|
-
evaluationResult.error,
|
|
194
|
-
);
|
|
195
|
-
recordSource.set(linkedID, linkedRecord);
|
|
196
|
-
|
|
197
|
-
// Link the resolver value record to the resolver field of the record being read:
|
|
198
|
-
|
|
199
|
-
// Note: We get a fresh instance of the parent record from the record
|
|
200
|
-
// source, because it may have been updated when we traversed into child
|
|
201
|
-
// resolvers.
|
|
202
|
-
const currentRecord = recordSource.get(recordID);
|
|
203
|
-
invariant(
|
|
204
|
-
currentRecord != null,
|
|
205
|
-
'Expected the parent record to still be in the record source.',
|
|
206
|
-
);
|
|
207
|
-
const nextRecord = RelayModernRecord.clone(currentRecord);
|
|
208
|
-
RelayModernRecord.setLinkedRecordID(nextRecord, storageKey, linkedID);
|
|
209
|
-
recordSource.set(recordID, nextRecord);
|
|
210
|
-
|
|
211
|
-
if (field.fragment != null) {
|
|
212
|
-
// Put records observed by the resolver into the dependency graph:
|
|
213
|
-
const fragmentStorageKey = getStorageKey(field.fragment, variables);
|
|
214
|
-
const resolverID = generateClientID(recordID, fragmentStorageKey);
|
|
215
|
-
addDependencyEdge(this._resolverIDToRecordIDs, resolverID, linkedID);
|
|
216
|
-
addDependencyEdge(this._recordIDToResolverIDs, recordID, resolverID);
|
|
217
|
-
const seenRecordIds = evaluationResult.snapshot?.seenRecords;
|
|
218
|
-
if (seenRecordIds != null) {
|
|
219
|
-
for (const seenRecordID of seenRecordIds) {
|
|
220
|
-
addDependencyEdge(
|
|
221
|
-
this._recordIDToResolverIDs,
|
|
222
|
-
seenRecordID,
|
|
223
|
-
resolverID,
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// $FlowFixMe[incompatible-type] - will always be empty
|
|
231
|
-
const answer: T = RelayModernRecord.getValue(
|
|
232
|
-
linkedRecord,
|
|
233
|
-
RELAY_RESOLVER_VALUE_KEY,
|
|
234
|
-
);
|
|
235
|
-
|
|
236
|
-
// $FlowFixMe[incompatible-type] - casting mixed
|
|
237
|
-
const snapshot: ?Snapshot = RelayModernRecord.getValue(
|
|
238
|
-
linkedRecord,
|
|
239
|
-
RELAY_RESOLVER_SNAPSHOT_KEY,
|
|
240
|
-
);
|
|
241
|
-
|
|
242
|
-
// $FlowFixMe[incompatible-type] - casting mixed
|
|
243
|
-
const error: ?Error = RelayModernRecord.getValue(
|
|
244
|
-
linkedRecord,
|
|
245
|
-
RELAY_RESOLVER_ERROR_KEY,
|
|
246
|
-
);
|
|
247
|
-
|
|
248
|
-
return [answer, linkedID, error, snapshot, undefined, undefined];
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
invalidateDataIDs(
|
|
252
|
-
updatedDataIDs: Set<DataID>, // Mutated in place
|
|
253
|
-
): void {
|
|
254
|
-
const recordSource = this._getRecordSource();
|
|
255
|
-
const visited: Set<string> = new Set();
|
|
256
|
-
const recordsToVisit = Array.from(updatedDataIDs);
|
|
257
|
-
while (recordsToVisit.length) {
|
|
258
|
-
const recordID = recordsToVisit.pop();
|
|
259
|
-
// $FlowFixMe[incompatible-call]
|
|
260
|
-
updatedDataIDs.add(recordID);
|
|
261
|
-
// $FlowFixMe[incompatible-call]
|
|
262
|
-
for (const fragment of this._recordIDToResolverIDs.get(recordID) ??
|
|
263
|
-
emptySet) {
|
|
264
|
-
if (!visited.has(fragment)) {
|
|
265
|
-
for (const anotherRecordID of this._resolverIDToRecordIDs.get(
|
|
266
|
-
fragment,
|
|
267
|
-
) ?? emptySet) {
|
|
268
|
-
this._markInvalidatedResolverRecord(
|
|
269
|
-
anotherRecordID,
|
|
270
|
-
recordSource,
|
|
271
|
-
updatedDataIDs,
|
|
272
|
-
);
|
|
273
|
-
if (!visited.has(anotherRecordID)) {
|
|
274
|
-
recordsToVisit.push(anotherRecordID);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
_markInvalidatedResolverRecord(
|
|
283
|
-
dataID: DataID,
|
|
284
|
-
recordSource: MutableRecordSource, // Written to
|
|
285
|
-
updatedDataIDs: Set<DataID>, // Mutated in place
|
|
286
|
-
) {
|
|
287
|
-
const record = recordSource.get(dataID);
|
|
288
|
-
if (!record) {
|
|
289
|
-
warning(
|
|
290
|
-
false,
|
|
291
|
-
'Expected a resolver record with ID %s, but it was missing.',
|
|
292
|
-
dataID,
|
|
293
|
-
);
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
const nextRecord = RelayModernRecord.clone(record);
|
|
297
|
-
RelayModernRecord.setValue(
|
|
298
|
-
nextRecord,
|
|
299
|
-
RELAY_RESOLVER_INVALIDATION_KEY,
|
|
300
|
-
true,
|
|
301
|
-
);
|
|
302
|
-
recordSource.set(dataID, nextRecord);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
_isInvalid(
|
|
306
|
-
record: Record,
|
|
307
|
-
getDataForResolverFragment: GetDataForResolverFragmentFn,
|
|
308
|
-
): boolean {
|
|
309
|
-
if (!RelayModernRecord.getValue(record, RELAY_RESOLVER_INVALIDATION_KEY)) {
|
|
310
|
-
return false;
|
|
311
|
-
}
|
|
312
|
-
// $FlowFixMe[incompatible-type] - storing values in records is not typed
|
|
313
|
-
const snapshot: ?Snapshot = RelayModernRecord.getValue(
|
|
314
|
-
record,
|
|
315
|
-
RELAY_RESOLVER_SNAPSHOT_KEY,
|
|
316
|
-
);
|
|
317
|
-
const originalInputs = snapshot?.data;
|
|
318
|
-
const readerSelector: ?SingularReaderSelector = snapshot?.selector;
|
|
319
|
-
if (originalInputs == null || readerSelector == null) {
|
|
320
|
-
warning(
|
|
321
|
-
false,
|
|
322
|
-
'Expected previous inputs and reader selector on resolver record with ID %s, but they were missing.',
|
|
323
|
-
RelayModernRecord.getDataID(record),
|
|
324
|
-
);
|
|
325
|
-
return true;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
const {data: latestValues} = getDataForResolverFragment(readerSelector);
|
|
329
|
-
const recycled = recycleNodesInto(originalInputs, latestValues);
|
|
330
|
-
if (recycled !== originalInputs) {
|
|
331
|
-
return true;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
if (RelayFeatureFlags.MARK_RESOLVER_VALUES_AS_CLEAN_AFTER_FRAGMENT_REREAD) {
|
|
335
|
-
// This record does not need to be recomputed, we can reuse the cached value.
|
|
336
|
-
// For subsequent reads we can mark this record as "clean" so that they will
|
|
337
|
-
// not need to re-read the fragment.
|
|
338
|
-
const nextRecord = RelayModernRecord.clone(record);
|
|
339
|
-
RelayModernRecord.setValue(
|
|
340
|
-
nextRecord,
|
|
341
|
-
RELAY_RESOLVER_INVALIDATION_KEY,
|
|
342
|
-
false,
|
|
343
|
-
);
|
|
344
|
-
|
|
345
|
-
const recordSource = this._getRecordSource();
|
|
346
|
-
recordSource.set(RelayModernRecord.getDataID(record), nextRecord);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
return false;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
ensureClientRecord(id: string, typename: string): DataID {
|
|
353
|
-
invariant(
|
|
354
|
-
false,
|
|
355
|
-
'Client Edges to Client Objects are not supported in this version of Relay Store',
|
|
356
|
-
);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
notifyUpdatedSubscribers(updatedDataIDs: DataIDSet): void {
|
|
360
|
-
invariant(
|
|
361
|
-
false,
|
|
362
|
-
'Processing @outputType records is not supported in this version of Relay Store',
|
|
363
|
-
);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
99
|
module.exports = {
|
|
368
100
|
NoopResolverCache,
|
|
369
|
-
RecordResolverCache,
|
|
370
101
|
};
|
|
@@ -112,12 +112,14 @@ function readFragment(
|
|
|
112
112
|
fragmentSelector.kind === 'SingularReaderSelector',
|
|
113
113
|
`Expected a singular reader selector for the fragment of the resolver ${fragmentNode.name}, but it was plural.`,
|
|
114
114
|
);
|
|
115
|
-
const {data, isMissingData,
|
|
116
|
-
|
|
115
|
+
const {data, isMissingData, fieldErrors} = context.getDataForResolverFragment(
|
|
116
|
+
fragmentSelector,
|
|
117
|
+
fragmentKey,
|
|
118
|
+
);
|
|
117
119
|
|
|
118
120
|
if (
|
|
119
121
|
isMissingData ||
|
|
120
|
-
(
|
|
122
|
+
(fieldErrors != null && fieldErrors.some(eventShouldThrow))
|
|
121
123
|
) {
|
|
122
124
|
throw RESOLVER_FRAGMENT_ERRORED_SENTINEL;
|
|
123
125
|
}
|
|
@@ -32,11 +32,14 @@ if (__DEV__) {
|
|
|
32
32
|
}
|
|
33
33
|
formattersInstalled = true;
|
|
34
34
|
// $FlowFixMe[incompatible-use] D61394600
|
|
35
|
+
// $FlowFixMe[cannot-resolve-name]
|
|
35
36
|
if (window.devtoolsFormatters == null) {
|
|
36
37
|
// $FlowFixMe[incompatible-use] D61394600
|
|
38
|
+
// $FlowFixMe[cannot-resolve-name]
|
|
37
39
|
window.devtoolsFormatters = [];
|
|
38
40
|
}
|
|
39
41
|
// $FlowFixMe[incompatible-use] D61394600
|
|
42
|
+
// $FlowFixMe[cannot-resolve-name]
|
|
40
43
|
if (!Array.isArray(window.devtoolsFormatters)) {
|
|
41
44
|
return;
|
|
42
45
|
}
|
|
@@ -47,6 +50,7 @@ if (__DEV__) {
|
|
|
47
50
|
'section.',
|
|
48
51
|
);
|
|
49
52
|
// $FlowFixMe[incompatible-use] D61394600
|
|
53
|
+
// $FlowFixMe[cannot-resolve-name]
|
|
50
54
|
window.devtoolsFormatters.push(...createFormatters());
|
|
51
55
|
};
|
|
52
56
|
|
|
@@ -137,6 +141,7 @@ if (__DEV__) {
|
|
|
137
141
|
): ?{[string]: mixed} => {
|
|
138
142
|
const record = source.get(dataID);
|
|
139
143
|
if (record == null) {
|
|
144
|
+
// $FlowFixMe[incompatible-return]
|
|
140
145
|
return record;
|
|
141
146
|
}
|
|
142
147
|
return new Proxy(
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
14
|
import type {RelayContext} from './RelayStoreTypes.js';
|
|
15
|
+
import type {Context} from 'react';
|
|
15
16
|
import typeof {createContext} from 'react';
|
|
16
17
|
|
|
17
18
|
const invariant = require('invariant');
|
|
@@ -24,10 +25,10 @@ type React = $ReadOnly<{
|
|
|
24
25
|
...
|
|
25
26
|
}>;
|
|
26
27
|
|
|
27
|
-
let relayContext: ?
|
|
28
|
+
let relayContext: ?Context<RelayContext | null>;
|
|
28
29
|
let firstReact: ?React;
|
|
29
30
|
|
|
30
|
-
function createRelayContext(react: React):
|
|
31
|
+
function createRelayContext(react: React): Context<RelayContext | null> {
|
|
31
32
|
if (!relayContext) {
|
|
32
33
|
relayContext = react.createContext(null);
|
|
33
34
|
if (__DEV__) {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow strict-local
|
|
8
|
+
* @format
|
|
9
|
+
* @oncall relay
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
import type {Context} from 'react';
|
|
15
|
+
import typeof {createContext} from 'react';
|
|
16
|
+
|
|
17
|
+
const invariant = require('invariant');
|
|
18
|
+
|
|
19
|
+
// Ideally, we'd just import the type of the react module, but this causes Flow
|
|
20
|
+
// problems.
|
|
21
|
+
type React = $ReadOnly<{
|
|
22
|
+
createContext: createContext<mixed | null>,
|
|
23
|
+
version: string,
|
|
24
|
+
...
|
|
25
|
+
}>;
|
|
26
|
+
|
|
27
|
+
let relayLoggingContext: ?Context<mixed | null>;
|
|
28
|
+
let firstReact: ?React;
|
|
29
|
+
|
|
30
|
+
function createRelayLoggingContext(react: React): Context<mixed | null> {
|
|
31
|
+
if (!relayLoggingContext) {
|
|
32
|
+
relayLoggingContext = react.createContext(null);
|
|
33
|
+
if (__DEV__) {
|
|
34
|
+
relayLoggingContext.displayName = 'RelayLoggingContext';
|
|
35
|
+
}
|
|
36
|
+
firstReact = react;
|
|
37
|
+
}
|
|
38
|
+
invariant(
|
|
39
|
+
react === firstReact,
|
|
40
|
+
'[createRelayLoggingContext]: You are passing a different instance of React',
|
|
41
|
+
react.version,
|
|
42
|
+
);
|
|
43
|
+
return relayLoggingContext;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = createRelayLoggingContext;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow strict-local
|
|
8
|
+
* @format
|
|
9
|
+
* @oncall relay
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
import type {DataID} from 'relay-runtime/util/RelayRuntimeTypes';
|
|
15
|
+
|
|
16
|
+
const TYPENAME_PREFIX = '__type:';
|
|
17
|
+
|
|
18
|
+
function generateTypenamePrefixedDataID(
|
|
19
|
+
typeName: string,
|
|
20
|
+
dataID: DataID,
|
|
21
|
+
): DataID {
|
|
22
|
+
return `${TYPENAME_PREFIX}${typeName}:${dataID}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = {generateTypenamePrefixedDataID};
|
|
@@ -48,6 +48,7 @@ const {
|
|
|
48
48
|
RELAY_RESOLVER_OUTPUT_TYPE_RECORD_IDS,
|
|
49
49
|
RELAY_RESOLVER_SNAPSHOT_KEY,
|
|
50
50
|
RELAY_RESOLVER_VALUE_KEY,
|
|
51
|
+
getReadTimeResolverStorageKey,
|
|
51
52
|
getStorageKey,
|
|
52
53
|
} = require('../RelayStoreUtils');
|
|
53
54
|
const getOutputTypeRecordIDs = require('./getOutputTypeRecordIDs');
|
|
@@ -129,7 +130,7 @@ class LiveResolverCache implements ResolverCache {
|
|
|
129
130
|
// resolvers on this parent record.
|
|
130
131
|
const record = expectRecord(recordSource, recordID);
|
|
131
132
|
|
|
132
|
-
const storageKey =
|
|
133
|
+
const storageKey = getReadTimeResolverStorageKey(field, variables);
|
|
133
134
|
let linkedID = RelayModernRecord.getLinkedRecordID(record, storageKey);
|
|
134
135
|
let linkedRecord = linkedID == null ? null : recordSource.get(linkedID);
|
|
135
136
|
|
|
@@ -656,9 +657,7 @@ class LiveResolverCache implements ResolverCache {
|
|
|
656
657
|
while (recordsToVisit.length) {
|
|
657
658
|
// $FlowFixMe[incompatible-type] We just checked length so we know this is not undefined
|
|
658
659
|
const recordID: string = recordsToVisit.pop();
|
|
659
|
-
|
|
660
|
-
visited.add(recordID);
|
|
661
|
-
}
|
|
660
|
+
visited.add(recordID);
|
|
662
661
|
|
|
663
662
|
// $FlowFixMe[incompatible-call]
|
|
664
663
|
updatedDataIDs.add(recordID);
|
|
@@ -669,9 +668,7 @@ class LiveResolverCache implements ResolverCache {
|
|
|
669
668
|
}
|
|
670
669
|
for (const fragment of fragmentSet) {
|
|
671
670
|
if (!visited.has(fragment)) {
|
|
672
|
-
|
|
673
|
-
visited.add(fragment);
|
|
674
|
-
}
|
|
671
|
+
visited.add(fragment);
|
|
675
672
|
|
|
676
673
|
const recordSet = this._resolverIDToRecordIDs.get(fragment);
|
|
677
674
|
if (recordSet == null) {
|
|
@@ -680,9 +677,7 @@ class LiveResolverCache implements ResolverCache {
|
|
|
680
677
|
for (const anotherRecordID of recordSet) {
|
|
681
678
|
markInvalidatedResolverRecord(anotherRecordID, recordSource);
|
|
682
679
|
if (!visited.has(anotherRecordID)) {
|
|
683
|
-
|
|
684
|
-
visited.add(anotherRecordID);
|
|
685
|
-
}
|
|
680
|
+
visited.add(anotherRecordID);
|
|
686
681
|
recordsToVisit.push(anotherRecordID);
|
|
687
682
|
}
|
|
688
683
|
}
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
14
|
import type {Fragment} from '../../util/RelayRuntimeTypes';
|
|
15
|
-
import type {FragmentType} from '../RelayStoreTypes';
|
|
15
|
+
import type {FragmentType, ResolverContext} from '../RelayStoreTypes';
|
|
16
16
|
|
|
17
17
|
const {readFragment} = require('../ResolverFragments');
|
|
18
18
|
const invariant = require('invariant');
|
|
19
19
|
|
|
20
|
-
type ResolverFn = ($FlowFixMe, ?$FlowFixMe) => mixed;
|
|
20
|
+
type ResolverFn = ($FlowFixMe, ?$FlowFixMe, ResolverContext) => mixed;
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
*
|
|
@@ -40,7 +40,11 @@ function resolverDataInjector<TFragmentType: FragmentType, TData: ?{...}>(
|
|
|
40
40
|
isRequiredField?: boolean,
|
|
41
41
|
): (fragmentKey: TFragmentType, args: mixed) => mixed {
|
|
42
42
|
const resolverFn: ResolverFn = _resolverFn;
|
|
43
|
-
return (
|
|
43
|
+
return (
|
|
44
|
+
fragmentKey: TFragmentType,
|
|
45
|
+
args: mixed,
|
|
46
|
+
resolverContext: ResolverContext,
|
|
47
|
+
): mixed => {
|
|
44
48
|
const data = readFragment(fragment, fragmentKey);
|
|
45
49
|
if (fieldName != null) {
|
|
46
50
|
if (data == null) {
|
|
@@ -52,7 +56,7 @@ function resolverDataInjector<TFragmentType: FragmentType, TData: ?{...}>(
|
|
|
52
56
|
fragment.name,
|
|
53
57
|
);
|
|
54
58
|
} else {
|
|
55
|
-
return resolverFn(null, args);
|
|
59
|
+
return resolverFn(null, args, resolverContext); // TODO: This statement does not seem to be covered by a test?
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
62
|
|
|
@@ -70,7 +74,7 @@ function resolverDataInjector<TFragmentType: FragmentType, TData: ?{...}>(
|
|
|
70
74
|
}
|
|
71
75
|
|
|
72
76
|
// $FlowFixMe[invalid-computed-prop]
|
|
73
|
-
return resolverFn(data[fieldName], args);
|
|
77
|
+
return resolverFn(data[fieldName], args, resolverContext);
|
|
74
78
|
} else {
|
|
75
79
|
// If both `data` and `fieldName` is available, we expect the
|
|
76
80
|
// `fieldName` field in the `data` object.
|
|
@@ -83,7 +87,7 @@ function resolverDataInjector<TFragmentType: FragmentType, TData: ?{...}>(
|
|
|
83
87
|
}
|
|
84
88
|
} else {
|
|
85
89
|
// By default we will pass the full set of the fragment data to the resolver
|
|
86
|
-
return resolverFn(
|
|
90
|
+
return resolverFn(null, args, resolverContext); // TODO: This statement does not seem to be covered by a test?
|
|
87
91
|
}
|
|
88
92
|
};
|
|
89
93
|
}
|