relay-runtime 11.0.0 → 13.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/handlers/RelayDefaultHandlerProvider.js.flow +2 -2
  2. package/handlers/connection/ConnectionHandler.js.flow +8 -10
  3. package/handlers/connection/MutationHandlers.js.flow +31 -7
  4. package/index.js +1 -1
  5. package/index.js.flow +60 -36
  6. package/lib/handlers/RelayDefaultHandlerProvider.js +1 -1
  7. package/lib/handlers/connection/ConnectionHandler.js +8 -8
  8. package/lib/handlers/connection/MutationHandlers.js +61 -5
  9. package/lib/index.js +58 -43
  10. package/lib/multi-actor-environment/ActorIdentifier.js +33 -0
  11. package/lib/multi-actor-environment/ActorSpecificEnvironment.js +152 -0
  12. package/lib/multi-actor-environment/ActorUtils.js +27 -0
  13. package/lib/multi-actor-environment/MultiActorEnvironment.js +419 -0
  14. package/lib/multi-actor-environment/MultiActorEnvironmentTypes.js +11 -0
  15. package/lib/multi-actor-environment/index.js +21 -0
  16. package/lib/mutations/RelayDeclarativeMutationConfig.js +4 -1
  17. package/lib/mutations/RelayRecordProxy.js +3 -2
  18. package/lib/mutations/RelayRecordSourceMutator.js +3 -2
  19. package/lib/mutations/RelayRecordSourceProxy.js +12 -4
  20. package/lib/mutations/RelayRecordSourceSelectorProxy.js +18 -5
  21. package/lib/mutations/applyOptimisticMutation.js +6 -6
  22. package/lib/mutations/commitMutation.js +14 -10
  23. package/lib/mutations/readUpdatableQuery_EXPERIMENTAL.js +238 -0
  24. package/lib/mutations/validateMutation.js +12 -5
  25. package/lib/network/ConvertToExecuteFunction.js +2 -1
  26. package/lib/network/RelayNetwork.js +3 -2
  27. package/lib/network/RelayQueryResponseCache.js +21 -4
  28. package/lib/network/wrapNetworkWithLogObserver.js +79 -0
  29. package/lib/query/GraphQLTag.js +3 -2
  30. package/lib/query/fetchQuery.js +6 -5
  31. package/lib/query/fetchQueryInternal.js +1 -1
  32. package/lib/query/fetchQuery_DEPRECATED.js +2 -1
  33. package/lib/store/ClientID.js +7 -1
  34. package/lib/store/DataChecker.js +141 -60
  35. package/lib/store/{RelayModernQueryExecutor.js → OperationExecutor.js} +532 -195
  36. package/lib/store/RelayConcreteVariables.js +24 -4
  37. package/lib/store/RelayModernEnvironment.js +175 -234
  38. package/lib/store/RelayModernFragmentSpecResolver.js +52 -26
  39. package/lib/store/RelayModernOperationDescriptor.js +2 -1
  40. package/lib/store/RelayModernRecord.js +47 -12
  41. package/lib/store/RelayModernSelector.js +14 -8
  42. package/lib/store/RelayModernStore.js +58 -29
  43. package/lib/store/RelayOperationTracker.js +34 -24
  44. package/lib/store/RelayPublishQueue.js +41 -13
  45. package/lib/store/RelayReader.js +287 -46
  46. package/lib/store/RelayRecordSource.js +87 -3
  47. package/lib/store/RelayReferenceMarker.js +55 -31
  48. package/lib/store/RelayResponseNormalizer.js +250 -108
  49. package/lib/store/RelayStoreReactFlightUtils.js +8 -12
  50. package/lib/store/RelayStoreSubscriptions.js +14 -9
  51. package/lib/store/RelayStoreUtils.js +11 -5
  52. package/lib/store/ResolverCache.js +213 -0
  53. package/lib/store/ResolverFragments.js +61 -0
  54. package/lib/store/cloneRelayHandleSourceField.js +5 -4
  55. package/lib/store/cloneRelayScalarHandleSourceField.js +5 -4
  56. package/lib/store/createRelayContext.js +4 -2
  57. package/lib/store/defaultGetDataID.js +3 -1
  58. package/lib/store/readInlineData.js +6 -2
  59. package/lib/subscription/requestSubscription.js +35 -9
  60. package/lib/util/RelayConcreteNode.js +4 -0
  61. package/lib/util/RelayFeatureFlags.js +11 -4
  62. package/lib/util/RelayProfiler.js +17 -187
  63. package/lib/util/RelayReplaySubject.js +22 -7
  64. package/lib/util/RelayRuntimeTypes.js +0 -6
  65. package/lib/util/StringInterner.js +71 -0
  66. package/lib/util/deepFreeze.js +1 -0
  67. package/lib/util/getFragmentIdentifier.js +15 -7
  68. package/lib/util/getOperation.js +2 -1
  69. package/lib/util/getPaginationMetadata.js +41 -0
  70. package/lib/util/getPaginationVariables.js +66 -0
  71. package/lib/util/getPendingOperationsForFragment.js +55 -0
  72. package/lib/util/getRefetchMetadata.js +36 -0
  73. package/lib/util/getRelayHandleKey.js +2 -2
  74. package/lib/util/getRequestIdentifier.js +2 -2
  75. package/lib/util/getValueAtPath.js +51 -0
  76. package/lib/util/isEmptyObject.js +1 -1
  77. package/lib/util/registerEnvironmentWithDevTools.js +26 -0
  78. package/lib/util/withDuration.js +31 -0
  79. package/multi-actor-environment/ActorIdentifier.js.flow +43 -0
  80. package/multi-actor-environment/ActorSpecificEnvironment.js.flow +225 -0
  81. package/multi-actor-environment/ActorUtils.js.flow +33 -0
  82. package/multi-actor-environment/MultiActorEnvironment.js.flow +506 -0
  83. package/multi-actor-environment/MultiActorEnvironmentTypes.js.flow +261 -0
  84. package/multi-actor-environment/index.js.flow +26 -0
  85. package/mutations/RelayDeclarativeMutationConfig.js.flow +32 -26
  86. package/mutations/RelayRecordProxy.js.flow +4 -5
  87. package/mutations/RelayRecordSourceMutator.js.flow +4 -6
  88. package/mutations/RelayRecordSourceProxy.js.flow +19 -10
  89. package/mutations/RelayRecordSourceSelectorProxy.js.flow +22 -7
  90. package/mutations/applyOptimisticMutation.js.flow +13 -14
  91. package/mutations/commitLocalUpdate.js.flow +1 -1
  92. package/mutations/commitMutation.js.flow +35 -46
  93. package/mutations/readUpdatableQuery_EXPERIMENTAL.js.flow +309 -0
  94. package/mutations/validateMutation.js.flow +28 -16
  95. package/network/ConvertToExecuteFunction.js.flow +2 -2
  96. package/network/RelayNetwork.js.flow +4 -5
  97. package/network/RelayNetworkTypes.js.flow +17 -8
  98. package/network/RelayObservable.js.flow +1 -1
  99. package/network/RelayQueryResponseCache.js.flow +34 -20
  100. package/network/wrapNetworkWithLogObserver.js.flow +100 -0
  101. package/package.json +3 -2
  102. package/query/GraphQLTag.js.flow +9 -9
  103. package/query/PreloadableQueryRegistry.js.flow +2 -1
  104. package/query/fetchQuery.js.flow +11 -13
  105. package/query/fetchQueryInternal.js.flow +6 -9
  106. package/query/fetchQuery_DEPRECATED.js.flow +6 -6
  107. package/relay-runtime.js +2 -2
  108. package/relay-runtime.min.js +2 -2
  109. package/store/ClientID.js.flow +14 -3
  110. package/store/DataChecker.js.flow +162 -67
  111. package/store/{RelayModernQueryExecutor.js.flow → OperationExecutor.js.flow} +616 -283
  112. package/store/RelayConcreteVariables.js.flow +27 -5
  113. package/store/RelayModernEnvironment.js.flow +176 -235
  114. package/store/RelayModernFragmentSpecResolver.js.flow +55 -31
  115. package/store/RelayModernOperationDescriptor.js.flow +12 -7
  116. package/store/RelayModernRecord.js.flow +67 -11
  117. package/store/RelayModernSelector.js.flow +24 -14
  118. package/store/RelayModernStore.js.flow +72 -36
  119. package/store/RelayOperationTracker.js.flow +59 -43
  120. package/store/RelayOptimisticRecordSource.js.flow +2 -2
  121. package/store/RelayPublishQueue.js.flow +79 -34
  122. package/store/RelayReader.js.flow +351 -72
  123. package/store/RelayRecordSource.js.flow +72 -6
  124. package/store/RelayReferenceMarker.js.flow +60 -33
  125. package/store/RelayResponseNormalizer.js.flow +288 -102
  126. package/store/RelayStoreReactFlightUtils.js.flow +9 -13
  127. package/store/RelayStoreSubscriptions.js.flow +19 -11
  128. package/store/RelayStoreTypes.js.flow +210 -44
  129. package/store/RelayStoreUtils.js.flow +25 -11
  130. package/store/ResolverCache.js.flow +249 -0
  131. package/store/ResolverFragments.js.flow +121 -0
  132. package/store/StoreInspector.js.flow +2 -2
  133. package/store/TypeID.js.flow +1 -1
  134. package/store/ViewerPattern.js.flow +2 -2
  135. package/store/cloneRelayHandleSourceField.js.flow +5 -6
  136. package/store/cloneRelayScalarHandleSourceField.js.flow +5 -6
  137. package/store/createFragmentSpecResolver.js.flow +3 -4
  138. package/store/createRelayContext.js.flow +3 -3
  139. package/store/defaultGetDataID.js.flow +3 -1
  140. package/store/normalizeRelayPayload.js.flow +6 -7
  141. package/store/readInlineData.js.flow +7 -8
  142. package/subscription/requestSubscription.js.flow +54 -27
  143. package/util/NormalizationNode.js.flow +16 -3
  144. package/util/ReaderNode.js.flow +38 -2
  145. package/util/RelayConcreteNode.js.flow +4 -0
  146. package/util/RelayFeatureFlags.js.flow +24 -8
  147. package/util/RelayProfiler.js.flow +22 -194
  148. package/util/RelayReplaySubject.js.flow +9 -9
  149. package/util/RelayRuntimeTypes.js.flow +73 -4
  150. package/util/StringInterner.js.flow +69 -0
  151. package/util/createPayloadFor3DField.js.flow +3 -3
  152. package/util/deepFreeze.js.flow +2 -1
  153. package/util/getFragmentIdentifier.js.flow +27 -15
  154. package/util/getOperation.js.flow +2 -2
  155. package/util/getPaginationMetadata.js.flow +72 -0
  156. package/util/getPaginationVariables.js.flow +108 -0
  157. package/util/getPendingOperationsForFragment.js.flow +62 -0
  158. package/util/getRefetchMetadata.js.flow +79 -0
  159. package/util/getRelayHandleKey.js.flow +1 -2
  160. package/util/getRequestIdentifier.js.flow +3 -3
  161. package/util/getValueAtPath.js.flow +46 -0
  162. package/util/isEmptyObject.js.flow +2 -1
  163. package/util/registerEnvironmentWithDevTools.js.flow +33 -0
  164. package/util/resolveImmediate.js.flow +1 -1
  165. package/util/withDuration.js.flow +32 -0
  166. package/lib/store/RelayRecordSourceMapImpl.js +0 -107
  167. package/lib/store/RelayStoreSubscriptionsUsingMapByID.js +0 -318
  168. package/store/RelayRecordSourceMapImpl.js.flow +0 -91
  169. package/store/RelayStoreSubscriptionsUsingMapByID.js.flow +0 -283
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @flow strict
7
+ * @flow strict-local
8
8
  * @format
9
9
  */
10
10
 
@@ -14,6 +14,9 @@
14
14
 
15
15
  import type {DataID} from '../util/RelayRuntimeTypes';
16
16
 
17
+ const RelayFeatureFlags = require('../util/RelayFeatureFlags');
18
+ const {intern} = require('../util/StringInterner');
19
+
17
20
  const PREFIX = 'client:';
18
21
 
19
22
  function generateClientID(
@@ -21,7 +24,11 @@ function generateClientID(
21
24
  storageKey: string,
22
25
  index?: number,
23
26
  ): DataID {
24
- let key = id + ':' + storageKey;
27
+ const internedId =
28
+ RelayFeatureFlags.STRING_INTERN_LEVEL <= 0
29
+ ? id
30
+ : intern(id, RelayFeatureFlags.MAX_DATA_ID_LENGTH);
31
+ let key = internedId + ':' + storageKey;
25
32
  if (index != null) {
26
33
  key += ':' + index;
27
34
  }
@@ -40,4 +47,8 @@ function generateUniqueClientID(): DataID {
40
47
  return `${PREFIX}local:${localID++}`;
41
48
  }
42
49
 
43
- module.exports = {generateClientID, generateUniqueClientID, isClientID};
50
+ module.exports = {
51
+ generateClientID,
52
+ generateUniqueClientID,
53
+ isClientID,
54
+ };
@@ -13,23 +13,7 @@
13
13
 
14
14
  'use strict';
15
15
 
16
- const RelayConcreteNode = require('../util/RelayConcreteNode');
17
- const RelayFeatureFlags = require('../util/RelayFeatureFlags');
18
- const RelayModernRecord = require('./RelayModernRecord');
19
- const RelayRecordSourceMutator = require('../mutations/RelayRecordSourceMutator');
20
- const RelayRecordSourceProxy = require('../mutations/RelayRecordSourceProxy');
21
- const RelayStoreReactFlightUtils = require('./RelayStoreReactFlightUtils');
22
- const RelayStoreUtils = require('./RelayStoreUtils');
23
-
24
- const cloneRelayHandleSourceField = require('./cloneRelayHandleSourceField');
25
- const cloneRelayScalarHandleSourceField = require('./cloneRelayScalarHandleSourceField');
26
- const getOperation = require('../util/getOperation');
27
- const invariant = require('invariant');
28
-
29
- const {isClientID} = require('./ClientID');
30
- const {EXISTENT, UNKNOWN} = require('./RelayRecordState');
31
- const {generateTypeID} = require('./TypeID');
32
-
16
+ import type {ActorIdentifier} from '../multi-actor-environment/ActorIdentifier';
33
17
  import type {
34
18
  NormalizationField,
35
19
  NormalizationFlightField,
@@ -46,18 +30,36 @@ import type {
46
30
  MutableRecordSource,
47
31
  NormalizationSelector,
48
32
  OperationLoader,
49
- ReactFlightReachableQuery,
33
+ ReactFlightReachableExecutableDefinitions,
50
34
  Record,
51
35
  RecordSource,
52
36
  } from './RelayStoreTypes';
53
37
 
38
+ const RelayRecordSourceMutator = require('../mutations/RelayRecordSourceMutator');
39
+ const RelayRecordSourceProxy = require('../mutations/RelayRecordSourceProxy');
40
+ const getOperation = require('../util/getOperation');
41
+ const RelayConcreteNode = require('../util/RelayConcreteNode');
42
+ const RelayFeatureFlags = require('../util/RelayFeatureFlags');
43
+ const {isClientID} = require('./ClientID');
44
+ const cloneRelayHandleSourceField = require('./cloneRelayHandleSourceField');
45
+ const cloneRelayScalarHandleSourceField = require('./cloneRelayScalarHandleSourceField');
46
+ const {getLocalVariables} = require('./RelayConcreteVariables');
47
+ const RelayModernRecord = require('./RelayModernRecord');
48
+ const {EXISTENT, UNKNOWN} = require('./RelayRecordState');
49
+ const RelayStoreReactFlightUtils = require('./RelayStoreReactFlightUtils');
50
+ const RelayStoreUtils = require('./RelayStoreUtils');
51
+ const {generateTypeID} = require('./TypeID');
52
+ const invariant = require('invariant');
53
+
54
54
  export type Availability = {|
55
55
  +status: 'available' | 'missing',
56
56
  +mostRecentlyInvalidatedAt: ?number,
57
57
  |};
58
58
 
59
59
  const {
60
+ ACTOR_CHANGE,
60
61
  CONDITION,
62
+ CLIENT_COMPONENT,
61
63
  CLIENT_EXTENSION,
62
64
  DEFER,
63
65
  FLIGHT_FIELD,
@@ -71,12 +73,8 @@ const {
71
73
  STREAM,
72
74
  TYPE_DISCRIMINATOR,
73
75
  } = RelayConcreteNode;
74
- const {
75
- ROOT_ID,
76
- getModuleOperationKey,
77
- getStorageKey,
78
- getArgumentValues,
79
- } = RelayStoreUtils;
76
+ const {ROOT_ID, getModuleOperationKey, getStorageKey, getArgumentValues} =
77
+ RelayStoreUtils;
80
78
 
81
79
  /**
82
80
  * Synchronously check whether the records required to fulfill the given
@@ -89,21 +87,25 @@ const {
89
87
  * If all records are present, returns `true`, otherwise `false`.
90
88
  */
91
89
  function check(
92
- source: RecordSource,
93
- target: MutableRecordSource,
90
+ getSourceForActor: (actorIdentifier: ActorIdentifier) => RecordSource,
91
+ getTargetForActor: (actorIdentifier: ActorIdentifier) => MutableRecordSource,
92
+ defaultActorIdentifier: ActorIdentifier,
94
93
  selector: NormalizationSelector,
95
94
  handlers: $ReadOnlyArray<MissingFieldHandler>,
96
95
  operationLoader: ?OperationLoader,
97
96
  getDataID: GetDataID,
97
+ shouldProcessClientComponents: ?boolean,
98
98
  ): Availability {
99
99
  const {dataID, node, variables} = selector;
100
100
  const checker = new DataChecker(
101
- source,
102
- target,
101
+ getSourceForActor,
102
+ getTargetForActor,
103
+ defaultActorIdentifier,
103
104
  variables,
104
105
  handlers,
105
106
  operationLoader,
106
107
  getDataID,
108
+ shouldProcessClientComponents,
107
109
  );
108
110
  return checker.check(node, dataID);
109
111
  }
@@ -121,24 +123,66 @@ class DataChecker {
121
123
  _recordWasMissing: boolean;
122
124
  _source: RecordSource;
123
125
  _variables: Variables;
126
+ _shouldProcessClientComponents: ?boolean;
127
+ +_getSourceForActor: (actorIdentifier: ActorIdentifier) => RecordSource;
128
+ +_getTargetForActor: (
129
+ actorIdentifier: ActorIdentifier,
130
+ ) => MutableRecordSource;
131
+ +_getDataID: GetDataID;
132
+ +_mutatorRecordSourceProxyCache: Map<
133
+ ActorIdentifier,
134
+ [RelayRecordSourceMutator, RelayRecordSourceProxy],
135
+ >;
124
136
 
125
137
  constructor(
126
- source: RecordSource,
127
- target: MutableRecordSource,
138
+ getSourceForActor: (actorIdentifier: ActorIdentifier) => RecordSource,
139
+ getTargetForActor: (
140
+ actorIdentifier: ActorIdentifier,
141
+ ) => MutableRecordSource,
142
+ defaultActorIdentifier: ActorIdentifier,
128
143
  variables: Variables,
129
144
  handlers: $ReadOnlyArray<MissingFieldHandler>,
130
145
  operationLoader: ?OperationLoader,
131
146
  getDataID: GetDataID,
147
+ shouldProcessClientComponents: ?boolean,
132
148
  ) {
133
- const mutator = new RelayRecordSourceMutator(source, target);
149
+ this._getSourceForActor = getSourceForActor;
150
+ this._getTargetForActor = getTargetForActor;
151
+ this._getDataID = getDataID;
152
+ this._source = getSourceForActor(defaultActorIdentifier);
153
+ this._mutatorRecordSourceProxyCache = new Map();
154
+ const [mutator, recordSourceProxy] = this._getMutatorAndRecordProxyForActor(
155
+ defaultActorIdentifier,
156
+ );
134
157
  this._mostRecentlyInvalidatedAt = null;
135
158
  this._handlers = handlers;
136
159
  this._mutator = mutator;
137
160
  this._operationLoader = operationLoader ?? null;
138
- this._recordSourceProxy = new RelayRecordSourceProxy(mutator, getDataID);
161
+ this._recordSourceProxy = recordSourceProxy;
139
162
  this._recordWasMissing = false;
140
- this._source = source;
141
163
  this._variables = variables;
164
+ this._shouldProcessClientComponents = shouldProcessClientComponents;
165
+ }
166
+
167
+ _getMutatorAndRecordProxyForActor(
168
+ actorIdentifier: ActorIdentifier,
169
+ ): [RelayRecordSourceMutator, RelayRecordSourceProxy] {
170
+ let tuple = this._mutatorRecordSourceProxyCache.get(actorIdentifier);
171
+ if (tuple == null) {
172
+ const target = this._getTargetForActor(actorIdentifier);
173
+
174
+ const mutator = new RelayRecordSourceMutator(
175
+ this._getSourceForActor(actorIdentifier),
176
+ target,
177
+ );
178
+ const recordSourceProxy = new RelayRecordSourceProxy(
179
+ mutator,
180
+ this._getDataID,
181
+ );
182
+ tuple = [mutator, recordSourceProxy];
183
+ this._mutatorRecordSourceProxyCache.set(actorIdentifier, tuple);
184
+ }
185
+ return tuple;
142
186
  }
143
187
 
144
188
  check(node: NormalizationNode, dataID: DataID): Availability {
@@ -177,6 +221,8 @@ class DataChecker {
177
221
  ...
178
222
  } {
179
223
  return {
224
+ /* $FlowFixMe[class-object-subtyping] added when improving typing for
225
+ * this parameters */
180
226
  args: field.args ? getArgumentValues(field.args, this._variables) : {},
181
227
  // Getting a snapshot of the record state is potentially expensive since
182
228
  // we will need to merge the sink and source records. Since we do not create
@@ -302,8 +348,13 @@ class DataChecker {
302
348
  this._checkLink(selection, dataID);
303
349
  }
304
350
  break;
351
+ case ACTOR_CHANGE:
352
+ this._checkActorChange(selection.linkedField, dataID);
353
+ break;
305
354
  case CONDITION:
306
- const conditionValue = this._getVariableValue(selection.condition);
355
+ const conditionValue = Boolean(
356
+ this._getVariableValue(selection.condition),
357
+ );
307
358
  if (conditionValue === selection.passingValue) {
308
359
  this._traverseSelections(selection.selections, dataID);
309
360
  }
@@ -316,7 +367,7 @@ class DataChecker {
316
367
  if (typeName === selection.type) {
317
368
  this._traverseSelections(selection.selections, dataID);
318
369
  }
319
- } else if (RelayFeatureFlags.ENABLE_PRECISE_TYPE_REFINEMENT) {
370
+ } else {
320
371
  // Abstract refinement: check data depending on whether the type
321
372
  // conforms to the interface/union or not:
322
373
  // - Type known to _not_ implement the interface: don't check the selections.
@@ -342,10 +393,6 @@ class DataChecker {
342
393
  // missing so don't bother reading the fragment
343
394
  this._handleMissing();
344
395
  } // else false: known to not implement the interface
345
- } else {
346
- // legacy behavior for abstract refinements: always check even
347
- // if the type doesn't conform
348
- this._traverseSelections(selection.selections, dataID);
349
396
  }
350
397
  break;
351
398
  }
@@ -381,9 +428,15 @@ class DataChecker {
381
428
  case STREAM:
382
429
  this._traverseSelections(selection.selections, dataID);
383
430
  break;
384
- // $FlowFixMe[incompatible-type]
385
431
  case FRAGMENT_SPREAD:
432
+ const prevVariables = this._variables;
433
+ this._variables = getLocalVariables(
434
+ this._variables,
435
+ selection.fragment.argumentDefinitions,
436
+ selection.args,
437
+ );
386
438
  this._traverseSelections(selection.fragment.selections, dataID);
439
+ this._variables = prevVariables;
387
440
  break;
388
441
  case CLIENT_EXTENSION:
389
442
  const recordWasMissing = this._recordWasMissing;
@@ -391,25 +444,23 @@ class DataChecker {
391
444
  this._recordWasMissing = recordWasMissing;
392
445
  break;
393
446
  case TYPE_DISCRIMINATOR:
394
- if (RelayFeatureFlags.ENABLE_PRECISE_TYPE_REFINEMENT) {
395
- const {abstractKey} = selection;
396
- const recordType = this._mutator.getType(dataID);
397
- invariant(
398
- recordType != null,
399
- 'DataChecker: Expected record `%s` to have a known type',
400
- dataID,
401
- );
402
- const typeID = generateTypeID(recordType);
403
- const implementsInterface = this._mutator.getValue(
404
- typeID,
405
- abstractKey,
406
- );
407
- if (implementsInterface == null) {
408
- // unsure if the type implements the interface: data is
409
- // missing
410
- this._handleMissing();
411
- } // else: if it does or doesn't implement, we don't need to check or skip anything else
412
- }
447
+ const {abstractKey} = selection;
448
+ const recordType = this._mutator.getType(dataID);
449
+ invariant(
450
+ recordType != null,
451
+ 'DataChecker: Expected record `%s` to have a known type',
452
+ dataID,
453
+ );
454
+ const typeID = generateTypeID(recordType);
455
+ const implementsInterface = this._mutator.getValue(
456
+ typeID,
457
+ abstractKey,
458
+ );
459
+ if (implementsInterface == null) {
460
+ // unsure if the type implements the interface: data is
461
+ // missing
462
+ this._handleMissing();
463
+ } // else: if it does or doesn't implement, we don't need to check or skip anything else
413
464
  break;
414
465
  case FLIGHT_FIELD:
415
466
  if (RelayFeatureFlags.ENABLE_REACT_FLIGHT_COMPONENT_FIELD) {
@@ -418,6 +469,12 @@ class DataChecker {
418
469
  throw new Error('Flight fields are not yet supported.');
419
470
  }
420
471
  break;
472
+ case CLIENT_COMPONENT:
473
+ if (this._shouldProcessClientComponents === false) {
474
+ break;
475
+ }
476
+ this._traverseSelections(selection.fragment.selections, dataID);
477
+ break;
421
478
  default:
422
479
  (selection: empty);
423
480
  invariant(
@@ -449,7 +506,14 @@ class DataChecker {
449
506
  const normalizationRootNode = operationLoader.get(operationReference);
450
507
  if (normalizationRootNode != null) {
451
508
  const operation = getOperation(normalizationRootNode);
509
+ const prevVariables = this._variables;
510
+ this._variables = getLocalVariables(
511
+ this._variables,
512
+ operation.argumentDefinitions,
513
+ moduleImport.args,
514
+ );
452
515
  this._traverse(operation, dataID);
516
+ this._variables = prevVariables;
453
517
  } else {
454
518
  // If the fragment is not available, we assume that the data cannot have been
455
519
  // processed yet and must therefore be missing.
@@ -506,6 +570,37 @@ class DataChecker {
506
570
  }
507
571
  }
508
572
 
573
+ _checkActorChange(field: NormalizationLinkedField, dataID: DataID): void {
574
+ const storageKey = getStorageKey(field, this._variables);
575
+ const record = this._source.get(dataID);
576
+ const tuple =
577
+ record != null
578
+ ? RelayModernRecord.getActorLinkedRecordID(record, storageKey)
579
+ : record;
580
+
581
+ if (tuple == null) {
582
+ if (tuple === undefined) {
583
+ this._handleMissing();
584
+ }
585
+ } else {
586
+ const [actorIdentifier, linkedID] = tuple;
587
+ const prevSource = this._source;
588
+ const prevMutator = this._mutator;
589
+ const prevRecordSourceProxy = this._recordSourceProxy;
590
+
591
+ const [mutator, recordSourceProxy] =
592
+ this._getMutatorAndRecordProxyForActor(actorIdentifier);
593
+
594
+ this._source = this._getSourceForActor(actorIdentifier);
595
+ this._mutator = mutator;
596
+ this._recordSourceProxy = recordSourceProxy;
597
+ this._traverse(field, linkedID);
598
+ this._source = prevSource;
599
+ this._mutator = prevMutator;
600
+ this._recordSourceProxy = prevRecordSourceProxy;
601
+ }
602
+ }
603
+
509
604
  _checkFlightField(field: NormalizationFlightField, dataID: DataID): void {
510
605
  const storageKey = getStorageKey(field, this._variables);
511
606
  const linkedID = this._mutator.getLinkedRecordID(dataID, storageKey);
@@ -522,12 +617,12 @@ class DataChecker {
522
617
  linkedID,
523
618
  RelayStoreReactFlightUtils.REACT_FLIGHT_TREE_STORAGE_KEY,
524
619
  );
525
- const reachableQueries = this._mutator.getValue(
620
+ const reachableExecutableDefinitions = this._mutator.getValue(
526
621
  linkedID,
527
- RelayStoreReactFlightUtils.REACT_FLIGHT_QUERIES_STORAGE_KEY,
622
+ RelayStoreReactFlightUtils.REACT_FLIGHT_EXECUTABLE_DEFINITIONS_STORAGE_KEY,
528
623
  );
529
624
 
530
- if (tree == null || !Array.isArray(reachableQueries)) {
625
+ if (tree == null || !Array.isArray(reachableExecutableDefinitions)) {
531
626
  this._handleMissing();
532
627
  return;
533
628
  }
@@ -538,13 +633,13 @@ class DataChecker {
538
633
  'DataChecker: Expected an operationLoader to be configured when using ' +
539
634
  'React Flight.',
540
635
  );
541
- // In Flight, the variables that are in scope for reachable queries aren't
542
- // the same as what's in scope for the outer query.
636
+ // In Flight, the variables that are in scope for reachable executable
637
+ // definitions aren't the same as what's in scope for the outer query.
543
638
  const prevVariables = this._variables;
544
639
  // $FlowFixMe[incompatible-cast]
545
- for (const query of (reachableQueries: Array<ReactFlightReachableQuery>)) {
546
- this._variables = query.variables;
547
- const normalizationRootNode = operationLoader.get(query.module);
640
+ for (const definition of (reachableExecutableDefinitions: Array<ReactFlightReachableExecutableDefinitions>)) {
641
+ this._variables = definition.variables;
642
+ const normalizationRootNode = operationLoader.get(definition.module);
548
643
  if (normalizationRootNode != null) {
549
644
  const operation = getOperation(normalizationRootNode);
550
645
  this._traverseSelections(operation.selections, ROOT_ID);