relay-runtime 10.1.3 → 11.0.2

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 (106) hide show
  1. package/handlers/connection/ConnectionHandler.js.flow +60 -0
  2. package/handlers/connection/MutationHandlers.js.flow +28 -0
  3. package/index.js +1 -1
  4. package/index.js.flow +9 -3
  5. package/lib/handlers/RelayDefaultHandlerProvider.js +1 -1
  6. package/lib/handlers/connection/ConnectionHandler.js +68 -6
  7. package/lib/handlers/connection/MutationHandlers.js +67 -8
  8. package/lib/index.js +3 -0
  9. package/lib/multi-actor-environment/ActorIdentifier.js +23 -0
  10. package/lib/multi-actor-environment/ActorSpecificEnvironment.js +108 -0
  11. package/lib/multi-actor-environment/MultiActorEnvironment.js +156 -0
  12. package/lib/multi-actor-environment/MultiActorEnvironmentTypes.js +11 -0
  13. package/lib/multi-actor-environment/index.js +17 -0
  14. package/lib/mutations/RelayRecordProxy.js +1 -1
  15. package/lib/mutations/RelayRecordSourceMutator.js +1 -1
  16. package/lib/mutations/RelayRecordSourceProxy.js +1 -1
  17. package/lib/mutations/RelayRecordSourceSelectorProxy.js +1 -1
  18. package/lib/mutations/applyOptimisticMutation.js +1 -1
  19. package/lib/mutations/commitMutation.js +1 -1
  20. package/lib/mutations/validateMutation.js +36 -15
  21. package/lib/network/RelayNetwork.js +1 -1
  22. package/lib/network/RelayQueryResponseCache.js +3 -2
  23. package/lib/query/GraphQLTag.js +1 -1
  24. package/lib/query/fetchQuery.js +129 -13
  25. package/lib/query/fetchQueryInternal.js +3 -4
  26. package/lib/query/fetchQuery_DEPRECATED.js +39 -0
  27. package/lib/store/DataChecker.js +26 -14
  28. package/lib/store/{RelayModernQueryExecutor.js → OperationExecutor.js} +117 -47
  29. package/lib/store/RelayConcreteVariables.js +8 -4
  30. package/lib/store/RelayModernEnvironment.js +105 -136
  31. package/lib/store/RelayModernFragmentSpecResolver.js +16 -9
  32. package/lib/store/RelayModernRecord.js +1 -1
  33. package/lib/store/RelayModernSelector.js +1 -1
  34. package/lib/store/RelayModernStore.js +19 -20
  35. package/lib/store/RelayOperationTracker.js +55 -49
  36. package/lib/store/RelayPublishQueue.js +9 -5
  37. package/lib/store/RelayReader.js +68 -14
  38. package/lib/store/RelayReferenceMarker.js +28 -14
  39. package/lib/store/RelayResponseNormalizer.js +109 -15
  40. package/lib/store/RelayStoreReactFlightUtils.js +6 -4
  41. package/lib/store/RelayStoreSubscriptions.js +18 -8
  42. package/lib/store/RelayStoreSubscriptionsUsingMapByID.js +90 -30
  43. package/lib/store/RelayStoreUtils.js +3 -2
  44. package/lib/store/ResolverFragments.js +57 -0
  45. package/lib/store/cloneRelayHandleSourceField.js +1 -1
  46. package/lib/store/cloneRelayScalarHandleSourceField.js +1 -1
  47. package/lib/store/createFragmentSpecResolver.js +2 -2
  48. package/lib/store/createRelayContext.js +1 -1
  49. package/lib/store/defaultGetDataID.js +3 -1
  50. package/lib/store/hasOverlappingIDs.js +11 -3
  51. package/lib/store/readInlineData.js +1 -1
  52. package/lib/subscription/requestSubscription.js +33 -5
  53. package/lib/util/RelayConcreteNode.js +2 -0
  54. package/lib/util/RelayFeatureFlags.js +8 -3
  55. package/lib/util/RelayProfiler.js +17 -187
  56. package/lib/util/RelayReplaySubject.js +1 -1
  57. package/lib/util/deepFreeze.js +1 -0
  58. package/lib/util/getRelayHandleKey.js +1 -1
  59. package/lib/util/getRequestIdentifier.js +1 -1
  60. package/multi-actor-environment/ActorIdentifier.js.flow +27 -0
  61. package/multi-actor-environment/ActorSpecificEnvironment.js.flow +189 -0
  62. package/multi-actor-environment/MultiActorEnvironment.js.flow +233 -0
  63. package/multi-actor-environment/MultiActorEnvironmentTypes.js.flow +196 -0
  64. package/multi-actor-environment/index.js.flow +24 -0
  65. package/mutations/RelayRecordSourceProxy.js.flow +3 -2
  66. package/mutations/commitMutation.js.flow +1 -1
  67. package/mutations/validateMutation.js.flow +40 -15
  68. package/network/RelayNetworkTypes.js.flow +31 -11
  69. package/network/RelayQueryResponseCache.js.flow +2 -1
  70. package/package.json +3 -2
  71. package/query/fetchQuery.js.flow +147 -20
  72. package/query/fetchQueryInternal.js.flow +2 -3
  73. package/query/fetchQuery_DEPRECATED.js.flow +47 -0
  74. package/relay-runtime.js +2 -2
  75. package/relay-runtime.min.js +2 -2
  76. package/store/DataChecker.js.flow +23 -15
  77. package/store/{RelayModernQueryExecutor.js.flow → OperationExecutor.js.flow} +128 -40
  78. package/store/RelayConcreteVariables.js.flow +5 -0
  79. package/store/RelayModernEnvironment.js.flow +100 -130
  80. package/store/RelayModernFragmentSpecResolver.js.flow +30 -8
  81. package/store/RelayModernStore.js.flow +28 -24
  82. package/store/RelayOperationTracker.js.flow +69 -56
  83. package/store/RelayPublishQueue.js.flow +7 -4
  84. package/store/RelayReader.js.flow +63 -11
  85. package/store/RelayRecordSource.js.flow +3 -3
  86. package/store/RelayRecordSourceMapImpl.js.flow +6 -2
  87. package/store/RelayReferenceMarker.js.flow +28 -18
  88. package/store/RelayResponseNormalizer.js.flow +134 -23
  89. package/store/RelayStoreReactFlightUtils.js.flow +9 -4
  90. package/store/RelayStoreSubscriptions.js.flow +22 -7
  91. package/store/RelayStoreSubscriptionsUsingMapByID.js.flow +36 -12
  92. package/store/RelayStoreTypes.js.flow +51 -22
  93. package/store/RelayStoreUtils.js.flow +2 -1
  94. package/store/ResolverFragments.js.flow +125 -0
  95. package/store/createFragmentSpecResolver.js.flow +2 -0
  96. package/store/defaultGetDataID.js.flow +3 -1
  97. package/store/hasOverlappingIDs.js.flow +11 -9
  98. package/subscription/requestSubscription.js.flow +25 -2
  99. package/util/NormalizationNode.js.flow +13 -0
  100. package/util/ReaderNode.js.flow +14 -1
  101. package/util/RelayConcreteNode.js.flow +2 -0
  102. package/util/RelayFeatureFlags.js.flow +12 -2
  103. package/util/RelayProfiler.js.flow +22 -194
  104. package/util/RelayRuntimeTypes.js.flow +4 -5
  105. package/util/deepFreeze.js.flow +2 -1
  106. package/util/isEmptyObject.js.flow +1 -1
@@ -17,17 +17,17 @@ const invariant = require('invariant');
17
17
  import type {RequestDescriptor} from './RelayStoreTypes';
18
18
 
19
19
  class RelayOperationTracker {
20
- _ownersToPendingOperations: Map<RequestDescriptor, Set<RequestDescriptor>>;
21
- _pendingOperationsToOwners: Map<RequestDescriptor, Set<RequestDescriptor>>;
22
- _ownersToPromise: Map<
23
- RequestDescriptor,
20
+ _ownersToPendingOperationsIdentifier: Map<string, Set<string>>;
21
+ _pendingOperationsToOwnersIdentifier: Map<string, Set<string>>;
22
+ _ownersIdentifierToPromise: Map<
23
+ string,
24
24
  {|promise: Promise<void>, resolve: () => void|},
25
25
  >;
26
26
 
27
27
  constructor() {
28
- this._ownersToPendingOperations = new Map();
29
- this._pendingOperationsToOwners = new Map();
30
- this._ownersToPromise = new Map();
28
+ this._ownersToPendingOperationsIdentifier = new Map();
29
+ this._pendingOperationsToOwnersIdentifier = new Map();
30
+ this._ownersIdentifierToPromise = new Map();
31
31
  }
32
32
 
33
33
  /**
@@ -41,43 +41,50 @@ class RelayOperationTracker {
41
41
  if (affectedOwners.size === 0) {
42
42
  return;
43
43
  }
44
- const newlyAffectedOwners = new Set();
44
+ const pendingOperationIdentifier = pendingOperation.identifier;
45
+ const newlyAffectedOwnersIdentifier = new Set();
45
46
  for (const owner of affectedOwners) {
46
- const pendingOperationsAffectingOwner = this._ownersToPendingOperations.get(
47
- owner,
47
+ const ownerIdentifier = owner.identifier;
48
+ const pendingOperationsAffectingOwner = this._ownersToPendingOperationsIdentifier.get(
49
+ ownerIdentifier,
48
50
  );
49
51
  if (pendingOperationsAffectingOwner != null) {
50
- // In this case the `owner` already affected by some operations
52
+ // In this case the `ownerIdentifier` already affected by some operations
51
53
  // We just need to detect, is it the same operation that we already
52
54
  // have in the list, or it's a new operation
53
- if (!pendingOperationsAffectingOwner.has(pendingOperation)) {
54
- pendingOperationsAffectingOwner.add(pendingOperation);
55
- newlyAffectedOwners.add(owner);
55
+ if (!pendingOperationsAffectingOwner.has(pendingOperationIdentifier)) {
56
+ pendingOperationsAffectingOwner.add(pendingOperationIdentifier);
57
+ newlyAffectedOwnersIdentifier.add(ownerIdentifier);
56
58
  }
57
59
  } else {
58
- // This is a new `owner` that is affected by the operation
59
- this._ownersToPendingOperations.set(owner, new Set([pendingOperation]));
60
- newlyAffectedOwners.add(owner);
60
+ // This is a new `ownerIdentifier` that is affected by the operation
61
+ this._ownersToPendingOperationsIdentifier.set(
62
+ ownerIdentifier,
63
+ new Set([pendingOperationIdentifier]),
64
+ );
65
+ newlyAffectedOwnersIdentifier.add(ownerIdentifier);
61
66
  }
62
67
  }
63
68
 
64
69
  // No new owners were affected by this operation, we may stop here
65
- if (newlyAffectedOwners.size === 0) {
70
+ if (newlyAffectedOwnersIdentifier.size === 0) {
66
71
  return;
67
72
  }
68
73
 
69
74
  // But, if some owners were affected we need to add them to
70
- // the `_pendingOperationsToOwners` set
71
- const ownersAffectedByOperation =
72
- this._pendingOperationsToOwners.get(pendingOperation) || new Set();
73
-
74
- for (const owner of newlyAffectedOwners) {
75
- this._resolveOwnerResolvers(owner);
76
- ownersAffectedByOperation.add(owner);
75
+ // the `_pendingOperationsToOwnersIdentifier` set
76
+ const ownersAffectedByOperationIdentifier =
77
+ this._pendingOperationsToOwnersIdentifier.get(
78
+ pendingOperationIdentifier,
79
+ ) || new Set();
80
+
81
+ for (const ownerIdentifier of newlyAffectedOwnersIdentifier) {
82
+ this._resolveOwnerResolvers(ownerIdentifier);
83
+ ownersAffectedByOperationIdentifier.add(ownerIdentifier);
77
84
  }
78
- this._pendingOperationsToOwners.set(
79
- pendingOperation,
80
- ownersAffectedByOperation,
85
+ this._pendingOperationsToOwnersIdentifier.set(
86
+ pendingOperationIdentifier,
87
+ ownersAffectedByOperationIdentifier,
81
88
  );
82
89
  }
83
90
 
@@ -86,64 +93,70 @@ class RelayOperationTracker {
86
93
  * from all tracking maps
87
94
  */
88
95
  complete(pendingOperation: RequestDescriptor): void {
89
- const affectedOwners = this._pendingOperationsToOwners.get(
90
- pendingOperation,
96
+ const pendingOperationIdentifier = pendingOperation.identifier;
97
+ const affectedOwnersIdentifier = this._pendingOperationsToOwnersIdentifier.get(
98
+ pendingOperationIdentifier,
91
99
  );
92
- if (affectedOwners == null) {
100
+ if (affectedOwnersIdentifier == null) {
93
101
  return;
94
102
  }
95
- // These were the owners affected only by `pendingOperation`
96
- const completedOwners = new Set();
103
+ // These were the owners affected only by `pendingOperationIdentifier`
104
+ const completedOwnersIdentifier = new Set();
97
105
 
98
- // These were the owners affected by `pendingOperation`
106
+ // These were the owners affected by `pendingOperationIdentifier`
99
107
  // and some other operations
100
- const updatedOwners = new Set();
101
- for (const owner of affectedOwners) {
102
- const pendingOperationsAffectingOwner = this._ownersToPendingOperations.get(
103
- owner,
108
+ const updatedOwnersIdentifier = new Set();
109
+ for (const ownerIdentifier of affectedOwnersIdentifier) {
110
+ const pendingOperationsAffectingOwner = this._ownersToPendingOperationsIdentifier.get(
111
+ ownerIdentifier,
104
112
  );
105
113
  if (!pendingOperationsAffectingOwner) {
106
114
  continue;
107
115
  }
108
- pendingOperationsAffectingOwner.delete(pendingOperation);
116
+ pendingOperationsAffectingOwner.delete(pendingOperationIdentifier);
109
117
  if (pendingOperationsAffectingOwner.size > 0) {
110
- updatedOwners.add(owner);
118
+ updatedOwnersIdentifier.add(ownerIdentifier);
111
119
  } else {
112
- completedOwners.add(owner);
120
+ completedOwnersIdentifier.add(ownerIdentifier);
113
121
  }
114
122
  }
115
123
 
116
- // Complete subscriptions for all owners, affected by `pendingOperation`
117
- for (const owner of completedOwners) {
118
- this._resolveOwnerResolvers(owner);
119
- this._ownersToPendingOperations.delete(owner);
124
+ // Complete subscriptions for all owners, affected by `pendingOperationIdentifier`
125
+ for (const ownerIdentifier of completedOwnersIdentifier) {
126
+ this._resolveOwnerResolvers(ownerIdentifier);
127
+ this._ownersToPendingOperationsIdentifier.delete(ownerIdentifier);
120
128
  }
121
129
 
122
- // Update all owner that were updated by `pendingOperation` but still
130
+ // Update all ownerIdentifier that were updated by `pendingOperationIdentifier` but still
123
131
  // are affected by other operations
124
- for (const owner of updatedOwners) {
125
- this._resolveOwnerResolvers(owner);
132
+ for (const ownerIdentifier of updatedOwnersIdentifier) {
133
+ this._resolveOwnerResolvers(ownerIdentifier);
126
134
  }
127
135
 
128
- // Finally, remove pending operation
129
- this._pendingOperationsToOwners.delete(pendingOperation);
136
+ // Finally, remove pending operation identifier
137
+ this._pendingOperationsToOwnersIdentifier.delete(
138
+ pendingOperationIdentifier,
139
+ );
130
140
  }
131
141
 
132
- _resolveOwnerResolvers(owner: RequestDescriptor): void {
133
- const promiseEntry = this._ownersToPromise.get(owner);
142
+ _resolveOwnerResolvers(ownerIdentifier: string): void {
143
+ const promiseEntry = this._ownersIdentifierToPromise.get(ownerIdentifier);
134
144
  if (promiseEntry != null) {
135
145
  promiseEntry.resolve();
136
146
  }
137
- this._ownersToPromise.delete(owner);
147
+ this._ownersIdentifierToPromise.delete(ownerIdentifier);
138
148
  }
139
149
 
140
150
  getPromiseForPendingOperationsAffectingOwner(
141
151
  owner: RequestDescriptor,
142
152
  ): Promise<void> | null {
143
- if (!this._ownersToPendingOperations.has(owner)) {
153
+ const ownerIdentifier = owner.identifier;
154
+ if (!this._ownersToPendingOperationsIdentifier.has(ownerIdentifier)) {
144
155
  return null;
145
156
  }
146
- const cachedPromiseEntry = this._ownersToPromise.get(owner);
157
+ const cachedPromiseEntry = this._ownersIdentifierToPromise.get(
158
+ ownerIdentifier,
159
+ );
147
160
  if (cachedPromiseEntry != null) {
148
161
  return cachedPromiseEntry.promise;
149
162
  }
@@ -156,7 +169,7 @@ class RelayOperationTracker {
156
169
  'RelayOperationTracker: Expected resolver to be defined. If you' +
157
170
  'are seeing this, it is likely a bug in Relay.',
158
171
  );
159
- this._ownersToPromise.set(owner, {promise, resolve});
172
+ this._ownersIdentifierToPromise.set(ownerIdentifier, {promise, resolve});
160
173
  return promise;
161
174
  }
162
175
  }
@@ -12,7 +12,6 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- const ErrorUtils = require('ErrorUtils');
16
15
  const RelayReader = require('./RelayReader');
17
16
  const RelayRecordSource = require('./RelayRecordSource');
18
17
  const RelayRecordSourceMutator = require('../mutations/RelayRecordSourceMutator');
@@ -55,6 +54,10 @@ type PendingUpdater = {|
55
54
  +updater: StoreUpdater,
56
55
  |};
57
56
 
57
+ const applyWithGuard =
58
+ global.ErrorUtils?.applyWithGuard ??
59
+ ((callback, context, args, onError, name) => callback.apply(context, args));
60
+
58
61
  /**
59
62
  * Coordinates the concurrent modification of a `Store` due to optimistic and
60
63
  * non-revertable client updates and server payloads:
@@ -299,7 +302,7 @@ class RelayPublishQueue implements PublishQueue {
299
302
  mutator,
300
303
  this._getDataID,
301
304
  );
302
- ErrorUtils.applyWithGuard(
305
+ applyWithGuard(
303
306
  updater,
304
307
  null,
305
308
  [recordSourceProxy],
@@ -334,7 +337,7 @@ class RelayPublishQueue implements PublishQueue {
334
337
  const processUpdate = optimisticUpdate => {
335
338
  if (optimisticUpdate.storeUpdater) {
336
339
  const {storeUpdater} = optimisticUpdate;
337
- ErrorUtils.applyWithGuard(
340
+ applyWithGuard(
338
341
  storeUpdater,
339
342
  null,
340
343
  [recordSourceProxy],
@@ -355,7 +358,7 @@ class RelayPublishQueue implements PublishQueue {
355
358
  selectorData = lookupSelector(source, operation.fragment);
356
359
  }
357
360
  if (updater) {
358
- ErrorUtils.applyWithGuard(
361
+ applyWithGuard(
359
362
  updater,
360
363
  null,
361
364
  [recordSourceSelectorProxy, selectorData],
@@ -28,6 +28,7 @@ const {
28
28
  LINKED_FIELD,
29
29
  MODULE_IMPORT,
30
30
  REQUIRED_FIELD,
31
+ RELAY_RESOLVER,
31
32
  SCALAR_FIELD,
32
33
  STREAM,
33
34
  } = require('../util/RelayConcreteNode');
@@ -44,15 +45,18 @@ const {
44
45
  getStorageKey,
45
46
  getModuleComponentKey,
46
47
  } = require('./RelayStoreUtils');
48
+ const {withResolverContext} = require('./ResolverFragments');
47
49
  const {generateTypeID} = require('./TypeID');
48
50
 
49
51
  import type {
50
52
  ReaderFlightField,
53
+ ReaderFragment,
51
54
  ReaderFragmentSpread,
52
55
  ReaderInlineDataFragmentSpread,
53
56
  ReaderLinkedField,
54
57
  ReaderModuleImport,
55
58
  ReaderNode,
59
+ ReaderRelayResolver,
56
60
  ReaderRequiredField,
57
61
  ReaderScalarField,
58
62
  ReaderSelection,
@@ -66,6 +70,7 @@ import type {
66
70
  SingularReaderSelector,
67
71
  Snapshot,
68
72
  MissingRequiredFields,
73
+ DataIDSet,
69
74
  } from './RelayStoreTypes';
70
75
 
71
76
  function read(
@@ -85,7 +90,7 @@ class RelayReader {
85
90
  _missingRequiredFields: ?MissingRequiredFields;
86
91
  _owner: RequestDescriptor;
87
92
  _recordSource: RecordSource;
88
- _seenRecords: {[dataID: DataID]: ?Record, ...};
93
+ _seenRecords: DataIDSet;
89
94
  _selector: SingularReaderSelector;
90
95
  _variables: Variables;
91
96
 
@@ -95,7 +100,7 @@ class RelayReader {
95
100
  this._missingRequiredFields = null;
96
101
  this._owner = selector.owner;
97
102
  this._recordSource = recordSource;
98
- this._seenRecords = {};
103
+ this._seenRecords = new Set();
99
104
  this._selector = selector;
100
105
  this._variables = selector.variables;
101
106
  }
@@ -169,7 +174,7 @@ class RelayReader {
169
174
  prevData: ?SelectorData,
170
175
  ): ?SelectorData {
171
176
  const record = this._recordSource.get(dataID);
172
- this._seenRecords[dataID] = record;
177
+ this._seenRecords.add(dataID);
173
178
  if (record == null) {
174
179
  if (record === undefined) {
175
180
  this._isMissingData = true;
@@ -191,6 +196,7 @@ class RelayReader {
191
196
  'RelayReader(): Undefined variable `%s`.',
192
197
  name,
193
198
  );
199
+ // $FlowFixMe[cannot-write]
194
200
  return this._variables[name];
195
201
  }
196
202
 
@@ -325,6 +331,13 @@ class RelayReader {
325
331
  }
326
332
  break;
327
333
  }
334
+ case RELAY_RESOLVER: {
335
+ if (!RelayFeatureFlags.ENABLE_RELAY_RESOLVERS) {
336
+ throw new Error('Relay Resolver fields are not yet supported.');
337
+ }
338
+ this._readResolverField(selection, record, data);
339
+ break;
340
+ }
328
341
  case FRAGMENT_SPREAD:
329
342
  this._createFragmentPointer(selection, record, data);
330
343
  break;
@@ -332,7 +345,11 @@ class RelayReader {
332
345
  this._readModuleImport(selection, record, data);
333
346
  break;
334
347
  case INLINE_DATA_FRAGMENT_SPREAD:
335
- this._createInlineDataFragmentPointer(selection, record, data);
348
+ this._createInlineDataOrResolverFragmentPointer(
349
+ selection,
350
+ record,
351
+ data,
352
+ );
336
353
  break;
337
354
  case DEFER:
338
355
  case CLIENT_EXTENSION: {
@@ -402,6 +419,43 @@ class RelayReader {
402
419
  }
403
420
  }
404
421
 
422
+ _readResolverField(
423
+ selection: ReaderRelayResolver,
424
+ record: Record,
425
+ data: SelectorData,
426
+ ): ?mixed {
427
+ const {name, alias, resolverModule, fragment} = selection;
428
+ const key = {
429
+ __id: RelayModernRecord.getDataID(record),
430
+ __fragmentOwner: this._owner,
431
+ __fragments: {
432
+ [fragment.name]: {}, // Arguments to this fragment; not yet supported.
433
+ },
434
+ };
435
+ const resolverContext = {
436
+ getDataForResolverFragment: singularReaderSelector => {
437
+ const resolverFragmentData = {};
438
+ this._createInlineDataOrResolverFragmentPointer(
439
+ singularReaderSelector.node,
440
+ record,
441
+ resolverFragmentData,
442
+ );
443
+ const answer = resolverFragmentData[FRAGMENTS_KEY]?.[fragment.name];
444
+ invariant(
445
+ typeof answer === 'object' && answer !== null,
446
+ `Expected reader data to contain a __fragments property with a property for the fragment named ${fragment.name}, but it is missing.`,
447
+ );
448
+ return answer;
449
+ },
450
+ };
451
+ const resolverResult = withResolverContext(resolverContext, () =>
452
+ // $FlowFixMe[prop-missing] - resolver module's type signature is a lie
453
+ resolverModule(key),
454
+ );
455
+ data[alias ?? name] = resolverResult;
456
+ return resolverResult;
457
+ }
458
+
405
459
  _readFlightField(
406
460
  field: ReaderFlightField,
407
461
  record: Record,
@@ -423,9 +477,7 @@ class RelayReader {
423
477
  const reactFlightClientResponseRecord = this._recordSource.get(
424
478
  reactFlightClientResponseRecordID,
425
479
  );
426
- this._seenRecords[
427
- reactFlightClientResponseRecordID
428
- ] = reactFlightClientResponseRecord;
480
+ this._seenRecords.add(reactFlightClientResponseRecordID);
429
481
  if (reactFlightClientResponseRecord == null) {
430
482
  data[applicationName] = reactFlightClientResponseRecord;
431
483
  if (reactFlightClientResponseRecord === undefined) {
@@ -607,8 +659,8 @@ class RelayReader {
607
659
  }
608
660
  }
609
661
 
610
- _createInlineDataFragmentPointer(
611
- inlineDataFragmentSpread: ReaderInlineDataFragmentSpread,
662
+ _createInlineDataOrResolverFragmentPointer(
663
+ fragmentSpreadOrFragment: ReaderInlineDataFragmentSpread | ReaderFragment,
612
664
  record: Record,
613
665
  data: SelectorData,
614
666
  ): void {
@@ -626,12 +678,12 @@ class RelayReader {
626
678
  }
627
679
  const inlineData = {};
628
680
  this._traverseSelections(
629
- inlineDataFragmentSpread.selections,
681
+ fragmentSpreadOrFragment.selections,
630
682
  record,
631
683
  inlineData,
632
684
  );
633
685
  // $FlowFixMe[cannot-write] - writing into read-only field
634
- fragmentPointers[inlineDataFragmentSpread.name] = inlineData;
686
+ fragmentPointers[fragmentSpreadOrFragment.name] = inlineData;
635
687
  }
636
688
  }
637
689
 
@@ -14,14 +14,14 @@
14
14
 
15
15
  const RelayRecordSourceMapImpl = require('./RelayRecordSourceMapImpl');
16
16
 
17
- import type {MutableRecordSource, RecordMap} from './RelayStoreTypes';
17
+ import type {MutableRecordSource, RecordObjectMap} from './RelayStoreTypes';
18
18
 
19
19
  class RelayRecordSource {
20
- constructor(records?: RecordMap): MutableRecordSource {
20
+ constructor(records?: RecordObjectMap): MutableRecordSource {
21
21
  return RelayRecordSource.create(records);
22
22
  }
23
23
 
24
- static create(records?: RecordMap): MutableRecordSource {
24
+ static create(records?: RecordObjectMap): MutableRecordSource {
25
25
  return new RelayRecordSourceMapImpl(records);
26
26
  }
27
27
  }
@@ -16,7 +16,11 @@ const RelayRecordState = require('./RelayRecordState');
16
16
 
17
17
  import type {DataID} from '../util/RelayRuntimeTypes';
18
18
  import type {RecordState} from './RelayRecordState';
19
- import type {MutableRecordSource, Record, RecordMap} from './RelayStoreTypes';
19
+ import type {
20
+ MutableRecordSource,
21
+ Record,
22
+ RecordObjectMap,
23
+ } from './RelayStoreTypes';
20
24
 
21
25
  const {EXISTENT, NONEXISTENT, UNKNOWN} = RelayRecordState;
22
26
 
@@ -27,7 +31,7 @@ const {EXISTENT, NONEXISTENT, UNKNOWN} = RelayRecordState;
27
31
  class RelayMapRecordSourceMapImpl implements MutableRecordSource {
28
32
  _records: Map<DataID, ?Record>;
29
33
 
30
- constructor(records?: RecordMap) {
34
+ constructor(records?: RecordObjectMap) {
31
35
  this._records = new Map();
32
36
  if (records != null) {
33
37
  Object.keys(records).forEach(key => {
@@ -24,7 +24,6 @@ const invariant = require('invariant');
24
24
 
25
25
  const {generateTypeID} = require('./TypeID');
26
26
 
27
- import type {ReactFlightPayloadQuery} from '../network/RelayNetworkTypes';
28
27
  import type {
29
28
  NormalizationFlightField,
30
29
  NormalizationLinkedField,
@@ -34,14 +33,17 @@ import type {
34
33
  } from '../util/NormalizationNode';
35
34
  import type {DataID, Variables} from '../util/RelayRuntimeTypes';
36
35
  import type {
36
+ DataIDSet,
37
37
  NormalizationSelector,
38
38
  OperationLoader,
39
39
  Record,
40
40
  RecordSource,
41
+ ReactFlightReachableExecutableDefinitions,
41
42
  } from './RelayStoreTypes';
42
43
 
43
44
  const {
44
45
  CONDITION,
46
+ CLIENT_COMPONENT,
45
47
  CLIENT_EXTENSION,
46
48
  DEFER,
47
49
  FLIGHT_FIELD,
@@ -60,8 +62,9 @@ const {ROOT_ID, getStorageKey, getModuleOperationKey} = RelayStoreUtils;
60
62
  function mark(
61
63
  recordSource: RecordSource,
62
64
  selector: NormalizationSelector,
63
- references: Set<DataID>,
65
+ references: DataIDSet,
64
66
  operationLoader: ?OperationLoader,
67
+ shouldProcessClientComponents: ?boolean,
65
68
  ): void {
66
69
  const {dataID, node, variables} = selector;
67
70
  const marker = new RelayReferenceMarker(
@@ -69,6 +72,7 @@ function mark(
69
72
  variables,
70
73
  references,
71
74
  operationLoader,
75
+ shouldProcessClientComponents,
72
76
  );
73
77
  marker.mark(node, dataID);
74
78
  }
@@ -80,20 +84,23 @@ class RelayReferenceMarker {
80
84
  _operationLoader: OperationLoader | null;
81
85
  _operationName: ?string;
82
86
  _recordSource: RecordSource;
83
- _references: Set<DataID>;
87
+ _references: DataIDSet;
84
88
  _variables: Variables;
89
+ _shouldProcessClientComponents: ?boolean;
85
90
 
86
91
  constructor(
87
92
  recordSource: RecordSource,
88
93
  variables: Variables,
89
- references: Set<DataID>,
94
+ references: DataIDSet,
90
95
  operationLoader: ?OperationLoader,
96
+ shouldProcessClientComponents: ?boolean,
91
97
  ) {
92
98
  this._operationLoader = operationLoader ?? null;
93
99
  this._operationName = null;
94
100
  this._recordSource = recordSource;
95
101
  this._references = references;
96
102
  this._variables = variables;
103
+ this._shouldProcessClientComponents = shouldProcessClientComponents;
97
104
  }
98
105
 
99
106
  mark(node: NormalizationNode, dataID: DataID): void {
@@ -118,6 +125,7 @@ class RelayReferenceMarker {
118
125
  'RelayReferenceMarker(): Undefined variable `%s`.',
119
126
  name,
120
127
  );
128
+ // $FlowFixMe[cannot-write]
121
129
  return this._variables[name];
122
130
  }
123
131
 
@@ -158,12 +166,8 @@ class RelayReferenceMarker {
158
166
  break;
159
167
  // $FlowFixMe[incompatible-type]
160
168
  case FRAGMENT_SPREAD:
161
- invariant(
162
- false,
163
- 'RelayReferenceMarker(): Unexpected fragment spread `...%s`, ' +
164
- 'expected all fragments to be inlined.',
165
- selection.name,
166
- );
169
+ this._traverseSelections(selection.fragment.selections, record);
170
+ break;
167
171
  case LINKED_HANDLE:
168
172
  // The selections for a "handle" field are the same as those of the
169
173
  // original linked field where the handle was applied. Reference marking
@@ -213,6 +217,12 @@ class RelayReferenceMarker {
213
217
  throw new Error('Flight fields are not yet supported.');
214
218
  }
215
219
  break;
220
+ case CLIENT_COMPONENT:
221
+ if (this._shouldProcessClientComponents === false) {
222
+ break;
223
+ }
224
+ this._traverseSelections(selection.fragment.selections, record);
225
+ break;
216
226
  default:
217
227
  (selection: empty);
218
228
  invariant(
@@ -289,12 +299,12 @@ class RelayReferenceMarker {
289
299
  return;
290
300
  }
291
301
 
292
- const reachableQueries = RelayModernRecord.getValue(
302
+ const reachableExecutableDefinitions = RelayModernRecord.getValue(
293
303
  reactFlightClientResponseRecord,
294
- RelayStoreReactFlightUtils.REACT_FLIGHT_QUERIES_STORAGE_KEY,
304
+ RelayStoreReactFlightUtils.REACT_FLIGHT_EXECUTABLE_DEFINITIONS_STORAGE_KEY,
295
305
  );
296
306
 
297
- if (!Array.isArray(reachableQueries)) {
307
+ if (!Array.isArray(reachableExecutableDefinitions)) {
298
308
  return;
299
309
  }
300
310
 
@@ -304,13 +314,13 @@ class RelayReferenceMarker {
304
314
  'DataChecker: Expected an operationLoader to be configured when using ' +
305
315
  'React Flight',
306
316
  );
307
- // In Flight, the variables that are in scope for reachable queries aren't
308
- // the same as what's in scope for the outer query.
317
+ // In Flight, the variables that are in scope for reachable executable
318
+ // definitions aren't the same as what's in scope for the outer query.
309
319
  const prevVariables = this._variables;
310
320
  // $FlowFixMe[incompatible-cast]
311
- for (const query of (reachableQueries: Array<ReactFlightPayloadQuery>)) {
312
- this._variables = query.variables;
313
- const operationReference = query.module;
321
+ for (const definition of (reachableExecutableDefinitions: Array<ReactFlightReachableExecutableDefinitions>)) {
322
+ this._variables = definition.variables;
323
+ const operationReference = definition.module;
314
324
  const normalizationRootNode = operationLoader.get(operationReference);
315
325
  if (normalizationRootNode != null) {
316
326
  const operation = getOperation(normalizationRootNode);